~widelands-dev/widelands-website/django_staticfiles

« back to all changes in this revision

Viewing changes to widelandslib/make_flow_diagram.py

  • Committer: franku
  • Date: 2016-12-13 18:28:51 UTC
  • mto: This revision was merged to the branch mainline in revision 443.
  • Revision ID: somal@arcor.de-20161213182851-bo5ebf8pdvw5beua
run the script

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
import subprocess
11
11
from tempfile import mkdtemp
12
12
 
13
 
tdir = ""
 
13
tdir = ''
14
14
 
15
15
##############################
16
16
# To Do Make_Flow_Diagram.py #
25
25
#############################
26
26
# Work around bugs in pydot #
27
27
#############################
28
 
## Pydot can't handle names with - in it. We replace them.
 
28
# Pydot can't handle names with - in it. We replace them.
 
29
 
29
30
 
30
31
def _cleanup_str(s):
31
32
    return s.replace('-', '')
32
33
 
 
34
 
33
35
class Subgraph(d.Subgraph):
 
36
 
34
37
    def __init__(self, name, *args, **kwargs):
35
38
        name = _cleanup_str(name)
36
39
        d.Subgraph.__init__(self, name, *args, **kwargs)
37
40
 
 
41
 
38
42
class Node(d.Node):
 
43
 
39
44
    def __init__(self, name, *args, **kwargs):
40
45
        name = _cleanup_str(name)
41
46
        d.Node.__init__(self, name, *args, **kwargs)
42
47
 
 
48
 
43
49
class Edge(d.Edge):
 
50
 
44
51
    def __init__(self, first, second, *args, **kwargs):
45
52
        first = _cleanup_str(first)
46
53
        second = _cleanup_str(second)
47
54
        d.Edge.__init__(self, first, second, *args, **kwargs)
48
55
 
 
56
 
49
57
class CleanedDot(d.Dot):
 
58
 
50
59
    def get_node(self, name, *args, **kwargs):
51
60
        name = _cleanup_str(name)
52
61
        return d.Dot.get_node(self, name, *args, **kwargs)
55
64
# Begin of drawing #
56
65
####################
57
66
 
 
67
 
58
68
def add_building(g, b, limit_inputs=None, limit_outputs=None, limit_buildings=None, link_workers=True, limit_recruits=None):
59
69
    # Add the nice node
60
 
    workers = ""
 
70
    workers = ''
61
71
    if isinstance(b, (ProductionSite,)):
62
72
        workers = r"""<table border="0px" cellspacing="0">"""
63
73
        for worker in b.workers:
67
77
            ))
68
78
            if link_workers:
69
79
                add_worker(g, wo)
70
 
                g.add_edge(Edge(b.name, wo.name, color="orange", arrowhead="none"))
 
80
                g.add_edge(
 
81
                    Edge(b.name, wo.name, color='orange', arrowhead='none'))
71
82
        for worker in b.recruits:
72
83
            if limit_recruits is None or worker in limit_recruits:
73
84
                wo = b.tribe.workers[worker]
74
85
                add_worker(g, wo, as_recruit=True)
75
 
                g.add_edge(Edge(b.name, wo.name, color="darkgreen"))
 
86
                g.add_edge(Edge(b.name, wo.name, color='darkgreen'))
76
87
        workers += r"""</table>"""
77
88
 
78
89
    if isinstance(b, (MilitarySite,)):
85
96
    costs = r"""<tr><td colspan="2"><table border="0px" cellspacing="0">"""
86
97
    for ware, count in b.buildcost.items():
87
98
        w = b.tribe.wares[ware]
88
 
        costs += ('<tr><td border="0px">%s x </td><td border="0px"><img src="%s"/></td><td border="0px">%s</td></tr>' % (count, w.image, w.descname))
 
99
        costs += ('<tr><td border="0px">%s x </td><td border="0px"><img src="%s"/></td><td border="0px">%s</td></tr>' %
 
100
                  (count, w.image, w.descname))
89
101
    costs += r"""</table></td></tr>"""
90
102
    if not b.buildcost:
91
 
        costs = ""
 
103
        costs = ''
92
104
 
