Archive for the ‘Uncategorized’ Category

drink maestro is live

Sunday, July 18th, 2010

Over the past 3 months, I’ve been furiously chipping away at drink maestro, a cocktail menu application built using a flash front end and backed with django. It is finally live.

flash slitscan experiments

Wednesday, March 3rd, 2010

I was digging through some old development and came across some flash slitscan experiments from ages ago. Slitscan is a special effects process of exposing film while moving the negative (or exposure) in a controlled manner, if you’ve seen a few early 80’s movies I can guarantee you’ve seen used it in credits or a special effects sequence. I’m surprised the technique hasn’t been utilized more within flash game development. In terms of a flash timeline, it is very easy to create – on one layer a graphic is either tweened or remains stationary while a layer mask (the slit) is tweened over it. The results are some really cool perspective tricks. The main constraint within flash is that creating the “exposure” requires many frames – and in interactive flash there’s not enough muscle to render a series of exposures in real time (e.g. 20 slit renders per exposure @ 20fps is like running 400 fps, at least using frame based rendering). What you can do with flash is present the actual exposure process, and with a bit of polish make some really neat effects. With pixel level control of bitmaps now available in AS3, there must be some possibility of overcoming the frame based rendering limitation using advanced filtering algorithms – though I wouldn’t say I’ll be experimenting with those any time soon..

Note: source fla files are experimental and way out of date (AS1 from many, many years ago).

“warp” source fla
“text effect” source fla

keenerview – open source zoomable flash image viewer

Tuesday, March 2nd, 2010

I’ve recently been working on an image viewer to display local restaurant menus. I looked around for an open source flash image viewer to modify for the development and came up empty handed… The flash community is a little odd in terms of open source. There’s a lot of components out there for sale/license without an open source parallel. This seems very odd after running with the python and jquery crowd where sharing code is a cultural norm. It is, of course, not all that  way with flash – the game developers and graphics tweakers are very active in releasing code, there are a number of fantastic 2d/3d and physics libraries which are extremely impressive. Hopefully the culture will shift with them.

In any case, with the development stable it seems only right to open it up some code for the next developer. I’ve profited immensely over the years from open source, and it feels good to give back – even if with just a tiny contribution as a zoomable image viewer. Take it, modify it, do whatever you need to do to make it work for you.

The source is available at google code, and I hope to have some documentation up before the week is out. In the mean time, here’s a simple example.

keenerview.swf?image_url=[uri or url with cross-domain privileges]


Apologies to the squeamish for the anatomy page, it was the first interesting public domain image I came across.

development as the golden hammer

Wednesday, February 3rd, 2010

I’ve been squirreled away for the past couple months developing keeners.org, and I’ve perhaps fallen into the trap of zoning into development the point of neglecting the marketing side. As anyone who has tried to build a moderately sized public site can attest, there’s a chicken and egg situation early on. To be successful, you need content and presentation -but you also need users. Users won’t visit until there’s content, nor will users come if they don’t know you exist. The reasonable conclusion seems to be that the site needs to be built out to the point where the handful that find it see it as useful enough to tell others, and others tell others and so forth.  There’s a subjective call that needs to be made at some point – it’s time to build the audience and relegate development to the back burner. It can be a difficult move to make – and I’ve been on both sides of the fence.  I’ve worked on projects upholding the highest standards possible only to find they could not gather a subscriber-base. On the other hand I’ve released demo code  only to see it become an overnight sensation, creating a maintenance  headache in its wake. Projects fail often due to a fear of commitment, humans faced with a (potentially bad) decision will naturally stall. It’s not lazy, and it’s not always a bad thing to give ideas some time to breathe – but applied generally it’s not effective either. I consider development a second nature, it’s far easier than building an audience. Most anyone reading this would likely agree – but it is important to be mindful that marketing a site is half the battle.

Note to self – set a milestone at which to put the programming down. Stick to it.

ipad fever

Friday, January 29th, 2010

