1"""Shared routines for the plotters."""
2
3import fileinput
4import collections
5
6Record = collections.namedtuple('Record', 'variant function bytes loops src_alignment dst_alignment run_id elapsed rest')
7
8
9def make_colours():
10    return iter('m b g r c y k pink orange brown grey'.split())
11
12def parse_value(v):
13    """Turn text into a primitive"""
14    try:
15        if '.' in v:
16            return float(v)
17        else:
18            return int(v)
19    except ValueError:
20        return v
21
22def create_column_tuple(record, names):
23    cols = [getattr(record, name) for name in names]
24    return tuple(cols)
25
26def unique(records, name, prefer=''):
27    """Return the unique values of a column in the records"""
28    if type(name) == tuple:
29        values = list(set(create_column_tuple(x, name) for x in records))
30    else:
31        values = list(set(getattr(x, name) for x in records))
32
33    if not values:
34        return values
35    elif type(values[0]) == str:
36        return sorted(values, key=lambda x: '%-06d|%s' % (-prefer.find(x), x))
37    else:
38        return sorted(values)
39
40def alignments_equal(alignments):
41    for alignment in alignments:
42        if alignment[0] != alignment[1]:
43            return False
44    return True
45
46def parse_row(line):
47    return Record(*[parse_value(y) for y in line.split(':')])
48
49def parse():
50    """Parse a record file into named tuples, correcting for loop
51    overhead along the way.
52    """
53    records = [parse_row(x) for x in fileinput.input()]
54
55    # Pull out any bounce values
56    costs = {}
57
58    for record in [x for x in records if x.function=='bounce']:
59        costs[(record.bytes, record.loops)] = record.elapsed
60
61    # Fix up all of the records for cost
62    out = []
63
64    for record in records:
65        if record.function == 'bounce':
66            continue
67
68        cost = costs.get((record.bytes, record.loops), None)
69
70        if not cost:
71            out.append(record)
72        else:
73            # Unfortunately you can't update a namedtuple...
74            values = list(record)
75            values[-2] -= cost
76            out.append(Record(*values))
77
78    return out
79