93
105
    n = Node(b.name,
94
 
        shape = "none",
95
 
        label = (r"""<<TABLE border="1px" cellborder="0px" cellspacing="0px" cellpadding="0px">
 
106
             shape='none',
 
107
             label=(r"""<<TABLE border="1px" cellborder="0px" cellspacing="0px" cellpadding="0px">
96
108
<TR><TD><IMG SRC="%s"/></TD>
97
109
<TD valign="bottom">%s</TD>
98
110
</TR>
99
111
<TR><TD align="left" colspan="2">%s</TD></TR>
100
112
%s
101
 
</TABLE>>""" % (b.image, workers, b.descname, costs)).replace('\n',''),
102
 
        URL = "../../buildings/%s/" % b.name,
103
 
        fillcolor = "orange",
104
 
        style = "filled",
105
 
    )
 
113
</TABLE>>""" % (b.image, workers, b.descname, costs)).replace('\n', ''),
 
114
             URL='../../buildings/%s/' % b.name,
 
115
             fillcolor='orange',
 
116
             style='filled',
 
117
             )
106
118
 
107
 
    sg = Subgraph("%s_enhancements" % b.name,
108
 
        ordering = "out", rankdir="TB", rank="same")
 
119
    sg = Subgraph('%s_enhancements' % b.name,
 
120
                  ordering='out', rankdir='TB', rank='same')
109
121
    if b.enhancement and not b.enhanced_building:
110
122
        cb = b
111
123
        while cb.enhancement:
112
124
            if limit_buildings == None or (cb.name in limit_buildings):
113
125
                sg.add_node(Node(_cleanup_str(cb.name)))
114
126
                if limit_buildings == None or (cb.enhancement in limit_buildings):
115
 
                    g.add_edge(Edge(cb.name, cb.enhancement, color="blue"))
 
127
                    g.add_edge(Edge(cb.name, cb.enhancement, color='blue'))
116
128
            cb = b.tribe.buildings[cb.enhancement]
117
129
        if limit_buildings == None or (cb.name in limit_buildings):
118
130
            sg.add_node(Node(_cleanup_str(cb.name)))
121
133
    else:
122
134
        g.add_node(n)
123
135
 
124
 
 
125
136
    if isinstance(b, (ProductionSite,)):
126
137
        # for worker,c in b.workers:
127
138
        #     g.add_edge(Edge(worker, name, color="orange"))
128
139
 
129
140
        for output in b.outputs:
130
141
            if limit_outputs is None or output in limit_outputs:
131
 
                g.add_edge(Edge(b.name, output, color="darkgreen"))
 
142
                g.add_edge(Edge(b.name, output, color='darkgreen'))
132
143
 
133
144
        for input_ in b.inputs:
134
145
            if limit_inputs is None or input_ in limit_inputs:
135
 
                g.add_edge(Edge(input_, b.name, color="#cd0000"))
 
146
                g.add_edge(Edge(input_, b.name, color='#cd0000'))
136
147
    return n
137
148
 
138
149
 
139
150
def add_ware(g, w):
140
151
    # Add the nice node
141
152
    n = Node(w.name,
142
 
             shape = "ellipse",
143
 
             label = (r"""<<TABLE border="0px">
 
153
             shape='ellipse',
 
154
             label=(r"""<<TABLE border="0px">
144
155
<TR><TD><IMG SRC="%s"/></TD></TR>
145
156
<TR><TD>%s</TD></TR>
146
157
</TABLE>>""") % (w.image, w.descname),
147
 
             URL = "../../wares/%s/" % (w.name),
148
 
             fillcolor = "#dddddd",
149
 
             style="filled",
150
 
)
 
158
             URL='../../wares/%s/' % (w.name),
 
159
             fillcolor='#dddddd',
 
160
             style='filled',
 
161
             )
151
162
 
152
163
    g.add_node(n)
153
164
 
 
165
 
154
166
def add_worker(g, w, as_recruit=False):
155
167
    # Add the nice node
156
168
    n = Node(w.name,
157
 
            shape = "octagon" if not as_recruit else "ellipse",
158
 
            label = (r"""<<TABLE border="0px">
 
169
             shape='octagon' if not as_recruit else 'ellipse',
 
170
             label=(r"""<<TABLE border="0px">
159
171
<TR><TD><IMG SRC="%s"/></TD>
160
172
<TD>%s</TD></TR>
161
173
</TABLE>>""") % (w.image, w.descname),
162
 
            URL="../../workers/%s/" % w.name,
163
 
            style="filled",
164
 
        )
 
174
             URL='../../workers/%s/' % w.name,
 
175
             style='filled',
 
176
             )
