Simulator Ruby Gem

Intro

I’ve been working on this off and on for awhile. Simulator is a Ruby gem which provides functionality for creating discrete time models, and running those models. You can find the Homepage for the Simulator gem on Github.

Take the following two examples included with the gem.

Ball Drop

Let’s say we want to model a ball that is dropped. Assuming I’m not modeling any bounces, I just need to show the affect of acceleration due to gravity on the position of the ball in space. Position is a function of velocity, which is a function of acceleration. We can model this system using the gem thusly.

# We create a model that simulates a ball drop
model = Simulator::Model.new do
  name = "Ball drop model"
  # create a couple static variables to represent acceleration with
  # default values
  var :ax, 0
  var :ay, - 9.8

  # create dynamic variables bound to some computation, with default
  # values.

  # velocity is affected by acceleration
  eqtn(:vx, 20) { vx + ax }
  eqtn(:vy, 50) { vy + ay }

  # position is affected by velocity
  eqtn(:x, 10) { x + vx }
  eqtn(:y, 100) { y + vy }
end

There is a simple DSL provided that makes creating the models easier. Hopefully it’s easy enough to follow. We initialize two static variables, ax and ay, which are set to 0 and -9.8, respectively (acceleration due to gravity is equal to -9.8m/s^2.)

Next, we create two “equations”. These are just dynamic variables, variables that depend on the values of other variables, or on some sort of computation. Note that we just pass regular ruby blocks to the eqtn method. These could really perform any ruby code. The result of the block gets stored in the variable given as a symbol. So, we state that the variable vy is dependent on a the addition of vy + ay. vy + ay will be the sum of the values vy and ay from the previous period. We do the same for vx.

Finally, the position of the ball, the coordinates x and y, depend on the velocity. We also set the default initial position of (10, 100).

Next, we create a “run” of the model, and step it 10 periods. This would be the equivalent of 10 seconds (because of what we set acceleration to).

model_run = model.new_run
model_run.step 10

Note that although we do not do so here, we could alter the values of run variables in each period, like so:

model_run.set ax: 5
model_run.step

This would give the ball an acceleration in the x direction, and this value would be propagated through subsequent periods (because the variable is static).

Once we have stepped the run, we can request the series data in case we want to plot it. We can retrieve and plot the data like so:

xs, ys = model_run.data.series :x, :y

require 'chunky_png'
image = ChunkyPNG::Image.new @width, @height,
  ChunkyPNG::Color::BLACK
pts.each do |pt|
  x, y = pt
  # flip y due to inverted coordinate system
  y = @height - y
  image.circle x, y, 3, ChunkyPNG::Color('red')
end
image.save filename

and we’d get something like this:
drop

Mortgages

A mortgage involves a balance, loan payment, and interest rate. Let’s create a model for that.

model = Model.new do
  name = "Mortgage model"

  # monthly steps
  var :base_rate, 0.08
  eqtn(:annual_rate) { base_rate }
  eqtn(:monthly_rate) { annual_rate / 12.0 }
  var :payment, 2000
  eqtn :balance, 250000 do
    balance * (1 + monthly_rate) - payment
  end
end

We want the period to be monthly instead of annually, so note the monthly_rate variable above. We also have various default values we will override in a bit. Let’s look at 3 types of mortgages, fixed, balloon, and variable. Fixed rate mortgages have a constant interest rate locked over a defined term (such as 30 years). Let’s see what happens to the balance at the end of 30 years for each of these loan types. A balloon loan has a lower monthly payment, but a large payment at the end of the term. A variable loan has a term where the interest rate is indexed to a published interest rate, and then a period where the rate is fixed. Below, we simplify things by assuming that we will just pay different amounts for each of the terms.

fixed = @model.new_run
fixed.set payment: 2100
fixed.step 30*12

# balloon
balloon = @model.new_run
balloon.set payment: 1850
balloon.step 30*12

variable = @model.new_run
# first 10 years, stick with low payment
variable.set payment: 1800
variable.step 10*12

