#!/usr/bin/env python def median(x): return sorted(x)[len(x)/2] def quartiles(x): s=sorted(x) return max(x),x[len(x)*3/4],median(x),x[len(x)/4],min(x) def parse_line(s): sp=s.split('\t') def parse_event(index): x=sp[index].split()[0] try: d=int(x) #Events that haven't started yet are showing 0 pts. if d>0: return d return None except: return None #print len(sp),sp return { 'rank':sp[0], 'total_points':int(sp[1]), 'team':sp[2], 'event1':parse_event(3), 'event2':parse_event(4) } def main(): lines=file('nw_standings2.txt').read().splitlines() m=map(parse_line,lines[:]) #for a in m: # print a scores=filter(lambda x: x,map(lambda x: x['event1'],m)+map(lambda x: x['event2'],m)) #for a in sorted(scores): print a #print 'Individual event score range:',quartiles(scores)#max(scores),median(scores),min(scores) max_pts_per_event=80#this is an assumption def max_pts(team_info): def get(name): if team_info[name] is None: return max_pts_per_event return team_info[name] return get('event1')+get('event2') l=list(reversed(sorted(map(max_pts,m)))) min_cutoff_for_dcmp=m[63]['total_points'] print 'Best-case points to make it to district cmp:',min_cutoff_for_dcmp max_cutoff_for_dcmp=l[63] print 'Worst-case points to make it to district cmp:',max_cutoff_for_dcmp average_points_per_event=22 #approx def expected_pts(team_info): def get(name): if team_info[name] is None: if team_info['event1'] is None: return average_points_per_event return team_info['event1'] return team_info[name] return get('event1')+get('event2') l=list(reversed(sorted(map(expected_pts,m)))) cutoff_best_est=l[63] print 'Best estimate:',cutoff_best_est #3 events left, #12*32*2 qualifi def points_per_event(): quals=2*3*70 elims=7*10*3 awards=60 return quals+elims+awards #for a in sorted(l): print a #points_left=3*points_per_event() #print points_left #print points_left/32 score_pairs=[] for x in m: if x['event1'] is None: continue if x['event2'] is None: continue score_pairs.append((x['event1'],x['event2'])) score_pairs.append((x['event2'],x['event1'])) def worst_of_at_least_as_good(score): #find all the teams that have one event that's at least that good and give back the worst performance that any of them have had #print 'score=',score return min(map(lambda x: x[1],filter(lambda x: x[0]>=score,score_pairs))) def best_of_this_or_worse(score): #the best performance that a team has had that's gotten a the score or better has gotten return max(map(lambda x: x[1],filter(lambda x: x[0]<=score,score_pairs))) def max_likely_points(team_info): if team_info['event2'] is not None: return team_info['total_points'] if team_info['event1'] is None: return average_points_per_event*2 return team_info['event1']+best_of_this_or_worse(team_info['event1']) def min_likely_points(team_info): if team_info['event2'] is not None: return team_info['total_points'] x=team_info['event1'] if x is None: return average_points_per_event*2 return team_info['event1']+worst_of_at_least_as_good(team_info['event1']) def status(team_info): if max_pts(team_info)max_cutoff_for_dcmp: return 'in' if max_likely_points(team_info)cutoff_best_est: return '~in' return 'bubble' def count(a): m={} for elem in a: if not m.has_key(elem): m[elem]=0 m[elem]+=1 return m st=map(status,m) print count(st) for i,team in enumerate(m): print '%s\t'%i,'%s\t'%status(team),team['team'] if __name__=='__main__': main()