The iPad seems to be all over the tech news, lots of excitement. While I can’t say I’m down on the hardware or interface, I’m extremely frustrated by the closed nature of these devices. And it’s not just that everyone seems to want an iPhone/iPad, it’s that every hardware company seems to want to be Apple these days. If computing follows this vector it will not be long until we find ourselves locked in the gaming console model where in order to develop on hardware that we own we must plead for permission and enter into some contract to do so. If the devices being produced by Apple are step forward, the cultural baggage that comes with them  is 5 steps back. It’s a shame that this concern is so difficult to get across to a non-developer, as it’s likely to have lasting implications on the future of innovation in computing. The equity gained in the past 10 years of open source culture is far more tenuous than I imagined only a few years ago.

Peter Kirn makes a far more persuasive argument here, http://createdigitalmusic.com/2010/01/27/how-a-great-product-can-be-bad-news-apple-ipad-and-the-closed-mac/

django dumpdata/loaddata import errors on recursive model

Saturday, January 16th, 2010

A quick note on recursive models – when creating a relation such as a category nest, it’s really easy to create a scenario where loaddata fails to load. What happens is that the dependency instance may get listed after the child in the dumpdata output. With certain database engines that relation must be resolved at point of mention during import. The solution seems obvious when you hear it, but may not seem so obvious when you hit it – in the model do not specify the order as anything other than “created” or “id” and create the recursion in drilldown order. Given these two conventions, data should be able to load regardless of the database.  I ran into trouble using a title order to get an alpha sort in the admin and just didn’t consider that the meta order would be represented in the dump as well, though upon further thought it makes perfect sense.

class Category(KeenerElementsBase):
    """
    recursive category nest model
    """
    ...
    parent = models.ForeignKey('self', blank=True, null=True)	

    class Meta:
        ...
        ordering = ('id',)
class Category(KeenerElementsBase):

“”"
Category model.
A nesting container, can be recursive using parent
“”"

weight = models.IntegerField(‘weight’,default=50)
parent = models.ForeignKey(’self’, blank=True, null=True)

class Meta:
verbose_name = ‘category’
verbose_name_plural = ‘categories’
# dump/loaddata recursive relationship needs to be maintained
ordering = (‘id’,)

gdata calendar api is a mess

Monday, December 21st, 2009

I just kind of figured it’d be relatively painless to extract a few calendar entries. That was my first and second mistake. Want an “id”? Get ready for fun – depending on your context an id can mean a url, a uri, or a 26 character string – and I’m talking about a reference to the same entry. Is consistent id representation not api design 101, day one material? Anyone else needlessly sinking time into this?

noodling with python gdata calendar and iCalendar data

Sunday, December 20th, 2009

I’ve started looking into means of connecting external google calendars into keeners.org, and found it took longer than anticipated just to get the appropriate tools in place to get started. Importing google calendars, which I had assumed to be well documented is really lacking. The goal was to not only capture occurrences of events but to capture the recurrence rrules and datetimes that define them. I downloaded the python gdata package (gdata + atom) and began hacking at a public calendar. It turns out there’s no apparent mechanism in gdata to parse the iCalendar data itself. After considering parsing out the ical data with regular expressions, I thought better and  started looking around. There’s a vobject package that seems to do the trick.

So.. Here’s some basic noodling with the two libraries, I’ve found that there’s plenty of documentation on connecting to and collecting google calendars, but little on the actual import of the data – so here’s the missing link, it requires the gdata and vobject python packages listed above.

from gdata.calendar import service
import vobject

cs = service.CalendarService()
cs.email = 'anygoogleaccount@example.com'
cs.password = 'google_password'
cs.ProgrammaticLogin()

calendar_uri = '/calendar/feeds/5hqt8fv2s3smdn4rnua5pd6hbc%40group.calendar.google.com/public/full'
feed = cs.GetCalendarEventFeed(uri=calendar_uri)

print feed.entry
# [<gdata.calendar.CalendarEventEntry object at 0x03390550>,
#    <gdata.calendar.CalendarEventEntry object at 0x03390590>,
#    <gdata.calendar.CalendarEventEntry object at 0x033909B0>]

recurrence_text = feed.entry[0].recurrence.text
recurrence = vobject.readOne(recurrence_text)
recurrence.prettyPrint()

