summaryrefslogtreecommitdiff
path: root/support/grapher/grapher.py
blob: 94880beb1a4757365fa0f44ef7c37f8c275bfeea (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
"""
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__()