« September 2007 | Main | November 2007 »

October 29, 2007

The Goal by Eliyahu M. Goldratt and Jeff Cox

I recently finished "The Goal". It is a great book on pull vs push manufacturing optimization. Here is what I want to remember from this book:

* Optimize the whole not parts
* The Goal is to make money
* focus on bottle necks, increase their capacity, drive the system by their schedule, distribute their load
* Inventory/Queuing is waste
* Use small uniform batch sizes

Posted by Chris at 05:24 PM

October 22, 2007

What is the What?

I just finished "What is the What" by Dave Eggers, it tells the story of Valentino Achak Deng. One of the lost boys of Sudan. I really loved Dave's first book "a heartbreaking work of staggering genius," so I bought this book on that. I read it in a couple days. It's an amazing page turner that manages to convey the loss of Deng's experience while not shoving your face in the horror of civil war. The whole book is told in a very matter of fact tone that holds you rapt. I feel like I now know more about Sudan, Darfur, and the lost boys than I ever did.

Posted by Chris at 08:36 PM

October 17, 2007

Eliza in Apex Code

Every time I do a new project I like to rebuild Eliza in a programming language. Here is Eliza with a Visual Force page and Apex code as the underlying implementation. It doesn't support a lot of different sentence types but there is enough to work now. The display is done as a Visual Force Page: <apex:page controller=\"ElizaController\" showHeader=\"false\">

<p>Hello Welcome to the Apex Question and Answer Page </p>

<apex:form id=\"questionForm\">

<apex:inputText id=\"questionText\" value=\"{!QuestionText}\"></apex:inputText>

<!-- apex:commandButton value=\"Click Here\"><apex:param name=\"question\" value=\"{!QuestionText}\"/></apex:commandButton -->

<apex:commandButton value=\"Click Here\"></apex:commandButton>

</apex:form>

<p>Your Question: {!questionText} </p><b> Your Answer: {!answer}</b></p>

</apex:page>

With a custom controller:

public class ElizaController {

    private String QuestionText;

    public void setQuestionText(String val) {
        questionText = val;
    }

    public String getQuestionText() {
      return questionText;
    }


   public String getAnswer() { 
      return Eliza.converse(questionText);
   }
}

Most of the work is done in the Eliza Util class:

public class ElizaUtil {

    private Map variables = new Map();
    private static String[] wwords = new String[]{'when','why','where','how'};

    public String getValue(String var) {
        return variables.get(var);
    }

    public void setValue(String var,String val) {
        variables.put(var,val);
    }

    public static String wWord() {
       Integer value = Math.round(Math.random()*3.0);
       return wwords[value];

    }

    public boolean atom(String s) {
       if (s == null) return true;
       return s.split(' ',2).size() == 1;
    }

    public String car(String s) {
       if (s == null) return null;
       String[] words = s.split(' ',2);
       if (words.size() == 0) return null;
       return words[0];
    }

    public String cdr(String s) {
       if (s == null) return null;
       String[]words = s.split(' ',30);
       if (words.size() < 2) return null;
       String result = words[1];
       for(Integer i=2;i < words.size();i++){ 
          result = result + ' ' + words[i];
       } 
       return result;
    }

    private static String variableName(String s) {
       if (s.length() < 2) return 'default';
       else return s.substring(1,2);
    }

    public Boolean match(String p, String s) {
        variables.clear();
        return submatch(p,s);
    } 

    public Boolean submatch (String p, String s) {
       if (p == null) { 
           return (s == null);
       } else if (s != null && (car(p) == car (s)) && submatch(cdr(p),cdr(s))) { 
           return true;
       } else if (s != null && car(p).startsWith('?')) {
           if (match(cdr(p),cdr(s))) {
               setValue(variableName(car(p)),car(s));
               return true;
           }
           else return false;
       } else if (s != null && car(p).startsWith('*')) {
           if (s != null && submatch(cdr(p),cdr(s))) {
               setValue(variableName(car(p)),car(s));
               return true;
           } else if (match(cdr(p),s)) {
               setValue(variableName(car(p)),null);
               return true;
           } else if (s!=null && submatch(p,cdr(s))) {
               String currentValue = getValue(variableName(car(p)));
               if (currentValue == null) currentValue ='';
               setValue(variableName(car(p)),car(s)+' '+currentValue);
               return true;
           }
           return false;
       }
       return false;
      
    }

