19 Feb 2011

Kaleidoscope

Posted by Jamis on Saturday, February 19

It’s funny how knowledge leads to knowledge. You start digging deeper into one thing, and discover threads leading off into related fields. I began by researching maze algorithms, decided I wanted to see what mazes in more complex tesselations would look like, and after one thing or anouther found myself learning about Wythoff constructions.

The result is Kaleidoscope, a library for generating uniform tilings using Wythoff constructions.

gem install kaleidoscope

A uniform tiling is a tesselation of a plane using regular polygons (with a few other constraints that I won’t go into here). What this means is that, in essense, you give Kaleidoscope a few input parameters, and it hands you a bunch of regular polygons.

1
2
3
4
5
6
7
8
9
10
11
require 'kaleidoscope'

pattern = Kaleidoscope::Pattern.new(6, 3)

pattern.generate! do |point|
  point.x * point.x + point.y * point.y < 10
end

pattern.polygons.each do |polygon|
  # ...
end

The polygons are generated around the origin of the plane, within a region you specify via the block to the generate! method. Once done, you can translate and scale the polygons to wherever you like, for rendering purposes. Kaleidoscope will even include basic tricoloring data for the polygons, to make it easy to decorate your pattern.

Some obligatory pretty pictures:

Click here to read the rest of this article.

Posted in Announcements Projects | 5 comments

09 Feb 2011

Mazes in CoffeeScript

Posted by Jamis on Wednesday, February 9

Several people have asked how I did the Javascript demos in my maze algorithm articles, and while I’ve answered them a couple of times in the comments, I thought it might be interesting enough to warrent its own post.

The demos are actually implemented in CoffeeScript, a really elegant little language that compiles to Javascript. CoffeeScript lets you ignore (most of) Javascript’s warts, while still enjoying all of Javascript’s strengths. I like.

So, the CoffeeScript sources for my maze demos are at https://github.com/jamis/csmazes.

I’ve tried to anticipate most questions about building, installation, and usage in the readme, but in a nutshell:

  1. You’ll need to install CoffeeScript if you want to do anything with the code.
  2. “cake build” will compile the sources to Javascript.
  3. “examples/index.html” has widgets for all the implemented algorithms for you to play with.
  4. “Maze.createWidget” is the quick-and-easy way to embed a maze somewhere.
  5. You can do it the hard way, too, if you need more control: instantiate a maze with the algorithm of your choice, then call Maze#step until the maze is generated (or Maze#generate to do it all at once).

Note that the implementations there are optimized for animating the algorithms; the source code is not a good place to learn how a typical maze implementation might look. Every algorithm is broken down so that it can be called piecewise, one step at a time. If you were going to implement any of these for any “serious” purpose, odds are you’d do it much more efficiently, and without all the ceremony that csMazes requires.

Still, if you just want to embed an animation of a maze algorithm on a web page, csMazes works quite well. Except for IE7. And probably other IE’s as well. (If you’re an IE guru, I’d appreciate patches, but please make sure your fixes don’t impact the animation performance on other browsers. I was able to make IE render the mazes okay, but then the animation performance on Chrome was abyssmal.)

The code is in the public domain, so do with it what you will. If you do something fun with it, let me know!

Posted in Announcements Projects | 1 comment

20 Dec 2010

Theseus 1.0

Posted by Jamis on Monday, December 20

Whenever I tackle a new programming language, I need a project to apply it to. Just experimenting with syntax isn’t enough; there has to be a real context for it, or it doesn’t stick. Some years ago I discovered a great “default” project: generating mazes.

Mazes explore a lot of the nooks and crannies of a language: random numbers, decision making, recursion and/or iteration, and several data structures, at the very least. If you want to be able to tweak your mazes without changing code, you then need to learn about passing arguments via the command-line, or environment variables, or even configuration files. Add the possibilty of actually displaying the maze and you introduce string manipulation and console IO (if emitting ASCII art), or graphics libraries and file IO (if writing to an image file).