# subsequent years, balloon to higher payment until its paid
variable.set payment: 2100
variable.step 20*12

And then we can get the series data and plot it similarly to before. It results in an image like the one below.

  • Fixed = yellow
  • Variable = blue
  • Balloon = red

mortgage

You can find the Homepage for the Simulator gem on Github and find the gem on RubyGems.

iOS App: Bunny Matcher

Introduction

I recently finished a game for iOS called Bunny Matcher. This will probably be my last iOS app for awhile, as I want to do more Android development. I’m also ramping up with my new job doing iOS development, so I get plenty of practice with Objective-C every day.

Bunny Matcher has the same concept as the classic game Super Munchers. You control a bunny which must match words on a grid to a presented topic. For example, if the topic is Planets, you may have to select words like Mars, Earth, and Venus. Conflict comes in the form of non-topic words, which penalize the player by hurting his score, and a fox that moves across the board. The player must avoid the fox, as touching the fox costs 1 of 3 total lives.

I spent between 25 and 40 hours on the game (I really should start to measure the time more accurately). With 5 to 10 hours spent on the graphics, which might be surprising since they are so basic. It’s tough to get more accurate with the time, because, as a working father, I have to squeeze in project time here and there. The graphics were done in Inkscape, which I haven’t used in a while for anything substantial, so part of the time was the learning curve there. I’m most proficient with Illustrator.

Project walkthrough

What follows is a brief description of the process of writing this app. I am looking through the commit log to refresh my memory.

git log --reverse --name-only

The first few commits involved setting up the project. I decided to target iOS 6 to simplify things and so I could use the built-in UICollectionView and try auto layout. This would come to aggravate me later. I created some simple placeholders like custom table cells that would display the words. The UIViewController for the board was the first one I worked on. I like to work on the primary functionality first.

The next major phase of the project was the creation of model classes to represent the various information that I would display. I worked on making things very modular and testable, and there are several OCUnit tests for the models. I also focused on implementing a simple and readable API that made the flow of game creation, round rollover, and word and topic drawing straightforward.

Next, I worked on implementing a HeroView and movement of this view within the BoardViewController’s view. Upon clicking a collection view cell, the hero needed to animate to the location of that cell and center on it. Since I was focusing on playability, I used a UIView with a colored background containing a UILabel with text “Hero” to represent the hero. I knew that eventually, I would have some animation playing in this view, but it was more important to focus on the playability of the game.

The next set of modifications deal with refinement to support “eating” board spots. This includes new model classes as well as changes to touch detection. There was also refactoring happening along the way. It’s important to refactor as you go rather than doing it all in one batch and leads to greater stability.

Scoring had been added by this point, and a TitleViewController provided a simple menu to start play. The score was the first quasi-objective available, and later I would decide there had to be a high scores list to make this a true objective. An enemy was soon added, along with a lives counter, adding additional conflict.

As movement became more complicated and the enemy and hero shared movement functions, I began to refactor movement into its own class, ActorMovement.

Round completion was the next major enhancement. Once the player had matched all the words with the presented topic, the next round would start, with a new topic. This would continue until the player lost by losing all her lives or running out of time.

At this point, I went on http://opengameart.org and found a few suitable sprite sheets to use in animating the hero and enemy. Specifically, I used this fox animation and a Tux animation by the same artist. These would serve as placeholders until the very end of the project, when I worked on my own sprites. Further work was also done on refining the flow from frame to frame.

One of the big comments I got from playtesting is that the original topics I seeded the game with were too difficult. They included gemstones, obscure dinosaurs, and types of fish. I simplified them later to make the game much more simple, as it is intended for kids anyway.

It’s funny how much sound can improve a game. I implemented a simple sound manager to play sound effects I generated using the Bxfr tool. It’s really simple to make old-school sound effects. Although I think the game could further benefit from some sort of background music, I submitted the first version without it.