   static testMethod void testMatchPositive() {
       ElizaUtil eu = new ElizaUtil();
       System.assertEquals(eu.match('Hello','Hello'),true);
       System.assertEquals(eu.match('Hello to you','Hello to you'),true); 
       System.assertEquals(eu.match('Another test','Another test'),true);
       System.assertEquals(eu.match(null,null),true);
    } 

    static testMethod void testMatchNegative() {
       ElizaUtil eu = new ElizaUtil();

       System.assertEquals(eu.match('Hello to you','Hello to me'),false);
       System.assertEquals(eu.match('a',null),false);
       System.assertEquals(eu.match(null,'a'),false);
       System.assertEquals(eu.match('me','you'),false);
    }

    static testMethod void testMatchAdvanced() {
       ElizaUtil eu = new ElizaUtil();
       System.assertEquals(eu.match('*X to you','Hello to me and to you'),true);
       System.debug(eu.getValue('X'));
       System.assertEquals(eu.getValue('X'),'Hello to me and');
       System.assertEquals(eu.match('?X to you','Hello to you'),true);
       System.assertEquals(eu.getValue('X'),'Hello');
       System.debug(eu.getValue('X'));

       System.assertEquals(eu.match('Hello to ?X *Y','Hello to Chris and friends'),true);
       System.debug('X->'+eu.getValue('X')+' Y->'+eu.getValue('Y'));
       System.assertEquals(eu.getValue('X'),'Chris');
       System.assertEquals(eu.getValue('Y'),'and friends');
       System.assertEquals(eu.match('*X to you','Hello to me'),false);
       System.assertEquals(eu.match('?X to you','Hello to me'),false);  
    }

    static testMethod void testCarCdr() {
       ElizaUtil eu = new ElizaUtil();
       System.assertEquals(eu.car('Hello'),'Hello');
       System.assertEquals(eu.car('Hello to you'),'Hello');
       System.assertEquals(eu.cdr('Hello to you'),'to you');
       System.assertEquals(eu.cdr('Hello'),null);
       System.assertEquals(eu.cdr(null),null);

    }
}

Posted by Chris at 04:30 PM

October 14, 2007

Games from the days of 1200 baud modems

pcal has done it to me again. He sent me a link which I think said don't click on this. Of course I have no willpower so I clicked on the link and am now addicted to travian, an online empire building game. Zero cost, it reminds me of the turn based games I used to play on BBSs when I was a kid but without the email and turn based systems.

Posted by Chris at 12:35 PM

October 04, 2007

Internet runtime environments

Marc Andreessen has a great post on internet platforms where he points out that Salesforce.com is a level 3 platform (Thanks to Adam Gross for pointing this out).

Here is Marc's terminology:

Level 1 is an Access API.
Level 2 is a Plug-In API.
Level 3 is an Internent Runtime Environment.

Level 2 is Facebook. Here is his description of Salesforce's platform:

Second, in a completely different domain, Salesforce.com is also taking a Level 3 platform approach -- Salesforce now provides quite sophisticated ways for users and developers to create and upload code and program the Salesforce platform from a browser.

Salesforce provides a Level 3 platform both because it lets users easily customize Salesforce to do whatever they need, and also because it definitively trumps the criticism they historically got from packaged software vendors like Siebel who accused Salesforce of not being as adaptable as a piece of software you install on your own servers.

You probably don't see this in action much -- unless you're a Salesforce user -- but they're doing really interesting work in this area and getting great results.

Posted by Chris at 10:31 PM