Daimoku Multi-Programmer Online is an environment written in Ruby and ActiveRecord and implemented using Why’s Freaky-Freaky Sandbox. Daimoku allows multiple Ruby programmers to chat, share code and objects in real-time in an EW-Two-style environment.

System Agent AIs

NPC System Agents are now online. The only thing left is to program their AI to look for game world anomalies.

In case you didn’t know, the Agents are there to keep order and prevent the Players from becoming ‘Neo’ and hacking the game world, from inside. NPC System Agents will patrol the system looking for anomalies and punish those that attempt to overthrow or hack the game world.



Alpha Testers Wanted

If you’re interested in being an alpha tester and messing around with the system, send an e-mail to [rdegraci @ gmail com] with the subject “Request Daimoku Alpha Test”.

Any questions? Just ask in the comments.

The default clean installation of Snow Leopard uses the en_US.us-ascii locale. Unfortunately, when installing postgresql 8.3 using macports, the installer will complain when initializing the database, for example:

sudo su postgres -c '/opt/local/lib/postgresql83/bin/initdb 
-D /opt/local/var/db/postgresql83/defaultdb'

You will get the following error

The database cluster will be initialized with locale en_US.us-ascii.
could not determine encoding for locale "en_US.us-ascii": codeset is "us-ascii" 
initdb: could not find suitable encoding for locale en_US.us-ascii
Rerun initdb with the -E option.
Try "initdb --help" for more information.

The solution is to change the locale. First we list the locales available:

Outrun:db rdegraci$ locale -a | grep en_US
en_US
en_US.ISO8859-1
en_US.ISO8859-15
en_US.US-ASCII
en_US.UTF-8

Now we set the locale to en_US.UTF-8

Outrun:~ rdegraci$ export LC_ALL=en_US.UTF-8
Now start the server
Outrun:~ rdegraci$ sudo su postgres -c '/opt/local/lib/postgresql83/bin/initdb 
-D /opt/local/var/db/postgresql83/defaultdb'
You should get the following output
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale en_US.UTF-8.
The default database encoding has accordingly been set to UTF8.
The default text search configuration will be set to "english".

fixing permissions on existing directory /opt/local/var/db/postgresql83/defaultdb ... ok
creating subdirectories ... ok
selecting default max_connections ... 20
selecting default shared_buffers/max_fsm_pages ... 1600kB/20000
creating configuration files ... ok
creating template1 database in /opt/local/var/db/postgresql83/defaultdb/base/1 ... ok
initializing pg_authid ... ok
initializing dependencies ... ok
creating system views ... ok
loading system objects' descriptions ... ok
creating conversions ... ok
creating dictionaries ... ok
setting privileges on built-in objects ... ok
creating information schema ... ok
vacuuming database template1 ... ok
copying template1 to template0 ... ok
copying template1 to postgres ... ok

A quick and dirty way of setting up Rails and Apache2, is using Apache’s balancer module. You’ll need to enable the proxy module, and the proxy balancer module and then setup the configuration, as follows:

Set up the load balancer, to forward requests to the localhost, port 4040

<proxy balancer://my_site.com>
        BalancerMember http://127.0.0.1:4040
        Order allow,deny
        Allow from all
</proxy>

Configure the virtual host to point to the Rails Application’s root directory, located at /var/www/my_site.com.site/

<VirtualHost *:80>
        ServerAdmin hostmaster@my_site.com

        ServerName my_site.com 
        ServerAlias www.my_site.com

        DocumentRoot /var/www/my_site.com.site/

        ErrorLog /var/log/apache2/error_my_site.com.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog /var/log/apache2/access_my_site.com.log combined

        ProxyPass / balancer://my_site.com/
        ProxyPassReverse / balancer://my_site.com/
        ProxyPreserveHost on
        ProxyPass /images !
        ProxyPass /stylesheets !

        Alias /images /var/www/my_site.com.site/public/images
        Alias /stylesheets /var/www/my_site.com.site/public/stylesheets

