On the iPad

Posted by sudothinker on January 28th 2010

I've been reading a lot of criticism and praise for the iPad today.

I think there has been an important point missed. For the first time ever* we, as app developers, are able to develop applications for a multitouch display. We've been developing applications for so long with just one input device and one point and click that to step back and think about the possibilities with 10+ inputs at once is awesome. It's the biggest change in app development since mobile app development. Mobile app development made us think about applications which you can take with you, multitouch app development will make us think what we can do with 10+ inputs. I haven't been this curious and excited about the possible applications that can be developed since the App Store first came out. As a tip of the iceberg, travel game developers are screwed.

* Couple of points, 1) The iPhone is multitouch, but you are only going to get 2 thumbs on it before its uncomfortable, not really 'multi' in my mind. 2) There are probably other tablets out there which are multitouch and you can write apps for - firstly good luck, secondly the iPad and App Store make it worth your time.

What will your book be?

Posted by sudothinker on January 23rd 2010

Mine was this:

July 2009
By Michael Murray & J...

Things I've been doing

  • New job at Blurb
  • Brewing more beer
  • Drinking more beer
  • Photography (banner above is from a trip to Chamonix)
  • Running
  • Drawing - scanner needed!
  • Skiing

Things I want to be doing (or more of)

  • Cycling
  • Painting
  • Rock climbing

Howcast on TV! - iPhone App

Posted by sudothinker on April 7th 2009

The Howcast Application for iPhone that I’ve been working on is featured in the new iPhone commercial!

If this video doesn’t work you can view it on the Apple site, under ‘Itchy’.

Download the app

twtbox - a jukebox powered by tweets

Posted by sudothinker on March 28th 2009

Expanding on the idea of twitter being a command line tool for the web – I’ve been working on a twitter powered jukebox – http://twtbox.com (with help from jesse and henry).

The idea is to have a community jukebox where requests are done via twitter. Tweet @twtbox with the song you want to hear and it’ll be queued on the jukebox – simple as that.

Its a working prototype right now but some cool stuff is in the works to make it even more fun.

Addition to acts_as_state_machine: on_transition

Posted by sudothinker on March 5th 2009

Here is a small addition to the acts_as_state_machine plugin to add an on_transition event.

acts_as_state_machine already allows you to specify :enter and :exit events which get triggered when a model enters or leaves a particular state. However, I ran into a situation where there were multiple ways to enter a particular state and I only wanted to call a method whenever a particular event transition happened.

Code is available on github: http://github.com/sudothinker/acts_as_state_machine/tree/master

Thanks to Scott Barron for writing the original acts_as_state_machine.

Here is an example usecase:

class Order < ActiveRecord::Base
   acts_as_state_machine :initial => :opened

   state :opened
   state :closed, :enter => Proc.new {|o| Mailer.send_notice(o)}
   state :returned

   event :close do
     transitions :to => :closed, :from => :opened
   end

   event :return do
     transitions :to => :returned, :from => :closed
   end
  
   event :return_with_email do
     transitions :to => :returned, :from => :closed, :on_transition => :email_user
   end

   def email_user
      Notifier.deliver_order_returned(self)
   end
 end

Erlang Exercises: Interaction between processes, Concurrency: Star of Processes

Posted by sudothinker on March 3rd 2009

Here is my solution to the last of the 3 Erlang ‘Interaction between processes, concurrency’ problems here: http://erlang.org/course/exercises.html#conc. It is definitely much shorter than my ring code.

Here are some things I assumed from the problem statement:

  • The center node is the main process and is not spawned.
  • The center node continues to send messages to the star nodes regardless of the response. It doesn’t wait for the response to send another message.
-module(star).
-export([star/2, star_node/1]).