The remaining commits added further polish including work on view controller flow, UI modifications, and the addition of graphics.

Speaking of UI modifications, I found at several points throughout the project that adding new subviews to the Board view would cause unexpected effects with regards to auto layout, causing hero and enemy animations to go haywire. The hero would start to move somewhere, and then get teleported back to its original position. It took me awhile to figure out this was due to constraints. Although I tried to programmatically remove constraints on the animated views, this didn’t seem to rectify the problem. I concede that I did not investigate the solution much, and might’ve been doing something wrong. The solution I wound up applying was to modify constraint priorities until the views could animate freely.

Animation

I used Inkscape to draw the graphics. I’m much more experienced with Illustrator, so I found working with it very clunky. I also ran into a nasty bug that I thought was a feature, that caused pasted objects to be inserted as bitmaps. Once I learned a few of the more common shortcuts, working with Inkscape wasn’t so bad.

I didn’t want to spend a lot of time on the graphics, since it is outside of the purpose of creating the application, so you’ll find the graphics fairly basic. I’ll briefly discuss the process of creating the animations for the uninitiated.

I worked on the bunny animation first. I looked for reference images of rabbits on Google, specifically of one at rest. I created the rough shape of a rabbit using graphical primitives such as ellipses. The following image shows the individual shapes used for the rabbit.

The most important thing was to try to group the primitives by movement areas. For example, to create shapes for the legs that could be rotated to show movement. The following image shows grouped body parts.

The Clone feature is a great way to make sure that similar shapes like those used for the legs or arms stay synchronized. By grouping body parts by movement areas, creating subsequent images based on this one is simple. For the running images, I created two new images based on this one, and rotated the body parts appropriately. I repeated this process for the fox. These images are available for use in the GitHub repository. They are also available from my opengameart profile page.

Once I created the svg’s in Inkscape, I exported the images as png’s and used ImageMagick to stitch them together. ImageMagick provides an adjoin command that makes creating sprite sheets simple.


convert -adjoin bunny_standing.png bunny_run_1.png bunny_run_2.png bunny_sprites.png

ImageMagick provides a handy command for this as well.

convert -delay 25 -dispose Previous bunny_run_1.png -delay 25 -dispose Previous bunny_run_2.png -loop 0 bunny_run.gif

Tools

I used various tools to complete the project. I’ve already mentioned Inkscape and ImageMagick. I also started using the XVim plugin with this project, and I’ve since started to use it at work as well.

I implemented a rake task to bump the version number. Some bash scripts provide simple building and distributing tasks. The shenzhen gem is what I use for building and distributing test builds via TestFlight.

I used QuickTime for my screencasts and Bxfr for the sound effects.

Conclusion

This was a fairly entertaining project to work on, as the concept was clear in my mind. I spent a lot of time focusing on clarity of code and refactoring as I went along. One thing that I could’ve done better was work on adding integration tests as I went along. Although I’ve used Frank for integration testing before, I didn’t think it would be very useful in this case. I’ve been finding Frank clunky for testing the more I use it. This application may be a good opportunity to investigate the other integration testing frameworks I’ve been interested in, namely UIAutomation and KIF.

I also enjoyed working on the animation and would like to spend time on my next project playing with Blender for the graphics.

If you are interested in the project, the source is on GitHub and here’s a link to the Bunny Matcher in the App Store.

Buzzy Bingo

I was chatting with a co-worker the other day about project management, and we mentioned the prevalence of buzzwords. Then, we mentioned Buzzword Bingo, and I decided that to implement a Bingo application as an iOS app. I looked up Buzzword Bingo in the app store and only saw two implementations. I figured I’d write this anyway as it’s a simple and well known concept and I need the practice anyway.

So, here it is, Buzzy Bingo! Full source is available here: https://github.com/jamiely/buzzword-bingo-ios.

The app is implemented using OCUnit for unit tests, Core Data to store word lists, and storyboards for layout. A simple server is written using the Sinatra light-weight Ruby web framework.