</VirtualHost>

Start the Rails app to listen on localhost, port 4040. Finally restart the Apache server. If all goes well, the Apache server will forward requests to the Rails app.

From an OS to a Conversation

December 1st, 2009

A deeper view of Google Wave suggests that Google may want to change how people converse (via Google Wave) and thereby build a platform of tools to let people manage how they converse.

The File Metaphor become a Conversation Metaphor and the concept of “OS” becomes “Tools to manage the Conversation.”

Continuing this idea, means…

  • File Copy becomes “a tool to copy Conversations”
  • File Diff becomes “a tool to diff Conversations”
  • File Delete becomes”a tool to delete Waves”
  • Folders become “a tool to group Conversations”
  • File Search becomes “a tool to search Conversations”

Possible innovation

  • Searching across Waves for common ideas and connecting people based upon those connections
  • The concept of Peripherals becomes “Devices that can understand Conversations”

An exciting idea

The idea of “Devices that can understand Conversations” is very exciting and that can possibly be the next set of innovations from Google, since they are already in-place with mobile devices.

A little bit of this and that

November 30th, 2009

Back in 2002, I started writing C++ with a unique style of combining Modern C++ Design and Domain Driven Design. My endeavor was to write a 3D game engine. It was a fun exercise.

First, define the Math Trait. We will use the Real Number System


template <typename T>
struct RealNumberSystem
{
    //3 tuple Reals
    static int const N=3;    

    typedef T Radian;
    typedef T Theta;
    typedef T Rho;
    typedef T Radius;
    typedef T Scalar;
};

Next, define the Geometry Trait. We will use Standard Euclidean. The Tuple4 typedef is interesting.


struct StandardEuclidean
{
    static int const RightHanded=1;
    static int const LeftHanded=0;

    typedef Vector1x3<float> RowVector;
    typedef Vector3x1<float> ColumnVector;
    typedef Matrix3x3<float> Matrix3;

    typedef ColumnVector Origin;
    typedef ColumnVector Axis;
    typedef ColumnVector AnyVector;
    typedef ColumnVector ComponentVector;
    typedef Matrix3    Basis;

    typedef ColumnVector Point;
    typedef ColumnVector Normal;
    typedef ColumnVector Direction;

    //Four dimensions
    typedef Vector<float,4,1,Storage2Dim> Tuple4;

};

The following is the most critical class, which I think is the linch-pin that holds the math and the geometry together. Without this class, there is NO mathematical representation of a geometrical point, therefore the domain semantics within the code would eventually break down. I think this is the most conceptually beautiful code I have ever written:

//Mathematical representation of Geometrical Point

#include "Vector.h" 

template <typename T>
class Cartesian : public Vector3x1<T>
{
public:

    Cartesian(T x, T y, T z) : Vector3x1<T>(x,y,z)
    {
    }
};

Finally, define the Coordinate Systems and transformations between the systems

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//CoordinateSystem Template Class Declaration

template <typename T,
          template <typename T1> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class Cartesian3DCoordinateSystem
{
public:
    //Direct Access
    typename GeometryTrait::Axis m_U[MathTrait<T>::N];
    typename GeometryTrait::Origin m_P;

    Cartesian3DCoordinateSystem()
    {
        if(GeometryTrait::RightHanded)
        {
            m_P.Set(0,0,0);
            m_U[0].Set(1,0,0);
            m_U[1].Set(0,1,0);
            m_U[2].Set(0,0,1);
        }
        else
        {
            m_P.Set(0,0,0);
            m_U[0].Set(0,0,1);
            m_U[1].Set(0,1,0);
            m_U[2].Set(1,0,0);
        }
    }

    //Create this Coordinate System's Basis to match X
    Cartesian3DCoordinateSystem(const typename GeometryTrait::AnyVector& X)
    {
        if(GeometryTrait::RightHanded)
        {
            m_P.Set(0,0,0);
            m_U[0].Set(1,0,0);
            m_U[1].Set(0,1,0);
            m_U[2].Set(0,0,1);
        }
        else
        {
            m_P.Set(0,0,0);
            m_U[0].Set(0,0,1);
            m_U[1].Set(0,1,0);
            m_U[2].Set(1,0,0);
        }

        typename MathTrait<T>::Scalar Y[MathTrait::N]={0};
        for (int i=0; i<MathTrait<T>::N; ++i);
        {
            Y[i]=VectorColumn3::Dot(m_U[i],(X-m_P));
            m_U[i]*=Y[i];
        }

    }

    typename GeometryTrait::Basis GetBasis()
    {
        typename GeometryTrait::Basis R(m_U[0],m_U[1],m_U[2]);
        return R;
    }
};

