Sean Stoops

Coder. Sysadmin.

3 notes &

Hometown Bicycling

Opinions:  I’ve never been a fan of them.  I don’t write about mine.  I don’t often care to read about others’.

With that being said…

It is, in my opinion, a great idea to bicycle around wherever it is you are.

Now let me try and clarify that slightly vague statement.  I live in Henderson, NV.  Before I started bicycling around here, I knew the freeway and a handfull of neighbor corridors.  The rest of the city was too crappy to explore, right?  Fortunately, negatory.  Once I started putting a few miles under my saddle, I began noticing all the friendly little neighborhoods, the parks and the quieter roads with bike lanes (which actually are crappy here, but I’ll not get into that).  I know where there are water fountains.  I know there’s a guy that lives near the Black Mountain golf course willing to help me if I have bicycle issues out in his neighborhood.  When you’re forced to go 10-15mph, you have plenty of time to look around.  You learn the street names.  You get a feel for the layout of the city.

Fact is, I still hate driving around here.  I’d much rather hop on my bicycle and take the back roads to run my errands.  After speaking with a friend who is a native of this city, she completely agrees.  She said that it wasn’t until she hopped on her bicycle and started exploring the back roads that she really learned the city.

Now on to the meat and potatoes of this post…

I recently took a trip back to my hometown of Hugoton, KS.  It’s way out in the southwest corner — out where it’s flat, dry, windy and nothing by fields, right?  Negatory, again.  Though I must admit, I say that with a new found perspective in mind.  For this trip back, I decided to drive back with my bicycle in tow.  I wanted to make an extended stay out of it and get a little saddle time in to explore where I once lived at a slower pace (which is funny as it seems most think Kansans are slow enough as is :-).  Having grown up there, I knew it mostly as wide open and desolate country, which isn’t entirely inaccurate.  However, it wasn’t until I did a little exploring via pedal power that the sentiment — that bit about “wide open and desolate” — became a little most positive.

My favorite ride of the area put me at around 80 miles.  This was enough to really get out of town, make a wide loop to a couple neighboring towns, stop off at a childhood fishing hole and cruise back home.  Normally — well I say normally as what normal was when I was growing up — you’d have few reasons to visit the small neighboring towns, especially the one with a population of 43.  I always knew it was there and even passed through it a couple times, but it was never a destination.  Until now.

In planning my ride, I knew the roads up in those parts were likely a little less traveled; exactly what I was looking for.  The town, albeit small, surely had a few hydrants around to refill my water bottles.  Thus, it became destination number one.

Smooth open road across the Cimarron River Valley.

And am I ever glad I followed my plans.  After a ride that wildly exceeded my expectations — smooth roads, curteous drivers, sprawling Cimarron River valley — I arrived in “shit, I don’t even like driving there” Richfield, KS.  I can’t claim to know much about the town.  Wikipedia doesn’t know much more.  I spent about an hour there, pedaling around the streets — resting in the park near a hydrant — and only saw two people.  One was passing by in a pickup, another I saw when stopping into the post office to ask about a paved road.  It ended up being a pleasant experience, though I could probably go on with emotion-filled ramble-fest about how sad it is to see small towns like this completely dry up.  Such is life.

A church and a primary street in Richfield, KS

Leaving Richfield, I headed on to side #2 of the triangle-shaped loop I was riding; back down across the Cimarron River valley again.

Heading South back across the river

This road is where you’d find Wilburton Ponds: a little wet spot fishing hole in the dried up Cimarron River.  I made it here a few times as a child years ago and was curious what came of it.  It would be a six mile limp down a hard-packed dirt road through open pastures on slick road tires, but I’d get there eventually.

This makes road tires unhappy.  Six miles of this make cyclist unhappy.

Turns out, not much had changed from what I remembered.  However, it was all surprisingly beautiful compared to the image I think I’ve concocted in my mind since moving away.

Wilburton Ponds, still there