The actual algorithms behind building a maze are pretty straightforward, which is ideal. You don’t want to waste time understanding algorithms when you’re trying to learn a new programming language.

This has served me well for several years. C++, C#, Haskell, Erlang, Scala, Io, and even Prolog! But I realized I’d never actually tried it in my favorite language: Ruby.

So, I gave it a try. And I had a blast. It kind of took on a life of its own, with features evolving as fast as I could implement them. The result: Theseus.

I released Theseus 1.0 last night, and it is available for installation via RubyGems. (You’ll get syntax errors if you try it on Ruby 1.8, though, so beware.) Feel free to fork it on GitHub, too. It’s in the public domain, so you can do whatever you want with it.

I am rather ashamed of the lack of tests, though. I realized as I was building this out that I need a good lesson in real test-driven development. I had a difficult time seeing how to test something like this. I’m going to be reading Kent Beck’s book next, I think.

Here are some examples of stuff that Theseus can do:

Click here to read the rest of this article.

Posted in Announcements Projects | 7 comments

23 Nov 2010

Ekawada: Approved for Sale!

Posted by Jamis on Tuesday, November 23

Last night I received a long-awaited email: Ekawada is finally approved for sale in the App Store!

It’s been a pretty wild ride, from start to finish. The first commit was made on May 25, but I’d been tinkering on it for at least a month before that, learning Objective-C and Cocoa and basically trying to prove to myself that this was something I could actually build. The app was submitted to the App Store on November 3rd, rejected (due to a bug in Ekawada) on the 11th, resubmitted, and finally accepted just last night. And here I am, almost 6 months since that initial commit, offering my creation to the world.

Really exhilarating. Even if no one else likes what I’ve built, I’ve learned a lot, and since I built the app primarily for myself, there will always be at least one passionate user!

So, the sales pitch: if you have an iOS device (iPad, iPhone, iPod Touch) with at least iOS 3.0, head on over to the App Store and download Ekawada. It’s free, comes with eight figures for you to learn, and includes nine tutorials to help you along. And if you happen to like what you see, there are almost 100 more figures (in 5 packs) available for purchase in-app, $0.99 per pack.

And let me know what you think, either with ratings and reviews in the App Store, comments here, notes on Twitter, or even just an old-fashioned email.

Thanks!

Posted in Announcements Projects | 4 comments

04 Nov 2010

Ekawada: Submitted!

Posted by Jamis on Thursday, November 4

Last night I finished the marketing site for Ekawada (at least, the first draft of it), plugged the last of the memory leaks reported by the Instruments tool, created some app icons that I finally felt did the app justice, and…and… YES! I submitted Ekawada to the App Store!

I’ve been told that the review process for new submissions is currently taking a little more than a week, so with a bit of luck Ekawada could be available for download sometime late next week.

I’m giddy!

Posted in Announcements Projects | 6 comments

14 May 2009

BucketWise v1.1.0

Posted by Jamis on Thursday, May 14

So, I’ve now been using BucketWise for almost two months, and it’s been fantastic. Admittedly, as the author of the application, I’m willing to overlook a lot of the warts and inconsistencies, but I can honestly say I’ve felt more control over my finances these last two months than I’ve felt in the last 10 years. It’s an awesome feeling!

Tonight, I tagged version 1.1.0 of BucketWise, which (if you haven’t been following along) fixes a few bugs and adds several new features (account reconciliation, memorized transactions, actor name autocompletion, simple budget reporting, and more; I’ll just refer you to the changelog for the full list). It’s really been a fun project to tinker on. The last feature I myself really want is scheduled transactions; I may be hacking on that one in the near future.

I figured this might be a good time to talk a little about how I, personally, am using BucketWise. I’ve been surprised by a few things, both good and bad: some features I’ve found to be less useful than I anticipated, and others have been surprisingly handy!