165
177
 
166
178
    g.add_node(n)
167
179
 
168
180
 
169
181
def make_graph(tribe_name):
170
182
    global tdir
171
 
    tdir = mkdtemp(prefix="widelands-help")
 
183
    tdir = mkdtemp(prefix='widelands-help')
172
184
 
173
 
    json_directory = path.normpath(MEDIA_ROOT + "/map_object_info")
174
 
    tribeinfo_file = open(path.normpath(json_directory + "/tribe_" + tribe_name + ".json"), "r")
 
185
    json_directory = path.normpath(MEDIA_ROOT + '/map_object_info')
 
186
    tribeinfo_file = open(path.normpath(
 
187
        json_directory + '/tribe_' + tribe_name + '.json'), 'r')
175
188
    tribeinfo = json.load(tribeinfo_file)
176
189
 
177
190
    t = Tribe(tribeinfo, json_directory)
178
191
 
179
 
    g = CleanedDot(concentrate="false", style="filled", bgcolor="white",
180
 
                overlap="false", splines="true", rankdir="LR")
 
192
    g = CleanedDot(concentrate='false', style='filled', bgcolor='white',
 
193
                   overlap='false', splines='true', rankdir='LR')
181
194
 
182
 
    for name,w in t.wares.items():
 
195
    for name, w in t.wares.items():
183
196
        add_ware(g, w)
184
197
    #
185
198
    # for name,w in t.workers.items():
186
199
    #     add_worker(g, w)
187
200
 
188
 
    for name,b in t.buildings.items():
 
201
    for name, b in t.buildings.items():
189
202
        add_building(g, b, link_workers=False)
190
203
 
191
 
 
192
 
    g.write_pdf(path.join(tdir, "%s.pdf" % tribe_name))
193
 
 
194
 
    g.set_size("32")
195
 
    g.write_gif(path.join(tdir, "%s.gif" % tribe_name))
196
 
 
197
 
    rtdir, tdir = tdir, ""
 
204
    g.write_pdf(path.join(tdir, '%s.pdf' % tribe_name))
 
205
 
 
206
    g.set_size('32')
 
207
    g.write_gif(path.join(tdir, '%s.gif' % tribe_name))
 
208
 
 
209
    rtdir, tdir = tdir, ''
198
210
    return rtdir
199
211
 
 
212
 
200
213
def make_building_graph(t, building_name):
201
214
    if isinstance(t, basestring):
202
215
        t = Tribe(t)
203
216
 
204
217
    b = t.buildings[building_name]
205
218
 
206
 
    g = CleanedDot(concentrate="false", bgcolor="transparent",
207
 
                overlap="false", splines="true", rankdir="LR")
 
219
    g = CleanedDot(concentrate='false', bgcolor='transparent',
 
220
                   overlap='false', splines='true', rankdir='LR')
208
221
 
209
222
    if not isinstance(b, (ProductionSite,)):
210
223
        inputs, outputs = [], []
211
224
    else:
212
 
        # TODO: prepare for tribes having buildings with a ware as both input and output.
213
 
        inputs, outputs = [[t.wares[name] for name in lst] for lst in [b.inputs, b.outputs]]
 
225
        # TODO: prepare for tribes having buildings with a ware as both input
 
226
        # and output.
 
227
        inputs, outputs = [[t.wares[name] for name in lst]
 
228
                           for lst in [b.inputs, b.outputs]]
214
229
 
215
230
    # find the uppermost building in the enhancement hierarchy
216
231
    bb = b
217
232
    while bb.base_building:
218
233
        bb = bb.base_building
219
 
        add_building(g, bb, limit_inputs=[], limit_outputs=[], link_workers=False)
 
234
        add_building(g, bb, limit_inputs=[],
 
235
                     limit_outputs=[], link_workers=False)
220
236
 
221
237
    add_building(g, b)
222
238
 
223
239
    bb = b
224
240
    while bb.enhancement:
225
241
        bb = t.buildings[bb.enhancement]
226
 
        add_building(g, bb, limit_inputs=[], limit_outputs=[], link_workers=False)
 
242
        add_building(g, bb, limit_inputs=[],
 
243
                     limit_outputs=[], link_workers=False)
227
244
 
228
245
    [add_ware(g, w) for w in inputs + outputs]
