Thursday, 2 July 2009

another LIFT rant...


Yesterday I got so frustrated with Liftweb and it's lack of documentation that I decided to pick up apache wicket. Now I had picked up wicket almost a year ago and despite all it's cool features I decided against pursueing it any further. Well guess what those same reasons popped up again yesterday. Needless to say I'm back with lift. I've seen a lot of complaints about lift's documentation and all that but I'm not convinced that the reason I'm still with lift is the self same reason I wont pick up wicket anytime soon. Enough ranting.
So I figure what's the point of joining the rants when I could spend my time better contributing in my own small way to solving the problem? So I decided to write a little tutorial (seriously this is nothing serious) about lift.

Some foundations...

Lift is written in scala (so if you dont know scala you might as well stop reading now). It is said to have picked up the nice things from all the other frameworks and of course since scala is said to scale well, it is expected that lift scales well (dont take my word for it). In anycase... enough cliches and truism... here's how I understand lift.

In lift there are basically 3 parts to your web app

1. The view - your normal (well formed) xhtml document. The special thing though is that there are all these special tags that correspond to class methods that you arbitrarily create.
2. The boot system - this is a class where all the configuration of your webapp is stored. For instance you'd store the package where you have the tag classes I mentioned above here.
3. Your special tags - ok, seriously, this can get really confusing but humour me for just a moment.

So how does this all come together? Well, the special tags I mentioned above are actually called 'snippets' - and yes they are much more than special tags. They are more like mini-controllers that have been thrown into your html file. So when lift is processing a request for an html view and it encounters any one of these special tags (snippets), the class method corresponding to the special tag's name is called. This class method is free to roam the wild and do what ever it likes (after all I just said it's a mini controller). But it's not all about the snippets.... the view (html files) that I talked about also have this cool feature called templating. What happens in essense is that you can have a template html file (one or more) that defines the common functionality. Then you can have other xhtml fragments in other files that then define only the part of your website that changes. No, I'm not exactly talking inheritance here but then again I'm not sure what I'm talking about ;)

pre implementation
Ok so let's see an implementation to get some concrete understanding of all the nonsense I've just said... I'll basically keep it really simple...

We'll have one web page (actually a template and 2 snippets)
One class with two methods

The website will basically give potential spellings of english words in yoruba. On that note some of the other things I'll touch on are session variables, request variables and .... that's it!
I just have to say one more thing... lift relies a lot on maven so if you hate maven... why would you hate someone that's never done anything to harm you?

view implementation

Remember the template we talked about earlier? well this is how it works. You have a standard xhtml file that contains how you want your site to look. Inside that file you can place <lift:bind name="content" /> tags at any position where you think the content should change dynamically. You then define other xhtml files that would define dynamic content. These other xhtml files will specify what template LIFT should use by using the <lift:surround with="default" at="content"></lift:surround> tag. These xhtml files would also contain special tags that map to class methods that you define. For instance <lift:yoruba.spell form="GET">, in the example below, tells lift that it should load and call the spell method from the "Yoruba" class defined in the snippet package.


<lift:surround with="default" at="content">

  <h2>Welcome to your project!</h2>
  <p>
    <lift:yoruba.spell form="GET">
      word: <yo:word /><br/>
      <yo:submit />
      <yo:spellings />
    </lift:yoruba.spell>
  </p>
</lift:surround>



snippet implementation

