Group Cycling
I went on my first group ride yesterday morning with the school cycling club. It was a bit depressing showing up at the meeting location with my toe clips, friction shifters, and 1989 Miyata, when everyone else present was sporting expensive carbon fiber and aluminum racing bikes with stiff racing shoes, but I ended up keeping up passably well, at least for the first half; I ended up falling behind the pack on the return trip since I wasn't really used to pumping out 20 MPH for three hours.
I had some trouble riding together in such a close pack. Its a little scary to ride a foot behind someone's wheel at 20 MPH, and my rather poor bike handling certainly didn't lend me any confidence. Towards the middle of the ride I started getting more comfortable with riding in a tight group, especially when I started to feel the burn in my thighs (drafting does make life a little easier).
My Miyata Alumicross was most definitely not made for racing, a fact which became very apparent on hills. On long descents when everyone ducked down into a tuck, the air resistance generated by my knobby cyclocross tires resulted in me slowly drifting more and more towards the back of the group, despite the fact that I practically had my nose on level with my headset. And on very small descents, when the group shifted into their smallest sprockets and started pedaling with speed, I was doing 120+ RPMs in my smallest sprocket, struggling to keep up.
Nevertheless, I found it to be a highly enjoyable ride, and I will definitely be going out for more group rides in the future.
Python Animated Progress Bar
I wanted to be able to have an animated progress bar to be displayed in a terminal for my current Python project. There are already various implementations on the Internet of something like what I wanted, but I couldn't find one that was animated. So for the sake of practice, I decided to write my own. In order to be able to have the bar animated, and still allow the program to get other work done, I had to create a seperate thread to manage the status bar.
Code for the bar, (and also sample code to create a demo) are below.
import time import sys import os import threading """ Display an animated statusbar, with progress and percentage ( items-completed/items-total ) displayed below the statusbar. Seperate thread is used to display the spinning "icon." In order to stop the statusbar thread early, calling thread can use join() example output created by StatusBar thread: [===============\--------------] 30/60 50% Written by chi (aka chi42) from 42gems.com-- 11 Sept, 2009 Copyright (C) 2009 chi (from 42g see for a copy of the license. """ class StatusBar(threading.Thread): # class variables: # max: number of total items to be completed # pos: number of completed items # inc: amount of items to increment completed 'pos' by # (shared resource) # comp: amount of '=' to display in the progress bar # running: whether or not the statusbar is running def __init__(self, pos=0, max=100): threading.Thread.__init__(self) self.pos = pos self.max = max self.busy_char = '|' self.running = 0 self.inc = 0 self.__getsize() self.comp = int(float(self.pos) / self.max * self.columns) self.inc_lock = threading.Lock() # find number of columns in terminal def __getsize(self): rows, columns = os.popen('stty size', 'r').read().split() if int(columns) > 80: self.columns = 80 - 2 else: self.columns = int(columns) - 2 return # redraw progress bar and all numerial values def __print(self): self.__getsize() sys.stdout.write('\x1b[1G') sys.stdout.write('[' + '=' * self.comp + self.busy_char + \ '-'*(self.columns - self.comp - 1) + ']' ) sys.stdout.write('\n\x1b[0K' + str(self.pos) + \ '/' + str(self.max) + '\t' + \ str( round(float(self.pos) / self.max * 100, 2)) + '%') sys.stdout.write('\x1b[1A\x1b[' + \ str(self.comp + 2) + 'G') sys.stdout.flush() return # run the thread def run(self): global busy_chars, inteval busy_chars = ['|','/','-','\\'] interval = 0.3 self.running = 1 self.__print() while 1: # loop and display the busy spinning icon for c in busy_chars: self.busy_char = c sys.stdout.write(c + '\x1b[1D') sys.stdout.flush() time.sleep(interval) self.inc_lock.acquire() if self.inc: if (self.pos + self.inc) >= self.max: self.inc_lock.release() self.pos = self.max self.comp = self.columns self.busy_char = '' self.__print() sys.stdout.write('\n\n') self.running = 0 return 0 else: self.pos += self.inc self.inc = 0 self.inc_lock.release() self.comp = int(float(self.pos) / self.max \ * self.columns) self.__print() else: self.inc_lock.release() return 1 # increment number of completed items used by calling thread def increment(self): if self.running: self.inc_lock.acquire() self.inc += 1 self.inc_lock.release() return 0 else: return 1
Annnd the demo code:
#!/usr/bin/python import statusbar import time import os print '\n' min, max = 0, 80 inc_sleep = 3 bar = statusbar.StatusBar(min, max) rows, columns = os.popen('stty size', 'r').read().split() print 'columns in screen: ', columns bar.start() while 1: time.sleep(inc_sleep) if bar.increment(): break print 'done!'
M.
Word of the Day…
I learned a new word today, and its possibly my most favorite word ever, beating out "doughty" (which I learned from reading The Lord of the Rings in middle school). And the word of the day is:
defenestration.
Defenestration is defined as being the act of throwing someone or something out of a window. I was not hitherto aware a word such such as defenestration existed, and am quite frankly astounded that a word was created to describe such an action.
I picked up the word today while watching an old episode of Dark Angel online.
Gmail Down Time Again…
So Gmail is down again and has been for at least thiry minutes, attempts to access the webpage results in a 502 error. I disallowed IMAP and POP forwarding on my account so I have no way of knowing if IMAP and POP are still accessible, but I am inclined to assume that they're not. Gmail outages while rare, are not unheard of, and I have always ridden out the down times without too much complaining. But Google's mail software is now officially out of beta, and it is not acceptable for a production-ready product to be having these kinds of outages. I may just have to create a 42gems.com e-mail and use that instead of my gmail account as my primary e-mail address.