As a matter of fact, that sentiment holds for the entire ride.  Western Kansas is really beautiful.  Sure when you’re passing field after field, it’s a little tougher to draw that conclusion.  But once you get out to an area still filled with the native grasses (which coincidently means the land is probably too poor to plow up and plant anything), the beauty opens up.  As I sat through the miles, I began wishing I had taken up bicycling many years sooner.  Had I given myself the chance to get out and explore my home territory at a slower pace, I may not have been quite so eager to leave (though I still would have, believe me!)

Coming full circle here, I’ve become a huge advocate of bicycling where you live.  While it’s nice when you can ride around the streets of your town, the world really opens up when you can tolerate enough saddle time to get some substantial miles on.  If you can push 100 miles, then you can obviously get far far away from where you’re familiar.  It wasn’t that long ago that ten miles was a feat for me.  Keep pushing yourself and those goals grow faster than you’d think.  It doesn’t have to be a race.  But it can be an adventure.

21 notes &

Proportional UI Scaling

(Disclaimer: I am not a UI/UX guru by trade.  I spend the majority of my time on the server-side and only occasionally get called upon to crank out a front-end project.  Everything in this post may be obvious to someone who spends their time in the UI world, but I’ll blab about it anyways.)

We recently made the decision to abandon our flash slideshow player in leu of one written in pure HTML/JS.  While we all have dreams of HTML #5 and CSS #3, we still have to support the ancient browsers that tend to frequent news sites, so old boring JS it had to be.

I’ll spare you the details for now of how I went about putting it all together (using mootools along with SlideShow.js) because anyone can figure that out (and if not, I’ll post about it later, maybe).  What I wanted to document here is how I managed my UI element scaling so it would look decent across a myriad of player sizes.

First, a few notes about my slideshow player layout (mind you I did not design it, I merely copied the UI of the flash player we were using before).  The player is called with a desired height and width.  Within this region, we have to render the photo itself, along with a bottom toolbar for displaying the current photo index along with buttons like: caption, share, buy, fullscreen.  The caption region is a semi-transparent overlay over the bottom of the photo which is displayed by default, but can be turned off.

I wanted the toolbar to scale a bit with the player size so that when the player was tiny (say, 200px tall), the toolbar was still usable.  Also when the player is fullscreened, I wanted the toolbar to have a bigger presence on the screen for easier clicking with both a mouse and a touch interface (tablets).

Here is my desired outcome (screenshots taken from my near-final player).

Small:

Medium:

Large:

I’ll spare you another screenshot as it would be the fullscreen version scaled down to fit in this post and thus look weird.

My first attempt at scaling was hand crafting pixel values based on a desired height ratio.  I soon abandoned this for a pure CSS solution.  At the default size of approximately 500px tall, I went with a 95/5 ratio of photo region to toolbar.  This looked nice at the default player size, but did not scale to either extreme very well.  When the player was tiny, the toolbar was too small.  When the player was fullscreened, the toolbar was gigantic.

At this point I decided that I needed to be able to set the ratios at each player size by hand.  Thinking back to some Arduino work I did with a friend using thermistor resistence values to map to a temperature curve, I wanted to throw some regression analysis at my problem.

I began by selecting a few different player sizes as my data points.  I would resize the player to each size, then manually resize the UI elements (toolbar, toolbar font, caption font) to where I thought looked good and recorded the pixel values.  Once I had my values for each element, I plugged them into Wolfram Alpha to give me the best curve fit.

The syntax for regressions in WA is “<method> fit {{x, y}, {x, y}, … }”.  My “x” was the height of the entire player and my “y” was the percentage of the photo region.

Starting with a linear regression, I realized it did not fit my data points near close enough.

Linear Regression

The curve appeared logarithmic, so I switched models.

Logarithmic Regression

The curve does not follow my data exactly, but it’s close enough that I was okay with its appearance across my sample sizes.  I took the formula WA gave me — 2.17007 log(26088992682669964 x) — and plugged it into my JS.  When I was scaling my player to a new size, I would feed my player height through the formula and get back my height value.