The snippet is a plain old scala class (POSC just doesn't do it as an acronym now does it?). In any case, this method should contain a method called spell (because in your html file you refered to a method called "spell" within the "Yoruba" class. This method should call a special method called bind where you define the default values of xhtml fields and how the corresponding class variables are populated when a request comes in. Ideally you should have a variable that corresponds to each <yo:submit /> tag within the <lift:yoruba.spell form="GET"> tag. The first parameter of the bind method is "yo". The 2nd should be pretty obvious. The third though, simply says where ever the <yo:word /> tag is encountered the default value is yoruba.word and the field that should populated when a request gets to the server is defined by the method "word = _" (if you dont understand this construct google "scala partial functions" as my fingers are beginning to ache!).

One note worthy thing is that the other of parameters in the bind method is important (or so I think). So for instance if I had put the submit binding definition after the spelling one then potentially the calculated spelling would only make it to the client on the next response not the current one. **I think this is something I should verify but then again there's a reason for the disclaimer at the top of this blog**

Another thing to note is that since each request comes on it's own and may (would) trigger another instance of your snippet class if you set the value of a field when the request comes in it may see that value set when the response gets back to the client. Ways around this include using RequestVar/SessionVar as I've done here or using S.mapSnippet("yoruba.spell", a local method defined within Yoruba.spell) to change the binding on the snippet. The result of the later makes smart use of scala's perspective on scope and the fact that scala accepts higher level methods. Actually you'll see this later method used here. I opted to go with the SessionVar/RequestVar approach because I want previous spellings to show up on the screen as long as the session hasn't timed out. To use these SessionVar, you create an object that extends SessionVar along with a default constructor. The use of RequestVar is a little different but it's explained in the LIFT Book (it may be a good idea for you at this time to google "liftbook master.pdf" if you've not already done so).


package eni.ola.snippet


import scala.xml.{ NodeSeq, Text }

import net.liftweb._
import http._
import SHtml._
import S._

import util._
import Helpers._

class Yoruba {
  object spellings extends SessionVar[NodeSeq](Text(""))
  var word = ""
  
  def spell(xhtml:NodeSeq):NodeSeq = {
    def process():Unit = {
      val x = koole(word.toString, null)
      
      spellings(
        <div>{ x }</div>
        <hr/>
        <span>{ spellings.is }</span>
      )
    }
    
    def yoBind(xhtml:NodeSeq):NodeSeq =
        bind("yo", xhtml,
                "word" -> SHtml.text(word, word = _),

                "submit" -> SHtml.submit("epeller", process),
                "spellings" -> spellings.is
        )
    

    yoBind(xhtml)
  }

  
  val afabeti = Set("a", "\u00E1", "\u00E0") ::
                        Set("e", "\u00e8", "\u00e9", "e\u0329", "\u00E8\u0329", "\u00E9\u0329") ::
                        Set("i", "\u00EC", "\u00ED") ::
                        Set("o", "\u00F2", "\u00F3", "o\u0329", "\u00F2\u0329", "\u00F3\u0329") ::
                        Set("u", "\u00F9", "\u00Fa") ::
                        Set("s", "s\u0329") :: Nil  
  def koole(word:String, combos:List[String]):String = {
    if(word.trim == "")
      combos.reduceLeft(_+", "+_)
    else if(combos == null || combos.isEmpty)
      koole(word, List(""))
    else{
      //get list of possible letters for current letter
      val letter = word(0).toString     
      val /span>choice = { Set(letter) :: afabeti.filter(_.contains(letter)) }.reduceLeft(_ ++ _).toList


      //append the list to each existing combo
      koole(word.substring(1), choice.flatMap(x => combos.map(_+x).toList))     

    }

  }
}



en fin

So what I've done here is pretty basic. I've not touched the boot class at all as I simply just tweaked/created 2 files. The learning curve of LIFT may be steep but it sure is concise. The error messages dont help that much either but you can't win them all now can you? I assumed that you already know how to create a LIFT project using maven. If you dont here's what you do...

Install eclipse (I'm sorry Netbeans fans but I can't bring myself to work in an ugly IDE) from eclipse.org.
Install the scala eclipse plugin and m2eclipse plugin (for maven) - if you dont know where to get these from then google or bing (bing sounds so perverse).
Once you have all these set up, create a maven project. When it's time to select archetype choose "lift-archetype-basic" and voila!
To run/demo the project, you can set up a maven run configuration for your project and make the goal "jetty:run".

koole - is the Yoruba word for write it down
afabeti - is my own yoruba transliteration for the english word alphabet

Phew! I definitely won't come back to this blog for another 2 months or so... quantum mechanics beckons :(
But never say never... after all the EPL season starts this month for us Gooners (someone has to talk some sense to those ArsenalAmerica.com guys - I'm not sure they know how much changes to their site may affect my sanity). Aight... happy 4th of July

Saturday, 11 April 2009

Salvation: 3 Steps (a functional programming look at salvation)


This is by no means a definitive write-up on Salvation. In stead, it's me spending part of the Sabbath thinking about something that's as important to me as life and death. In Matthew 16:24, there's a simple three step program for salvation. The steps are

1. Deny yourself
2. Take up your cross
3. Follow me

It's easy to think of these steps as been sequential but a closer look may tell us otherwise. In fact it may also be understood that these steps are somewhat interwoven. Denying one's self is actually a fundamental and integral part of taking up your cross and following Jesus involves taking up your cross, daily (Luke includes that word in this rendation of this 3 step program). I'd like to understand this thingy more and clarify the questions. These questions include, among many others

- Is it really this easy to get salvation (what does each step entail)
- What ever happened to righteousness by grace through faith
- Is this 3 step program sequential or simultaneous


def deny(self:HumanBeing):EmptyBeing = self.recant()


freedictionary.com defines self-denial gives 2 definitions of self-denial - "Sacrifice of one's own desires or interests." and "the repression or sacrifice of one's own desires". So another question to ask is is was Jesus talking about this. If this is what he had in mind then we have to ask ourselves what if anything is the product of self denial? The simplistic answer would be losing out on some fun or better still losing out on what we truly crave. However the next question quickly springs to mind - at what cost? Interestingly, Jesus also says "we ought to count the cost" of following him. Since the question of cost will come up in every one of this 3 step program I'll leave the question of cost to either another blog or another section of this blog (I've got about 2 hours left this Sabbath after all)

An alternate explanation of "deny yourself" is to find similar phrase or scenario used by Jesus in the bible. Jesus once told Peter that he [Peter] would "deny him [Jesus]" thrice. Now this may sound like a rather ridiculous example of similar phrasology (dont think this word exists) but humor me anyway. So how does Peter deny Jesus? He very well renounces all relations and knowledge of Jesus and goes to the very extreme of cursing and swelling. He must have sounded a little like Tupac in Hit 'Em Up with quite a few 'F' words. It brings to mind how Nero and then the large christain church in the Dark Ages would require you to recant or die. So if this was what Jesus had in mind then Jesus was talking about more than just self denial (i.e. sacrificing or repressing one's own desire). He was talking about recanting on all that you believe in or would personally, individually, stand for. He's saying use sanctified 4 letter words to describe yourself (and mean it too) every moment of your life. Ok so it's looking like I'm making a meal of a man's little white lie in attempting to save his life but dont they say "Life and death is in the power of the tongue" and "out of the fullness of the heart the mouth speaketh"? Peter may have just been trying to save his life no more desperately than we should be too but in that moment he most definately meant every word of what he said enough for him to feel deep sorrow when he realized what he had just done. Interestingly I think self-denial (as seen in the first definition) is natural product of this second explanation. Or put another way deny yourself results inevitably in complete and utter self-denial.

So where the self-denial says "no thank you" when you are offered pork - it's unclean after all (if you are Jewish, Muslim or a christian that shares that believe) - Peter's example of Denial not only simple says "no thank you" but it says I never had it before, I dont know how it tastes and I sure as hell dont want anything to do with it. It's kind of like a violent attempt to rip out the very essence of you from you that's what it is (the kingdom of God suffereth violence anyone?). Denying yourself should be an act much like Daniel and his friends proposing in their hearts not be defy themselves with ....
So whereas the self-denial looks the harder and the second attempt looks extremely easier yet more far reaching. I think we'll have to talk about why it's extremely easier real soon.


def takeUpCross(being:EmptyBeing):DeadBeing = being.die()


That the cross, that must popular christian symbol of death (yes that's what I really symbolizes), has become a fashion statement is interesting. In fact as I type this I'm thinking to myself that I really should go get me a cross pendant. Seriously, though, for the Jew and in Jesus' time the cross was a symbol of more than Roman oppression - it was a symbol humilation and death. To understand this you've got to be an African (or at least from a non-western culture). Many african cultures have tightly interwoven extended family structures and if something as disgraceful such as been caught stealing happened to you were usually stuck with the stigma for the rest of your life. Now that I think of it, it's rather easy to explain in Western culture (or more specifically American culture since I've only been to Africa and US). Been seen with a cross is kind of like that stain on your record as a medical practitioner that prevents you from practicing as a doctor many years after that mark found it's way to into your record. The cross was not a palatable thing for the jew - it was simply put a death sentence - and no one wants to die (why do you think I bother reading this stuff).

The cross is such a terrible thing that it takes been utterly empty of self for you (denying yourself) to be willing and able to carry it. And to be able to continually carry the cross you've got to continually deny yourself. The cross is you signing or better still accepting your death warrant. Dietrich Bonhoeffer puts it like this "When Christ calls a man, he bids him come and die." Like Dietrich goes on to explain, this isn't physical death but more importantly it's death to all that you ever would have been had you not denied your self. The cross is only possible as a consequence of denying yourself. Both are tightly coupled (no pun intended) and inseperable. In functional programming, you'll probably want to pass the deny() function as a parameter to the takeUpCross() function so that the takeUpCross() function can call it with impunity within itself.


def followChrist(corpse:DeadBeing):TrueBeing = corpse.resurrect().live()


Jesus said a lot of things. One that stands out and that I like to hear is "I have come that they might have life and have it more abundantly". Paul, I think, says if anyone be in Christ he is a new creature. The old has passed away the new has come. The thing is since Jesus is the resurrection and the life when you've denied yourself and taken up that cross (that is when you are dead to the world for all intents and purposes), then you can follow Jesus. You can do this because it's no longer you but the Christ in you that's alive. Paul talks a lot of salvation and grace and stuff like this. He says "...and it is no longer I who live, but Christ lives in me..." when he describes he's walking with Christ experience. In fact preceeding this he talks about dying with Christ (which I figure should be synonymous with taking up your cross).


def comeAfterChrist(deny, self)(takeUpCross)(followChrist) =
                                                     followChrist(takeUpCross(deny(self)))



The beauty of the 3 step program is that it offers life not death. It easy to stop at step 2 and cringe when you realize it's death that's been talked about. But the program does not end at step 2 it ends at 3. It ends with life. Christianity is not meant to be an easy walk but it's a worthwhile walk and it's the only walk genuinely worth walking. It's a walk of faith, hope and love (I'm beginning to sound trite). In Socrate's "The Republic", Plato talks about the impact of knowledge on courage and fear. The summary goes something like this... if you really know something you'll act out on it and people would think you courageous and vise versa. That's why for instance playing against a 10-man football team when one of them was wrongly sent off is not such a great idea. The 10 left on the pitch can sometimes surprisingly play much better than they would otherwise in the knowledge that they've been wronged and that Justice would only be done if they go down fighting the unjust decision to kick one of their own off the pitch."
Jesus puts it like this "... the truth shall set you free". Counting the cost is nothing more than knowing and accepting the truth. In fact faith comes by knowing the truth. Or as Paul puts it "faith comes by hearing and hearing by the word of God". And what's the word of God if not the truth. So why am I ranting about knowledge and truth and all what not? I know I have to start counting the cost each day. I'm not a good rep of Christ right now but I know God is still reaching out for me.

