""" 1999 Manuel Gutierrez Algaba You are free to use , modify, distribute and copy this piece of python code, if you keep this free copyright notice in it. grapher.py Version 1.0 This small programm produces state diagrams, just specifying the relationship among the different states """ class graphstate: def __init__(self, label1, label2 = None): self.label1= label1 self.label2 = label2 self.next = None self.goto=[] self.label_next = None self.make_width() self.size = "" self.numberlabel = None self.figure = "ellipse" self.already_drawn = 0 self.already_drawn_arrows = 0 self.index_of_goto_arrows = 0 def do_size(self, s): """ valid sizes are: 0.9 and 0.8, or greater """ self.size = s def rel(self,n=None, l= None, f = None, g=[] ): """ This makes a relationship among this state and those stated in n and g. n = the next one state, g = a list of states where this state goes l = label of the transition of this state to the next one f = forced_next , this forces f to be the next node to be visited. """ self.next = n self.label_next = l self.goto = g self.forced_next = f def make_width(self): if self.label2 is None: t = len(self.label1) else: t = max(len(self.label1), len(self.label2)) self.width = t def generate_gpic_code(self, file ): f = open( file, "w") self.write_headings(f) self.write_body(f) self.write_footnote(f) f.close() def make_size(self, size ): self.size = size def write_headings(self, f): if self.size=="": f.write(".PS \ndown\narrowhead=7\narrow\n") else: f.write(".PS "+`self.size`+"\ndown\narrowhead=7\narrow\n") def write_footnote(self, f): f.write(".PE\n") def write_body(self , f, numberlabel = None): self.assign_numberlabel() self.start_drawing(f) self.arrows_and_such(f) def start_drawing(self,f): print self.numberlabel, self.already_drawn if self.already_drawn == 1: return self.already_drawn = 1 self.write_label(f) self.write_enclosing_figure(f) self.write_movement(f) self.write_rest_of_it(f) def write_rest_of_it(self,f): if not self.forced_next is None: self.forced_next.start_drawing(f) if not self.next is None: self.next.start_drawing(f) for i in self.goto: i[0].start_drawing(f) def write_rest_of_it_arrows(self,f): if not self.next is None: self.next.arrows_and_such(f) for i in self.goto: i[0].arrows_and_such(f) def write_movement(self,f): if self.label_next is None: f.write("move 0.2\n") else: f.write("move 0.5\n") def write_enclosing_figure(self, f ): if self.label2 is None: part1 = self.figure+ ' "'+self.label1 + '" ' else: part1 = self.figure+ ' "'+ self.label1 + '" "' + self.label2 + '" ' #print "line 200",self.width part2 = " ht 0.5 wid " + str( 0.12 * self.width ) f.write(part1 + part2 + "\n") def convert_numberlabel(self): return self.numberlabel[0]+str(self.numberlabel[1]) def write_label(self,f): f.write(self.convert_numberlabel() +": ") def what_numberlabel(self): return self.numberlabel def assign_numberlabel(self, numberlabel= None): """ We go through all the states in the drawing. And we label them. """ if not self.numberlabel is None: return # first we assign our own numberlabel if numberlabel is None: self.numberlabel = ('L', 0) else: #print "line 224",self.numberlabel self.numberlabel = ('L', numberlabel + 1) # then we propagate the numberlabels propagated_numberlabel = self.numberlabel[1] if not self.forced_next is None: propagated_numberlabel = self.forced_next.assign_numberlabel( propagated_numberlabel) if not self.next is None: propagated_numberlabel = self.next.assign_numberlabel( propagated_numberlabel) for i in self.goto: if i[0].what_numberlabel() is None: propagated_numberlabel = i[0].assign_numberlabel(propagated_numberlabel) return propagated_numberlabel def arrows_and_such(self, f): if self.already_drawn_arrows == 1: return self.already_drawn_arrows = 1 self.write_arrows(f) self.write_rest_of_it_arrows(f) def write_arrows(self, file): ''' Cases: arrow next: arrow "health" rjust from Gairst.s to Econd.n arrow from Econd.s to Erd.n arrow self: PAPER : spline from Erd.e then up 0.2 right 0.3 then down 0.4 then up 0.2 left 0.3 -> box invis "apteros" at PAPER + ( 0.6, 0.0) arrow goto: D: arc -> from Erd.e to Gairst.e sprintf("zoom") ljust at D.e + (0.2, 0.0) ''' self.write_arrow_next(file) self.write_arrow_goto(file) def write_arrow_next(self, f): if not self.forced_next is None: self.arrow_forced_west((self.next, self.label_next),f ) return if not self.next is None: if not self.label_next is None: f.write('arrow "'+self.label_next+'" rjust from '+self.convert_numberlabel()+'.s to '+ self.next.convert_numberlabel()+'.n\n') else: f.write('arrow from '+self.convert_numberlabel()+'.s to '+ self.next.convert_numberlabel()+'.n\n') def write_arrow_goto(self,f): ''' arrow goto down to up: D: arc -> from Erd.e to Gairst.e sprintf("zoom") ljust at D.e + (0.2, 0.0) arrow goto up to down : D: arc -> from Erd.w to Gairst.w sprintf("zoom") rjust at D.e + (-0.2, 0.0) ''' for i in self.goto: if i[0] != self: self.make_arrow(i,f) else: self.write_arrow_self(i,f) def make_arrow(self,arrow,f): if self.is_lower(arrow[0]): self.arrow_down_up(arrow,f) else: self.arrow_up_down(arrow,f) def arrow_down_up(self, arrow, f): intlabel = self.generate_goto_arrow_internal_label(f) self.generate_arc(arrow,f,"DOWN-UP") self.generate_goto_arrow_label(arrow,f,intlabel,"DOWN-UP") def arrow_up_down(self, arrow, f): intlabel = self.generate_goto_arrow_internal_label(f) self.generate_arc(arrow,f,"UP-DOWN") self.generate_goto_arrow_label(arrow,f,intlabel,"UP-DOWN") def arrow_forced_west(self, arrow, f): intlabel = self.generate_goto_arrow_internal_label(f) self.generate_arc(arrow,f,"FORCED-WEST") self.generate_goto_arrow_label(arrow,f,intlabel,"FORCED-WEST") def generate_goto_arrow_internal_label(self, f): self.index_of_goto_arrows = self.index_of_goto_arrows + 1 to_return = self.convert_numberlabel()+`self.index_of_goto_arrows`+" :" f.write(to_return) return to_return def generate_arc(self, arrow, f, location): if location =="DOWN-UP": f.write('arc -> from '+self.convert_numberlabel()+'.w to '+ arrow[0].convert_numberlabel()+'.w\n') elif location =="UP-DOWN": f.write('arc -> from '+self.convert_numberlabel()+'.e to '+ arrow[0].convert_numberlabel()+'.e\n') elif location=="FORCED-WEST": f.write('arc -> from '+self.convert_numberlabel()+'.w to '+ arrow[0].convert_numberlabel()+'.w\n') def generate_goto_arrow_label(self, arrow,f,intlabel,location): if arrow[1] is None: return if location =="DOWN-UP": #print "line 163", `arrow[1]`, intlabel f.write('sprintf("'+arrow[1]+'") ljust at '+intlabel[:-2]+'.w +(0.2, 0.0)\n') elif location =="UP-DOWN": f.write('sprintf("'+arrow[1]+'") rjust at '+intlabel[:-2]+'.e +(-0.2, 0.0)\n') elif location=="FORCED-WEST": f.write('sprintf("'+arrow[1]+'") ljust at '+intlabel[:-2]+'.w +(0.2, 0.0)\n') def is_lower(self, another_state): return self.what_numberlabel()[1] < another_state.what_numberlabel()[1] def write_arrow_self(self, arrow, f): ''' PAPER : spline from Erd.e then up 0.2 right 0.3 then down 0.4 then up 0.2 left 0.3 -> box invis "apteros" at PAPER + ( 0.6, 0.0) ''' intlabel = self.generate_goto_arrow_internal_label(f) if arrow[1] is None: label= "" else: label = arrow[1] f.write(' spline from '+ self.convert_numberlabel()+'.e then up 0.2 right 0.3 then down 0.4 then up 0.2 left 0.3 -> \n \ box invis "'+label +'" at '+ intlabel[:-2] + " +( 0.6, 0.0)\n") def gs(label1 = None, label2 = None): return graphstate(label1,label2) def __test24__(): st1 = graphstate("wake up") st2 = graphstate("breakfast") st3 = graphstate("homework", "done?") st4 = graphstate("nice ", "class day") st5 = graphstate("bad", "class day") st6 = graphstate("have lunch") st7 = graphstate("go to","party") st8 = graphstate("have fun") st9 = graphstate("next day") #st1.do_size(2) st1.rel(n=st2) st2.rel(n=st3) st3.rel(n=st4, l='Yes', g=[(st5,'No')]) st4.rel(n=st6,f=st5) st5.rel(n=st6) st6.rel(n=st7) st7.rel(n=st8) st8.rel(n=st9,g=[(st8, "have fun")]) st9.rel(g=[(st1,"Sleep")]) st1.generate_gpic_code("test1.gpic") def __test25__(): st1 = graphstate("consideraciones metafisicas up") st2 = graphstate("kuntakinte en norte america") st3 = graphstate("burros y otros", "el burro espa'nol") st1.rel(n=st2) st2.rel(n=st3) st3.rel(g=[(st1,"hola"),(st2,"adios")]) st1.generate_gpic_code("test1.gpic") if __name__=='__main__': __test24__()