genhtml: Almost finished axis changing
[can-benchmark.git] / gw-tests / genhtml / genhtml.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 import os;
4 import dircache;
5 import sys;
6 import urllib
7
8 class DimValue:
9     def __init__(self, dim, value):
10         self.dim = dim
11         self.value = value
12     def __str__(self):
13         return self.dim.val2str(self.value)
14     def __repr__(self):
15         return "DimValue("+str(self.dim.__class__.__name__) + ", "+repr(self.value)+")"
16     def htmlTableHeading(self):
17         return self.dim.htmlTableHeading(self.value)
18
19 class DimValues(list):
20     def replace(self, val):
21         for i in xrange(len(self)):
22             if self[i].dim == val.dim:
23                 self[i] = val
24     def __add__(self, val):
25         return DimValues(self).append(val)
26     def __sub__(self, dim):
27         result = DimValues(self)
28         print repr(result)
29         for v in self:
30             if v.dim == dim:
31                 result.remove(v)
32         return result
33
34 class Dimension(dict):
35     def __init__(self, atype, name=None):
36         self.type = atype
37         if (name):
38             self.name = name
39         else:
40             self.name = atype
41         self.sortedKeys = []
42
43     def __iter__(self):
44         for i in xrange(len(self)):
45             yield self.getValue(i)
46     def getValue(self, index):
47         print self.sortedKeys
48         return self[self.sortedKeys[index]]
49
50     def addValue(self, *values):
51         for value in values:
52             if value not in self:
53                 self[value] = DimValue(self, value)
54         self.sortedKeys = self.keys()
55         self.sortedKeys.sort()
56     def val2str(self, v):
57         return str(v)
58     def htmlTableHeading(self, v):
59         return self.val2str(v)
60     def __str__(self):
61         return self.name
62     def __repr__(self):
63         return self.type
64
65 class DimensionKern(Dimension):
66     def __init__(self):
67         Dimension.__init__(self, 'gwkern', 'GW kernel')
68     def htmlTableHeading(self, v):
69         i=v.find(":")
70         if i>0: kver=v[:i]
71         else: kver=v
72         return v+"<br><a href='config-%s'>config</a>"%(urllib.quote(kver))
73     def versions(self):
74         for v in self.values:
75             i=v.find(":")
76             if i>0: kver=v[:i]
77             else: kver=v
78             yield kver
79
80 class DimensionHostKern(Dimension):
81     def __init__(self):
82         Dimension.__init__(self, 'hostkern', 'Host kernel')
83     def val2str(self, v):
84         if v.find("host-") == 0:
85             v = v[5:]
86         return v
87     def htmlTableHeading(self, v):
88         v = self.val2str(v)
89         i = v.find(":")
90         if i>0: kver = v[:i]
91         else: kver = v
92         return v+"<br><a href='config-%s'>config</a>"%(urllib.quote(kver))
93     def versions(self):
94         for v in self.values:
95             i=v.find(":")
96             if i>0: kver=v[:i]
97             else: kver=v
98             yield kver
99
100 class DimensionTest(Dimension):
101     def __init__(self):
102         Dimension.__init__(self, 'test', 'Test')
103     def htmlTableHeading(self, v):
104         return v+"<br><a href='%s.sh.html'>source</a>"%(urllib.quote(v))
105
106 class DimensionTraffic(Dimension):
107     def __init__(self):
108         Dimension.__init__(self, 'traf', 'Traffic')
109     def val2str(self, v):
110         if v == "50":
111             return "50%"
112         elif v == "oneatatime":
113             return "one message at a time"
114         else:
115             return v
116     def htmlTableHeading(self, v):
117         return self.val2str(v)
118 class Test:
119     @classmethod
120     def isOnPath(cls, path):
121         f = os.path.join(path, '.results')
122         return os.path.isfile(f)
123     def __init__(self, path):
124         self.path = path
125         self.name = os.path.basename(path)
126     def printThumbLink(self, file):
127         thumb = self.path+'/thumb'
128         try:
129             imgs = [img for img in dircache.listdir(thumb)]
130         except OSError:
131             imgs = [ self.name + ".png" ]
132         for img in imgs:
133             print >>file, "<a href='%s/%s'><img src='%s/thumb/%s'></a>" % \
134                   (urllib.quote(self.path), img, urllib.quote(self.path), img)
135
136 def iterDimValues(dimensions):
137     idx = [0 for i in xrange(len(dimensions))]
138     done=False
139     while not done:
140         values=DimValues()
141         for i in xrange(len(dimensions)):
142             values.append(dimensions[i].values()[idx[i]])
143         yield values
144         done=True
145         for i in xrange(len(dimensions)):
146             idx[i] += 1
147             if idx[i] < len(dimensions[i]):
148                 done=False
149                 break
150             idx[i] = 0
151
152 class Tests(dict):
153     """Represents all tests organized along several dimensions"""
154     def __init__(self, rootpath, *dimensions):
155         dict.__init__(self)
156         self.dimensions = dimensions
157         if (rootpath):
158             self.populate(rootpath)
159     def getTest(self, key):
160         realkey=[]
161         for d in self.dimensions:
162             for i in key:
163                 if i.dim == d:
164                     realkey.append(i.value)
165         if len(realkey) != len(self.dimensions):
166             raise KeyError("The coordinates in key do not match dimensions")
167         return self[tuple(realkey)]
168
169     def addTest(self, test, coordinates):
170         if len(coordinates) != len(self.dimensions):
171             raise KeyError("The number coordinates do not match the number of dimensions: " + str(coordinates))
172         self[tuple(coordinates)] = test
173         for i in xrange(len(coordinates)):
174             self.dimensions[i].addValue(coordinates[i])
175
176     def populate(self, rootpath):
177         for root, dirs, files in os.walk(rootpath):
178             if (root.find(rootpath) == 0):
179                 coordinates = root[len(rootpath):]
180             else:
181                 coordinates = rootpath
182             if Test.isOnPath(root):
183                 self.addTest(Test(root), coordinates.split("/"))
184     def iterDimensionPairs(self):
185         for i in xrange(len(self.dimensions)):
186             for j in xrange(i+1, len(self.dimensions)):
187                 yield (self.dimensions[i], self.dimensions[j])
188                 yield (self.dimensions[j], self.dimensions[i])
189     def iterRemainingDimensions(self, dimensionPair):
190         for d in self.dimensions:
191             if d not in dimensionPair:
192                 yield d
193     def generateHtml(self):
194         for pair in self.iterDimensionPairs():
195             remDims = [d for d in self.iterRemainingDimensions(pair)]
196             for vals in iterDimValues(remDims):
197                 page = Page(pair, remDims, vals, self)
198                 page.generate()
199         try:
200             os.remove("index.html")
201         except OSError: pass
202         os.symlink(page.getName(), "index.html")
203
204         #os.system("source-highlight -d --output-dir=. ../*.sh")
205
206 class Page:
207     def __init__(self, dimPair, dimOther, valsOther, tests):
208         self.dimy, self.dimx = dimPair
209         self.dimOther = dimOther
210         self.valsOther = valsOther
211         self.tests = tests
212     def getName(self, dimy=None, dimx=None, valsOther=None):
213         return "%s-vs-%s-for-%s.html"%(dimx or self.dimy.type,
214                                        dimy or self.dimx.type,
215                                        "-".join([v.value for v in valsOther or self.valsOther]))
216     def generate(self):
217         html = open(self.getName(), "w")
218         title = "CAN gateway timing analysis" 
219         print >> html, """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
220 <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
221 <head>
222 <meta http-equiv="content-type" content="text/html; charset=utf-8" />
223 <title>%s</title>
224 <style>
225 img { border: 0; }
226 table { border-collapse: collapse; }
227 th, td { border: 1px solid lightgray; padding: 4px;}
228 </style>
229 </head>
230 <body>
231 <h1>%s</h1>"""  % (title, title)
232         params = ["%s %s" % (v.dim, v) for v in self.valsOther]
233         print >>html, "Results for:", ", ".join(params), "<hr />"
234         for d in self.dimOther:
235             print >>html, "%s: " % d
236             print >>html, "<a href='%s'>X axis</a>, " % \
237                 self.getName(dimx=d,
238                              valsOther=self.valsOther - d + self.dimx.getValue(0))
239             print >>html, "<a href='%s'>Y axis</a>;&nbsp;&nbsp;" % self.getName(dimy=d)
240             links = []
241             for v in d.values():
242                 if v in self.valsOther:
243                     links.append(str(v))
244                 else:
245                     vv = DimValues(self.valsOther)
246                     vv.replace(v)
247                     links.append("<a href='%s'>%s</a>"%(urllib.quote(self.getName(valsOther=vv)), str(v)))
248             print >>html, " | ".join(links)
249             print >>html, "<br>"
250             try:
251                 print >>html, d.htmlPreamble()
252             except Exception:
253                 pass
254
255         print >>html, "<table><thead><tr><td>%s &rarr; <br />%s &darr;</td>" % (self.dimx.name, self.dimy.name)
256         for x in self.dimx:
257             print >>html, "<th>%s</th>" % x.htmlTableHeading()
258         print >>html, "</tr></thead>"
259         for y in self.dimy:
260             print >>html, "<tr><th>%s</th>" % y.htmlTableHeading()
261
262             for x in self.dimx:
263                 print >>html, "<td>"
264                 idx = [x,y]
265                 idx.extend(self.valsOther)
266                 try:
267                     test = tests.getTest(idx)
268                     test.printThumbLink(html)
269                 except KeyError:
270                     print >>html, "N/A"
271                 print >>html, "</td>"
272             print >>html, "</tr>"
273         print >> html, """
274 </table>
275 <div style="font-size: small; color: gray; margin-top: 1em;">Authors: Michal Sojka, Pavel Píša, Copyright © 2010 Czech Technical University in Prague</div>
276 </body>
277 """
278
279
280 if __name__ == "__main__":
281     os.chdir(sys.argv[1])
282     os.system("rm *.html")
283     tests = Tests("./", DimensionHostKern(), DimensionKern(), DimensionTraffic(), DimensionTest())
284     tests.generateHtml()
285     sys.exit(0)