Available on iTunes: https://itunes.apple.com/us/app/buzzy-bingo/id570491609?ls=1&mt=8

Code for America: Philly 2012

This past weekend I attended the Code for America event held at Azavea’s offices around 12th and Callowhill. Their office was spacious and well accommodated, but the wireless was slow during the day.

I met a coworker, Hector, there and had some coffee and breakfast. We didn’t really get started until at least quarter of ten, a bit late. Organizers passed out Post-It notes for us to write down ideas. Various people involved in city government and other civic organizations took turns presenting their ideas of projects to work on. I took notes as best I could and when they were done, we discussed which seemed most interesting to work on. People were encouraged to stick the ideas written down onto a whiteboard at the front of the room. Half of the participants helped to group the ideas by topic.

Hector and I talked again about what to work on. Organizers meanwhile passed out colored dot stickers to use in voting for ideas. Once the herd thinned out, we voted as well. Once the voting was complete, 8 main topics/ideas were selected and participants self-selected into those different groups. We considered working on a project to make lobbyist information accessible, but decided to work on a project to publicize statistics about the plight of the more downtrodden areas of the city.

Originally, the concept was to take statistics about the city such as crime and poverty rates, and relate them to a person through their neighborhood. Someone would enter either their zipcode or various other statistics about themselves (perhaps highschool class size), and the site would use that information to give them a statistic like:

If you lived in Philadelphia, only 58 of the 100 students in your class would’ve graduated.

or

If you lived in Philadelphia, 3 of your 200 neighbors would’ve been the victim of violent crime.

We discussed this concept with other people, and someone suggested this type of site might make someone glad they didn’t live in Philadelphia rather than promote civic engagement. This helped to lead to the concept that we eventually ran with. We decided that we should use people’s friends to illustrate the statistics.

So, we went to work implementing Facebook authentication, querying the Graph API, designing the site views, and writing code. I mostly paired with Hector and focused with him on the Graph API. We needed to retrieve friend names and profile pictures. We worked on various other pieces such as sampling friends for the statistics, wiring up the views, and pushing to Heroku.

We had some last minute difficulties shortly before our demo, including:

  • Heroku having limited functionality for the free-app tier
  • Problems connecting the site on Heroku with the Facebook app
  • Wireless network issues
I am proud of the project we completed, especially since I think we all had fun working on it. There are some things that could be improved, but it was a great experience overall. It’s up now if you’d like to check it out at http://theotherphiladelphia.org. We wound up winning 3rd place. Here’s the repo location: https://github.com/CfABrigadePhiladelphia/the-other-philadelphia.

In case you’re wondering, the project that won first price was http://lobbying.ph/, the site that provides information about Philadelphia’s registered lobbyists. Technically Philly has a writeup about the event. You can find our presentation on Viddler.

OSX Lion Rubygame Install

I tried setting up Rubygame on Snow Leopard this time last year. I had many difficulties setting up SDL. I had some time to kill so I tried to set it up again, this time on my new MacBook Air running Lion.

This old blog post from 2005 helped me this time around: http://inquirylabs.com/blog2005/?p=21 to nail down the requirements. Instead of following the installation instructions here, I used Homebrew to set things up.

One of the key requirements is rubysdl, ruby bindings for the SDL multimedia library, and the rsdl gem. The following Gist is a rubysdl Homebrew formula that will help install the required packages: https://gist.github.com/1394440. The SGE formula is not part of the included formulas. I forked the following Gist to provide SGE: https://gist.github.com/1394414/.


# install the sge graphics lib
wget https://gist.github.com/raw/1394414/4a6bfa4a8bab179ebe263b1d044a4322c7628f60/sge.rb
brew install sge

# install rubysdl ruby sdl bindings
wget https://raw.github.com/gist/1394440/8a71160306ad277f08fbad3eaf028b2e8700f2f1/rubysdl.rb
brew install rubysdl

# install the required gem
gem install rsdl
gem install rubygame