template <typename T,
          template <typename> class MathTrait,
          typename GeometryTrait>
Vector3x1<T> Cylindrical2Cartesian(const CylindricalCoordinateSystem<T,MathTrait,GeometryTrait>& c)
{
    //m_Angle must be in Radians
    return (Vector3x1<float>((c.m_R*sin(c.m_Angle)),(c.m_R*cos(c.m_Angle)),0)); 
}

template <typename T,
          template <typename T> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class CylindricalCoordinateSystem
{
public:
    //Direct Access
    typename GeometryTrait::Origin m_Z;
    typename MathTrait<T>::Theta m_Angle;
    typename MathTrait<T>::Radius m_R;    //Radians

    CylindricalCoordinateSystem()
    {
        m_Angle=T();
        m_R=T();
    }

    void SetAngleDegrees(T angle)
    {
        const float pi=3.141592653f;
        const float radconv=pi/180;
        m_Angle=angle*radconv;
    }

    //The axis parameters are perpendicular
    CylindricalCoordinateSystem(T x, T y, typename GeometryTrait::Origin Z)
    {
        //x and y are relative to Z
        x=Z.x-x;
        y=Z.y=y;

        m_R=sqrt((pow(x,2)+pow(y,2)));
        m_Angle=(acos(x/m_R));
        if(y<=0) m_Angle=-m_Angle;
    }
};

template <typename T,
          template <typename T> class MathTrait,
          typename GeometryTrait>
Vector3x1<T> Spherical2Cartesian(const SphericalCoordinateSystem<T,MathTrait,GeometryTrait>& c)
{
    return (Vector3x1<float>((c.m_R*sin(c.m_PolarAngle)*cos(c.m_Azimuth)),(c.m_R*sin(c.m_PolarAngle)*cos(c.m_Azimuth)),(c.m_R*cos(c.m_PolarAngle)))); 
}

template <typename T,
          template <typename T1> class MathTrait=RealNumberSystem,
          typename GeometryTrait=StandardEuclidean>
class SphericalCoordinateSystem
{
public:
    //Direct Access
    typename MathTrait<T>::Radius m_R;
    typename MathTrait<T>::Theta m_Azimuth;
    typename MathTrait<T>::Rho m_PolarAngle;

    SphericalCoordinateSystem(typename GeometryTrait::Point P)
    {
        m_R=sqrt((pow(P.x,2)+pow(P.y,2)+pow(P.z,2)));
        m_PolarAngle=acos(P.z/m_R);
        m_Azimuth=acos(x/(sqrt(pow(P.x,2)+pow(P.y,2))));
    }
};

Define a linear component and a plane. I often wonder how things would be different, if we used: typename GeometryTrait = NonEuclidean

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//LinearComponent Template Class Definition

template <typename T,
          typename GeometryTrait=StandardEuclidean>
class LinearComponent
{
public:
    //Direct access
    typename GeometryTrait::Point m_B;
    typename GeometryTrait::ColumnVector m_M;

    LinearComponent(typename const GeometryTrait::Point& B, typename const GeometryTrait::ColumnVector& M) : 
    m_B(B), m_M(M)
    {
        m_M.Normalize();
    }
};

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Plane Template Class Definition