What's the point of my rant today? I don't think I can tell you. I heard this sermon today in Church and I figured like the Bereans, for once, I should go over the material again since right now I know my walk with Jesus has faltered.

There's one more thing to talk about though and it's really the hardest part to explain of it all (in fact I know I can't explain it). The thing is after all I've written so far it should be obvious that salvation is beyond me. I can't (and believe it or not you can't either) deny yourself, take up your cross and follow Christ on your own. And that my friends is the beauty of grace - I dont have to. I've just got to be willing to. I can't quite remember where but I think it says somewhere in the bible that it's God that gives us the will to do every good deed (or something of that nature). The only way to not be saved is to deny Christ outright (apparently someone has to be denied)

I've got truck loads of questions as I'm sure you do and I dont have good enough answers but "now abides faith, hope, love, these three; but the greatest of these is love". And life doesn't get any better.

Sunday, 15 March 2009

next thing to learn - jpa

After much thought, I've decided to make jpa my next thing to learn (cue much confusion and heartbreak). I actually want to learn lift but I have no desire to learn lift mapper (I'm much too lazy for that right now). In any case, I hope to fool around with the toodledo api a little and learn some more scala, lift, jpa, maven and some voodoo while at it. I already have a broad (and largely vague) understanding of scala, jpa and maven so I wont go into details there except if there's wierd stuff to mention.