Firstly, when you log into BucketWise, you see a short list at the top, called “Recent transactions”. This list was intended to let you see, at a glace, what you most recently had entered. (It also provided a handy landing place for newly entered transactions.) It hasn’t been very useful, though; I find that what I really want is to see the register of transactions for my checking account. I may be reworking that dashboard view soon.

Also, bucket reallocations haven’t been quite as useful as I expected. I do use them, and they are definitely handy, but I find that if you shuffle money around too much, it muddies your register. The reallocations are basically noise, especially when viewing transactions at the account level. I’m going to be pondering ways to reduce their visibility.

Buckets, though, I’ve found to be spectacularly useful. I’ve got my savings account partitioned into three buckets (short term, medium term, and long term), and that’s been a great way to keep track of how those savings funds are earmarked. Also, I’m trying to save 10% of each paycheck (trying, but not very successfully yet!), so I’ve got a “savings” bucket in my checking account, too. When the funds get to a certain threshold, I transfer the money to my savings account. (Yeah, I could just do a transfer with each paycheck…but I find I’m more likely to do it if I do it infrequently. Not sure why that is.)

Buckets are also great for indicating money that was given as a gift. My wife and I share the same checking account, so when it was her birthday, I transfered money from my Paypal account and put it in a “Tarasine” bucket. She was then welcome to record whatever purchases she wanted against that bucket. Similarly, when I receive money as a gift (birthday, Christmas, whatever) I just deposit it into a “Jamis” bucket.

Lastly, having credit card debt repayment built into the application has been awesome. I’ve loved being able to immediately indicate which checking account bucket a credit card purchase will be repaid from, and seeing that those funds are set aside, inviolate, ready for when the credit card bill comes.

My checking account currently has 35 buckets, and I can see my wife and I adding more. Most are purely for budgeting purposes (“groceries”, “auto fuel”, etc.), but they are so handy as ways to arbitrarily earmark money. Tithes, charitable offerings, savings, and credit card repayment are just some of the ways I’ve used them. (In fact, I’ve found myself wishing I could mark additional buckets as being “aside” buckets; I’m still pondering ways to make that happen, if it needs to.)

I’ll probably blog more about BucketWise down the road, and talk about specific use cases and how it’s helped me with them. However, I’d love to hear from others, too. Are you using BucketWise? If so, what do you like and dislike about it? I’m definitely only writing this application for me, but I’m curious to hear what the experience is like for others.

Lastly, if you’re interested in giving BucketWise a test drive, I’ve set up a demo account that you are welcome to log into and play with. I’ll reset the data there periodically, so feel free to try out all the features! Just go to http://www.bucketwise.com, and log in with the “bw.demo” user (password “demo”). Note that this is hosted on a modest Linode host, and will almost certainly be swamped into unusability with any significant traffic, but you’re welcome to try it out.

Posted in Announcements Projects | 20 comments

20 Apr 2009

BucketWise v1.0.0

Posted by Jamis on Monday, April 20

BucketWise is now available! It’s far from “done”, but I’m labelling it “1.0.0” because giving code pre-1.0 version numbers is a coward’s game. (ha!)

At any rate, fork it on GitHub, see what you think, and contribute back if you feel so inclined. The TODO includes a list of unresolved issues and features I’d like to see land someday: knock yourselves out. :)

Note that I’ve tried to document the REST API for BucketWise, too; the first draft is in doc/API.rdoc let me know if any of that is too confusing or not informative enough (I’m sure that will be the case). I’m really looking forward to seeing what people use the API for.

Note that while the source code is now available, I’m only actually hosting the application itself for myself and a few close friends. But please feel free to deploy it to your own servers, or even just run it locally. And let me know what you think! BucketWise is super opinionated, so I’m sure I’ll get some hate mail, but that’s the name of the game when you’re playing things like this on the Internet. For me, personally, BucketWise has already proved more than worth the time I’ve invested in it so far; hopefully it’ll prove useful to others as well.

Enjoy!