% Write a function which starts N processes in a star, 
% and sends a message to each of them M times. 
% After the messages have been sent the processes should terminate gracefully.
star(N, M) ->
  Nodes = lists:map(fun(X) -> spawn(star, star_node, [self()]) end, lists:seq(1, N)),
  io:format("Built nodes ~w~n", [Nodes]),    
  send(M, Nodes).

% Sends a ping +M+ times to each of the nodes in +Nodes+
send(0, Nodes) ->
  lists:flatmap(fun(X) -> X ! {self(), stop}, [X] end, Nodes);
send(M, Nodes) when M > 0 ->
  lists:flatmap(fun(X) -> X ! {self(), ping}, [X] end, Nodes),
  send(M - 1, Nodes).

% An element of the star, receives messages from +Center+ and sends them back
star_node(Center) ->
  receive
    {Center, ping} ->
      io:format("~w recieved a ping, sending it back to ~w~n", [self(), Center]),
      Center ! ping,
      star_node(Center);
    {Center, stop} ->
      io:format("~w recieved a stop~n", [self()]),
      true
  end.

Rails 2.3 Upgrade Problems and Solutions

Posted by sudothinker on March 2nd 2009

Cucumber

This fix will address “undefined method `visits' for #<ActionController::Integration::Session:0xb702e6a0> (NoMethodError)”

# features/env.rb

require 'webrat/rails'
Webrat.configure do |config|
  config.mode = :rails
end

Gems

This fix will address “uninitialized constant RedCloth (NameError)”

# config/environment.rb

config.gem "RedCloth", :lib => "redcloth", :source => "http://code.whytheluckystiff.net"
rake gems:unpack
rake gems:build

Forms

Fields for now should be called on the outter form, before I had

fields_for 'video[ingredient_attributes][]', ingredient do |i_form|

which used the “Multimodel Forms plugin”:http://code.google.com/p/multimodel-forms/.

Now this becomes:

video_form.fields_for :ingredients do |i_form|

See “http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes”:http://ryandaigle.com/articles/2009/2/1/what-s-new-in-edge-rails-nested-attributes for more information.

Try

The version of try I had was this:


class Object
  def try(method)
    send method if respond_to? method
  end
end

in rails 2.3 though the try method is changed to this:


class Object
  def try(method, *args, &block)
    send(method, *args, &block)
  end
end

class NilClass
   def try(method, *args, &block)
     nil
   end
end

So I got a bunch of undefined method errors which I had to change around to use respond_to, or move the try up the chain so it gets called on nil.

SimplyHelpful

Get rid of this, the functionality has been added to rails. You might see “uninitialized constant SimplyHelpful::Record Identifier (ActionView::TemplateError)” otherwise.

route_for

After a change to edge rails broke our monkey-patched #route_for method, I decided to just delegate to rails' #assert_generates method. For most cases, this will not present a problem, but for some it might. You’ll know if you upgrade and see any newly failing, route-related examples. Here are the things that you might need to change.

  • Make sure IDs are strings

If you had :id => 1 before, you need to change that to :id => “1”


#old
route_for(:controller => 'things', :action => 'show', :id => 1).should == "/things/1"
  
#new
route_for(:controller => 'things', :action => 'show', :id => "1").should == "/things/1"
  • Convert paths for non-get methods to hashes

If you had an example with a route that requires post, put, or delete, you’ll need to declare that explicitly.


#old
route_for(:controller => 'things', :action => 'create').should == "/things"
  
#new
route_for(:controller => 'things', :action => 'create').should == {:path => "/things", :method => :post}

assert_select

I was using assert_select (should have_tag) in rspec in model specs to verify to_xml representations of models. This isn’t really recommended as have_tag should really only be used for html. Instead I used Hpricot to parse the xml (Hpricot.XML) and then verified the contents of the hpricot object.

Twitter: Command Line for the Web

Posted by sudothinker on February 28th 2009

Twitter bots: The basic idea is that there are twitter bots which have twitter accounts. When they receive direct messages, they lookup who they are from and perform the action in the message for the twitter user who sent the message. They might even reply back with some options, responses or confirmations.

@comcast record entourage tonight
@netflix add 'slumdog millionaire' to my queue
@amazon I want an iPhone armband

Amazon bot could maybe respond back to me with some choices?

@reddit whats the top link?
@laundry are you free?
@ticketmaster I want 2 tickets to see the redsox this saturday
@weather tomorrow in tahoe?
@home preheat the oven to 400

Hmm..

@twitter I'm making some coffee

Erlang Exercises: Interaction between processes, Concurrency: Ring Code

Posted by sudothinker on February 27th 2009

Solution to the Erlang ring problem: Write a function which starts N processes in a ring, and sends a message M times around all the processes in the ring. After the messages have been sent the processes should terminate gracefully.

This solution is perhaps more complex than other solutions on the web, one of the reasons is that each node knows about the node before and after it (other solutions just make each node know about the node after it). The reason is so that we can be sure that the message is making the correct path around the ring.

This is also a first attempt, I am sure there are cleanups and optimizations that could be done (after looking around it looks like foldl would have been handy).

-module(ring).
-export([ring/2, node/0]).

% The algorithm, is to first create a list of the N processes.
% For each process we need to hook it up to the before and after process in the ring.
% Then we have hooked everything up:
%   we send the message from the first node in the ring
%   and wait until there is a response (went all the way around the ring)
%   we then repeat M times
% When we have repeated this M times, then we use the infastructure to pass around a stop
% message which will terminate the processes gracefully.

% We also include checks to make sure that the message came from the process before it in the ring
% and only advance it if it did.

% Starts N processes in a ring, and sends a message M times around all the nodes in the ring.
ring(N, M) ->
  Nodes = spawn_nodes(N),
  io:format("Built nodes ~w~n", [Nodes]),  
  ring(N, M, Nodes, []).
  
% This will be in charge of spawning +N+ nodes and adding them to +Nodes+
spawn_nodes(N) when N > 0 -> 
  [spawn(ring, node, [])] ++ spawn_nodes(N - 1);
spawn_nodes(0) -> [].
  
% When there are no nodes ordered yet then we make a from Node at the start
ring(N, M, [X,Y|Nodes], []) when N > 2 ->
  X ! {to, Y},
  ring(N - 1, M, [Y] ++ Nodes, [X]);

% Recursive case when there are full nodes to hook up
ring(N, M, [X,Y|Nodes], Ordered_nodes) when N > 2 ->
  X ! {lists:last(Ordered_nodes), Y},
  ring(N - 1, M, [Y] ++ Nodes, Ordered_nodes ++ [X]);

% When there are 2 nodes left to hook up we make a to Node at the end
ring(2, M, [X|Y], Ordered_nodes) when length(Ordered_nodes) > 0 ->
  X ! {from, lists:last(Ordered_nodes)},
  ring(1, M, Y, Ordered_nodes ++ [X]);

% Special case whenever we just want a ring of 2 nodes
ring(2, M, [X, Y], []) ->
  Y ! {X, X},
  X ! {Y, Y, M};

% Special case ring of 1
ring(1, M, [X], []) ->
  X ! {X, X, M};
    
% 1 node left to build which will be the instigator of the pinging  
ring(1, M, [Node], [X|Ordered_nodes]) ->
  % hook up the 2 ends with Node
  X ! {from, Node},  
  lists:last(Ordered_nodes) ! {to, Node},
  % Kick it all off
  Node ! {lists:last(Ordered_nodes), X, M}.

% Intermediary nodes which don't have a From and To hooked up yet
% Can be upgraded to a full node by passing in {from/to, From/To}
to(To) -> receive {from, From} -> node(From, To) end.
from(From) -> receive {to, To} -> node(From, To) end.
  
% Starting point for all nodes, from there they can be made into a 
% From/To/Full From,To pair  
node() ->
  receive
    {to, To} -> to(To);
    {from, From} -> from(From);
    {From, To} -> node(From, To);
    % A driver node
    {From, To, M} -> node(From, To, M)
  end.
   
% Will receive a ping from +From+ and will pass it on to +To+
% If it receives a stop it will pass that on to +To+ and then stop
node(From, To) ->
  receive
    {From, ping} ->
      io:format("Passing along a ping from ~w to ~w~n", [self(), To]),
      To ! {self(), ping},
      node(From, To);
    {From, stop} ->
      io:format("Passing along a stop from ~w to ~w~n", [self(), To]),      
      To ! {self(), stop},
      true;
    Other -> node(From, To)
  end.
  
% The driver node, this will ping +To+ +M+ times 
% It will only ping +To+ again whenever it gets a ping back from its +From+  
node(From, To, M) when M > 0 ->
  io:format("Sending around a ping starting from ~w to ~w, ~w left~n", [self(), To, M]),
  To ! {self(), ping},
  receive {From, ping} -> node(From, To, M - 1) end;
  
% Base case for driver node, we're done sending it around so just stop all the nodes
% Each node in the ring is responsible for passing along a stop.
node(From, To, 0) ->
  io:format("Sending around a stop starting from ~w to ~w~n", [self(), To]),  
  To ! {self(), stop},
  receive {From, stop} -> true end.

Erlang Exercises: Interaction between processes, Concurrency

Posted by sudothinker on February 25th 2009

From http://erlang.org/course/exercises.html#conc.

  1. Write a function which starts 2 processes, and sends a message M times forewards and backwards between them. After the messages have been sent the processes should terminate gracefully.
-module(bouncer).
-export([bounce/1, ping/2, ponger/0]).

% Spawn a pinger and a ponger and message back and forth +M+ times
bounce(M) ->
  Ponger = spawn(bouncer, ponger, []),
  spawn(bouncer, ping, [Ponger, M]).
  
% I'm going to ping +Ponger+ +M+ times  
% When I've done that I'm going to tell Ponger to stop, and I'll stop
ping(Ponger, M) when M > 0 ->
  Ponger ! {self(), ping},
  receive
    {Ponger, pong} ->
      io:format("Ponged"),
      ping(Ponger, M - 1);
    stop ->
      true;
    % This is a safe guard, we only want to count pong's from +Ponger+
    Other ->
      ping(Ponger, M)
  end;
ping(Ponger, 0) ->
  Ponger ! stop.
  
% If I get a ping, im going to pong back  
ponger() ->
  receive
    {From, ping} ->
      io:format("Pinged"),
      From ! {self(), pong},
      ponger();
    stop ->
      true;
    % We'll ping anyone back, but it has to be in form {From, ping}
    Other ->
      ponger()
  end.

Erlang Exercises: Simple recursive programs

Posted by sudothinker on February 24th 2009

My solutions to simple sequential program exercises: http://erlang.org/course/exercises.html#recurs

-module(lists1).
-export([min/1, max/1, min_max/1]).

min([H|L]) -> 
  min(H, L).
min(M, []) ->
  M;
min(M, [H|L]) when M < H ->
  min(M, L);
min(_M, [H|L]) ->
  min(H, L).
  
max([H|L]) -> 
  max(H, L).
max(M, []) ->
  M;
max(M, [H|L]) when M > H ->
  max(M, L);
max(_M, [H|L]) ->
  max(H, L).  
  
min_max(L) ->
  {min(L), max(L)}.
-module(time).
-export([swedish_date/0]).

swedish_date() ->
  string:substr(integer_to_list(element(1, date())), 3, 4) ++ pad_string(integer_to_list(element(2, date()))) ++ pad_string(integer_to_list(element(3, date()))). 
  
pad_string(A_string) ->
  if 
    length(A_string) == 1 -> "0" ++ A_string;
    true -> A_string
  end.