« Earlier12 items total Later »

Liquid Planner : Project Management Tool

I have been looking for a project management tool for ages, one that doesn't make me curl up inside and want to die and one that helps my team get stuff done rather than waste their time.

Finally stumbled across Liquid Planner which turns out to be an amazing little tool.

The features that I really like are

* Range estimation for tasks.
* Category vs Project views.

LP takes a novel approach to planning. Instead of giving a single point estimate. ie this task will take 10d to complete I estimate that the task will take between 8d and 12d to complete. This uncertainty is percolated up into the estimates for the rollup tasks and eventually to the estimate for the entire project. Range estimates fit my brain better than single point estimates and I think they make me more honest.

The second feature I like is that there are two views of the system.


The category view allows you to do a functional decomposition of the project. Containers can be nested and are navigable via a tree view. So this view is great for design and requirements capture.

The "project view" is again a tree view but items higher up on the screen and containers represent milestones. Containers are nested so you can model intermediate deliverables or sprints within you greater plan.

The project view is orthogonal to the category view and this is important because when designing a view you want to see the functional layout. When planning you want to see the order in which things need to be delivered.

This has solved my one gripe about other tools I see. They are either good for requirements capture or good for scheduling but never for both.

Scheduling works quite well. It performs resource leveling and supports precedes and depends on dependencies. Scheduling is done in the background and you are notified by an icon when the scheduling is finished and you should refresh the screen.

On the downside, here in Europe the site is a bit sluggish but to be fair they are still in beta and the devs seems quite responsive on the forums. As it is in beta it is currently free to sign up to but will eventually cost about $25 USD per user per month. Fair enough if it saves me an hour a month in time.

As a final note the site is a Ruby On Rails application which may excite or turn some people off depending on their religion :)

Integers as HEX in IRB

Want to display integers as hex in IRB without messing with printf. Add this snippet to your .irbrc


class Integer
    @@as_hex = false
    def self.toggle_base
        @@as_hex = ! @@as_hex
    end

    alias old_inspect inspect
    def inspect
        if @@as_hex
            sprintf("0x%x", self)
        else
            old_inspect
        end
    end
    def to_hex
        sprintf("0x%x", self)
    end
end


Then you can do the following in your IRB session


$ irb
>> 255
=> 255
>> 25
=> 25
>> Integer.toggle_base
=> true
>> 255
=> 0xff
>> 25
=> 0x19
>>


Reactive Programming In Ruby

In reactive programming a set of variables with dependencies are created. When a variable is modified it notifies all other variables that it depends on to update their values.

The below simple class Reactive implements one such solution to this problem.

a = react 10
b = react 20
c = react(a,b){ |x,y| x + y }
d = react(b,c){ |x,y| x + y }


vars = {:a=>a,:b=>b,:c=>c,:d=>d}
vk = [:a, :b, :c, :d]
report = proc do
    vk.each do |k|
       puts "#{k} #{vars[k].value}"
    end
end

puts " Initial value of variables "
report[]

a.value = 40
puts " New value of variables "
report[]


generates

 Initial value of variables
a 10
b 20
c 30
d 50
 New value of variables
a 40
b 20
c 60
d 50


Implementation


class Reactive

   # On change of value dependants are notified
   # of updates
   def value=(val)
      @value=val
      @depends.each do |d|
         d.notify
      end
   end

   # Add d as a listener
   def notify_me d
      @depends << d
   end

   # Get the cached value unless the
   # dirty flag has been set then
   # recalc the value from the block
   def value
      if @block && @dirty
         argv = []
         @args.each do |a|
            if a.respond_to? :value
               argv << a.value
            else
               argv << a
            end
         end
         @value = @block.call *argv
      end
      @dirty=false
      @value
   end

   # Notify this object that at
   # least one dependant has changed.
   def notify
      @dirty=true
   end

   # Init the class with the dependant
   # reative variables and a block to
   # evaluate to compute the value
   # of this object.
   def initialize *args, &block
      @depends = []
      if block_given?
         @args = args
         @block = block
         @args.each do |a|
            a.notify_me self
         end
      else
         # This is a literal
         @value = *args
      end
      @dirty=true
   end