template <typename T,
          typename GeometryTrait=StandardEuclidean>
class Plane
{

public:
    //Three dimensional representation
    typename GeometryTrait::Point m_P;
    typename GeometryTrait::Normal m_N;

    //Four dimensional representation
    typename GeometryTrait::Tuple4    m_ND;    // <N,D>

    Plane() : m_P(),m_N() 
    {

    }

    Plane(const T& px, const T& py, const T& pz,
          const T& nx, const T& ny, const T& nz, const T& d) : m_P(px,py,pz),m_N(nx,ny,nz),m_ND(nx,ny,nz,d)
    {
        m_N.Normalize();

        assert( (Vector<float,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0])==0));
    }

    Plane(const T& A, const T& B, const T& C, const T& D) : m_N(A,B,C), m_P(), m_ND(A,B,C,D)
    {
        assert(m_N.Magnitude()>0);

        (m_ND.m_Storage.M[3][0])/=m_N.Magnitude();
        m_N.Normalize();

        //Create a dummy Point
        m_P=m_N * -m_ND.m_Storage.M[3][0];

        //D==-(N dot P)
        T ndotp=(Vector<T,3,1>::Dot(m_N,m_P));
        T d=m_ND.m_Storage.M[3][0];
        assert(fabs(d + ndotp) < 0.001f); 

        // N dot P + D == 0
        T dd=(Vector<T,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0]));
        assert(fabs(dd) < 0.001f);    //dd==zero
    }

    void SetNormal(const T& x, const T& y, const T& z)
    {
        m_N.Set(x,y,z);

        m_N.Normalize();

        m_ND.Set(m_N.x,m_N.y,m_N.z,0);    //Direction
    }

    void SetPoint(const T& x, const T& y, const T& z)
    {
        m_P.Set(x,y,z);
    }

    void SetD(const T& d)
    {
        m_ND.m_Storage.M[3][0]=d;
    }

    T GetD() const
    {
        return m_ND.m_Storage.M[3][0];
    }

    Plane(typename const GeometryTrait::Point& P, typename const GeometryTrait::Normal& N) : m_P(P), m_N(N)
    {
        //Make calculations easier by normalizing
        m_N.Normalize();

        m_ND.Set(N.x,N.y,N.z,-(Vector<float,3,1>::Dot(m_N,P)));

        assert( (Vector<float,3,1>::Dot(m_N,m_P) + (m_ND.m_Storage.M[3][0])==0));
    }
};

I’ve left out the Matrix template and Vector template code, since it’s pretty boring.

Hyper-Meta-Protocol

November 18th, 2009

Twitter is an informal protocol for transferring ideas and opinions in extremely compact form. Interestingly, Humans have adapted to the protocol, instead of the protocol adapting to Humans. These User-created protocols ride on top of of Twitter and are adopted by other Twitter users, if found useful.

Meta Protocol?

If we consider this informal protocol for a moment, we start to realize the protocols can be considered a Hyper-Meta-Protocol (HMP) or a protocol that is extensible but can also define itself.

Mechanization

So let’s try to mechanize the adoption of meta-protocols that ride on top of a particular protocol:

1) A protocol is essentially the process of synchronizing two or more state machines and optionally, transferring information between two or more two state machines.

2) Given the definition of protocol, we can constrain state machine changes such that those changes can be synchronized between the two or more separate state machines and therefore create different state-machines pairs, maintaining different meta-protocol sessions.

3) We reconcile differences or contradictions between different Users of the protocol, by performing squelching of non-popular meta-protocol sessions at the server level..

Some properties

  • Stateful

    HMPs are stateful, in that an HMP is implemented by a State Machine

  • In-Band

    HMPs are recursively in-band capable. That is to say, an HMP may contain another in-band HMP.

  • In-Band Modification

    In-band HMP/State-Machine may inspect/modify the containing HMP, but only if the containing HMP/State-Machine allows.

Humanity Friendly Technology

November 9th, 2009