I repeated this with my other UI elements — toolbar font and caption font — for a total of three formulae.  Ideally I would like to have a single formula for all UI scaling to ensure they scale equally.  However, using the independant formulae proved adequate for my use, though I suspect they may break down in the extreme player sizes (I’m talking thousands of pixels).

0 notes &

Up & Running

After much procrastination, I’ve finally given my Tumblr page some attention.  I have a few things I want to get out there to hopefully be of some assistance to others and I’m tired of maintaining my own blog, so Tumblr it is.  I’ll look at enabling comments eventually.

20 notes &

VirtualBox and KVM conflict

Archive from thesigb.com.

DISCLAIMER: I’m running Ubuntu 8.10 32bit, though I’ve seen this problem in previous releases as well.

I just wanted to make a quick post because I couldn’t immediately find any information about this problem out there anywhere. This problem arises if you have both KVM and VirtualBox installed at the same time, VirtualBox refuses to start. It will give you the following message:

brutimus@localhost:~$ VirtualBox Headless Interface 2.0.4
(C) 2008 Sun Microsystems, Inc.
All rights reserved

Listening on port 3389
Error: failed to start machine. Error message: VirtualBox
can't operate in VMX root mode. Please disable the KVM kernel
extension, recompile your kernel and reboot.
VBox status code: -4011 (VERR_VMX_IN_VMX_ROOT_MODE)

[1]+  Exit 5                  VBoxHeadless -startvm dev1

This will likely differ a little from your error message as I’m using VBoxHeadless and also trying to kick it to the background with the trailing ampersand.

The error message is a little daunting, I thought. I need to recompile my kernel?! Turns out, not so. All you need to do is issue:

brutimus@localhost:~$ sudo /etc/init.d/kvm stop
 * Succesfully unloaded kvm module kvm_intel

VirtualBox started up fine after this. To keep it this way (if you don’t want to completely uninstall KVM) just kill KVM from your startup scripts.

(Source: thesigb.com)

0 notes &

Debugging Python Regular Expressions

Archive from thesigb.com.

Ever since I learned regular expressions, they have been one of my most beloved features of any language, especially Python. I know lots of people just cringe at the thought of having to sit down for 30 minutes to hash out a 40 character pattern, but it’s too powerful to pass up. Up until recently, my process was just to think the problem through and slowly work up the pattern until I got something that worked. Debugging consisted of merely pulling pieces out and trying them individually. That was until I discovered the hidden Python regex debugging feature a couple weeks ago on Stack Overflow, thanks to BatchyX.

I was unable to find any other official resources on this particular trick, so I’ve decided to do a little experimentation and and write out a few examples.

Lets start with a simple example of what I’ve been rambling about thus far. Don’t feel like you should understand this at all, yet.

>>> re.compile(r'(.+)', 128)
literal 60
literal 97
literal 32
literal 104
literal 114
literal 101
literal 102
literal 61
literal 34
subpattern 1
  min_repeat 1 65535
    any None
literal 34
literal 62
subpattern 2
  max_repeat 1 65535
    any None
literal 60
literal 47
literal 97
literal 62

This is a fairly simple regex. It will pull the link and the text out of an href tag. Notice, however, the 128 passed at the second argument. That is the key that enables the fancy debugging mode. The printed output is a little daunting at first glance, but lets try to clear that up. I’ll start with a slightly smaller regex, so you can get the feel for how this works.

>>> re.compile('foo', 128)
literal 102
literal 111
literal 111

This output is a little nicer to look at. You get three ‘literal’ statements followed by numbers. This just means that the pattern is looking for three exact characters represented by their ordinal integer. Try this:

>>> for x in 'foo':
...     ord(x)
... 
102
111
111

See! Same values!

Moving on…

>>> re.compile('fo{1,2}', 128)
literal 102
max_repeat 1 2
  literal 111