end

def react *args, &block
   Reactive.new *args, &block
end

Textual Regular Expressions

Regular expressions can be a bit cryptic. I had a short go at implementing a DSL for Ruby regular expressions. It is by no means complete but it gives ideas for further work.


class RexpAtom
    def initialize str
        @str = str
        @m = 1
    end
    def * m
        @m = m
    end
    def to_s
        if @m == 1
            return @str
        end

        if @str !~ /^\(.*\)$/  && @str.length != 1
            str = ( "(" + @str + ")" )
        else
            str = @str + ""
        end

        case @m
        when :many
            str = str + '*'
        when :opt
            str = str + '?'
        else
            if @m.is_a? Range
                str = str + "{#{@m.min},#{@m.max}}"
            else
                str = str + "{#{@m}}"
            end
        end
        str
    end
    def | other
        @str << "|"
        other
    end
end

class RexpBuilder
    def initialize &blk
        @s = []
        self.instance_eval &blk
    end

    def [](literal=nil, &blk)
        l(literal, &blk)
    end

    def _ literal=nil, &blk
        s = ''
        if block_given?
            s << "("
        end

        if block_given?
            o = RexpBuilder.new &blk
            s << o.to_s
        elsif literal
            if literal.is_a? String
                s << literal.to_s
            elsif literal.is_a? Range
                s << ( "[" + literal.min.to_s + "-" + literal.max.to_s + "]" )
            elsif literal.is_a? Enumerable
                s << "("
                s << literal.join('|')
                s << ")"
            else
                s << literal.to_s
            end
        end

        if block_given?
            s << ")"
        end
        a = RexpAtom.new s
        @s << a
        a
    end

    def to_s
        @s.collect do |s|
            s.to_s
        end.join ""
    end
end

class Rexp
    def self.rexp &blk
        RexpBuilder.new(&blk).to_s
    end
end



And an example of use


a = Rexp.rexp do
    _('hello') * 2
    _ do

       _('x') | _('y') * :opt

    end * (1..3)
    _('x') |
        _('y') |
        _(1..3) |
        _('a'..'z') |
        _([1,2,3])
end
puts a



generates

(hello){2}(x|y?){1,3}x|y|[1-3]|[a-z]|(1|2|3)

IRB and issuing shell commands with pipes.

If you wish to issue pipe two commands together in bash then it is easy.

ls /bin | grep grep


generates

bzegrep
bzfgrep
bzgrep
egrep
fgrep
grep
zegrep
zfgrep
zgrep


but how to do this neatly in IRB

How about like


require './shell.rb'
Sh.ls("/bin").grep("grep")


using the library


module Sh
    class Command

        def initialize(cmd, *args)
            @cmd = cmd
            @args = args
            @io = nil
        end

        def inspect
            to_s
        end

        def to_str
            to_s
        end

        def to_s
            call
            str = @io.read
            @io.close
            str
        end

        def | other
            call
            other.call(@io)
        end

        def method_missing(name, *args)
            self | Command.new(name, *args)
        end

        def call (io=nil)

            # The @io object can only be assigned
            # once
            return self if @io

            command =  @cmd.to_s + " " + @args.join(" ")

            if io
                #  We need a new process
                #  and a pipe to connect the
                #  this command to the previous
                #  command in the chain.
                rd, wr = IO.pipe

                if fork
                    # Parent
                    wr.close
                else
                    # Child
                    rd.close
                    begin
                        # Reconnect the STDIN of the
                        # new process to the io parameter
                        $stdin.reopen(io)
                        IO.popen command do |f|
                            while txt = f.read(4096)
                                wr.write txt
                            end
                        end
                    rescue Errno::EPIPE
                        # Ignore the broken pipe
                        # cause the other process
                        # has thrown away the pipe
                        # earlier than we used outs
                    ensure
                        wr.close
                    end
                    exit
                end
                @io = rd
            else
                # This command is executed standalone.
                @io = IO.popen command
            end
            self
        end
    end

    def self.method_missing (name, *args)
        Command.new(name, *args)
    end