Posted in Announcements | 15 comments

01 Feb 2009

Net::SSH and friends, update

Posted by Jamis on Sunday, February 1

This is a multi-project release announcement, so brace yourselves.

In short, Net::SSH 2.0.9, Net::SFTP 2.0.2, Net::SSH::Gateway 1.0.1, and Net::SSH::Multi 1.0.1 have been released. Get ‘em while they’re hot!

It’s all just bug fixes, for the most part, but if you want more nitty gritty, read on.

Net::SSH 2.0.9

The following issues have been addressed in Net::SSH 2.0.9:

  • If you specify a non-nil user argument to Net::SSH#start, it will override whatever setting exists for User in your .ssh/config file. (Prior to this, the .ssh/config’s User setting would always be used, regardless of what user you specified to Net::SSH::start.)
  • Some naughty ssh servers send channel requests even after the channel has been closed. Net::SSH handles these spurious requests better now.
  • Net::SSH::Connection::Session#shutdown! has been added for hard shutdown scenarios (where an error leaves the connection in an ambiguous state and you just want to terminate the connection without all that touchy-feely “graceful shutdown” nonsense).
  • The key loading behavior has been further tweaked so that Net::SSH will try to load public keys first (by appending ”.pub” to the given key file name), and if no public key with that name exists, the corresponding private key will be attempted. This way, operations that only need the public key will not require the (possibly encrypted) private key to be loaded in order to succeed.
  • The :passphrase option was being dropped on its way to the key manager. It is now passed all the way through, so that specifying the :passphrase option actually works now.

Net::SFTP 2.0.2

Only one bug fix: if an exception was raised from within the Net::SFTP::start block, it could leave the Net::SSH session trying to gracefully close channels on a borked connection. Net::SFTP will now, instead, do a hard shutdown of the ssh session connection, rather than trying to gracefully close, if an exception every bubbles up outside the block. (A side effect of this is that Net::SFTP 2.0.2 depends on Net::SSH 2.0.9, so you can’t get one without the other.)

Net::SSH::Gateway 1.0.1

Just one minor new feature was added: you can now specify the exact port number on the local host that you want the gateway to be created on. Just pass an optional third parameter to Gateway#open. This will default to the original behavior (selecting the next available port number), but now allows you greater flexibility in how you use Net::SSH::Gateway.

Net::SSH::Multi 1.0.1

Just one minor new feature: an Channel#on_open_failed callback hook was added, to mirror the on_open_failed callback hook in Net::SSH.

Posted in Announcements | 4 comments

28 Aug 2008

Capistrano 2.5.0

Posted by Jamis on Thursday, August 28

Capistrano 2.5.0 is now available! You can read the full release announcement on the capify.org news blog.

Posted in Announcements | 0 comments

27 Aug 2008

SQLite3-Ruby 1.2.3

Posted by Jamis on Wednesday, August 27

SQLite3-Ruby version 1.2.3 is now available. It is a maintenance release, fixing just a few things:

  • The permissions on the database.rb and translator.rb files in 1.2.2 were incorrect, resulting in broken sqlite3-ruby installations for many *nix users. This is now fixed.
  • A few more Ruby 1.9 compatibility issues were patched.
  • Some optimizations were applied to speed up iterating over result sets.

To install or upgrade:


  gem install sqlite3-ruby

Thanks!

Posted in Announcements | 5 comments

04 Aug 2008

Online Capistrano Tutorial #2

Posted by Jamis on Monday, August 4

The first online Capistrano tutorial session was very successful, thanks to everyone who participated. Now, it’s time to try again!

The second online Capistrano tutorial session is now open for registration: http://events.capify.org/events/2.

It is scheduled for Wednesday, August 13th, at 7pm (Mountain time), and will last two hours (plus up to an hour at the end for Q&A). As before, this tutorial is targeted at beginning Capistrano users, those will little or no prior experience. (If you’re looking for a session for more advanced users, keep watching this space—I’ll probably do one of those eventually, as soon as I can write a curriculum for it.)

