#!/usr/bin/python3
'''Report the datastructures from best performers to worst for a given area of comparison'''
import re
#mport sys
import glob
#mport pprint
import functools
#mport collections
def return_javascript_code():
'''
Output the required javascript for drilling down to greater levels of detail.
Derived from http://www.gnostice.com/nl_article.asp?id=208&t=Interactive_Tree_Control_Using_An_HTML_List_and_JavaScript
'''
# BTW, this dislikes it when you close your
's with 's
# This xml tag makes chrome and perhaps others have problems
#
string = '''
Python Dictionary Results Table
'''
return string
def get_last_line(file_):
'''Get the last line of file_'''
last = None
for line in file_:
last = line
return last
@functools.total_ordering
class Number_Pattern_Key(object):
'''Store a number pattern key'''
# pylint: disable=too-few-public-methods
def __init__(self, number_pattern):
self.number_pattern = number_pattern
def __hash__(self):
return hash(self.number_pattern)
def __str__(self):
return self.number_pattern
__repr__ = __str__
def cmp(self, other):
'''Compare two number pattern keys'''
if self.number_pattern < other.number_pattern:
return -1
elif self.number_pattern > other.number_pattern:
return 1
else:
return 0
def __lt__(self, other):
if self.cmp(other) == -1:
return True
else:
return False
def __eq__(self, other):
if self.cmp(other) == 0:
return True
else:
return False
@functools.total_ordering
class Size_Key(object):
'''Store a size key'''
# pylint: disable=too-few-public-methods
def __init__(self, size):
self.size = size
def __hash__(self):
return hash(self.size)
def __str__(self):
return str(self.size)
__repr__ = __str__
def cmp(self, other):
'''Compare two size keys in order'''
if self.size < other.size:
return -1
elif self.size > other.size:
return 1
else:
return 0
def __lt__(self, other):
if self.cmp(other) == -1:
return True
else:
return False
def __eq__(self, other):
if self.cmp(other) == 0:
return True
else:
return False
@functools.total_ordering
class Interpreter_Key(object):
'''A class to hold an interpreter key'''
# pylint: disable=too-few-public-methods
def __init__(self, interpreter):
self.interpreter = interpreter
def __hash__(self):
return hash(self.interpreter)
def __str__(self):
return str(self.interpreter)
__repr__ = __str__
def cmp(self, other):
'''Compare two interpreter names'''
if self.interpreter < other.interpreter:
return -1
elif self.interpreter > other.interpreter:
return 1
else:
return 0
def __lt__(self, other):
if self.cmp(other) == -1:
return True
else:
return False
def __eq__(self, other):
if self.cmp(other) == 0:
return True
else:
return False
@functools.total_ordering
class Tree_Type_Key(object):
'''Store a tree type key'''
# pylint: disable=too-few-public-methods
def __init__(self, tree_type):
self.tree_type = tree_type
def __hash__(self):
return hash(self.tree_type)
def __str__(self):
return str(self.tree_type)
__repr__ = __str__
def cmp(self, other):
'''Compare two Tree_Type_keys'''
if self.tree_type < other.tree_type:
return -1
elif self.tree_type > other.tree_type:
return 1
else:
return 0
def __lt__(self, other):
if self.cmp(other) == -1:
return True
else:
return False
def __eq__(self, other):
if self.cmp(other) == 0:
return True
else:
return False
@functools.total_ordering
class Performer(object):
'''Class for holding a description of a top performing datastructure'''
# pylint: disable=too-few-public-methods,too-many-return-statements
def __init__(self, size, tree_type, duration, standard_deviation):
self.size = int(size.size)
self.tree_type = tree_type
self.duration = float(duration)
self.standard_deviation = float(standard_deviation)
def cmp(self, other):
'''Compare two Top_Performer's'''
# Compare size in reverse
if self.size < other.size:
return 1
elif self.size > other.size:
return -1
else:
# Compare duration forward
if self.duration < other.duration:
return -1
elif self.duration > other.duration:
return 1
#else:
# if self.tree_type < other.tree_type:
# return -1
# elif self.tree_type > other.tree_type:
# return 1
# else:
# return 0
else:
return 0
def __lt__(self, other):
if self.cmp(other) == -1:
return True
else:
return False
def __eq__(self, other):
if self.cmp(other) == 0:
return True
else:
return False
def gen_performers(dict_):
'''Generate the top performers'''
for size_key in dict_:
tree_type_dict = dict_[size_key]
for tree_type_key in tree_type_dict:
mean = tree_type_dict[tree_type_key][0]
standard_deviation = tree_type_dict[tree_type_key][1]
yield Performer(size_key, tree_type_key, mean, standard_deviation)
def main():
# pylint: disable=too-many-locals
'''Main function'''
dict_ = {}
for filename in glob.glob('*.dat'):
fixed_red_black = filename.replace('red-black', 'red_black')
fields = fixed_red_black.split('-')
interpreter = '-'.join(fields[:2])
number_pattern = fields[2]
# tree_type = re.sub(r'\.dat$', '', '-'.join(fields[5:7]))
tree_type = re.sub(r'\.dat$', '', fields[3])
with open(filename, 'r') as file_:
last_line = get_last_line(file_)
size, duration, standard_deviation = last_line.split()
size = int(size)
duration = round(float(duration), 1)
standard_deviation = round(float(standard_deviation), 3)
number_pattern_key = Number_Pattern_Key(number_pattern)
size_key = Size_Key(size)
interpreter_key = Interpreter_Key(interpreter)
tree_type_key = Tree_Type_Key(tree_type)
if number_pattern_key not in dict_:
dict_[number_pattern_key] = {}
if interpreter_key not in dict_[number_pattern_key]:
dict_[number_pattern_key][interpreter_key] = {}
if size_key not in dict_[number_pattern_key][interpreter_key]:
dict_[number_pattern_key][interpreter_key][size_key] = {}
if tree_type_key not in dict_[number_pattern_key][interpreter_key][size_key]:
dict_[number_pattern_key][interpreter_key][size_key][tree_type_key] = (duration, standard_deviation)
num_top_performers = 20
print(return_javascript_code())
print('')
for number_pattern in sorted(dict_):
print('- {}'.format(number_pattern))
print('\t
')
for interpreter_key in sorted(dict_[number_pattern]):
print('\t- {}'.format(interpreter_key))
print('\t\t
')
performers_it = gen_performers(dict_[number_pattern][interpreter_key])
performers = list(performers_it)
performers.sort()
for performer in performers[:num_top_performers]:
# print('1:', type(performer.size))
# print('2:', type(performer.duration))
# print('3:', type(performer.tree_type))
string = '\t\t\t- Ops: {:>7}, duration: {:>5} +/- {}, ops/sec: {:>11.2f}, dictionary type: {}'.format(
performer.size,
performer.duration,
performer.standard_deviation,
float(str(performer.size)) / float(str(performer.duration)),
performer.tree_type,
)
print(string.replace(' ', ' '))
print('\t\t
')
print('\t
')
print('
')
print('')
print('')
main()