end

Sugared Ruby Case Statement

Here's is a little trick that generalizes the Ruby case statement. It adds a method to Object called *casey* that
creates a new object which in turn creates a new object when any method is applied on it. This final object implements '==' which is applied in turn on each 'when' expression. The trick is that within the '==' method the original method is called. Get that? Take a look at the example code and run it to see what happens.


class Casey
    def initialize(o)
        @o = o
    end
    def method_missing(name)
        CaseyMethod.new(@o, name)
    end
end

class CaseyMethod
    def initialize(o, m)
        @o = o
        @m = m
    end
    def ==(other)
        @o.send(@m, other)
    end
end

class Object
    def casey
        Casey.new(self)
    end
end


case [2,3,4].casey.include?
when 1
    puts "a"
when 2
    puts "b"
else
    puts "c"
end

Ruby style Python

After upsetting the Gods by getting Ruby to look a a bit like python, I thought about trying to offend in the opposite direction.

The most distinguishing thing about Ruby of course is the block notation which everybody, except pythonistas, love. They have lambda but it is just allows a single expression. Anonymous blocks have been deliberately left out of the language but with some hackery it is possible to get close to what we want.

The solution still has some cruft but it is pure python and just uses that standard toolkit of for loops, generators, iterators and decorators.

The trick is to decorate an iterator so that it has a few more desired features. Ie we need to be able to return values from the body of the for loop back into the generator.

The decorator adds an extra ret function parameter to the head of the parameter list of the generator function. This enables the generator to provide a final value to the top level code.

It also adds another r parameter to the head of the parameter list in the body of the for loop so that it can return values to the generator after every iteration.


from ruby import rubyfi

@rubyfi
def inject(ret, iter, a = 0):
   for x in iter:
      a = yield a, x
   ret(a)

@rubyfi
def collect(ret, iter):
   r = []
   for x in iter:
      x = yield x,
      r.append(x)
   ret(r)

# Do a sum over a range
for r, s, x in inject ( range (1,6), 1 ) :
   r(s+x)
print r()

# Generate a list
for r, s, x in inject ( range (1,6), [] ) :
   s.append(x*x)
   r(s)
print r()

# Collect items
for r, x in collect ( range (1,6) ) :
   r(x+x)
print r()



which generates
>> python iterator.py
16
[1, 4, 9, 16, 25]
[2, 4, 6, 8, 10]


The library to make it work (ruby.py) is


class Interceptor:

   def value(self, *v):
      if len(v) > 0:
         self.val = v[0]
      return self.val

   def __init__(self, generator):
      self.generator = generator
      self.val = None

   def __iter__(self):
      return self

   def next(self):

      def c(*args, **kwargs):
         return self.value(*args, **kwargs)

      y = self.generator.send(self.val)

      r = [c]
      r.extend(y)
      return r


def rubyfi(function):

      def wrapper(*args, **kw):

         g = []

         def ret(val):
            g[0].value(val)

         generator = function(ret, *args, **kw)

         g.append ( Interceptor(generator))

         return g[0]

      return wrapper



The critical trick I discovered was switching the next method which is called by default by the for loop mechanism into a call to the send method of the original generator. This allows me to feed values back into the iteration from the for loopp.

It is still uglier than Ruby but it can be done

:)

Matlab & Ruby Together

Found a project on rubyforge that adds a Matlab interface to Ruby via the Matlab Engine. Check it out. Ruby is the language Matlab should be if it got it's act together. For Matlab programmers who have never seen Ruby then goto http://www.ruby-lang.org

Camping Love

Another ruby post!

My download site has been broken for many months. I scoured the net looking for a simple replacement for the Mambo document manager that has ceased to work. I didn't want a full blown CMS, just something that would provide a list of files to download and a button to press that would allow the user to accept the software license or not before the download starts. I couldn't find something lightweight and specific enough so I bit the bullet and rolled my own.