Afterwards, most of the rubygame samples ran fine, but the ones requiring opengl had issues. I installed ruby 1.9.2 using rbenv, compiled a new dynamic library libruby.dylib, based on the 1.9.2 source. Then, I cloned this repo providing an upgraded ruby-opengl gem: https://github.com/theymaybecoders/ruby-opengl.

# clone the repo
git clone https://github.com/theymaybecoders/ruby-opengl
cd ruby-opengl

# make sure that the libruby.1.9.1.dylib compiled from the 
# ruby 1.9.2 source is present in the gcc class path. For 
# me, it was ~/.rbenv/versions/1.9.2-p290/lib/libruby.dylib
# use build option --enable-shared

rake

# build the gem
rake gem

# install the gem
gem install pkg/ruby-opengl-0.60.1.gem

Afterwards, the rubygame opengl samples compiled fine.

Philly Give Camp 2010: Part 5

The Builder

To keep the teams working as separately as possible with the least interference, we decided that the PAAL Builder, the tool used to build student schedules and lessons, would be completely HTML and Javascript. That means that there would be no server-side code, no ERB or HAML template files, and no Rails special sauce. This allowed the designers to work without developer support, and allowed developers who did not know Ruby or Rails to work solely on Javascript code. The Builder would interact with the API via ajax calls with JSON responses. A simple format for the response envelope was designed:


{
version: 0.1,
error: '',

data: {
  task: {
    id: 1,
    name: 'Brush Teeth'
  }
}
}

This is an example response upon the creation of a task with the name “Brush Teeth.” On each request, the error property would be checked to make sure that it was blank. The version property would also allow changing the API in the future without breaking the application.

In the previous post I discussed the problems of having a simple API. One common scenario is to create a task and link it with a parent task. This would happen if you wanted to create a task like “Brush Teeth” and steps underneath it like “get toothpaste,” “get toothbrush”, “brush front teeth.” Here is the code necessary to do that (I am just posting the necessary jQuery calls rather than the wrapper functions I wound up writing):

// create the task via a POST
$.post(
  '/tasks',
  taskData,
  function(envelope, textStatus, request) {
    if ( envelope.error != '' ) {
      // error
    }
    else {
      // on success, tie the newly created task
      // to a parent task
      function callbackSuccess(newTask, envelope) {
        $.post(
          '/task_parents',
          {
            task_parent: {
              task_id: newTask.id,
              task_parent_id: some_parent_id
            }
          },
          function(innerEnvelope, textStatus, request) {
            if ( innerEnvelope.error != '' ) {
              // error
            }
            else {
              // success!
            }
          },
          'json'
        );
      }
      
      callbackSuccess(envelope.data.task, envelope);
      
    }
  },
  'json'
);

Wrapper functions make this simpler to understand, but the fact that it requires two posts troubled me. Still, I avoided adding a new method to the API to do this all in one step.

When we were working on the project, the designers and another developer worked mostly on basic UI. I then worked on “installing the plumbing” as I put it, making all the API calls and using the live data. A lot of this plumbing went into the product after Give Camp. One aspect of the project I found hard after Give Camp was figuring out how a feature or UI element would work. Often, I’d be hooking up the plumbing, but be unsure of whether they wanted a stand-up shower or a bathtub. Both would get the job done, but I wasn’t sure what they had in mind, and it wasn’t clear from the design.

Part of this was due to the fact that I didn’t have the most recent design. We switched versioning systems two times during the course of Give Camp, and repository locations 3-4 times. Part of this was due to lack of notes or obvious visual stimuli. In general, after Give Camp was over, it was hard to coordinate with each other.

Philly Give Camp 2010: Part 4

Thinking about the problem domain, Trevor, Sebastian, and I decided to abstract away the complexity. The problem (as I understood it then) can be explained thusly:

Students need a way to follow a list of scheduled tasks throughout the day, to assist them in performing daily activities. These tasks can be broken into more detailed tasks with steps or choices. A choice, such as what to have for lunch, is non-linear. A choice helps a student develop his sense of independence. Each choice and task may have accompanying text and audio.

