Saturday, March 13, 2010

Blogger is stupid

Trying to edit a blog (this one) I've had it: this editor right here is one of the worst I've used in a long time. It's still close to impossible to quote nice code snippets and the html it generates is riddled with DIV tags worse than a word document.

I guess this is the fate of things. The bad ones become good enough and the good get worse.

Shame. I shall investigate options to blogger, since the best voting is done with the feet...or, in this case, with the...fingertips...?

I shall create my own nice code quoting system, based on the scripster I just put together. I should probably thank them for the idea...

Friday, February 26, 2010

Implementing a state machine in scala DSL

I had a bit of fun in the past few days writing a telnet server implementation in #scala. Part of that was implementing a state machine, which I then cleaned up so the definitions are simple.

Here's a sample state machine:

class SampleSM extends razie.SM.StateMachine {
import razie.SM._
implicit val sm = this

val states @ (s1, s2, s3) = ("s1", "s2", "s3")
override def start = state("s1") // TODO there's an issue if i use s1 instead of "s1"

override val transitions : Seq[Transition] =
(s1, 2) -> s2 ::
(s1, 0) -> s1 :: // NOP
(s2, 1) -> s1 + echo ("back to s1") :: // CR
(s2, 3) -> s3 ::
(s3, Seq(4, 5, 6, 7)) -> s2 ::
(s3, AnyEvent) -> s1 ::
(s2, {_:Event=>true}) -> s2 + eatChar + echo ("s2 eats all others") :: // eating stuff
(""".*""".r, -1) -> s1 :: // some reset event applies to all states
Nil

def eatChar (sm:StateMachine, t:Transition, e:Event) =
println ("ate char: " + e.asInstanceOf[IEvent].i.toChar)
}

object SampleSMain extends Application {
implicit def e (i:Int) = SM.IEvent(i)
val sm = new SampleSM()
sm move 2 move 1 move 3 move -1 move 2 move 3 move 6 move 59
}

The code is at http://code.google.com/p/razie/source/browse/trunk/razie/src/razie/SM.scala

The basic structure is:
 (state, event-matcher) -> newstate + callback ++ unitcalback... + callback :: Nil
The event-matcher can be:
  • an event
  • a sequence of events
  • a function taking an event and returning...Boolean, of course
The callback is a function with either of these signatures:
  • def push (sm:StateMachine, t:Transition, e:Event) - use + for these
  • def reset : Unit - use ++ for these (hey, I'm still getting my head around advanced scala stuff)

Enjoy, and if you likee, contribute, eh?

Here's the definition (in-work) of the high-level telnet state machine, a little more complicated but not much.

The picture (thanks to http://tomi.vanek.sk/index.php?page=telnet):



The state machine (when it's ready I'll post the link to the entire code):

// based on diagram at http://tomi.vanek.sk/index.php?page=telnet

implicit val sm = this

val sstates @ (data, cmd, app, param, neg, subneg) = ("data", "cmd", "app", "param", "neg", "subneg")
override def start = state("data")

override val transitions : Seq[Transition] =
(data, IAC) -> cmd ::
(data, 0) -> data :: // NOP - don't know why i get these after CR
(data, 10) -> data :: // NOP - LF ignored?
(data, 13) -> data + eatLine + echo ("") :: // CR
(data, {_:Event=>true}) -> data + eatChar + echo ("") :: // remaining chars
(cmd, IAC) -> data ::
(cmd, Seq(WILL, WONT, DO, DONT)) -> neg + push ::
// TODO 3-2 should negociate stuff, i.e. reply with will/won't
(neg, {_:Event=>last==SM(DO)}) -> data + mode(true) + pop ::
(neg, {_:Event=>last==SM(DONT)}) -> data + mode(false) + pop ::
(neg, AnyEvent) -> data + echo("interesting sequence...") + pop :: // What is this?
(cmd, SB) -> subneg ::
(""".*""".r, CR) -> data :: // it's important to reset the thing on ENTRE
Nil

def eatChar (sm:StateMachine, t:Transition, e:Event)
def eatLine (sm:StateMachine, t:Transition, e:Event)
Enjoy and, more importantly, have fun!

If you'd like to read more of my rants about scala, see http://wiki.homecloud.ca/thinking-in-scala

Wednesday, January 20, 2010

Start dowloading torrents remotely

Say you're at work and you stumble onto a torrent you'd like to watch tonite (some documentary or the latest episode from http://www.cbc.ca/nextprimeminister/blog/2008/03/download_canadas_next_great_pr.html).

Well, here's one way to do it...

1. Run uTorrent at home, 24/7, even if it's not downloading anything. Configure it to automatically load torrents from a folder say "torrentstodo". This is in Preferences/Directories at the bottom.
2. Install LiveMesh both at home and at work
3. map this folder as shared on both computers: right click and say "share with LiveMesh" at home and at work just right click the "LiveMesh Folders" in explorer.

Then, when you like a torrent, save it to the local "torrentstodo" folder at work. LiveMesh will transfer it at home automatically. Then uTorrent will pick it up and start downloading it.

Please don't steal copyrighted material when it's easily available (online) at a reasonable price :)