In this example, you see the new statement: max_repeat. This is thanks to our ‘{1,2}’ tacked on to the first ‘o’. It should make sense. Literal 111, or ‘o’, will appear 1 or 2 times. This same designation is used for other repeating techniques: *, + and &. The * and + both allow ranges up to 65535.

>>> re.compile('f(o{1,2})', 128)
literal 102
subpattern 1
  max_repeat 1 2
    literal 111

This pattern introduces a group, designated by the ‘subpattern’. Then everything inside that group you will find indented beneath subpattern. Each accessibly group will be signified by a number (the 1). Even if you used named groups, it will still output a number.

>>> re.compile('f(?:o{1,2})', 128)
literal 102
subpattern None
  max_repeat 1 2
    literal 111

Notice what changed? The subpattern is now followed by a None. This is because we switched over to using a non-accessible group with (?: … ). The next debugging statement you’ll likely see often (and one which BatchyX alluded to in his example) is ‘in’ when using square brackets.

>>> re.compile('f(?:[Oo]{1,2})', 128)
literal 102
subpattern None
  max_repeat 1 2
    in
      literal 79
      literal 111

This pattern will match both capital and lowercase ‘o’. In the debugging output, you see that with the ‘in’ used, either literal 79 or 111 can appear 1 or 2 times.

One more example of with square brackets shows the ‘range’ statement.

>>> re.compile('f(?:[a-z]{1,3})', 128)
literal 102
subpattern None
  max_repeat 1 3
    in
      range (97, 122)

I had to skew my example a little bit, but you see that when I search for [a-z], it is actually shown as a range of ordinals from 97-122.

Lets say we give up on matching various forms of ‘foo’ and just want to make ‘f’ followed by any number of anything (previously stated to have a max of 65536).

>>> re.compile('f(?:.*)', 128)
literal 102
subpattern None
  max_repeat 0 65535
    any None

There you go. max_repeat 0 through 65536 with ‘any’ used to denote the period. I don’t know what the None following the ‘any’ represents, yet. This concludes the main part of what I know about regex debugging. The only items left I’ve experimented with are the escaped character patterns: \W, \d, etc.

>>> re.compile('\w+\D{5,10}', 128)
max_repeat 1 65535
  in
    category category_word
max_repeat 5 10
  in
    category category_not_digit

This is just a sample of what the output from these look like. The \w gives you ‘category category_word’ and the \D gives you ‘category category_not_digit’. Pretty self explanatory. I’ll leave you to play with the rest of the escaped characters.

A couple other things to note: You can combine the ‘128’ passed as the second argument with others like re.VERBOSE and re.MULTILINE just by adding them together. Also, when compiling your patterns, note that the debugging output is only printed the first time you compile the pattern. If you immediately follow with the same compilation, no debugging output will be printed.

That’s all the tips I’ve been able to come up with on this subject. Please, if anyone else knows some added syntax, leave a comment.

Cheers!

(Source: thesigb.com)

6 notes &

Textmate Dpaster

Archive from thesigb.com.

For the past couple years, I’ve switched back and forth between TextMate and VIM as my primary editor. Lately, I’ve been on a huge TextMate kick and decided to see what all I could do to customize it. Python, being my primary language, is what I wanted to write my scripts in. However, most of the TextMate bundles are written in Ruby (a language I don’t at all understand — it looks crazy to me). After much digging around in the source of some of these bundles and pecking through Ruby to see how it’s interacting with TextMate, I was able come up with a little script.

The second point I’d like to make it that I use dpaste.com (a code pastebin) on a daily basis. I know TextMate has built in support for pasting to its own pastebin site, but I don’t like it as well at dpaste (also, dpaste is a django site, a plus for me).

I decided to set out and write my own script to paste code to dpaste.com from within TextMate. Right now, it’s far from perfect. Every time I look at it, I see parts that I know I should handle better for errors, etc. But it works for me right now and I have more pressing issues to deal with.

So here is the code.

#!/usr/bin/python 

import os, sys, urllib, re, commands