Humanity Friendly Technology (HFT) is a term that describes technology that helps to mitigate the flaws of Humanity, especially our short-term thinking and our selfish nature.

The current state of Technology not as friendly to humanity as one would think, since he design of technology is based upon the profit/cost ratio. We have to remember that the profit/cost ratio (a construct of the corporation) has no relation to improving the quality of Humanity itself.

Fundamental Information System Design

If the following items have not been achieved, the Information System is fundamentally flawed.

  • Information must be difficult to destroy
  • The Information System must be automatically redundant (minimal human maintenance is required)

A good example of a Humanity Friendly Information System would be the Western Digital My Book World Edition II NAS with 4TB (two 2TB disks) with out of the box RAID mirroring, along with support for Time Machine and file versioning.

Technology Design

Technology that does not mitigate the worse case and support the best case, is fundamentally flawed.

  • Technology must mitigate the worse case (prevent destruction of itself or by its design prevent human death or injury)
  • Technology must support the best case (self diagnosis of its system or by its design improve the quality of life of humans)

An example of Humanity Friendly Technology Design would be the Tesla Roadster Battery System

Artificial Intelligence Design

If preventing human death or injury has not been achieved, the AI is fundamentally flawed.

  • AI must, by its design, prevent human death or injury
  • AI must, by its design, ensure the replication and redundancy of information

An example of Humanity Friendly AI Design would be the Volvo Collision Warning System.

Power Systems Design

Power systems that enslave humanity to its maintenance or pollutes the biosphere is fundamentally flawed.

  • Power Systems, must by design, be self maintaining (minimal to no human maintenance is required)
  • Power Systems must be non polluting to the biosphere
  • Power Systems must be distributed at no cost or at low cost to the public.

An example of a Humanity Friendly Power System would be the Westinghouse AP 1000 Nuclear Power Plant which is designed to be passively safe, even with no operator action and a complete loss of all on-site and off-site ac power, the AP1000 will safely shut down and remain cool.

If you want to set up a specific public/private keypair specifically for Heroku, so that you don’t have to use your own Mac OS X userid keypair, the following procedure should work:

1) Create a new keypair named id_heroku and id_heroku.pub

cd ~/.ssh
ssh-keygen -t rsa -C "Keypair for Heroku" -f id_heroku

2) Add the keypair to Heroku

heroku keys:add ./id_heroku.pub

3) Create a ssh config file

vi ~/.ssh/config

In the config file, make sure you have:

Host heroku.com
Hostname heroku.com
Port 22
IdentitiesOnly yes
IdentityFile ~/.ssh/id_heroku
TCPKeepAlive yes
User your_userid

Now when you execute git operations, ssh will use the config file and therefore use the specified IdentityFile for authenticating with heroku.com

Daimoku Multi-Programmer Online is an environment written in Ruby and ActiveRecord and implemented using Why's Freaky-Freaky Sandbox. Daimoku allows multiple Ruby programmers to chat, share code and objects in real-time in an EW-Two-style environment.

An RPG for Ruby Programmers

The motivation for writing Daimoku, was to write an RPG for programmers, specifically Ruby programmers. The game interface uses IRB, to speak to another player, use a string literal, for example "hello world", which the game server will display to all Players within the same room. The game world uses a shared IRB, therefore all variables are immediately shared.

Chat

Players in the same room can see each other's Ruby code, as they are typing the code in, as well as being able to see the IRB evaluation. For privacy, simply move to another empty room.

Sharing Objects

Any objects that are instantiated are automatically shared. Obviously, Players in the same room would be able to see the variable name that holds a reference to the object.

In World API

The game world has an API, which is immediately invokable by the Players. The API allows a Player to run a socket server and socket client within the game world.

Commands:

north, south, east, west, up, down, exits

Of course, you get an IRB (interactive Ruby) prompt, so that you can hack Ruby while you play

Soon to be implemented

System Agent AIs