#    DTEND: 20091213T210000
#    params for  DTEND:
#       TZID [u'America/New_York']
#    DTSTART: 20091213T200000
#    params for  DTSTART:
#       TZID [u'America/New_York']
#    RRULE: FREQ=DAILY;WKST=SU
#    VTIMEZONE
#       TZID: America/New_York
#       DAYLIGHT
#          DTSTART: 19700308T020000
#          TZOFFSETFROM: -0500
#          TZNAME: EDT
#          TZOFFSETTO: -0400
#          RRULE: FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
#
#       STANDARD
#          DTSTART: 19701101T020000
#          TZOFFSETFROM: -0400
#          TZNAME: EST
#          TZOFFSETTO: -0500
#          RRULE: FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
#
#       X-LIC-LOCATION: America/New_York

dt_start = recurrence.contents['dtstart'][0]
print dt_start.prettyPrint()
# DTSTART: 20091213T200000
# params for  DTSTART:
#    TZID [u'America/New_York']
print dt_start.params
# {u'TZID': [u'America/New_York']}
print dt_start.params['TZID'][0]
# u'America/New_York'

print recurrence.contents['rrule'][0].value
# u'FREQ=DAILY;WKST=SU'
print recurrence.contents['dtstart'][0].value
# u'20091213T200000'

optional kwargs in the django url dispatcher

Friday, December 11th, 2009

I was hitting a wall setting up a few urls where I was using optional kwargs in the url. I imagine this is a common scenario where content can live in more than one place, especially if the url itself is holding down some context to maintain an anonymous view. Here’s a quick example:

(r’^blotter/(?P<filter_name>(categories|arrests|personnel))/$’, render_blotter, {}, ‘blotter’),
(r’^blotter/(?P<filter_name>(categories|arrests|personnel))/(?P<filter_value>([\w-]+))/$’, render_blotter, {}, ‘blotter’),

The two routes are dispatched to the same named function ‘blotter’, but have a unique signature depending on what arguments are passed. A more common example might be a YYYY/, YYYY/MM, YYYY/MM/DD/ situation where they should share a common render mapping. The url dispatcher can handle this fine, and for the most part it can be handled in the application logic without much of a headache by removing kwargs equal to None before revers() is called to retrieve the url. The crux of the issue is really the url tag in the templates which is not happy unless it gets an exact match of arguments.

A better explanation is available here. In any case, I’ve put a templatetag together to handle optional kwargs. Hopefully someone will find it useful.

"""
     exactly the same as from django.template.defaulttags.url EXCEPT kwargs equal to None are removed
     this allows a bit more flexibility than the use of {% url %} where nesting is rested on optional
     base kw arguments.

     see http://code.djangoproject.com/ticket/9176
"""

from django import template
from django.template.defaulttags import URLNode, url

register = template.Library()

class URLNodeOptional(URLNode):

    """
    identical to django.template.defaulttags.URLNode
    but removes kwargs equal to None before resolving the url
    """

    def render(self, context):
        for k, v in self.kwargs.items():
            if v.resolve(context) is None:
                self.kwargs.pop(k)
        return super(URLNodeOptional, self).render(context)

def url_optional(parser, token): 

    """
     creates the default URLNode, then routes it to the Optional resolver with the same properties
     by first creating the URLNode, the parsing stays in django core where it belongs.
    """ 

    urlnode = url(parser, token)
    return URLNodeOptional(urlnode.view_name, urlnode.args, urlnode.kwargs, urlnode.asvar)

url_optional = register.tag(url_optional)

google flash maps, more marker headroom

Friday, December 11th, 2009

A quick note on google flash maps. Somewhere in the vicinity of a few thousand markers, initialization time starts to slow down perceptibly; this is not unexpected mind you.. In the maps application I was working on, a  minority of pages passed that mark – enough to look into options, but not enough to rethink “the metaphor”. It turns out getting more headroom in flash maps is really easy. The first thing to do is to create a custom marker to replace the google pin (a movie clip asset will do) using the MarkerOptions icon property. Now the important move – cache the clip as a bitmap (marker_icon.cacheAsBitmap = true;), and pass it into the overlay as the icon. Finally make sure shadow rendering is off (MarkerOptions hasShadow property).

Caching a custom marker as a bitmap and disabling shadow isn’t going solve all your issues if you’re looking to put too many more markers in the map, but it can at least triple the marker threshold before the map becomes unusable, which if you’re dealing with a few wild fringe cases can come in handy..