Camping to the rescue. Camping is an über light weight web framework from _Why the lucky stiff For simple mini web-apps it rocks. It uses all the magic that Ruby allows to allow you to peform little bits of magic.

What I wanted was to have a configuration file in YAML format listing the files to download and their respective licenses

xtargets_hglayouts-Version1.4.zip: lgpl
xtargets_mdistributed-Version3.1.2.zip: lgpl
xtargets_mhash-Version1.0.zip: lgpl
xtargets_mtemplate-Version1.4.zip: gpl
xtargets_munit-Version2.4.zip: gpl


This file would be used to generate the listing on the main page of the download manager. When the link is clicked the user is asked to accept the associated license. Only when that is done is the download accepted.


#!/usr/local/bin/ruby18
require 'rubygems'
require 'camping'

def path
    File.dirname(File.expand_path(__FILE__))
end

require path + '/xtargets_gpl'
require 'mime/types'

Camping.goes :Download

module Download::Models
    class Post < Base; end
end


# Load the license file
Licenses = YAML.load_file  "#{path}/.." + "/downloads/licenses.yaml"


# Send a file from the downloads dir
# to the client using X-Sendfile header
def send_file(fname)
    unless path.include? ".." # prevent directory traversal attacks

        full_path ="#{path}/.." + "/downloads/#{fname}"
        puts full_path
        type = (MIME::Types.type_for(fname)[0] || '/text/plain').to_s
        @headers['Content-Type'] = type
        @headers['X-Sendfile'] =  full_path
    else
        @status = "403"
            "403 - Invalname path"
    end
end

module Download::Controllers

    # Handle the front page
    class Index < R '/'
        def get
            render :index
        end
    end

    # Send a file after authorisation
    class SendFile < R '/download/(.+)'
        def get(fname)
                send_file fname
        end
    end

    # Authorize the sending of the file.
    # However it seems that the X-Sendfile
    # http header does not work from a post
    # so we redirect to a SendFile as a
    # get.
    class AuthFile < R '/download'
        def post
            if @input.Yes
                redirect R(SendFile, @input.File)
            else
                render :license_rejected
            end
        end
    end

    # Present the license to the client
    class License < R '/license/(.+)'
        def get(file)
            if Licenses.has_key? file
                @file    = file
                @license = Licenses[file]
                render :license
            else
                @file = file
                render :file_not_found
            end
        end
    end

    # Deal with rubbish URL's and
    # go back to the index
    class CatchAll < R '/(.+)'
        def get(foo)
            redirect R(Index)
        end
    end
end

# Rendering of pages using Markaby
module Download::Views


   # Layout commong to all pages
   def layout
     html do
       title { 'XTargets Download Area' }
       text 'XTargets '
       a :href => 'http://xtargets.com' do
           text 'Home'
       end
       h1 'XTargets Download Area'
       text 'Here you can download utilities referenced in the tutorials'
       body { self << yield }
     end
   end

   # Inform the user that they rejected the license
   def license_rejected
       text 'License Rejected'
       p
       a :href => R(Index) do
           'Go back to downloads'
       end
   end

   # Present the license of the selected file
   def license
       pre do
           case @license
           when "gpl"
               text GPL
           when "lgpl"
               text LGPL
           else
               text "ERROR: license #{@license} not found"
           end
           p
           p
           b 'Accept License?'
           form :action => R(AuthFile), :method => 'post' do
               input :name => 'File',
                   :type => 'hidden',
                   :value => @file

               input :name => 'Yes',
                   :type => 'submit',
                   :value => 'Yes'

               input :name => 'No',
                     :type => 'submit',
                     :value => 'No'
           end
       end
   end

   # Front page
   def index
       ul do
           for file in Licenses.keys do
               li do
                   a :href => R(License, file) do
                       file
                   end
               end
           end
       end
   end

   # A file not in the repository is requested
   def file_not_found
       b do
           text @file
       end
       text " is not in the repository"
   end
end


if __FILE__ == $0
    require 'camping/fastcgi'
    fast = Camping::FastCGI.start(Download)
end