229
246
 
230
 
    try: makedirs(path.join(tdir, "help/%s/buildings/%s/" % (t.name, building_name)))
231
 
    except: pass
232
 
    g.write(path.join(tdir, "help/%s/buildings/%s/source.dot" % (t.name, building_name)))
 
247
    try:
 
248
        makedirs(path.join(tdir, 'help/%s/buildings/%s/' %
 
249
                           (t.name, building_name)))
 
250
    except:
 
251
        pass
 
252
    g.write(path.join(tdir, 'help/%s/buildings/%s/source.dot' %
 
253
                      (t.name, building_name)))
 
254
 
233
255
 
234
256
def make_worker_graph(t, worker_name):
235
257
    if isinstance(t, basestring):
237
259
 
238
260
    w = t.workers[worker_name]
239
261
 
240
 
    g = CleanedDot(concentrate="false", bgcolor="transparent",
241
 
                overlap="false", splines="true", rankdir="LR")
 
262
    g = CleanedDot(concentrate='false', bgcolor='transparent',
 
263
                   overlap='false', splines='true', rankdir='LR')
242
264
 
243
265
    buildings = [bld for bld in t.buildings.values() if
244
 
            isinstance(bld, ProductionSite) and
245
 
              (w.name in bld.workers or w.name in bld.recruits)]
 
266
                 isinstance(bld, ProductionSite) and
 
267
                 (w.name in bld.workers or w.name in bld.recruits)]
246
268
 
247
269
    for bld in buildings:
248
 
        add_building(g, bld, limit_inputs=[], limit_outputs=[], limit_buildings=[buildings], link_workers=False, limit_recruits=[w.name])
 
270
        add_building(g, bld, limit_inputs=[], limit_outputs=[], limit_buildings=[
 
271
                     buildings], link_workers=False, limit_recruits=[w.name])
249
272
        if w.name in bld.workers:
250
 
            g.add_edge(Edge(bld.name, w.name, color="orange", arrowhead="none"))
 
273
            g.add_edge(Edge(bld.name, w.name, color='orange', arrowhead='none'))
251
274
 
252
 
    sg = Subgraph("%s_enhancements" % w.name,
253
 
        ordering = "out", rankdir="TB", rank="same")
 
275
    sg = Subgraph('%s_enhancements' % w.name,
 
276
                  ordering='out', rankdir='TB', rank='same')
254
277
    # find exactly one level of enhancement
255
278
    for other in t.workers.values():
256
279
        if other.becomes == w.name:
257
280
            add_worker(sg, other)
258
 
            g.add_edge(Edge(other.name, w.name, color="blue"))
 
281
            g.add_edge(Edge(other.name, w.name, color='blue'))
259
282
        elif w.becomes == other.name:
260
283
            add_worker(sg, other)
261
 
            g.add_edge(Edge(w.name, other.name, color="blue"))
 
284
            g.add_edge(Edge(w.name, other.name, color='blue'))
262
285
 
263
286
    add_worker(sg, w)
264
287
    g.add_subgraph(sg)
265
288
 
266
 
    try: makedirs(path.join(tdir, "help/%s/workers/%s/" % (t.name, w.name)))
267
 
    except OSError: pass
268
 
    g.write(path.join(tdir, "help/%s/workers/%s/source.dot" % (t.name, w.name)))
 
289
    try:
 
290
        makedirs(path.join(tdir, 'help/%s/workers/%s/' % (t.name, w.name)))
 
291
    except OSError:
 
292
        pass
 
293
    g.write(path.join(tdir, 'help/%s/workers/%s/source.dot' % (t.name, w.name)))
 
294
 
269
295
 
270
296
def make_ware_graph(t, ware_name):
271
297
    if isinstance(t, basestring):
272
298
        t = Tribe(t)
273
299
    w = t.wares[ware_name]
274
300
 
275
 
    g = CleanedDot(concentrate="false", bgcolor="transparent",
276
 
                overlap="false", splines="true", rankdir="LR")
 
301
    g = CleanedDot(concentrate='false', bgcolor='transparent',
 
302
                   overlap='false', splines='true', rankdir='LR')
277
303
 
278
 
    buildings = [bld for bld in t.buildings.values() if isinstance(bld, (ProductionSite, )) and (w.name in bld.inputs or w.name in bld.outputs)]