To keep order and prevent the Players from becoming 'Neo' and hacking the game world, from inside, Daimoku will have NPC System Agents that will patrol the system looking for anomalies.

Player Attributes (Programmer vs. Programmer)

Players will have hit points, armor class, and will be able to create daemons which will damage or heal other programmers; this leads to an interesting PvP game.

Alpha Testers Wanted

If you're interested in being an alpha tester and messing around with the system, send an e-mail to [rdegraci @ gmail com] with the subject "Request Daimoku Alpha Test".

Any questions? Just ask in the comments.

Hungarian notation is a programming language naming convention. Writing with Hungarian notation entails creating variable names that start with a group of lower-case letters which are mnemonics for the type or purpose of that variable. Hungarian notation, fully implemented can be more trouble that it is worth. However, a subset of Hungarian notation can be useful.

A subset of Hungarian Notation

Modified Hungarian Notation (MHN) is a self-coined term, that described slight changes to normal Hungarian notation and also defines a subset of full Hungarian notation. The main point of MH is to help define scope and consistency of variable naming. We can differentiate between local variables and member variables that are semantically similar, by the prepended mnemonic; this results in less time wasted trying to determine a different variable name.

MHN Guidelines

Mnemonics

  • integer i
  • string str
  • float f
  • double dw

String Variables

Always prepend with the scope and the mnemonic:

string strMyName, g_strMyName;

Local Variables

Looping variables are: i, j, n, t

Short name local variables are the full type name but in lower case:

int counter(0), index(0), age;
float average, rateofclimb;

If the type of the local variable is important (mathematical or type operations) then the type is specified in lowercase:

float fSomeValue;

Do not place “C” before the class name, instead use the class name itself in lowercase when instantiating:

MyClass myclass; 

Global Variables

Prepend with g_ for example :

MyClass g_MyClass;

If the type is POD or string then always prepend the type mnemonic:

float g_fRateOfClimb;
string g_strNameOfTheShip;

Class member variables

Preped with m_ and always for example:

class A 
{
  string m_strValue;
  public:
  A(string s) { m_strValue = s; }
};

A a("hello world"); 

Function Signatures

Single letter lowercase can be used for the variable name if the function is a setter. If the single letters conflict then append a number:

int MyFunction(string s1, string s2, int i, float f1, float f2);

If the function is non-trivial (not a settor or getter) then use the full semantic name in lowercase. If conflicting then append a number:

void MyFunction2(string strFirstName, string strLastName);

Competence Delusion

April 22nd, 2009

My favorite APA article:

“Unskilled and Unaware of It: How Difficulties in Recognizing One’s Own Incompetence Lead to Inflated Self-Assessments”

From the article:
People tend to hold overly favorable views of their abilities in many social and intellectual domains. The authors suggest that this overestimation occurs, in part, because people who are unskilled in these domains suffer a dual burden: Not only do these people reach erroneous conclusions and make unfortunate choices, but their incompetence robs them of the metacognitive ability to realize it.

PDF Download

We believe that our computer anti-virus software will protect our computer and our data. Is that belief justified? Let’s take an informal look:

First some definitions

Let’s define the term “unknown virus/worm” as a virus that is “in the wild” and the anti-virus companies do not know about it because the behavior of the virus/worm is so stealthy (or so targeted, or just new) that it does not call attention to itself.

Let’s define the term “known virus/worm” as a virus that has a virus signature and can be scanned and found.

Now some numbers:

Symantec reported in 2007 that a little more than 700,000 computer viruses were identified. Let’s say that the 700,000 viruses represent 99.99% of all virus/worm (known and unknown), leaving at least .01% unknown . The number of unknown virus/worm would then be about 70.

Let’s divide that 70 by 12 months, that comes out to 6 unknown virus/worm per month or about 0.2 viruses a day. To make this simpler, let’s say on average there is 1 unknown virus/worm that is produced each 5 days.

Let’s say that of each unknown virus, it takes about an average of 72 hours for it to become detected and a virus signature created.

Now for the kicker:

Such an unknown virus/worm would have an infection rate of 100% during those 72 hours. This suggests that the larger the computer network, the higher the probability of infection.

The true horror:

Since the infection rate, of that virus/worm is 100%, during those 72 hours, this means you’ve most likely been infected but you just don’t know it (yet), and your anti-virus software is running perfectly. This means for at least 72 hours, your computer is under the control of the virus/worm writer.

Are we doomed?

The majority of experts believe that the vast majority of virus/worm writers are not state sponsored, which means state resources (human, equipment, material) are not being actively used to create viruses/worms for the purposes of world computer domination of the average person. That is not to say, such resources are not being actively used to target specific computers in particular governments.

If you are considered an average target, then you are at risk. An average target consists of computer users that run active-content from the Internet, either by receiving non text-e-mail, downloading and installing questionable free tools and utilities, or running non text-based browsers that run active-content either through client-side or plugin technologies.

What if you are directly targeted?

Sucks to be you. If you think you are actually targeted (if your paranoia is really justified), the only hope is to go totally offline. Otherwise the following may help:

  • Don’t be an average target
  • Maintain multiple backups of your data
  • Maintain archives of your data
  • Subdividing your network results in a reduction of risk, on average; a network consisting of one computer is the safest (but still not 100% safe).

Managing Knowledge

March 22nd, 2009

I like to explore new software technology and it is enjoyable to learn the mechanics and technical details inherent with new technology. However, there is the challenge of retaining as much of the knowledge gained. I think a knowledge base is mandatory, now-a-days, to keep up with the fast changing technology landscape.

Here are my basic requirements of a knowledge base engine:

  • Knowledge must be difficult to destroy
  • Knowledge must be transferable
  • Knowledge must be easily found and easily edited

The knowledge base engine must have the following technical capabilities:

  • A free form schema that self defines itself
  • Free-form data entry that supports text, multimedia, and HTML
  • The schema is abstracted as data that is fully editable and extensible from within the User Interface
  • Reports and Search is abstracted as data that is fully editable and extensible from within the User Interface

So far the only free knowledge base that fits the above is Wagn. Wagn is a combination of a Wiki and a Database. The innovation is that the Wiki allows free form exposure of the database schema; this means this knowledge base is extremely flexible and extensible. The Wagn site explains:

One of the most exciting things about using Wagn as a database is that, unlike most databases, the public-facing website and the database are all wrapped up into one. With conventional tools you have your data structure (aka model), where you store everything, your web interface design (aka view), and a whole layer of programming to communicate between the two (aka controller). Then, if you want to change any one of them, you often have to change all three! Wagn wraps all of these into one simple organizing unit: the card.

I have Wagn set up on a Slackware instance on my VMware “beta” host. The Wagn installation serves as my personal IT knowledge base. It is customized to store various code snippets and server administration procedures as well as little bits of knowledge that is tactically useful for solving interesting but esoteric software/system problems.

I just reviewed Apple’s online video presentation and given the improvements and new APIs I think the iPhone OS 3.0 is the Killer App of the iPhone. This is similar to how the Java API itself was the Killer App for Java. Apple has provided most of the heavy-lifting, leaving the creativity to the iPhone software developers.

I think the upcoming APIs are going to make near-future iPhone applications so compelling, the end result will be that purchasing an iPhone will no longer be based upon the hardware or even cost. Competing mobile applications and their phones that are non touch and button-based, will be seriously outclassed.

The 3rd Party device API, will make the iPhone the ‘brains’ of dumb devices; the potential for innovation founded upon the iPhone enabled 3rd party devices is just too staggering to consider.

The new features and APIs will compel the building of new enterprise-level applications. I think that a new enterprise-level software/hardware development industry might just have been born today.

Impossible

March 1st, 2009

I first heard this when watching the old Disney movie “Black Hole”. It turns out, the quote is much much older:

“Impossible is a word to be found only in the dictionary of fools.”
[Napolean Bonaparte]