Day to day within a week, the schedule of tasks may be different. Weeks can also differ from each other.

Given these simple business requirements, we decided that a step, a task, and a choice were all the same in that they had a name, audio content, text content, and that they had a parent-child relationship with each other. We decided that all of these would be “tasks” and that there would be a “task type” field to differentiate between these. The “task” paradigm yields the following definitions:

  • A task is a task with linear/sequential sub-tasks
  • A step is a task with no sub-tasks
  • A choice is a task with non-linear, non-sequential sub-tasks

We also decided, after further discussion to make certain other things tasks. We thought that days and weeks were similar enough to a task in the parent-child relationship. We decided that

  • A day is a task with linear/sequential sub-tasks whose name is a weekday
  • A week is a task with day sub-tasks (days as defined above)

This allowed us to have a single Task model, and a Task Parent model, which greatly simplified the API. Instead of making REST calls to create a step, create a week, or create a choice, there would be just one create call, with a task type defining the behavior of the task. This would also make copying tasks and task trees easier, since we would only have to work with one model when doing a deep copy of a task tree.

Although this made the API really quick to build, when I started writing the builder code, interacting with the API, I found the API to be a bit low level. For example, I would have to make two calls to bind a new task to a user. First, I would have to create the task via the API, and then create the user-task relationship via the API. As I was writing nested callbacks with the jQuery ajax functions, I questioned our decision to make the API so simple. Still, I think the API is a thing of beauty, and I am still proud of what we did that weekend.

Philly Give Camp 2010: Part 3

As the MECA staff were describing the application, I didn’t have a clear sense of how beneficial our work would be. To illustrate how our application would help people, they showed us a video of a student going to a gym. In the first clip, the student has trouble following directions and signage about the use of gym equipment. In the second clip, the student is following auditory prompts and exercising at the gym with little trouble.  Another student was able to prepare a meal with the help of visual prompts from a PDA. It was illuminating to see the difference that prompts could in someone’s daily life and spurred us to work even harder.

We decided to split the application into 3 components:

  • A REST API written using Rails
  • A HTML/Ajax builder web application
  • An iPhone user application

We had a team of about eight people, and we knew we had to separate tasks somehow. There were some individuals with iPhone experience (mostly novice stuff like simple view demos), and some with Ruby experience, and then there were two designers with CSS and some jQuery experience.

We figured Trevor, who has extensive Rails experience should lead the API effort, and that Brian, who has done the most, albeit little, iPhone development using MonoTouch should lead the student application effort, while the designers should focus on designing and implementing some of the builder code. (The interface for the user application had already been worked out by group consensus.)

I decided I could best help with the API, so I worked with Trevor on that. Something that I think amazed all of us was that once we had assigned ourselves to teams and broken the project up, we functioned seamlessly, all of us entering the zone in our respective areas. It’s the kind of synergy and flow you get when the majority of your team knows their shit. It was an incredible experience to be a part of that.

We had a good framework and sample response API for the student interface and builder to start building plumbing by the time we left on Friday. Meanwhile, the iPhone app team had gotten some samples working using Monotouch. The builder interface was looking really sharp. We were off to a good start when we decided to break for the night around midnight.

In the next post, I will describe some of the insights behind the API.

Mediawiki-Usage/Changes Storage and Visualizations

A coworker and I have been doing some work on visualizations of wiki updates. The server-side code, written in Ruby, stores changes from a media-wiki feed.

Media-wiki Changes Feed

Media-wiki Changes Feed

I got a chance to use the Google Visualization API, which is really simple and useful for a wide variety of domains.

He also turned me on to HAML, which offers a concise, structured way of specifying HTML.

Project Page: http://github.com/hectcastro/mediawiki-usage/
Demo: http://www.angelforge.org/mediawiki-usage/

Media-wiki Changes Visualization

Media-wiki Changes Visualization