# Independent recount of asr-acd-sample-cdr.csv using only the rules stated on the page (not the tool's code).
import csv, collections
rows = list(csv.reader(open('asr-acd-sample-cdr.csv', newline='')))
hdr, data = rows[0], rows[1:]; ix = {h: i for i, h in enumerate(hdr)}
legs, rejected = [], []
for n, r in enumerate(data, start=2):
    if len(r) < len(hdr): rejected.append((n, 'too few columns')); continue
    try: dur, bill = int(r[ix['duration']]), int(r[ix['billsec']])
    except ValueError: rejected.append((n, 'duration or billsec not a number')); continue
    legs.append(dict(time=r[ix['calldate']], disp=r[ix['disposition']], dur=dur, bill=bill,
                     trunk=r[ix['dstchannel']].rsplit('-', 1)[0], linkedid=r[ix['linkedid']]))
rank = {'ANSWERED': 4, 'BUSY': 3, 'NO ANSWER': 2, 'FAILED': 1}
by = collections.OrderedDict()
for l in legs: by.setdefault(l['linkedid'], []).append(l)
calls = []
for ls in by.values():
    best = max(ls, key=lambda l: (rank[l['disp']], l['bill']))   # answered if any leg answered
    c = dict(best); c['time'] = ls[0]['time']; calls.append(c)  # call time = first leg
def summary(cs):
    a = [c for c in cs if c['disp'] == 'ANSWERED']; n = len(cs)
    k = collections.Counter(c['disp'] for c in cs)
    bill = sum(c['bill'] for c in a)
    return dict(calls=n, answered=len(a), busy=k['BUSY'], no_answer=k['NO ANSWER'], failed=k['FAILED'],
                asr=round(100 * len(a) / n, 1), ner=round(100 * (len(a) + k['BUSY'] + k['NO ANSWER']) / n, 1),
                billed_s=bill, acd_s=round(bill / len(a), 1) if a else None,
                short_lt6=sum(1 for c in a if 0 < c['bill'] < 6), zero_s=sum(1 for c in a if c['bill'] == 0),
                time_to_answer_avg_s=round(sum(c['dur'] - c['bill'] for c in a) / len(a), 1) if a else None)
print('rows', len(data), 'legs', len(legs), 'rejected', rejected)
print('TOTAL', summary(calls))
for key, f in (('trunk', lambda c: c['trunk']), ('hour', lambda c: c['time'][11:13] + ':00')):
    g = collections.OrderedDict()
    for c in calls: g.setdefault(f(c), []).append(c)
    for k, cs in g.items(): print(key, k, summary(cs))
ungrouped = [dict(l) for l in legs]; print('UNGROUPED', summary(ungrouped))
