# Collect user interaction statistics from remote server, and # display as a nice graphical bar-chart. DEFHOST = 'flapjack.cs.orst.edu' DEFPORT = 55571 import ihEvent,string,ihApp,ihURL MODE_READY = 0 MODE_VIEW = 1 class StatsCollector(ihURL.LineURL): def __init__(self,doc,server,*args): self.div_stats = None self.total_time = 0.0 self.mode = MODE_READY ihURL.LineURL.__init__(self,doc,server) result = (self.GetStatus(),self.GetURL()) self.sock_result = `result` self.sock_address = self.GetURL() self.Write("* watch\n") def OnLine(self,lines): for i in lines: #print 'Line from : %s' % (self.GetURL(),`i`) cmds = string.split(i) if( cmds and cmds[0] == '>' ): if( self.mode == MODE_VIEW ): #print 'VIEW MODE' if( cmds[1] == 'total' ): self.total_time = string.atof(cmds[2]) elif( cmds[1] == 'div' ): self.div_stats.append(string.atof(cmds[2])) elif( cmds[1] == 'end' and cmds[2] == 'view' ): #print 'Going to READY MODE' self.mode = MODE_READY self.OnNewData() elif( cmds[1] == 'begin' and cmds[2] == 'view' ): #print 'Going to VIEW MODE' self.div_stats = [] self.mode = MODE_VIEW class ihEmbed(ihApp.Application,StatsCollector): def __init__(self,**args): # print 'Starting statistics display...' apply(ihApp.Application.__init__,(self,),args) # Allocate colors, buffer. self.red = self.MakeColor(.9,.2,.1) self.white = self.MakeColor(1,1,1) self.black = self.MakeColor(0,0,0) self.background = self.BackPen() self.foreground = self.ForePen() x, y, width, height = self.Dimensions() self.buffer = self.MakePixmap(width,height) self.buffer.ForePen(self.background) self.buffer.FillRectangle(0,0,width,height) # Extract arguments if( args.has_key('Server') ): self.server = args['Server'] else: self.server = 'tcp://'+DEFHOST+':'+`DEFPORT` # Find font dimensions self.fw,self.fh,self.asc,self.desc = self.TextExtent('Wg') self.frame_w = width self.frame_h = height - (self.fh*2) self.tick_y = height - self.desc - 2 self.inner_w = self.frame_w - 2 self.inner_h = self.frame_h - 2 # Initialize an array to hold current bar values #print self._Document_ StatsCollector.__init__(self,self._Document_,self.server) def OnNewData(self): #print 'New data:',self.div_stats #print 'New total:',self.total_time self.num = len(self.div_stats) self.current = [] # [ barvalue, currentvalue, topy, width ] self.area_h = self.inner_h / self.num self.bar_h = (self.area_h*2)/3 if( self.bar_h < (self.fh+2) ): self.bar_h = self.fh+2 if( self.bar_h > self.area_h ): self.bar_h = self.area_h self.maxval = 0.0 top = (self.area_h-self.bar_h)/2 for i in self.div_stats: texty = top + (self.bar_h/2) - (self.fh/2) + self.asc self.current.append( [i, 0.0, top, 0.0, texty, "%.2f" % i] ) if( self.maxval < i ): self.maxval = i top = top + self.area_h if( self.maxval <= 0 ): self.maxval = 1.0 #print 'Doing step #',cur for i in self.current: i[1] = i[0] #(i[0]*cur)/self.steps i[3] = (self.inner_w*i[1])/self.maxval #print 'Ready to draw...' self.draw_bars() #print 'Updating display...' self.redraw() def draw_bars(self): x, y, width, height = self.buffer.Dimensions() self.buffer.ForePen(self.background) self.buffer.FillRectangle(0,0,width,height) for i in self.current: x, y, w, h = 1, i[2], i[3], self.bar_h #print 'Drawing bar: (%s,%s) at (%sx%s)' % (x,y,w,h) self.buffer.ForePen(self.red) self.buffer.FillRectangle(x,y,w,h) if( w > 0 ): self.buffer.ForePen(self.black) self.buffer.DrawLine(x,y+h-1,x+w-1,y+h-1) self.buffer.DrawLine(x+w-1,y,x+w-1,y+h-1) self.buffer.ForePen(self.white) self.buffer.DrawLine(x,y,x+w-1,y) self.buffer.DrawLine(x,y,x,y+h-1) self.buffer.ForePen(self.foreground) self.buffer.DrawText(x+5,i[4],i[5],-1) def draw_scales(self): x, y, width, height = self.Dimensions() self.buffer.ForePen(self.background) self.buffer.FillRectangle(0,0,width,height) # Place the tick marks self.tick_marks = [] for i in range(self.ticks): text = '%.0f' % ((i*self.maxval)/(self.ticks-1)) tw,th,ta,td = self.buffer.TextExtent(text) xpos = (i*self.frame_w)/(self.ticks-1) - 1 val = (i*self.maxval)/(self.ticks-1) tx = xpos - (tw/2) if( tx < 0 ): tx = 0 elif( (tx+tw) > self.frame_w ): tx = self.frame_w - tw - 1 self.tick_marks.append( ( val, xpos, tx, text, ) ) self.buffer.ForePen(self.foreground) for i in self.tick_marks: self.buffer.DrawLine(i[1],0,i[1],self.frame_h-1) self.buffer.DrawText(i[2],self.tick_y,i[3],-1) self.buffer.ForePen(self.black) self.buffer.DrawLine(0,self.frame_h-1,self.frame_w-1,self.frame_h-1) self.buffer.DrawLine(self.frame_w-1,0,self.frame_w-1,self.frame_h-1) self.buffer.ForePen(self.white) self.buffer.DrawLine(0,0,self.frame_w-1,0) self.buffer.DrawLine(0,0,0,self.frame_h-2) def redraw(self): self.Paste(0,0,self.buffer) self.Flush() def OnRedraw(self,ev,x,y,w,h): self.redraw() def OnMouse(self,ev,x,y,state,hit): if( ev.Code == ihEvent.CodeNames['MousePress'] ): if( self.call ): self.call.Stop() self.update(1) __export__ = ['ihEmbed']