Nitpickers will detect that the client is actually capable of downloading the file without going through the form if they know
the download URL. I could easily fix this with a session variable
that knows the name of the file that the license was accepted
for but I am too lazy to set up the sq1ite db to do that.

Oh and the text of the license files is stored in a file xtargets_gpl.rb but I won't include the source of that here cause it is really boring.

Serializing Enumerable

The following code demonstrates a memory saving technique for using a sequence of Enumerable methods on an input array. Turns out that you can have your cake and eat it as the speed performance is comparable but the memory consumption should be less

Library

require 'rubygems'
require 'ruby-prof'
require 'enumerator'

class Serializer

    attr_accessor :obj

    def collect(*args, &block)
        @obj.collect!(*args, &block)
    end

    def select(*args, &block)
        @obj = @obj.select(*args, &block)
    end

   def self.flatten(o)
       length = o.inject(0) {|m,i|m+i.length}
       out = Array.new(length)
       base = 0
       o.each do |sub|
           top = base + sub.length
           out[base..top]=sub
           base = top
       end

   end
end

module Enumerable

   def flatten
       length = @obj.inject(0) {|m,i|m+i.length}
       out = Array.new(length)
       base = 0
       @obj.each do |sub|
           out[base..base+sub.length]=sub
           base = base + sub.length
       end

   end
    def serially(slice=50, &b)
        t = []
        o = Serializer.new
        self.each_slice(slice) do |x|
            o.obj = x
            o.instance_eval(&b)
            t << o.obj
        end
        Serializer.flatten t
    end
end



Example

require 'serially'
require 'benchmark'

Benchmark.bmbm(15) do |bench|
    bench.report("serially") do
        a = (1..900000)

        b = a.serially(1000) do
            select do |x|
                if x > 500
                    true
                else
                    false
                end
            end
            collect do |x|
            "0x" + x.to_s
            end
            select do |x|
                if x == "0x15"
                    false
                else
                    true
                end
            end
        end
    end


    bench.report("classic") do
        a = (1..900000)

        b = a.select do |x|
            if x > 500
                true
            else
                false
            end
        end.collect do |x|
                "0x" + x.to_s
        end.select do |x|
            if x == "0x15"
                false
            else
                true
            end
        end
    end
end



#Results
Rehearsal --------------------------------------------------
serially         7.410000   0.120000   7.530000 (  7.731576)
classic          5.890000   0.080000   5.970000 (  6.123102)
---------------------------------------- total: 13.500000sec

                     user     system      total        real
serially         6.500000   0.000000   6.500000 (  6.581172)
classic          3.160000   0.010000   3.170000 (  3.199095)


Python style Ruby.

Following from a thread on comp.lang.ruby I wondered what it would take to make Ruby more like Python. Yuk you say! Well probably but here is a start.

I updated the code after reading Giles Bowkett's" response to my post about needing the *.pyrb files. After a little poking around and finding hyphen-ruby I discovered a smarter way to do this.

I also made some other improvements to allow deeper dedenting. The trick to the new version is to use the __END__ keyword to block the Ruby scanner and then reload the current file after doing the preprocessing.

Also you only need the __END__ thingie in the first file that is loaded. All subsequent loads will do the preprocessing automatically.



test.pyrb

require 'pyrb.rb'
__END__

def foo:
    [1,2,3,4].each do |i|:
        puts i
        [1,2,3,4].each do |j|:
            puts i
        if i == 2 :
            puts "foo"
        else:
            puts "bar"


foo




pyruby.rb