class dpaster(object):
    def __init__(self):
        self.mode_conversion = {'Python': 'Python', 'Python Django': 'Python', 'SQL': 'Sql', 'HTML (Django)': 'DjangoTemplate', 'JavaScript': 'JScript', 'CSS': 'Css', 'XML': 'Xml', 'Diff': 'Diff', 'Ruby': 'Ruby', 'Ruby on Rails': 'Rhtml', 'Apache': 'Apache', 'Schell Script (Bash)': 'Bash', 'Plain Text':''}
        self.TM_SELECTED_TEXT = os.environ.get('TM_SELECTED_TEXT', '')
        self.TM_SUPPORT_PATH = os.environ.get('TM_SUPPORT_PATH', '')
        self.TM_MODE = os.environ.get('TM_MODE', '')
        if self.TM_SELECTED_TEXT and self.TM_SUPPORT_PATH and self.TM_MODE:
            self.TM_SUPPORT_PATH = os.path.join(self.TM_SUPPORT_PATH, "lib")
            if not self.TM_SUPPORT_PATH in os.environ:
                sys.path.insert(0, self.TM_SUPPORT_PATH)
        else:
            self.dialog("Error!", "You need to select text first.")
            raise "Required environment variables are not present"
        if self.TM_MODE in self.mode_conversion:
            self.TM_MODE = self.mode_conversion[self.TM_MODE]
        else:
            self.dialog("Warning!", "dpaste.com does not currently support this language.\nPasting as Plain Text.")
            self.TM_MODE = ''
        
        self.url = "dpaste.com"
        self.id_regex = re.compile('dpaste: #(\d+)')
    
    def ping(self):
        ping_re = re.compile('0% packet loss')
        if ping_re.search(commands.getstatusoutput('ping -c 1 %s' % self.url)[1]):
            return True
        return False
    
    def paste(self):
        data = urllib.urlencode({'content': self.TM_SELECTED_TEXT, 'language':self.TM_MODE, 'title': '', 'poster':'TextMate Script'})
        req = urllib.urlopen('http://%s' % self.url, data)
        self.post_url = "http://dpaste.com/%s/" % self.id_regex.search(req.read()).groups()[0]
    
    def copy(self):
        os.system("echo %s | pbcopy" % self.post_url)
    
    def dialog(self, message, text):
        os.system("$DIALOG -ep '{messageTitle = \"%s\"; informativeText = \"%s\"; alertStyle = informational;}'" % (message, text))
    
    def successDialog(self):
        message = "dpaste.com URL"
        text = "%s\n\nThis URL has been copied to your clipboard." % self.post_url
        self.dialog(message, text)
        
if __name__ == '__main__':
    dpaster = dpaster()
    if dpaster.ping():
        dpaster.paste()
        dpaster.copy()
        dpaster.successDialog()

To make this work, just go into your Bundle Editor, create a New Command and paste this code into the Commands text area. Set the Output to Discard and then setup a keyboard shortcut key — I chose Ctrl + Option + Command + d. Enjoy!

(Source: thesigb.com)

0 notes &

sortByCount() method

Archive from thesigb.com.

A few days ago, I was generating some XML to feed a video player. I would grab a list of the last 20 uploaded videos, then grab the categories associated with each video to create a set of “tabs” for the player. For instance, five of the videos may belong to the “high_school_football” category, so we would have a “High School Football” tab containing five videos. I then needed the categories to be ranked by the number of videos in each.

Here is an example of what I needed to accomplish:

>>> l = ['a','a','a','b','c','c']

I need the list to be reordered and reduced down to one instance of each value in the list, like so:

>>> l = ['b','c','a']  # Normal
>>> l = ['a','c','b']  # Reversed

After trying a few different techniques, I came up with a little method that makes this pretty easy. I doubt it’s perfect by any means, so if you have a better idea, let me know.