Posted in Announcements | 1 comment

07 Jul 2008

Online Capistrano Tutorial Session

Posted by Jamis on Monday, July 7

Today I’m pleased to announce the first online Capistrano tutorial session. It will be held via Campfire on July 15 at 7pm MDT, focusing on Capistrano basics for Rails deployment. The session will accomodate only ten people. For all details, read up at capify.org:

http://www.capify.org/2008/7/6/online-capistrano-tutorial-session

If this proves popular enough, and if the format works out well, I’ll consider hosting more of these on more advanced topics.

Posted in Announcements | 2 comments

28 Jun 2008

Capistrano 2.4.3

Posted by Jamis on Saturday, June 28

Capistrano 2.4.3 is now available!

gem install capistrano

This is a maintenance release. The changes since 2.4.0 include:

  • In 2.4.0 and earlier, port settings in ssh_config files were not honored by Capistrano. 2.4.3 will now honor those settings.
  • The capture() helper no longer raises an exception if stderr text is received, but instead emits a warning.

Please report bugs to the Capistrano bug tracker at Lighthouse:

http://capistrano.lighthouseapp.com/projects/8716/tickets

Patches should be generated against the latest version of the code at GitHub:

http://github.com/jamis/capistrano

You may submit patches via email, as submissions to the Capistrano bug tracker, or as GitHub pull-requests.

Posted in Announcements | 1 comment

Net::SSH 2.0.3

Posted by Jamis on Saturday, June 28

Net::SSH 2.0.3 is now available!

gem install net-ssh

This is a maintenance release that fixes the following issues:

  • Net::SSH 2.0.2 and earlier wouldn’t work with Mocana SSH and a few other esoteric SSH servers commonly used on routers and other hardware. (Net::SSH truncated the server’s identity string at the first space, rather than at the end of the line as required by the specification, causing subsequent algorithm negotiations to fail.) 2.0.3 now preserves the entire identity string as reported by the remote server.
  • Malformed entries in ssh_config files are silently ignored now.
  • Entries in ssh_config files that are delimited with equals-signs are now parsed correctly.
  • The NameError raised when a forwarded port request could not be satisfied now raises the correct exception.
  • Net::SSH::Version is now Comparable, so you can test two version objects using comparison operators.

Please report bugs to the bug tracker for net-ssh on rubyforge:

http://rubyforge.org/tracker/?atid=1123&group_id=274&func=browse

If you have a patch you want to submit, please make sure to create it against the latest version of the code in the Net::SSH repository on GitHub:

http://github.com/jamis/net-ssh/commits/master

Patches may be submitted via email, as GitHub pull-requests, or as posts to the net-ssh tracker on rubyforge.

Posted in Announcements | 0 comments

13 Jun 2008

Capistrano 2.4.0

Posted by Jamis on Friday, June 13

Capistrano 2.4.0 is now available.

gem install capistrano

Report bugs to Capistrano’s Lighthouse project. And if you have some ideas for patches, please patch against the code at Capistrano’s GitHub repository.

Here’s the skinny on 2.4.0:

death to “git fetch --tags“