here's the game plan -

  • This project is nothing serious so eni.ola isn't going to get all worked up about it (I wish!)
  • I'll create the entities (and database stuff generally) to start with,
  • then I'll create a backend interface to manage the entities.
  • interface the app with toodledo (I plan to create an xml based cache or some sort)
  • Finally throw in some lift.

so let's start with the database thingy...

I set up the project as a plain scala project by installing maven and running the following from the commandline (actually I used eclipse to create a maven project here and then added the scala nature to the project but I have no aim of writing a tutorial on q4e):

mvn org.apache.maven.plugins:maven-archetype-plugin:1.0-alpha-7:create \
-DarchetypeGroupId=org.scala-tools.archetypes \
-DarchetypeArtifactId=scala-archetype-simple \
-DarchetypeVersion=1.1 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-DgroupId=your.proj.gid -DartifactId=your-proj-id


A simple scala maven project comes configured already with support for junit4 and specs - so you can start testing right away. However, you've got to set up dependencies for eclipselink, derby and one or two other things. This is done by adding the following to the to the dependencies section of your pom.xml file...

    <dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.derby</groupId>
<artifactId>derby</artifactId>
<version>10.4.2.0</version>
</dependency>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
</dependency>


And then adding the following repository to the repositories section of the pom.xml file.
<repository>
<id>EclipseLink Repo</id>
<url>http://www.eclipse.org/downloads/download.php?r=1&amp;nf=1&amp;file=/rt/eclipselink/maven.repo</url>
</repository>
We'll be using 2 classes for the entities - Tasque and Folder. A folder would contain a list of tasques (there's a one to many mapping here) and many tasque may belong to a folder (manytoone mapping). Scala makes doing stuff like this real easy. Here's the code for these two classes...

package eni.ola

import javax.persistence._

@Entity
class Tasque {
@Id @GeneratedValue{ val strategy=GenerationType.TABLE }
var id:Int = _
var description = ""
var createdOn:Long = _
@ManyToOne
var folder:Folder = _
}

@Entity
class Folder {
@Id @GeneratedValue{ val strategy=GenerationType.TABLE }
var id:Int = _
var name = ""
var description = ""
var tags = ""
var createdOn:Long = _
@OneToMany{ val mappedBy="folder", val targetEntity=classOf[Tasque] }
var tasques:java.util.List[Tasque] = new java.util.ArrayList[Tasque]()
}