def sortByCount(item_list, reverse=False):
    """Takes a list of items and sorts them based on the count of each item in the list.
    >>> l = ['a','b','b','b','c','c']
    >>> sortByCount(l)
    ['a','c','b']
    >>> sortByCount(l, reverse=True)
    ['b','c','b']
    """
    import operator
    from sets import Set #For python2.3 compat.
    item_counter = Set([(x, item_list.count(x)) for x in item_list])
    return [x[0] for x in sorted(item_counter, key=operator.itemgetter(1), reverse=reverse)]

Feel free to take this and use it if you like. If you’ve got any improvements, I would love to know about them; just leave a note in the comments.

(Source: thesigb.com)

25 notes &

Solaris + FreeTDS + Pymssql + MSSQL

Archive from thesigb.com.

A couple weeks ago, I had the pleasure of querying a MSSQL 2000 database from Solaris using python. It was a bit of a hassle to get it all setup so it finally worked like I needed. I spent a couple days researching before I was finally successful. I thought I would try to remember my experience and share it here.

To make this a little more difficult, I didn’t have root access on the machine I was working on. I had to do all compiling and installation from within my home directory.

First, you will need to download a few things to work with.

Lets start off with FreeTDS, as it gives us the set of libraries we need to access a MSSQL server. Download and untar the source into your home directory somewhere.

$ mkdir src
$ cd src
$ wget ftp://ftp.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-stable.tgz
$ gunzip -c freetds-stable.tgz | tar -xvf -

Then you will need to configure and compile FreeTDS into your home directory. I’ll create a special directory to install FreeTDS into.

$ mkdir ../freetds
$ cd freetds-stable
$ ./configure --prefix=/home/username/freetds --enable-msdblib --disable-libiconv
$ make; make install; make clean

Notice that I used the —endable-msdblib and —disable-libiconv flags. The first flag enables some Microsoft specific behavior in the db-lib API. As for the second flag, you should try compiling and installing first without that flag and see if you have any success. My first compile didn’t quite work. When I would try to connect to a database, it would give me errors (I don’t recall exactly what they were, sorry). I spent the better part of an afternoon Googling and reading but still found no solution. I just happened to try the —disable-libiconv flag and everything seems to work correctly. I haven’t run into any encoding issues, yet.

Next, its on to the pymssql install. Download and unpack pymssql as you did with FreeTDS above.

$ wget http://downloads.sourceforge.net/pymssql/pymssql-0.8.0.tar.gz
$ gunzip -c pymssql-0.8.0.tar.gz | tar -xvf -

Next, we will build pymssql, but not install. This will allow us to manually place our pymssql library where we need.

$ cd pymssql-0.8.0
$ python setup.py build

If you get gcc or any other build errors, you will either have to troubleshoot those yourself, or get the admin to install the packages you need. You could also download and install whatever packages you may need into your home directory like we did with FreeTDS.

Once built, you should copy the pymssql.py and _mssql.so found in a subdirectory of build/ into a directory you have in your python path (or put a directory into your python path).

$ mkdir ../python-libs
$ cp build/lib.solaris-2.10-i86pc-2.5/* ../python-libs/
$ export PYTHONPATH=$PYTHONPATH:/home/username/python

Add that last line into your .bash_profile, too. Next, we’ll need to write a quick config file. You’ll have to reference the FreeTDS docs to see how you’ll want to configure your install.

$ vi ~/freetds/etc/freetds.conf

Once you have this all setup, you can crank up your python interpreter for a quick test. Quick note: ‘hostname’ is the name you defined in your freetds.conf file, not the entire hostname of the server.

>>> import pymssql
>>> con = pymssql.connect(user="username", password="password", hostname="server", database="db1")
>>> cur = con.cursor()
>>> query = "select * from table1;"
>>> cur.execute(query)
>>> cur.fetchall()

If everything went as planned, you should see a bunch of data. If you get errors, you’ll need to consult the appropriate documentation (or leave a comment and I can attempt to help).

That’s it! You should now be querying a MSSQL database from Solaris. Feel proud! Like I said, if you run into any issues, read, read, read!

(Source: thesigb.com)