You git users out there will be pleased to learn that this release will no longer do “git fetch --tags”, meaning your git-based deploys will finally work again. Sorry that took so long to fix. It was really ridiculously simple. :(

cap -d

Mark Imbriaco added a debug switch for enabling conditional execution of commands. This is fantastic for debugging and testing tasks, since you can basically step through your tasks and approve or deny each remote command as it is executed. Just give cap the “-d” switch to enable this.

New and improved sudo helper

No, really. This time I mean it. I pulled the version of sudo introduced in 2.3.0 (where each sudo command was wrapped in an explicit sh invocation), and put it back almost exactly as it was. However, if you call sudo without a command to execute, it will instead return the sudo command to use. On top of that, if the run() helper detects that you’re using sudo, it will listen for password prompts. So you can now do arbitrarily complex sudo commands like this:

1
run "if [ -d /some/directory ]; then #{sudo} chmod -R g+w /some/directory; fi"

In other words, just dump the sudo() call into your command as an interpolated value, and the real sudo command gets substituted. You can pass options to it as well:

1
run "#{sudo :as => "bob"} something"

And, naturally, the original sudo() syntax we all know and love remains as before:

sudo "something", :as => "bob" 

The deployment recipes themselves have been updated to use this new syntax, as needed.

:runner vs. :admin_runner

Some cappers have noted that having deploy:setup and deploy:cleanup run as the :runner user messed up their carefully crafted permissions. I agreed that this was a problem. With this release, deploy:start, deploy:stop, and deploy:restart all continue to use the :runner user when sudoing, but deploy:setup and deploy:cleanup will use the :admin_runner user. The :admin_runner variable is unset, by default, meaning those tasks will sudo as root, but if you want them to run as :runner, just do “set :admin_runner, runner”.

deploy:upload with globs

You can now specify glob patterns with deploy:upload:

1
$ cap deploy:upload FILES="config/apache/*.conf" 

As before, you can also specify entire folders to upload, but now the upload is being done via the upload() helper (introduced in 2.3.0) so the behavior is more standardized.

before/after hooks use well-defined server scope

Prior to this release, if you defined a before hook using a block, the block would be executed within the same server scope as the original task that invoked task that this hook was attached to. (whew!)

In other words:

1
2
3
4
5
6
7
8
9
10
11
12
task :first, :roles => :app do 
  # ... 
  second 
end 

task :second, :roles => :db do 
  # ... 
end 

before :second do 
  # ... 
end 

Prior to this release, when “first” calls “second”, the before hook at the bottom would get called, but it would get called with the :roles => :app server constraint active, instead of :roles => :db. This preview release makes those hooks use the server scope of the task they are attached to.

host reported correctly from SCM output

Prior to this release, when any output was processed by the :checkout, :export, or :remote_cache strategies, you’d not be able to tell what host the output was from (it’d just be prefixed [err] or [out]). With this release, that output is correctly tagged with the host that generated it, making it easier to troubleshoot issues with SCM command execution.

Disable asset timestamp normalization

Some SCM’s give you the option of forcing the modification times of files that are being checked out to be the time that they were last modified in the repository. If your SCM gives you that capability, and if you enable it (however that works in your SCM), then you don’t need the massive touch command that Capistrano’s default deployment tasks run on each deploy, which is cap’s way of forcing all assets on all of your servers to have the same timestamp.

To disable Capistrano’s default timestamp normalization step, just set the :normalize_asset_timestamps variable to false:

1
set :normalize_asset_timestamps, false

You could also do this if you are deploying to a single server only. Note, though, that if you do this when deploying to multiple servers, and you haven’t configured your SCM to set the timestamps on the files on checkout, then Rails may use inconsistent timestamps on the assets, causing caching of your assets to fail and resulting in longer load times for your users.

Other lesser fixes, straight from the CHANGELOG

  • Make git SCM honor the :scm_verbose option [Jamis Buck]
  • Don’t follow symlinks when using :copy_cache [Jamis Buck]
  • If :mode is given to upload() helper, do a chmod after to set the mode [Jamis Buck]
  • Fix load_from_file method for windows users [Neil Wilson]
  • Display a deprecation error if a remote git branch is specified [Tim Harper]
  • Make set(:default_shell, false) work for not using a shell on a per-command basis [Ryan McGeary]
  • Use upload() instead of put() with the copy strategy [Jamis Buck]
  • Improved test coverage [Ryan McGeary]
  • Fixed “coverage” take task [Ryan McGeary]
  • Fix deploy:pending when using git SCM [Ryan McGeary]
  • Make sure deploy:check works with :none scm (which has no default command) [Jamis Buck]

Posted in Announcements | 21 comments