Fixes a number of issues with the results display:
- clicking on the intersection of a job+test takes you to the results for that specific test
- use different colours to indicate the percentage of failures
- when looking at multiple results for the same test, display job_id/name on one axis and test_name on the other, instead of job_id on one axis and job_name on the other

From: Vladimir Samarskiy <[email protected]>
Signed-off-by: John Admanski <[email protected]>



git-svn-id: http://test.kernel.org/svn/autotest/trunk@1249 592f7852-d20e-0410-864c-8624ca9c26a4
diff --git a/tko/display.py b/tko/display.py
index f29da92..ecdc09e 100755
--- a/tko/display.py
+++ b/tko/display.py
@@ -1,13 +1,6 @@
 import os, re, parse, sys, frontend
 
 color_map = {
-	'GOOD'		: '#88ff88', # green
-	'WARN'		: '#fffc00', # yellow
-	'ALERT'		: '#fffc00', # yellow
-	'FAIL'		: '#ff8888', # red
-	'ABORT'		: '#ff8888', # red
-	'ERROR'		: '#ff8888', # red
-	'NOSTATUS'	: '#ffffff', # white
 	'header'        : '#e5e5c0', # greyish yellow
 	'blank'         : '#ffffff', # white
 	'plain_text'    : '#e5e5c0', # greyish yellow
@@ -16,15 +9,66 @@
 	'green'		: '#66ff66', # green
 	'yellow'	: '#fffc00', # yellow
 	'red'		: '#ff6666', # red
+
+	#### additional keys for shaded color of a box 
+	#### depending on stats of GOOD/FAIL
+	'100pct'  : '#00ff00', # green, 94% to 100% of success
+	'94pct'   : '#a0ff00', # step twrds yellow, 88% to 94% of success
+	'88pct'   : '#ffff00', # yellow, 82% to 88%
+	'82pct'   : '#ffa000', # 76% to 82%
+	'76pct'   : '#ff0000', # red, 1% to 76%
+	'0pct'    : '#d000d0', # violet, <1% of success	
+
 }
 
 
+def color_keys_row():
+	""" Returns one row table with samples of 'NNpct' colors
+		defined in the color_map
+		and numbers of corresponding %%
+	"""
+	### This function does not require maintenance in case of	
+	### color_map augmenting - as long as 
+	### color keys for box shading have names that end with 'pct'
+	keys = filter(lambda key: key.endswith('pct'), color_map.keys())
+	def num_pct(key):
+		return int(key.replace('pct',''))
+	keys.sort(key=num_pct)
+	html = ''
+	for key in keys:
+		html+= "\t\t\t<td bgcolor =%s>&nbsp;&nbsp;&nbsp;</td>\n"\
+				% color_map[key]
+		hint = key.replace('pct',' %')
+		if hint[0]<>'0': ## anything but 0 %
+			hint = 'to ' + hint
+		html+= "\t\t\t<td> %s </td>\n" % hint
+
+	html = """
+<table width = "500" border="0" cellpadding="2" cellspacing="2">\n
+	<tbody>\n
+		<tr>\n
+%s
+		</tr>\n
+	</tbody>
+</table><br>
+""" % html
+	return html
+
+
 class box:
-	def __init__(self, data, color_key = None, header = False, link = None):
-		if link:
+	def __init__(self, data, color_key = None, header = False, link = None,
+		     tooltip = None ):
+		if link and tooltip:
+			self.data = '<a href="%s" title="%s">%s</a>' \
+						% (link, tooltip, data)
+		elif tooltip:
+			self.data = '<a href="%s" title="%s">%s</a>' \
+						% ('#', tooltip, data)			
+		elif link:
 			self.data = '<a href="%s">%s</a>' % (link, data)
 		else:
 			self.data = data
+
 		if color_map.has_key(color_key):
 			self.color = color_map[color_key]
 		elif header:
@@ -51,22 +95,76 @@
 					(box_html, self.color, data, box_html)
 
 
-def status_html(db, status_count):
+def grade_from_status(status):
+	# % of goodness
+	# GOOD (6)  -> 1
+	# WARN(5), NOSTATUS(1) -> 0.5
+	# else -> 0
+	# ??? ALERT(7)
+
+	if status == 6:
+		return 1.0
+	if status in [1,5]:
+		return 0.5
+	if status in [2,3,4]:
+		return 0.0
+
+
+def average_grade_from_status_count(status_count):
+	average_grade = 0
+	total_count = 0
+	for key in status_count.keys():
+		average_grade += grade_from_status(key)*status_count[key]
+		total_count += status_count[key]
+	average_grade = average_grade / total_count
+	return average_grade
+
+
+def shade_from_status_count(status_count):
+	if not status_count:
+		return None
+	
+	## average_grade defines a shade of the box
+	## 0 -> violet
+	## 0.76 -> red
+	## 0.88-> yellow
+	## 1.0 -> green	
+	average_grade = average_grade_from_status_count(status_count)
+	
+	## find appropiate keyword from color_map
+	if average_grade<0.01:
+		shade = '0pct'
+	elif average_grade<0.76:
+		shade = '76pct'
+	elif average_grade<0.82:
+		shade = '82pct'
+	elif average_grade<0.88:
+		shade = '88pct'
+	elif average_grade<0.94:
+		shade = '94pct'
+	else:
+		shade = '100pct'
+		
+	return shade
+
+
+def status_html(db, status_count, shade):
 	"""
 	status_count: dict mapping from status (integer key) to count
 	eg. { 'GOOD' : 4, 'FAIL' : 1 }
 	"""
-#	total = sum(status_count.values())
-#	status_pct = {}
-#	for status in status_count.keys():
-#		status_pct[status] = (100 * status_count[status]) / total
-	rows = []
+	if 6 in status_count.keys():
+		html = "%d / %d " \
+			%(status_count[6],sum(status_count.values()))
+	else:
+		html = "%d / %d " % \
+			(0, sum(status_count.values()))
+	tooltip = ""
+
 	for status in sorted(status_count.keys(), reverse = True):
 		status_word = db.status_word[status]
-		# string = "%d&nbsp(%d%%)" % (status_count[status], status_pct[status])
-		string = "%d&nbsp;%s" % (status_count[status], status_word)
-		rows.append("<tr>%s</tr>" % box(string, status_word).html())
-	return '<table>%s</table>' % '\n'.join(rows)
+		tooltip += "%d %s " % (status_count[status], status_word)
+	return (html,tooltip)
 
 
 def status_count_box(db, tests, link = None):
@@ -91,15 +189,14 @@
 	Display a table within a box, representing the status count of
 	the group of tests (e.g. 10 GOOD, 2 WARN, 3 FAIL)
 	"""
+		
 	if not status_count:
 		return box(None, None)
-
-	worst = sorted(status_count.keys())[0]
-	html = status_html(db, status_count)
-	if link:
-		html = '<a href="%s">%s</a>' % (link, html)
-	return box(html, db.status_word[worst])
-
+	
+	shade = shade_from_status_count(status_count)	
+	html,tooltip = status_html(db, status_count, shade)
+	precounted_box = box(html, shade, False, link, tooltip)
+	return precounted_box
 
 def print_table(matrix):
 	"""