279
 
    [add_building(g, bld, limit_inputs=[w.name], limit_outputs=[w.name], limit_buildings=[b.name for b in buildings], link_workers=False) for bld in buildings]
 
304
    buildings = [bld for bld in t.buildings.values() if isinstance(
 
305
        bld, (ProductionSite, )) and (w.name in bld.inputs or w.name in bld.outputs)]
 
306
    [add_building(g, bld, limit_inputs=[w.name], limit_outputs=[w.name], limit_buildings=[
 
307
                  b.name for b in buildings], link_workers=False) for bld in buildings]
280
308
 
281
309
    add_ware(g, w)
282
310
 
283
 
    try: makedirs(path.join(tdir, "help/%s/wares/%s/" % (t.name, ware_name)))
284
 
    except OSError: pass
285
 
    g.write(path.join(tdir, "help/%s/wares/%s/source.dot" % (t.name, ware_name)))
 
311
    try:
 
312
        makedirs(path.join(tdir, 'help/%s/wares/%s/' % (t.name, ware_name)))
 
313
    except OSError:
 
314
        pass
 
315
    g.write(path.join(tdir, 'help/%s/wares/%s/source.dot' % (t.name, ware_name)))
 
316
 
286
317
 
287
318
def process_dotfile(directory):
288
 
    subprocess.Popen(("dot -Tpng -o %s/menu.png -Tcmapx -o %s/map.map %s/source.dot" % (directory, directory, directory)).split(" ")).wait()
289
 
    #with open(directory,"w") as html:
290
 
    #    html.write(r"""<IMG SRC="menu.png" border="0px" usemap="#G"/>""" + open(path.join(directory, "map.map")).read())
 
319
    subprocess.Popen(('dot -Tpng -o %s/menu.png -Tcmapx -o %s/map.map %s/source.dot' %
 
320
                      (directory, directory, directory)).split(' ')).wait()
 
321
    # with open(directory,"w") as html:
 
322
    # html.write(r"""<IMG SRC="menu.png" border="0px" usemap="#G"/>""" +
 
323
    # open(path.join(directory, "map.map")).read())
 
324
 
291
325
 
292
326
def make_all_subgraphs(t):
293
327
    global tdir
294
 
    tdir = mkdtemp(prefix="widelands-help")
 
328
    tdir = mkdtemp(prefix='widelands-help')
295
329
    if isinstance(t, basestring):
296
330
        t = Tribe(t)
297
 
    print "making all subgraphs for tribe", t.name, "in", tdir
 
331
    print 'making all subgraphs for tribe', t.name, 'in', tdir
298
332
 
299
 
    print "  making wares"
 
333
    print '  making wares'
300
334
 
301
335
    for w in t.wares:
302
 
        print "    " + w
 
336
        print '    ' + w
303
337
        make_ware_graph(t, w)
304
 
        process_dotfile(path.join(tdir, "help/%s/wares/%s/" % (t.name, w)))
 
338
        process_dotfile(path.join(tdir, 'help/%s/wares/%s/' % (t.name, w)))
305
339
 
306
 
    print "  making workers"
 
340
    print '  making workers'
307
341
 
308
342
    for w in t.workers:
309
 
        print "    " + w
 
343
        print '    ' + w
310
344
        make_worker_graph(t, w)
311
 
        process_dotfile(path.join(tdir, "help/%s/workers/%s/" % (t.name, w)))
 
345
        process_dotfile(path.join(tdir, 'help/%s/workers/%s/' % (t.name, w)))
312
346
 
313
 
    print "  making buildings"
 
347
    print '  making buildings'
314
348
 
315
349
    for b in t.buildings:
316
 
        print "    " + b
 
350
        print '    ' + b
317
351
        make_building_graph(t, b)
318
 
        process_dotfile(path.join(tdir, "help/%s/buildings/%s/" % (t.name, b)))
 
352
        process_dotfile(path.join(tdir, 'help/%s/buildings/%s/' % (t.name, b)))
319
353
 
320
 
    rtdir, tdir = tdir, ""
 
354
    rtdir, tdir = tdir, ''
321
355
    return rtdir
322
356
 
 
357
 
323
358
def add_bases(tribe, building, g):
324
359
    if b.enhanced_building:
325
360
        add_building()
326
361
 
327
 
if __name__ == "__main__":
 
362
if __name__ == '__main__':
328
363
    make_all_subgraphs()