The major things to note right now is that for the oneToMany annotation we set the targetEntity to the 'Tasque' class (i.e. classOf[Tasque]). I think this isn't necessary for good ole' java but thank God scala is not good ole' java. In any case, you'll notice all the other normal stuff like @Entity annotation to make the class as an entity, @Id and @GeneratedValue to make the field as the annotation's id and to say that the value of the id should be auto-generated using a TABLE. We also make use of the oneToMany and ManyToOne annotations on the Folder and Tasque classes respectively. Note that the mappedBy field of the Folder class' oneToMany (tasques field) annotation refers to 'folder' which is the name of the field for the corresponding ManyToOne annotation in the Tasque class. So basically we've created two entities... just like that...

but before we go on we need to specify the persistence mapping file

This file (persistence.xml) basically contains all the configuration data needed to get the jpa implementation (eclipselink, in our case) to work. This file is listed below

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="tasquePU">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>

<class>eni.ola.Tasque</class>
<class>eni.ola.Folder</class>

<properties>
<property name="eclipselink.target-database" value="DERBY" />

<property name="eclipselink.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver" />
<property name="eclipselink.jdbc.url" value="jdbc:derby:tasquedb;create=true" />
<property name="eclipselink.jdbc.user" value="" />
<property name="eclipselink.jdbc.password" value="" />

<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
</persistence>


The important thing to note here is that the entity classes are listed in this file along with the necessary info like location of the database, what type of dbms you'll be using, the name of the driver class, our the jpa implementation should handle ddl generation etc. You may visit the eclipselink website for more info.

Another thing that didn't work for me was where to put this persistence file. The persistence.xml should be put in the 'META-INF' folder and this folder should be on the classpath of your project so that the necessary classes can find it. The problem for me was that even though, I put this folder under the src folder, the generated 'META-INF' in the target folder didn't contain any xml file... so I had to manually copy the persistence file to the target folder after each "mvn clean" (of course you can tell that I almost never run that maven command).

the icing on the cake

As the icing on the cake (or just to make sure the program works) here's the junit test code...

package eni.ola

import org.junit.Test
import org.junit.Before
import org.junit.Assert._

import javax.persistence._

class EntityTest {
var factory:EntityManagerFactory = _

@Before
def setup() = {
factory = Persistence.createEntityManagerFactory("tasquePU")

val em = factory.createEntityManager
em.getTransaction.begin

val q = em.createQuery("select f from Folder f")
if(q.getResultList.size==0){
val f = new Folder

f.createdOn = System.currentTimeMillis
f.name = "First Folder Ever"
f.description = "This folder was created for testing purposes only"
f.tags = "test junit jpa"

em.persist(f)
}

em.getTransaction.commit
em.close
}

//change this function to return only one em per session
private def em = factory.createEntityManager

@Test
def testFolder() = {
val q = em.createQuery("select f from Folder f")
assertTrue(q.getResultList.size >= 1)
//assertTrue(false)
}
}


Yes, it is a messed-up test. I should have a scala object that inherits from the EntityTest class and that contains the factory (should is the keyword). But since I'm not cut out for hard work I've just gone with a straight forward class (terrible terrible programming I say).
The way jpa is defined, you create a factory and then create an entitymanager from the factory. The entity manager is used to manage your entities (duh) and that's it! It really is that simple until you run into issues with jar versions and other java black magic :(

In any case that's all for now folks... I'll upload the zipped file for the project when I'm feeling like it.

by the way

did you know Spurs are 2 goals up against Villa right now just beat Villa 1-2... ha ha! Kiss the Crest, Up the Arse!

Wednesday, 4 March 2009

Ayo and Scala 4

Ayo is a game that played in various forms across parts of west africa. I learnt it as a kid growing up in Benin City but with a different set of rules from what the way it's played in large parts of the yoruba people. The Yorubas call it Ayo but you've probably heard of it by the more popular name of mencala. Needless to say I'm implementing the game as explained here. Find out more about the game here

This is the last installment before I switch to building a fancy interface. Today I'll go over the main class of the program - aptly called 'Game'. The game class makes use of virtually all the scala features that I've talked about so far and it is a rather long class by the standard of the other classes/objects so I'll look at it one interesting method at a time.


def start = {
val s = List(0,0)
val h = List(Set(0,1,2,3,4,5), Set(6,7,8,9,10,11))
val l = List(4,4,4,4,4,4,4,4,4,4,4,4)

move(Config(s, h, 0, l))
}