module PyRuby
    public


    def self.require(base_name)
        if $".include? base_name
            return false
        else
            file = find_file base_name
            if file
                load(file)
                $" << base_name
                return true
            end
        end
    end

    def self.load(file)
        if file
            txt = PyRuby.pyrb_convert file
            begin
                Object.module_eval txt, file, 1
            rescue SyntaxError => e
                $stderr.print "Preprocessing Fail: " + $!
                $stderr.print "-----------------------------------\n"
                $stderr.print txt
                raise
            end
            return true
        end
        false
    end

    def self.find_file(fname)
        if FileTest.exist?(fname)
            return fname
        else
            $:.each do |path|
                path = File.join(path, fname)
                for ext in [ '.rb' ] do
                    p = path + ext
                    return p if FileTest.exist?(p)
                end
            end
        end
    end

    def self.pyrb_convert file
        txt = ""
        stack = []
        found_pyrb_req = false
        do_preprocess = false

        File.open file do |fh|


            fh.each_line do |l|
                l.chomp!
                if l =~ /^require\s*'pyrb.rb'\s*$/
                    found_pyrb_req = true
                end
                if l =~ /^__END__\s*$/ && found_pyrb_req
                    do_preprocess = true
                    txt = ''
                elsif do_preprocess

                    # Do the indent preprocessing
                    indent = (l.gsub /\S.*/,'').length
                    stack.reverse.each do |pindent|
                        if indent <= pindent
                            case l.gsub /^\s*/,''
                            when /(else|end|rescue).*/
                            else
                                txt << (" " * pindent) + "end\n"
                            end
                            stack.pop
                        end
                    end
                    if l =~ /:\s*$/
                        stack.push indent
                        l.gsub! /:\s*$/,''
                    end
                    txt << l << "\n"


                else
                    # Treat the code as normal Ruby code
                    # and pass straight through.
                    txt << l << "\n"
                end
            end
        end
        if do_preprocess
            while not stack.empty?
                txt << (" " * stack.pop) + "end\n"
            end
        end
        txt
    end
end

alias __pyrb_load load

def load base_name
    PyRuby.load base_name
end

def require base_name
    PyRuby.require base_name
end

PyRuby.load $0



( updated 29/05/2007 )

WMII and gnome menus.

This is not a matlab based snippet but for the excellent WMII window manager. I use the ruby extension to WMII and have written a plugin to emulate the gnome menu system.

I have seen posts on the net asking how to get gnome panel working with WMII. The main reason for the request seems to be to get access to the system menus. This script will provide that use case.

Plugin.define "bradphelan@xtargets.com" do
  author '"Brad Phelan" <bradphelan@xtargets.com>'

  # This plugin reads the app names and commands from the system
  # .desktop files using the output from the gnome-menu-test-spec
  # to group them into the same menus you would see if using the
  # gnome window manager.
  #
  # In your wmiirc-config file place the lines
  #
  #   from "bradphelan@xtargets.com" do
  #     use_binding "execute-gnome-menu"
  #   end
  #
  #
  # Place this file in the .wmii-3/plugins directory
  #
  # By default the menu is activated by MODKEY-Y
  #
  # TODO:
  #
  # - Write a threaded version that monitors the menus
  #   for change.
  #
  ######################################################



  menus = {}
  txt = `gnome-menu-spec-test`
  txt << "\n"
  txt << `gnome-menu-spec-test -f /etc/xdg/menus/settings.menu`

  txt.each_line do |l|
    l.chomp!

    # Sample line :
    # Sound & Video/  gnome-sound-recorder.desktop    /usr/share/applications/gnome-sound-recorder.desktop
    l.scan /^([^\/]*)\/[^\/]*(.*)$/ do |group,app|

      if group
        # lower case is easier to work with
        group.downcase!
        app.downcase!

        menus[group] = {} unless menus[group]
        File.open app do |file|
          name = ''
          cmd =  ''
          file.each_line do |line|
            name = $1 if line =~ /^Name\s*=\s*(.*)$/
            cmd = $1.sub(/%\w+/, '') if line =~ /^Exec\s*=\s*(.*)$/
          end
          menus[group][name.downcase] = cmd
        end if File.exist? app
      end
    end
  end
  binding("execute-gnome-menu", "MODKEY-y") do |wmii,|
    Thread.new do
      wmii.wmiimenu(menus.keys) do |category|
        wmii.wmiimenu(menus[category].keys) do |name|
          system menus[category][name]
        end
      end
    end
  end

end

« Earlier12 items total Later »




Sponsored by

Sole Central

Your one stop shop for Birkenstock and Crocs shoes and sandles.