The 'start' method basically starts the ball rolling. It's the only method an external entity should ever have to call and hence it should be the only public class of the method (but what the heck). You'll notice that the method has no parameter list or even brackets (a scala feature we've mentioned in the past but didnt show an example of). Also the method calls the move method.



def move(cfg:Config):Unit = {
if(!Rules.hasHouse(cfg.getHouses)){
//print message alerting player of change of turn
move(cfg.changeTurn)
}

Board.draw(cfg.list)

println("\nPlayer "+(cfg.turn+1)+"\n"+cfg)
//get current player's choice... player can only select his own house and if it has seeds
val choice = getInput(cfg.getHouses.filter(cfg.list(_) != 0))
val (list, index) = plant(choice, cfg.list) //playout the choice

val ncfg =
if(Rules.canKeep(list(index)))
cfg.setList(list).plusStone(4).updateList(index,0)
else
cfg.setList(list)

val ocfg = houseKeeping(0, ncfg)
val pcfg = houseKeeping(1, ocfg)

if(!Rules.gameOver(pcfg.list))
move(pcfg.changeTurn)
else
println("Game Over: \n"+pcfg)
}


This 'move' method is the most important (depending on where you stand with the whole chicken before or after the egg issue). The method runs recursively until there's no move left and the game ends (if it ever really ends). First there's a check to see if the current player is in any position to make a move (that is if he has any house he can start a move from). The Board is then drawn on the screen and the user input is collected by called 'getInput' (another recursive function by the way). Once the user input is validated, the move is initiated proper by calling the 'plant' function which actually called the board class' roll function. Once the 'plant' function returns the rules are applied to see if any player can claim any seeds and then the game continues - the game attempts to switch play to the next player.

The only other function that's important at this stage is the 'housekeeping' method which is used to actually apply the rules i.e. assign users won seeds and, perhaps in the far inconceivable future, assign houses too. The fact that this method is pretty easy on the eye is one of the reeeally nice things about scala. You can create monstrousities with scala but elegant gamine (you can tell I just heard that word today) beauties.



def houseKeeping(turn:Int, cfg:Config, houses:List[Int]):Config={
//Board.draw(cfg.list)
//println(">>> "+houses)

if(houses.isEmpty)
return cfg
else{
var nConfig =
if(Rules.canKeep(cfg.list(houses.head)))
cfg.updateList(houses.head, 0).plusStone(4, turn)
else
cfg

houseKeeping(turn, nConfig, houses.tail)Mankala
}
}



On a personal note I'm somewhat completed something for once :| Seriously, this is perhaps the first thing apart from work and school that I think I've done for myself in a long time. I like it I think I'll continue. Since I'm just learning lift I dont know how much I'll be able to cook up for next week but we'll see.

Ciao!

Saturday, 28 February 2009

Ayo and Scala 3.5

Ayo is a game that played in various forms across parts of west africa. I learnt it as a kid growing up in Benin City but with a different set of rules from what the way it's played in large parts of the yoruba people. The Yorubas call it Ayo but you've probably heard of it by the more popular name of mencala. Needless to say I'm implementing the game as explained here. Find out more about the game here.

Last time around I gave a quick overview of the scala implementation. Today I'll be looking at each component in a little more detail starting with the board. The board of ayo is made up of 12 holes, 6 on each side. Each one of these 12 holes has 4 seeds to start with. Each player also 'owns' all the houses (6) on one side of the board.

Here's a list of what I've design the board to be able to do:

- draw itself out to the console
- carry out a complete sequence of moves

So how do we implement this in scala?


object Board {


A scala object is a singleton class. So one rather crude and incorrect way of looking at a scala object is that you are looking at a java static class.


Declarations in scala are done using the def, val, and var keywords among other stuff. 'def' is used to define a method. In the case where a method takes no parameters you can leave the () brackets off the definition of the method. 'val' defines what can be called, in java parlance, a constant. Variables defined with 'val' can never be reassigned to another value. Then there's the 'var' keyword that defines regular good old fashion variables. These can be reassigned and all that...

There'd be no point in using scala if it didnt have a good enough library of containers among other things. The cool thing about scala is that it not only has libraries of its own but it also can leverage java libraries transparently - kind of like what python is to c/c++. In scala though, and largely because of its cool functionaly idiosyncresis, there're 2 types of container objects - mutable and immutable (actually there are 3 packages but that's besides the point here). A very popular example of a mutable object is java string class. Nothing can be done to the class itself that doesn't result in the creation of a brand new string. Well in scala you have lists and iterable elements that have this characteristic (we'll talk about this a little more later). I've digressed... let's take a look at the code again.


def roll(index:Int, stoneBuffer:Int, list:Array[Int]):(List[Int],Int) =
if(stoneBuffer==0)
(list.toList, position(index-1))
else{
list(position(index)) += 1; draw(list.toList)
roll(index+1, stoneBuffer-1, list)
}


The roll function is a recursive one. The signature of the method is that had to grasp. Where java would say int i, scala would say i:Int. So this is a method that takes 3 parameters. The method returns a 2 tuple containning an array and an integer. The contents of the tuple actually are the stones as they are arranged on the board after a sequence of moves and the position where the sequence of moves ended.
You'd also notice that the method contains just one if block and that there are no return statements. Well, that's because in scala all expressions are ... ok I dont know how to put it but by default the last expression in a method is returned. So one of the last statement in each of 'if' block's conditional subunits gets returned when the method is called.

What the roll function actually does is to check if there are any stones left to move about, if there isn't it returns the board and the current location. Otherwise, it adds one stone to the current location, reduces the number of stones left to move by one and then calls itself again... simple!

Next stop is the Rules object.

object Rules {
def canMove(plantedSeeds:Int) = plantedSeeds!=0
def canKeep(plantedSeeds:Int) = plantedSeeds==4
def hasHouse(houses:Set[Int]) = !houses.isEmpty
def gameOver(list:List[Int]) = list.reduceLeft(_+_) < 4
}

One thing you may have noticed is that I appear to be passing around a lot of excess luggage from function to function. Well that, I've heard, is one of the features of functional programming. Functional programming avoids side effects - which means I only deal with what the function returns and not with any changes that the function may have made to the parameters that I passed to it. One way of implementing this is to make sure that only immutable objects are used and passed along from method to method. That way I'm sure that if I sent you a parameter you wont be able to change it and all i'll have to worry about is what you've passed back to me. Consequently it's becomes pretty easy to test methods as everything is easily compartmentalized.

The Rules object basically just contains the rules of the game. For instance a player can only start a move (canMove) when there are seeds in the hole from which he wants to start the move. But this is an incomplete rule because a player cannot start a move from a house he doesn't own (Perhaps this is a design flaw).

Now it makes perfect sense to use singletons for both the Rules and the Board classes because both classes dont really have any fields. In essence, I'm trying my best to make this a fully working functional game (I think I wont succeed though, it's so paaaaainful). The other methods in the Rules object appear to be straight forward or in the words of one of my fav college teachers - "think small" (go figure)

Now let's talk interesting stuff

There's a class that stores the current configuration of the game. It's called Config. This class is a case class (what?). Well, in scala there's this cool type of class you can create that will authomatically create a toString method and comparison (equals/compareTo) method that works off of the toString method (I may be wrong here but's that how I understand it). The major advantage of this is that you can do some pattern matching on this class and generally write less code. So we define a case class that actually stores the seeds won by each player, the houses won by each player, the player whose turn it is to play and the arrangement of the stones left over on the board.
Now you cant change the values of the fields of a case class without really running into trouble since the toString class is created at class initialization (I need to verify this... but when I started learning scala way back on 1.6 or thereabout this appears to have been the case). In any case, each method of this config class that appears to modify any of its fields actually creates and returns a brand new Config object (cool eh?).

The constructor of a class in scala is the same of what appears to be the parameter list of the class itself, so in our case stones:List[Int], houses:List[Set[Int]], turn:Int, list:List[Int] are the parameters of the constructor of the Config class. The methods of this class are pretty straight forward so I wont be talking about them at all.


case class Config(stones:List[Int], houses:List[Set[Int]], turn:Int, list:List[Int]){

def plusStone(count:Int):Config = plusStone(count, turn)
def plusStone(count:Int, player:Int) = {
val s = stones.toArray
s(player) += count
Config(s.toList, houses, turn, list)
}
.
.
.
.


Ha! That's all for this week folks. I'll talk about how it all comes together when I look at the last part of the game (an object called 'Game') next week maybe.

Sunday, 22 February 2009

Ayo in Scala 3

I can't believe it's been more than 6 months since last.... I guess that's one of the perks of having nobody read your blog. In any case, I've figured that for once in my life (cue Harry Connick Jnr singing for once in my life, I have someone...) I'll get something done completely. So each day of the week, last week, I took that old Ayo program from 2 years ago and gradually tweaked it. I'm at a stage now that I can say I'm done. I've practically completely what I had in mind 2 years ago. Of course there are now things that I'll love to add but these will be another project for another day. The game plan for now is to talk about a component of the program each day of this week (note I'm not saying I'll post everyday of the week...) and then start a new project next week of implementing a fancy interface using either LIFT or JAVAFX (I've never done anything previously in either so that would be fun).
So here's a general overview of what I'll be going over this week. I've divided AYO into about 5 components.
  1. The board - This represents the wood (or eWood since this wood is intelligent). The wood can carry out arbitrary operations during the game like counting and moving (sowing) seeds.
  2. The Rules - This represents a kind of 10 commandments. The board references it when moving seeds and other components reference it as need be
  3. The Config - This represents the configuration of the game at any point in time. It stores the number of seeds each player has, the player whose current turn it is to play, how many houses a player has won, etc. Obviously the game starts with a new config
  4. The Game - This actually is a misnomer. It should be called the referee or umpire. This component starts the game, receives input from the user, and calls the other components as needed.
  5. I said about 5 didn't I?

Here's the complete source code (buggy and quaint) as it is right now.




object Game {Mankala

def start = {
val s = List(0,0)
val h = List(Set(0,1,2,3,4,5), Set(6,7,8,9,10,11))
val l = List(4,4,4,4,4,4,4,4,4,4,4,4)

move(Config(s, h, 0, l))
}

def move(cfg:Config):Unit = {
if(!Rules.hasHouse(cfg.getHouses)){
//print message alerting player of change of turn
move(cfg.changeTurn)
}

Board.draw(cfg.list)

println("\nPlayer "+(cfg.turn+1)+"\n"+cfg)
//get current player's choice... player can only select his own house and if it has seeds
val choice = getInput(cfg.getHouses.filter(cfg.list(_) != 0))
val (list, index) = plant(choice, cfg.list) //playout the choice

val ncfg =
if(Rules.canKeep(list(index)))
cfg.setList(list).plusStone(4).updateList(index,0)
else
cfg.setList(list)

val ocfg = houseKeeping(0, ncfg)
val pcfg = houseKeeping(1, ocfg)

if(!Rules.gameOver(pcfg.list))
move(pcfg.changeTurn)
else
println("Game Over: \n"+pcfg)
}

/**
* get current player's choice
* if the choice is not valid display message and prompt user again
*/
def getInput(restrictions:Set[Int]):Int = {
print("Please start move ["+restrictions.foldLeft("")(_+","+_)+"]: ")
val x = readInt

if(restrictions.contains(Board.position(x)))
Board.position(x)
else
getInput(restrictions)
}

def plant(pos:Int, l:List[Int]):(List[Int],Int)={
val (listn, index) =
Board.roll(pos+1, l(pos), {l.slice(0,pos):::List(0):::l.slice(pos+1,l.size)}.toArray)

if(Rules.canMove(listn(index)-1) && !Rules.canKeep(listn(index)))
plant(index, listn)
else
(listn, index)
}

def houseKeeping(turn:Int, cfg:Config, houses:List[Int]):Config={
//Board.draw(cfg.list)
//println(">>> "+houses)

if(houses.isEmpty)
return cfg
else{
var nConfig =
if(Rules.canKeep(cfg.list(houses.head)))
cfg.updateList(houses.head, 0).plusStone(4, turn)
else
cfg

houseKeeping(turn, nConfig, houses.tail)Mankala
}
}

def houseKeeping(turn:Int, cfg:Config):Config = houseKeeping(turn, cfg, cfg.houses(turn).toList)
}

case class Config(stones:List[Int], houses:List[Set[Int]], turn:Int, list:List[Int]){
def this() = this(List(0,0), List(Set(0,1,2,3,4,5), Set(6,7,8,9,10,11)), 0, List(4,4,4,4,4,4,4,4,4,4,4,4))

def plusStone(count:Int):Config = plusStone(count, turn)
def plusStone(count:Int, player:Int) = {
val s = stones.toArray
s(player) += count
Config(s.toList, houses, turn, list)
}

def updateList(l:List[Int], index:Int, value:Int):List[Int] =
l.slice(0,index):::List(0):::l.slice(index+1,l.size)

def updateList(index:Int, value:Int):Config =Mankala
Config(stones, houses, turn, updateList(list, index, value))

def setList(l:List[Int]) =
Config(stones, houses, turn, l)

def changeTurn =
Config(stones, houses, (turn+1)%2, list)

def getHouses = houses(turn)
def getHouses(nTurn:Int) = houses(nTurn%2)
}

object Board {
def draw(list:List[Int]):Unit = {
println
list.slice(6,list.size).reverse.foreach(x => print(x+"\t"))
println
list.slice(0, 6).foreach(x => print(x+"\t"))
println
}

def position(i:Int) = (i+12)%12

def roll(index:Int, stoneBuffer:Int, list:Array[Int]):(List[Int],Int) =
if(stoneBuffer==0)
(list.toList, position(index-1))
else{
list(position(index)) += 1; draw(list.toList)
roll(index+1, stoneBuffer-1, list)
}

}

object Rules {
def canMove(plantedSeeds:Int) = plantedSeeds!=0
def canKeep(plantedSeeds:Int) = plantedSeeds==4
def hasHouse(houses:Set[Int]) = !houses.isEmpty
def gameOver(list:List[Int]) = list.reduceLeft(_+_) < 4
}

object Ayo {
def main(args : Array[String]) : Unit = {
Game.start
}
}