SHARE
TWEET

Gencon schedule solver

a guest May 12th, 2012 52 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import urllib
  2. import random
  3. import time
  4. import pickle
  5. import zipfile
  6. import itertools
  7. from os import *
  8.  
  9. def mysplitcsv(linetosplit):
  10.  
  11.     #custom line splitting code
  12.     #like line.split(','), except it keeps text surrounded by quotes intact
  13.    
  14.     items = list()
  15.  
  16.     currentitem = ''
  17.  
  18.     currentnest = ''
  19.  
  20.     for c in linetosplit:
  21.         if currentnest != '':
  22.             if c == currentnest:
  23.                 currentnest = ''
  24.             else:
  25.                 currentitem = currentitem + c
  26.         else:
  27.             if c == '"':
  28.                 currentnest = c
  29.             elif c == ',':
  30.                 items.append(currentitem)
  31.                 currentitem = ''
  32.             else:
  33.                 currentitem = currentitem + c
  34.  
  35.     items.append(currentitem)
  36.  
  37.     return items
  38.  
  39. def translate_UTF8(line):
  40.  
  41.     #translate exotic UTF-8 characters - smart quotes and such - to plain ASCII
  42.  
  43.     utfstat = ''
  44.  
  45.     newline = ''
  46.  
  47.     for c in line:
  48.         if c >= '\x80':
  49.             if len(utfstat) < 3:
  50.                 utfstat = utfstat + c
  51.             else:
  52.                 utfstat = utfstat[1] + utfstat[2] + c
  53.             if UTF8translation.has_key(utfstat):
  54.                 newline = newline + UTF8translation[utfstat]
  55.                 utfstat = ''
  56.    
  57.         else:
  58.             newline = newline + c
  59.             utfstat = ''
  60.  
  61.     return newline
  62.  
  63. def process_text_string(line):
  64.  
  65.     #line2 = line.lower()
  66.  
  67.     line2 = ''
  68.     p = ''
  69.  
  70.     for c in line:
  71.         if c.lower() != p.lower() or (c.isupper() and p.isupper()) or c.isdigit():
  72.             p = c
  73.             line2 += p.lower()
  74.  
  75.     line2 = line2.replace('&','and')
  76.  
  77.     for c in ('#,:!?"\'.'):
  78.         line2 = line2.replace(c,'')
  79.  
  80.     line2 = ''.join(line2.split())
  81.  
  82.     line2 = line2.rstrip('s')
  83.  
  84.     return line2
  85.  
  86.     #return 'foo'
  87.  
  88. def mysplit(linetosplit):
  89.  
  90.     #custom line splitting code
  91.     #like line.split(''), except it keeps text surrounded by quotes intact
  92.    
  93.     items = list()
  94.  
  95.     currentitem = ''
  96.  
  97.     currentnest = ''
  98.  
  99.     for c in linetosplit:
  100.         if currentnest != '':
  101.             if c == currentnest:
  102.                 currentnest = ''
  103.             else:
  104.                 currentitem = currentitem + c
  105.         else:
  106.             if c == '"' or c == "'":
  107.                 currentnest = c
  108.             elif len(c.strip()) == 0:
  109.                 if currentitem != '':
  110.                     items.append(currentitem)
  111.                 currentitem = ''
  112.             else:
  113.                 currentitem = currentitem + c
  114.  
  115.     items.append(currentitem)
  116.  
  117.     return items
  118.  
  119. def non_recursively_solve_schedule(event_info):
  120.  
  121.     #event_info
  122.     #list of
  123.         #tuple,
  124.         #first element is priority
  125.         #second element is list of
  126.             #tuple
  127.             #first element is list of
  128.                 #tuple
  129.                     #first element is event ID
  130.                     #second element is start time
  131.                     #third element is end time
  132.                     #fourth element is location
  133.             #second element is total time penalty
  134.  
  135.      
  136.     found_schedules = list()
  137.    
  138.     free_times = []
  139.    
  140.     free_times.append((time.mktime(min(unique_entries[start_index])),
  141.                        time.mktime(max(unique_entries[end_index]  )),
  142.                        None,
  143.                        None
  144.                        ))
  145.  
  146.     found_schedules.append((0.0,[],free_times))
  147.  
  148.     #schedules:
  149.     #list of found schedules so far
  150.     #each of which is
  151.     #(cost,(list of eventID added so far),(free times remaining))
  152.  
  153.     while len(event_info) > 0:
  154.         next_event_to_add = event_info[0]
  155.         remaining_events = event_info[1:]
  156.  
  157.         priority = next_event_to_add[0]
  158.  
  159.         next_schedules = list()
  160.  
  161.         for prior_sched in found_schedules:
  162.             #for each schedule found so far...
  163.  
  164.             score = prior_sched[0]
  165.             schedule = prior_sched[1]
  166.  
  167.             for eventslot in next_event_to_add[1]:
  168.  
  169.                 #print prior_sched,eventslot
  170.  
  171.                 #for each possible slot for this event...
  172.  
  173.                 events_toadd = list()
  174.  
  175.                 remaining_free = list()
  176.  
  177.                 free_times = prior_sched[2]
  178.  
  179.                 free_slot = True
  180.  
  181.                 penalty = eventslot[1] + priority
  182.  
  183.                 for thiseventinfo in eventslot[0]:
  184.  
  185.                     if free_slot != None:
  186.  
  187.                         free_slot = None
  188.  
  189.                         eventID,slot_start,slot_end,location = thiseventinfo
  190.  
  191.                         time_penalty = penalty
  192.  
  193.                         remaining_free = list()
  194.  
  195.                         for timeslot in free_times:
  196.                             if timeslot[0] <= slot_start and timeslot[1] >= slot_end:
  197.                                 free_slot = timeslot
  198.                             else:
  199.                                 remaining_free.append(timeslot)
  200.  
  201.                         if free_slot != None: #found a slot!
  202.  
  203.                             #if float(unique_entries[cost_index][events_byID[eventID][cost_index]]) != 0.0:
  204.                             if True:
  205.                                
  206.                                 start_time_spare = slot_start - free_slot[0]
  207.  
  208.                                 end_time_spare = free_slot[1] - slot_end
  209.  
  210.                                 start_time_location = free_slot[2]
  211.  
  212.                                 end_time_location = free_slot[3]
  213.  
  214.                                 #Penalize events which start or end too close to other events
  215.  
  216.                                 if start_time_spare < 900:
  217.                                     if start_time_location != location:
  218.                                         time_penalty -= 2.0
  219.                                 elif start_time_spare < 1800:
  220.                                     if start_time_location != location:
  221.                                         time_penalty -= 0.5
  222.                                 else:
  223.                                     remaining_free.append((free_slot[0],slot_start,start_time_location,location))
  224.                                        
  225.                                 if end_time_spare < 900:
  226.                                     if end_time_location != location:
  227.                                         time_penalty -= 2.0
  228.                                 elif end_time_spare < 1800:
  229.                                     if end_time_location != location:
  230.                                         time_penalty -= 0.5
  231.                                 else:
  232.                                     remaining_free.append((slot_end,free_slot[1],location,end_time_location))
  233.                             else:
  234.                                 remaining_free.append(free_slot)
  235.  
  236.                             events_toadd.append(eventID)
  237.                        
  238.                         free_times = remaining_free
  239.                
  240.                 if free_slot != None:
  241.                    
  242.                     new_score = score + time_penalty
  243.                     new_schedule = schedule + events_toadd
  244.                            
  245.                     next_schedules.append((new_score,new_schedule,remaining_free))
  246.    
  247.         if next_event_to_add[0] < 10:
  248.             found_schedules += next_schedules
  249.         else:
  250.             found_schedules = next_schedules
  251.         event_info = remaining_events
  252.  
  253.         found_schedules.sort(reverse = True)
  254.  
  255.         found_schedules = found_schedules [:10000]
  256.  
  257.     return found_schedules
  258.  
  259. def solve_schedule(schedule):
  260.  
  261.     schedule.sort(key = lambda s:len(s[1]) * 1000 - s[0])
  262.  
  263.     time_one = time.time()
  264.  
  265.     event_info = list()
  266.    
  267.     for event in schedule:
  268.         priority = event[0]
  269.  
  270.         eventlist = event[1]
  271.  
  272.         events_with_times = list()
  273.  
  274.         for eventID in eventlist:
  275.  
  276.             eventstack = [[eventID]]
  277.  
  278.             if events_following.has_key(eventID):
  279.  
  280.                 eventstack = eventstack + events_following[eventID]
  281.  
  282.             eventstack = map(list,list(itertools.product(*eventstack)))
  283.  
  284.  
  285.             for eventIDlist in eventstack:
  286.  
  287.                 thiseventinfo = list()
  288.  
  289.                 time_penalty = 0.0
  290.  
  291.                 last_end_time = None
  292.  
  293.                 for eventID in eventIDlist:
  294.                     anevent = events_byID[eventID]
  295.  
  296.                     location = anevent[location_index]
  297.  
  298.                     starttime = unique_entries[start_index][anevent[start_index]]
  299.                     endtime = unique_entries[end_index][anevent[end_index]]
  300.  
  301.                     start_hour = int(time.strftime('%H',starttime))
  302.                     end_hour = int(time.strftime('%H',endtime))
  303.                    
  304.                     starttime = int(time.mktime(starttime))
  305.                     endtime = int(time.mktime(endtime))
  306.                    
  307.                     if eventID.startswith('TDA'):
  308.                         starttime = starttime - 900 #True Dungeon events need you to be there 15 minutes early
  309.  
  310.                     if last_end_time != None and last_end_time > starttime:
  311.                         starttime = last_end_time
  312.  
  313.                     last_end_time = endtime
  314.  
  315.                     #Penalize late-night or early-morning events
  316.                            
  317.                     if start_hour > 23:
  318.                         time_penalty -= 2.0
  319.                     if end_hour > 23:
  320.                         time_penalty -= 2.0
  321.                        
  322.                     if start_hour < 20:
  323.                         time_penalty -= 1.0
  324.                     if end_hour > 21:
  325.                         time_penalty -= 1.0
  326.                        
  327.                     if end_hour > 16:
  328.                         time_penalty -= 0.1
  329.                     if end_hour > 17:
  330.                         time_penalty -= 0.1
  331.                        
  332.                     if start_hour < 8:
  333.                         time_penalty -= 0.4
  334.                     if end_hour < 9:
  335.                         time_penalty -= 0.
  336.                        
  337.                     if start_hour < 5:
  338.                         time_penalty -= 2.0
  339.                     if end_hour < 6:
  340.                         time_penalty -= 2.0
  341.  
  342.                     thiseventinfo.append((eventID,starttime,endtime,location))
  343.                
  344.                 events_with_times.append((thiseventinfo,time_penalty))
  345.        
  346.         event_info.append((priority,events_with_times))
  347.  
  348.     free_times = []
  349.    
  350.     free_times.append((int(time.mktime(min(unique_entries[start_index]))),
  351.                        int(time.mktime(max(unique_entries[end_index]  )))))
  352.     found_schedules = non_recursively_solve_schedule(event_info)
  353.    
  354.     time_four = time.time()
  355.  
  356.     found_schedules.sort(reverse = True)
  357.  
  358.     if len(found_schedules) > 0:
  359.         return found_schedules
  360.     else:
  361.         return None
  362.        
  363.        
  364.  
  365. def dosearch(search,eventpool):
  366.  
  367.     #print search
  368.    
  369.     foundevents = list()
  370.    
  371.     keyword = search[0]
  372.  
  373.     word = search[1]
  374.  
  375.     if word == '':
  376.         return eventpool
  377.  
  378.     if keyword in ['any','all']:
  379.         for eventID in eventpool:
  380.             for i in [title_index,desc_index,long_desc_index,type_index,system_index,rules_index,company_index,gm_index]:
  381.                 event = events_byID[eventID]
  382.                 if word in filter(lambda c:c.islower() or c.isdigit() or c in word,unique_entries[i][event[i]].lower()):
  383.                     foundevents.append(eventID)
  384.         if word.upper() in eventpool:
  385.             foundevents.append(word.upper())
  386.  
  387.     elif keyword in ['in','at']:
  388.         for eventID in eventpool:
  389.             for i in [location_index,room_index]:
  390.                 event = events_byID[eventID]
  391.                 if word in filter(lambda c:c.islower() or c.isdigit() or c in word,unique_entries[i][event[i]].lower()):
  392.                     foundevents.append(eventID)
  393.  
  394.     elif keyword in ['by']:
  395.         for eventID in eventpool:
  396.             for i in [company_index,gm_index]:
  397.                 event = events_byID[eventID]
  398.                 if word in filter(lambda c:c.islower() or c.isdigit() or c in word,unique_entries[i][event[i]].lower()):
  399.                     foundevents.append(eventID)
  400.                    
  401.     elif keyword in ['type']:
  402.         for eventID in eventpool:
  403.             for i in [type_index]:
  404.                 event = events_byID[eventID]
  405.                 if unique_entries[i][event[i]].lower().startswith(word.lower()):
  406.                 #if word in filter(lambda c:c.islower() or c.isdigit() or word.startswith(c),unique_entries[i][event[i]].lower()):
  407.                     foundevents.append(eventID)
  408.                    
  409.     elif keyword in ['on']:
  410.         for eventID in eventpool:
  411.             for i in [start_index,end_index]:
  412.                 event = events_byID[eventID]
  413.                 if time.strftime('%A',unique_entries[i][event[i]]).lower().startswith(word):
  414.                     foundevents.append(eventID)
  415.                    
  416.     elif keyword in ['age']:
  417.         for eventID in eventpool:
  418.             for i in [age_index]:
  419.                 event = events_byID[eventID]
  420.                 if word.lower() in unique_entries[i][event[i]].lower():
  421.                     foundevents.append(eventID)
  422.  
  423.     elif keyword in ['before']:
  424.         thetime = None
  425.         try:
  426.             thetime = time.strptime(word,'%H')
  427.         except ValueError:
  428.             try:
  429.                 thetime = time.strptime(word,'%H:%M')
  430.             except ValueError:
  431.                 try:
  432.                     thetime = time.strptime(word,'%I%p')
  433.                 except ValueError:
  434.                     try:
  435.                         thetime = time.strptime(word,'%I:%M%p')
  436.                     except ValueError:
  437.                         if word == 'noon':
  438.                             thetime = time.strptime('12','%H')
  439.         if thetime != None:              
  440.             for eventID in eventpool:
  441.                 event = events_byID[eventID]
  442.                 if time.strptime(time.strftime('%H:%M',unique_entries[end_index][event[end_index]]),'%H:%M') < thetime:
  443.                     if time.strptime(time.strftime('%H:%M',unique_entries[start_index][event[start_index]]),'%H:%M') < thetime:
  444.                         foundevents.append(eventID)
  445.  
  446.     elif keyword in ['after']:
  447.         thetime = None
  448.         try:
  449.             thetime = time.strptime(word,'%H')
  450.         except ValueError:
  451.             try:
  452.                 thetime = time.strptime(word,'%H:%M')
  453.             except ValueError:
  454.                 try:
  455.                     thetime = time.strptime(word,'%I%p')
  456.                 except ValueError:
  457.                     try:
  458.                         thetime = time.strptime(word,'%I:%M%p')
  459.                     except ValueError:
  460.                         if word == 'noon':
  461.                             thetime = time.strptime('12','%H')
  462.         if thetime != None:              
  463.             for eventID in eventpool:
  464.                 event = events_byID[eventID]
  465.                 if time.strptime(time.strftime('%H:%M',unique_entries[end_index][event[end_index]]),'%H:%M') > thetime:
  466.                     if time.strptime(time.strftime('%H:%M',unique_entries[start_index][event[start_index]]),'%H:%M') > thetime:
  467.                         foundevents.append(eventID)
  468.  
  469.     elif keyword in ['not']:
  470.         not_found_events = dosearch(word,eventpool)
  471.  
  472.         foundevents = filter(lambda e:e not in not_found_events,eventpool)
  473.  
  474.  
  475.     foundevents = list(set(foundevents))
  476.  
  477.     foundevents.sort()
  478.  
  479.     return foundevents
  480.  
  481.  
  482. def find_events(wordlist):
  483.  
  484.     searches = list()
  485.  
  486.     search_keywords = ['any','all','on','in','at','by','before','after','type','not','age']
  487.  
  488.     latest_keyword = ''
  489.  
  490.     #first_permitted_start = min(unique_entries[start_index])
  491.     #last_permitted_end = max(unique_entries[end_index])
  492.  
  493.     next_not = False
  494.  
  495.     for word in wordlist:
  496.         if word.lower() in search_keywords:
  497.             if word.lower() == 'not':
  498.                 next_not = True
  499.             else:
  500.                 latest_keyword = word.lower()
  501.         else:
  502.             if latest_keyword == '':
  503.                 if len(searches) > 0:
  504.                     last_search = searches.pop()
  505.                     if last_search[0] in ['any','all']:
  506.                         searches.append((last_search[0],last_search[1] + ' ' + word))
  507.                     else:
  508.                         searches.append(last_search)
  509.                         searches.append(('any',word.lower()))
  510.                         latest_keyword = ''
  511.                 else:
  512.                     searches.append(('any',word.lower()))
  513.                     latest_keyword = ''
  514.             else:
  515.                 if next_not:
  516.                     searches.append(('not',(latest_keyword,word.lower())))
  517.                 else:
  518.                     searches.append((latest_keyword,word.lower()))
  519.                 latest_keyword = ''
  520.                 next_not = False
  521.  
  522.     eventpool = events_canprereg + events_generic
  523.  
  524.     #eventpool.sort(key = lambda eventID:unique_entries[start_index][events_byID[eventID][start_index]])
  525.  
  526.  
  527.     #uncomment this line to filter events with no slots left
  528.  
  529.    # eventpool = filter(lambda e:unique_entries[tickets_available_index][events_byID[e][tickets_available_index]] > 0,eventpool)
  530.  
  531.  
  532.     #eventpool = events_byID.keys()
  533.  
  534.     for search in searches:
  535.         #print search
  536.         eventpool = dosearch(search,eventpool)
  537.    
  538.     #results = list()
  539.    
  540.     event_unique_keys = dict()
  541.  
  542.     #print 'Finding unique keys...'
  543.  
  544.     for eventID in eventpool:
  545.         foo = ' '.join(map(str,map(lambda j:j in ident_indices and
  546.                                    events_byID[eventID][j] or -1,range(number_of_colums))))
  547.        
  548.         #foo = ' '.join(map(str,map(lambda j:events_byID[eventID][j],ident_indices)))
  549.         event_unique_keys[eventID] = foo
  550.     #    print eventID,foo
  551.  
  552.     unique_keys = set(event_unique_keys.values())
  553.  
  554.     events_by_unique_keys = dict()
  555.  
  556.     #eventIDs = events_byID.keys()
  557.  
  558.     for key in unique_keys:
  559.         matching_events = filter(lambda k:event_unique_keys[k] == key,eventpool)
  560.  
  561.         #print matching_events
  562.         newkey = map(lambda j:map(lambda eventID:events_byID[eventID][j],matching_events),range(number_of_colums))
  563.         #print foo
  564.         #print foo
  565.         newkey = map(lambda s:len(s) == 1 and list(s)[0] or -1,map(set,newkey))
  566.         newkey = ' '.join(map(str,newkey))
  567.         #print foo
  568.        
  569.         events_by_unique_keys[newkey] = matching_events
  570.  
  571.     #events_by_unique_keys.sort(key = lambda eventIDlist:unique_entries[start_index][events_byID[eventIDlist[0]][start_index]])
  572.  
  573.     #print len(unique_keys),'unique event keys'
  574.  
  575.     return events_by_unique_keys
  576.  
  577. def fix_location(location):
  578.     location = location.replace(' Bllrm',' Ballroom')
  579.     location = location.replace(' Blrm',' Ballroom')
  580.     location = location.replace('Notra ','Notre ')
  581.     location = location.replace('Penn ','Pennsylvania ')
  582.     location = location.replace(' Stn',' Station')
  583.     location = location.replace(' & ',' and ')
  584.     location = location.replace(' SE',' Southeast')
  585.     location = location.replace(' NE',' Southwest')
  586.     location = location.replace(' SW',' Northeast')
  587.     location = location.replace(' NW',' Northwest')
  588.     location = location.replace(' Cntrl',' Central')
  589.     location = location.replace('Exhibit Hl','Exhibit Hall')
  590.  
  591.     if location.endswith(' I'):
  592.         location = location.replace(' I',' 1')
  593.     elif location.endswith(' II'):
  594.         location = location.replace(' II',' 2')
  595.     elif location.endswith(' III'):
  596.         location = location.replace(' III',' 3')
  597.     elif location.endswith(' IV'):
  598.         location = location.replace(' IV',' 4')
  599.     elif location.endswith(' V'):
  600.         location = location.replace(' V',' 5')
  601.  
  602.     if location == 'Family Fun Pavilion':
  603.         location = 'Exhibit Hall: Family Fun Pavilion'
  604.     return location
  605.  
  606. def get_catalog(url):
  607.     filenames = listdir('.')
  608.  
  609.     mydir = 'Catalogs'
  610.  
  611.     if not mydir in filenames:
  612.         mkdir(mydir)
  613.  
  614.     #filenames = listdir(mydir)
  615.     filenames = []
  616.  
  617.     try:
  618.  
  619.         data = urllib.urlopen(url).read()
  620.  
  621.         #print data
  622.  
  623.         filefindstring = '<div class="FileFileName">'
  624.  
  625.         event_file_locations = list()
  626.  
  627.         while data.find(filefindstring) > -1:
  628.  
  629.             data = data[data.find(filefindstring) + len(filefindstring):]
  630.  
  631.             item = data[data.find('<a href'):data.find('</a>')]
  632.  
  633.             fileloc = item.split('"')[1]
  634.  
  635.             #print fileloc
  636.  
  637.             if 'pmcompletecatalogs' in fileloc:
  638.  
  639.                 event_file_locations.append(fileloc)
  640.  
  641.         #print
  642.  
  643.         print "Checking for new event catalog files..."
  644.  
  645.         found = False
  646.  
  647.         for csvfileloc in event_file_locations:
  648.  
  649.             #print csvfileloc
  650.  
  651.             print 'checking',csvfileloc
  652.            
  653.             url = 'http://community.gencon.com' + csvfileloc
  654.  
  655.             data = urllib.urlopen(url).read()
  656.  
  657.             #print data
  658.  
  659.             data = data[data.find('<div class="CommonContentArea">'):]
  660.  
  661.             #print data
  662.  
  663.             data = data[data.find('<a class="CommonImageTextButton CommonDownloadButton'):]
  664.  
  665.             zipfileloc = data[data.find('href="'):data.find('</a>')]
  666.  
  667.             zipfileloc = zipfileloc.split('"')[1]
  668.  
  669.             #print zipfileloc
  670.  
  671.             while data.find('<td class="FilePropertyName">') > -1:
  672.                 data = data[data.find('<td class="FilePropertyName">'):]
  673.                 propertyname = data[data.find('>')+1:data.find('</td>')]
  674.                 #print propertyname,
  675.                 data = data[data.find('<td class="FileProperty">'):]
  676.                 propertyvalue = data[data.find('>')+1:data.find('</td>')]
  677.                 #print propertyvalue
  678.                 data = data[data.find('</td>'):]
  679.  
  680.             #data =
  681.  
  682.             url = 'http://community.gencon.com' + zipfileloc
  683.  
  684.             thisfilename = zipfileloc.split('/')
  685.             print thisfilename
  686.             thisfilename = thisfilename[len(thisfilename)-2]
  687.  
  688.             #print thisfilename
  689.  
  690.             #print filenames
  691.  
  692.             if not thisfilename + '.zip' in filenames:
  693.  
  694.                 found = True
  695.  
  696.                 print 'Found new event catalog:',thisfilename
  697.                 print 'Downloading it...'
  698.  
  699.                 urllib.urlretrieve(url,mydir + '/' + thisfilename + '.zip')
  700.  
  701.                 print 'Done.  Decompressing and processing now.'
  702.  
  703.                 data = None
  704.                
  705.                 try:
  706.                     zf = zipfile.ZipFile(mydir + '/' + thisfilename + '.zip','r')
  707.  
  708.                     files = zf.namelist()
  709.  
  710.                     data = ''
  711.  
  712.                     for filename in files:
  713.                         if filename.endswith ('.csv') and filename.find('/') == -1 and filename.find('..') == -1:
  714.                             zf.open(filename)
  715.                             data = zf.read(filename)
  716.  
  717.                     zf.close()
  718.                 except:
  719.                     print 'Failed, unable to decompress.'
  720.                     data = None
  721.  
  722.                 if data != None:
  723.                     lines = data.split('\n')
  724.  
  725.                     lines = map(lambda x:x.rstrip('\r'),lines)
  726.  
  727.                     splitlines = map(mysplitcsv,lines)
  728.  
  729.                     column_titles = map(translate_UTF8,splitlines[0])
  730.  
  731.                     ll = len(column_titles)
  732.  
  733.                     proclines = list()
  734.  
  735.                     for line in splitlines[1:]:
  736.                         if len(line) == ll:
  737.                             fixedline = list()
  738.                             for i in range(len(line)):
  739.                                 if 'room' in column_titles[i].lower():
  740.                                     fixedline.append(fix_location(translate_UTF8(line[i])))
  741.                                 else:
  742.                                     fixedline.append(translate_UTF8(line[i]))
  743.                                    
  744.                             proclines.append(fixedline)
  745.                            
  746.                             #proclines.append(map(translate_UTF8,line))
  747.                             #print
  748.                             #print line
  749.                             #print fixedline
  750.  
  751.                     columntypes = list()
  752.  
  753.                     unique_entries_by_category = dict()
  754.                     #entries_as_shown_by_category = dict()
  755.                     unique_to_as_shown_map_by_category = dict()
  756.                     unique_to_as_shown_votes_by_category = dict()
  757.  
  758.                     for i in range(len(column_titles)):
  759.  
  760.                         lowtitle = column_titles[i].lower()
  761.  
  762.                         columntype = 'TEXT'
  763.  
  764.                         unique_contents = list()
  765.  
  766.                         nonefailedbool = True
  767.                         anybool = False
  768.                        
  769.                         nonefailedfloat = True
  770.                         anynumeric = False
  771.  
  772.                         nonefaileddate = True
  773.                         anydate = False
  774.  
  775.                         for line in proclines:
  776.                            
  777.                             item = line[i].lower().strip(' ')
  778.  
  779.                             if nonefailedfloat and item != '':
  780.                                 try:
  781.                                     foo = float(item)
  782.                                     anynumeric = True
  783.                                 except ValueError:
  784.                                     nonefailedfloat = False
  785.  
  786.                             if nonefaileddate and item != '':
  787.                                 try:
  788.                                     foo = time.strptime(item,'%m/%d/%Y %H:%M')
  789.                                     anydate = True
  790.                                 except ValueError:
  791.                                     nonefaileddate = False
  792.  
  793.                             if nonefailedbool and item != '':
  794.                                 if (item == 'no' or item == 'yes' or
  795.                                     item == 'true' or item == 'false'):
  796.                                     anybool = True
  797.                                 else:
  798.                                     nonefailedbool = False
  799.                            
  800.                             if not item in unique_contents:
  801.                                 unique_contents.append(item)
  802.  
  803.                         if nonefailedbool and anybool:
  804.                             columntype = 'BOOL'
  805.  
  806.                         elif nonefailedfloat and anynumeric:
  807.                             columntype = 'FLOAT'
  808.                            
  809.                         elif nonefaileddate and anydate:
  810.                             columntype = 'DATE'
  811.                            
  812.                         elif len(unique_contents) == len(proclines):
  813.                             columntype = 'ID'
  814.                            
  815.                         else:
  816.                             columntype = 'TEXT'
  817.  
  818.                         columntypes.append(columntype)
  819.                         unique_entries_by_category[i] = list()
  820.                         #entries_as_shown_by_category[i] = list()
  821.                         unique_to_as_shown_map_by_category[i] = dict()
  822.                         unique_to_as_shown_votes_by_category[i] = dict()
  823.                            
  824.  
  825.                     events_byID = dict()
  826.  
  827.                     for line in proclines:
  828.  
  829.                         #processed_event = list()
  830.                         #eventID = None
  831.  
  832.                         for i in range(len(column_titles)):
  833.                             shown_item = line[i]
  834.                            
  835.                             if columntypes[i] == 'BOOL':
  836.                                 item = shown_item.lower()
  837.  
  838.                                 if item == 'yes' or item == 'true':
  839.                                     item = True
  840.                                 else:
  841.                                     item = False
  842.                             elif columntypes[i] == 'FLOAT':
  843.                                 if shown_item != '':
  844.                                     item = float(shown_item)
  845.                                 else:
  846.                                     item = 0.0
  847.                             elif columntypes[i] == 'DATE':
  848.                                 if shown_item != '':
  849.                                     item = time.strptime(shown_item,'%m/%d/%Y %H:%M')
  850.                                 else:
  851.                                     item = 0
  852.                             elif columntypes[i] == 'TEXT':
  853.                                 item = process_text_string(shown_item)
  854.  
  855.                             #if i == 4:
  856.                             #    print item[:20]+'... = '+shown_item[:20]+'...'
  857.  
  858.                             if columntypes[i] != 'ID':
  859.                                 if not item in unique_entries_by_category[i]:
  860.                                     unique_entries_by_category[i].append(item)
  861.                                     #if i == 4:
  862.                                     #    print 'item not in unique_entries_by_category[i]'
  863.                                    
  864.                                 if not unique_to_as_shown_map_by_category[i].has_key(item):
  865.                                     unique_to_as_shown_map_by_category[i][item] = list()
  866.                                     unique_to_as_shown_votes_by_category[i][item] = dict()
  867.                                     #if i == 4:
  868.                                     #    print 'not unique_to_as_shown_map_by_category[i].has_key(item)'
  869.  
  870.                                 if not shown_item in unique_to_as_shown_map_by_category[i][item]:
  871.                                     unique_to_as_shown_map_by_category[i][item].append(shown_item)
  872.                                     unique_to_as_shown_votes_by_category[i][item][shown_item] = 1
  873.                                     #if i == 4:
  874.                                     #    print 'not shown_item in unique_to_as_shown_map_by_category[i][item]'
  875.                                 else:
  876.                                     unique_to_as_shown_votes_by_category[i][item][shown_item] += 1
  877.                                     #if i == 4:
  878.                                     #    print 'unique_to_as_shown_votes_by_category[i][item][shown_item] =', unique_to_as_shown_votes_by_category[i][item][shown_item]
  879.  
  880.                     for i in range(len(column_titles)):
  881.                         unique_entries_by_category[i].sort()
  882.  
  883.                         for item in unique_to_as_shown_map_by_category[i].keys():
  884.                             bestscore = 0
  885.                             bestsub = ''
  886.  
  887.                             for shown_item in unique_to_as_shown_map_by_category[i][item]:
  888.                                 if unique_to_as_shown_votes_by_category[i][item][shown_item] > bestscore:
  889.                                     bestsub = shown_item
  890.                                     bestscore = unique_to_as_shown_votes_by_category[i][item][shown_item]
  891.  
  892.                             #if i == 4:
  893.                             #if len(unique_to_as_shown_map_by_category[i][item]) > 1:
  894.                                 #print item
  895.                                 #for shown_item in unique_to_as_shown_map_by_category[i][item]:
  896.                                 #    print '\t',shown_item,unique_to_as_shown_votes_by_category[i][item][shown_item]
  897.                                 #print
  898.                                 #print bestsub
  899.                                 #print
  900.  
  901.                             unique_to_as_shown_map_by_category[i][item] = bestsub
  902.  
  903.                    
  904.                     for line in proclines:
  905.  
  906.                         processed_event = list()
  907.                         eventID = None
  908.  
  909.                         for i in range(len(column_titles)):
  910.                             shown_item = line[i]
  911.                            
  912.                             if columntypes[i] == 'ID':
  913.                                 eventID = shown_item
  914.                             elif columntypes[i] == 'BOOL':
  915.                                 item = shown_item.lower()
  916.  
  917.                                 if item == 'yes' or item == 'true':
  918.                                     item = True
  919.                                 else:
  920.                                     item = False
  921.                             elif columntypes[i] == 'FLOAT':
  922.                                 if shown_item != '':
  923.                                     item = float(shown_item)
  924.                                 else:
  925.                                     item = 0.0
  926.                             elif columntypes[i] == 'DATE':
  927.                                 if shown_item != '':
  928.                                     item = time.strptime(shown_item,'%m/%d/%Y %H:%M')
  929.                                 else:
  930.                                     item = 0
  931.                             elif columntypes[i] == 'TEXT':
  932.                                 item = process_text_string(shown_item)
  933.  
  934.                             if columntypes[i] != 'ID':
  935.  
  936.                                 #if i == 4:
  937.                                 #    print item,unique_entries_by_category[i].index(item)
  938.                                
  939.                                 item = unique_entries_by_category[i].index(item)
  940.  
  941.                                 processed_event.append(item)
  942.  
  943.                         if eventID != None:
  944.                             events_byID[eventID] = processed_event
  945.  
  946.                     unique_entries = list()
  947.  
  948.                     for i in range(len(column_titles)):
  949.                         if columntypes[i] == 'TEXT':
  950.                             mapped_unique = list()
  951.                             for item in unique_entries_by_category[i]:
  952.                                 #if i == 4:
  953.                                 #    print item,unique_to_as_shown_map_by_category[i][item]
  954.                                 mapped_unique.append(unique_to_as_shown_map_by_category[i][item])
  955.                             unique_entries.append(mapped_unique)
  956.                             #unique_entries.append(entries_as_shown_by_category[i])
  957.                         elif columntypes[i] != 'ID':    
  958.                             unique_entries.append(unique_entries_by_category[i])
  959.  
  960.                     column_titles.remove(column_titles[columntypes.index('ID')])
  961.  
  962.                     columntypes.remove('ID')
  963.  
  964.                     print 'Saving to disk...'
  965.  
  966.                     outfile = file(mydir + '/' + thisfilename + '_processed.pcl','w')
  967.  
  968.                     pickle.dump(column_titles,outfile)
  969.                     pickle.dump(columntypes,outfile)
  970.                     pickle.dump(unique_entries,outfile)
  971.                     pickle.dump(events_byID,outfile)
  972.  
  973.                     outfile.close()
  974.  
  975.                     print 'Done.'
  976.                    
  977.                 else:
  978.  
  979.                     print 'Already have',thisfilename
  980.  
  981.         if not found:
  982.             print "None found."
  983.     except IOError:
  984.         print "Unable to connect to Internet."
  985.  
  986. def print_nicely_formatted(text,linelength):
  987.  
  988.     print text
  989.  
  990.     return
  991.  
  992.     i = 0
  993.     line = ''
  994.     for word in text.split():
  995.         if i + 1 + len(word) > linelength:
  996.             if len(line) < linelength:
  997.  
  998.                 increment = float(linelength) / (linelength - len(line) + 1)
  999.  
  1000.                 line_words = line.split()
  1001.  
  1002.                 line = ''
  1003.  
  1004.                 index = increment
  1005.  
  1006.                 for aword in line_words:
  1007.                     if len(line) > 0:
  1008.                         while (len(line) + len(aword) >= int(index)) and (len(line) + len(aword)) < linelength:
  1009.                             line = line + ' '
  1010.                             index = index + increment
  1011.                        
  1012.                     line = line + aword + ' '
  1013.                    
  1014.                     while len(line) >= int(index):
  1015.                         line = line + ' '
  1016.                         index = index + increment
  1017.  
  1018.  
  1019.             print line
  1020.             line = word
  1021.             i = len(word)
  1022.         else:
  1023.             if i > 0:
  1024.                 line = line + ' '
  1025.                 i = i + 1
  1026.             line = line + word
  1027.             i = i + len(word)
  1028.     print line
  1029.  
  1030.  
  1031. UTF8translation = dict()
  1032.  
  1033. UTF8translation['\xe2\x80\x82'] = ' '
  1034. UTF8translation['\xe2\x80\x83'] = ' '
  1035. UTF8translation['\xe2\x80\x89'] = ' '
  1036. UTF8translation['\xe2\x80\x93'] = '-'
  1037. UTF8translation['\xe2\x80\x94'] = '--'
  1038. UTF8translation['\xe2\x80\x98'] = "'"
  1039. UTF8translation['\xe2\x80\x99'] = "'"
  1040. UTF8translation['\xe2\x80\x9A'] = "'"
  1041. UTF8translation['\xe2\x80\x9C'] = '"'
  1042. UTF8translation['\xe2\x80\x9D'] = '"'
  1043. UTF8translation['\xe2\x80\x9E'] = '"'
  1044. UTF8translation['\xe2\x80\xA0'] = '!'
  1045. UTF8translation['\xe2\x80\xA1'] = '!'
  1046. UTF8translation['\xe2\x80\xB0'] = '%o'
  1047. UTF8translation['\xe2\x80\xB9'] = '<'
  1048. UTF8translation['\xe2\x80\xBA'] = '>'
  1049. UTF8translation['\xe2\x80\xAC'] = 'E'
  1050.  
  1051. UTF8translation['\xe2\x80\xA2'] = '*'
  1052. UTF8translation['\xe2\x80\xA6'] = '...'
  1053. UTF8translation['\xe2\x80\xB2'] = "'"
  1054. UTF8translation['\xe2\x80\xB3'] = '"'
  1055. UTF8translation['\xe2\x80\xBE'] = '-'
  1056. UTF8translation['\xe2\x81\x84'] = '/'
  1057.  
  1058. print 'Welcome to Andrew\'s Gencon 2012 Schedule Solver'
  1059. print 'This software is an experimental tool for solving schedules with events'
  1060. print 'with many different slots, where there are large numbers of different combinations'
  1061. print 'possible.  Only designed to work with the specific format of the Gencon 2012 csv'
  1062. print 'files. Use at your own risk.'
  1063. print
  1064.  
  1065. reply = raw_input("Download latest events from website?")
  1066.                    
  1067. if reply.lower().startswith('y'):
  1068.     #Get the calendar from the Gencon community site
  1069.     get_catalog('http://community.gencon.com/files/folders/pmcompletecatalogs/default.aspx')
  1070.  
  1071. print 'Reading from disk...'
  1072.  
  1073. mydir = 'Catalogs'
  1074.  
  1075. filenames = listdir('.')
  1076.  
  1077. if not mydir in filenames:
  1078.     mkdir(mydir)
  1079.  
  1080. filenames = listdir(mydir)
  1081.  
  1082. files = filter(lambda f:f.endswith('.pcl') and not f.endswith('schedule.pcl'),filenames)
  1083.  
  1084. files.sort()
  1085.  
  1086. column_titles = list()
  1087. unique_entries = dict()
  1088. events_byID = dict()
  1089.  
  1090. for fn in files:
  1091.  
  1092.     print 'Loading from',fn
  1093.  
  1094.     infile = file(mydir + '/' + fn,'r')
  1095.  
  1096.     this_column_titles = pickle.load(infile)
  1097.     this_columntypes = pickle.load(infile)
  1098.     this_unique_entries = pickle.load(infile)
  1099.     this_events_byID = pickle.load(infile)
  1100.  
  1101.     infile.close()
  1102.  
  1103.     for i in range(len(this_column_titles)):
  1104.         ctitle = this_column_titles[i]
  1105.         if not ctitle in column_titles:
  1106.             column_titles.append(ctitle)
  1107.         if not unique_entries.has_key(i):
  1108.             unique_entries[i] = list()
  1109.         for entry in this_unique_entries[i]:
  1110.             if not entry in unique_entries[i]:
  1111.                 unique_entries[i].append(entry)
  1112.  
  1113.     for eventID in this_events_byID:
  1114.         processed_event = list()
  1115.         this_file_event = this_events_byID[eventID]
  1116.  
  1117.         for i in range(len(column_titles)):
  1118.             item = this_unique_entries[i][this_file_event[i]]
  1119.             processed_event.append(unique_entries[i].index(item))
  1120.            
  1121.         events_byID[eventID] = processed_event
  1122.  
  1123.    
  1124. if len(events_byID) == 0:
  1125.     print 'No events found.'
  1126.     print 'Unable to do anything without a valid event file!'
  1127.     exit(1)
  1128.  
  1129. print len(events_byID),'total events'
  1130.  
  1131. number_of_colums = len(column_titles)
  1132.  
  1133. is_tournament_index = None
  1134. can_register = None
  1135. round_number_index = None
  1136. total_rounds_index = None
  1137. start_index = None
  1138. end_index = None
  1139. title_index = None
  1140. desc_index = None
  1141. long_desc_index = None
  1142. type_index = None
  1143. system_index = None
  1144. rules_index = None
  1145. company_index = None
  1146. gm_index = None
  1147. email_index = None
  1148. webaddress_index = None
  1149. age_index = None
  1150.  
  1151. location_index = None
  1152. room_index = None
  1153. table_index = None
  1154.  
  1155. modified_index = None
  1156. tickets_available_index = None
  1157. cost_index = None
  1158.  
  1159.  
  1160. for i in range(number_of_colums):
  1161.    
  1162.     if 'room' in column_titles[i].lower():
  1163.         room_index = i
  1164.  
  1165.     if 'modified' in column_titles[i].lower():
  1166.         modified_index = i
  1167.        
  1168.     if 'location' in column_titles[i].lower():
  1169.         location_index = i
  1170.        
  1171.     if 'table' in column_titles[i].lower():
  1172.         table_index = i
  1173.  
  1174.     if 'title' in column_titles[i].lower():
  1175.         title_index = i
  1176.  
  1177.     if 'short desc' in column_titles[i].lower():
  1178.         desc_index = i
  1179.  
  1180.     if 'long desc' in column_titles[i].lower():
  1181.         long_desc_index = i
  1182.  
  1183.     if 'start ' in column_titles[i].lower():
  1184.         start_index = i
  1185.  
  1186.     if 'end ' in column_titles[i].lower():
  1187.         end_index = i
  1188.  
  1189.     if 'round number' in column_titles[i].lower():
  1190.         round_number_index = i
  1191.  
  1192.     if 'total rounds' in column_titles[i].lower():
  1193.         total_rounds_index = i
  1194.  
  1195.     if 'cost' in column_titles[i].lower():
  1196.         cost_index = i
  1197.  
  1198.     if 'tourn' in column_titles[i].lower():
  1199.         is_tournament_index = i
  1200.        
  1201.     if 'regist' in column_titles[i].lower():
  1202.         can_register = i
  1203.  
  1204.     if 'type' in column_titles[i].lower():
  1205.         type_index = i
  1206.        
  1207.     if 'system' in column_titles[i].lower():
  1208.         system_index = i
  1209.        
  1210.     if 'rules' in column_titles[i].lower():
  1211.         rules_index = i
  1212.        
  1213.     if 'edition' in column_titles[i].lower():
  1214.         edition_index = i
  1215.  
  1216.     if 'group' in column_titles[i].lower():
  1217.         company_index = i
  1218.        
  1219.     if 'company' in column_titles[i].lower():
  1220.         company_index = i
  1221.        
  1222.     if 'gm' in column_titles[i].lower():
  1223.         gm_index = i
  1224.        
  1225.     if 'email' in column_titles[i].lower():
  1226.         email_index = i
  1227.        
  1228.     if 'web' in column_titles[i].lower():
  1229.         webaddress_index = i
  1230.        
  1231.     if 'tickets ava' in column_titles[i].lower():
  1232.         tickets_available_index = i
  1233.        
  1234.     if 'age ' in column_titles[i].lower():
  1235.         age_index = i
  1236.        
  1237.  
  1238. print
  1239.  
  1240. print 'Event types found:'
  1241.  
  1242. for i in range(len(unique_entries[type_index])):
  1243.  
  1244.     foo = len(filter(lambda e:events_byID[e][type_index] == i,events_byID.keys()))
  1245.     foo = str(foo)
  1246.  
  1247.     print ' ' * (5 - len(foo)),foo,
  1248.    
  1249.     print unique_entries[type_index][i]
  1250. print
  1251.  
  1252.  
  1253. VIG_events = list()
  1254. tournament_prelim_events = list()
  1255. tournament_final_events = list()
  1256. tournament_generic_events = list()
  1257. nontournament_prelim_events = list()
  1258. nontournament_final_events = list()
  1259. nontournament_generic_events = list()
  1260.  
  1261. for eventID in events_byID.keys():
  1262.     event = events_byID[eventID]
  1263.     event_is_tournament = unique_entries[is_tournament_index][event[is_tournament_index]]
  1264.     event_can_register = unique_entries[can_register][event[can_register]]
  1265.  
  1266.     if 'VIG' in event_can_register:
  1267.         VIG_events.append(eventID)
  1268.     elif event_is_tournament:
  1269.         if event_can_register.lower().startswith('yes'):
  1270.             tournament_prelim_events.append(eventID)
  1271.         elif 'generic' in event_can_register.lower():
  1272.             tournament_generic_events.append(eventID)
  1273.         else:
  1274.             tournament_final_events.append(eventID)
  1275.     else:
  1276.         if event_can_register.lower().startswith('yes'):
  1277.             nontournament_prelim_events.append(eventID)
  1278.         elif 'generic' in event_can_register.lower():
  1279.             nontournament_generic_events.append(eventID)
  1280.         else:
  1281.             nontournament_final_events.append(eventID)
  1282.  
  1283. events_canprereg = tournament_prelim_events + nontournament_prelim_events + nontournament_final_events
  1284. events_generic = tournament_generic_events + nontournament_generic_events
  1285.  
  1286. tournament_eventID = tournament_prelim_events + tournament_final_events + tournament_generic_events
  1287.  
  1288. tournament_eventID.sort()
  1289.  
  1290. events_following = dict()
  1291.  
  1292. for eventID in tournament_eventID:
  1293. #for eventID in events_byID.keys():
  1294.     event = events_byID[eventID]
  1295.  
  1296.     rounds_total = unique_entries[total_rounds_index][event[total_rounds_index]]
  1297.     round_number = unique_entries[round_number_index][event[round_number_index]]
  1298.  
  1299.     event_title = unique_entries[title_index][event[title_index]]
  1300.     event_desc = unique_entries[desc_index][event[desc_index]]
  1301.  
  1302.     if round_number < rounds_total:
  1303.         event_system = event[system_index]
  1304.         event_end = time.mktime(unique_entries[end_index][event[end_index]])
  1305.         event_company = event[company_index]
  1306.        
  1307.         #print unique_entries[system_index][event_system],
  1308.         #print unique_entries[company_index][event_company]
  1309.         #print
  1310.         #print eventID
  1311.         #print event_title
  1312.         #print event_desc
  1313.         #print round_number,
  1314.         #print rounds_total
  1315.         #print time.strftime('%A %I:%M%p',unique_entries[start_index][event[start_index]])
  1316.  
  1317.         proc_title = ''
  1318.         lastdigit = False
  1319.         skip = 0
  1320.         for c in event_desc.lower():
  1321.             if c.isalnum() or c == ':':
  1322.                 proc_title = proc_title + c
  1323.                 if c.isdigit():
  1324.                     lastdigit = True
  1325.                 else:
  1326.                     lastdigit = False
  1327.             elif c == ' ':
  1328.                 if not lastdigit:
  1329.                     proc_title = proc_title + ' '
  1330.             elif c != '.':
  1331.                 proc_title = proc_title + ' '
  1332.                 lastdigit = False
  1333.  
  1334.         proc_title = proc_title.split()
  1335.  
  1336.         alldays = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
  1337.  
  1338.         thisday = []
  1339.         thistime = []
  1340.            
  1341.         for item in proc_title:
  1342.             if item in alldays and item not in thisday:
  1343.                 thisday.append(item)
  1344.             elif item == 'noon' or item == '12noon':
  1345.                 thistime.append('12pm')
  1346.             elif (item.endswith('am') or item.endswith('pm')) and item[0].isdigit():
  1347.                 thistime.append(item)
  1348.                
  1349.         #if len(thisday) = 0:
  1350.         #    thisday = alldays
  1351.         #print thisday,thistime
  1352.  
  1353.         possible_following_events = dict()
  1354.  
  1355.         events_following[eventID] = list()
  1356.  
  1357.         #for aneventID in events_byID.keys():
  1358.         #for aneventID in tournament_prelim_events + tournament_final_events + tournament_generic_events:
  1359.         for aneventID in tournament_final_events + nontournament_final_events:
  1360.  
  1361.             timeok = True
  1362.             anevent = events_byID[aneventID]
  1363.  
  1364.             if len(thisday) != 0:
  1365.                
  1366.                 timeok = False
  1367.                 for item in thisday:
  1368.                     timeok = timeok or item == time.strftime('%A',unique_entries[start_index][anevent[start_index]]).lower()
  1369.  
  1370.             if timeok and len(thistime) != 0:
  1371.                
  1372.                 timeok = False
  1373.                
  1374.                 for item in thistime:
  1375.                     timeok = timeok or item == time.strftime('%I%p',unique_entries[start_index][anevent[start_index]]).lower().lstrip('0')
  1376.                
  1377.                     timeok = timeok or item == time.strftime('%I:%M%p',unique_entries[start_index][anevent[start_index]]).lower().lstrip('0')
  1378.                
  1379.            
  1380.             if (timeok and anevent[system_index] == event_system and
  1381.                 anevent[company_index] == event_company and
  1382.                 time.mktime(unique_entries[start_index][anevent[start_index]]) >= event_end and
  1383.                 #(event_desc != unique_entries[desc_index][anevent[desc_index]] or
  1384.                 # event_title != unique_entries[title_index][anevent[title_index]]) and
  1385.                  unique_entries[round_number_index][anevent[round_number_index]] > round_number and
  1386.                 unique_entries[total_rounds_index][anevent[total_rounds_index]] == rounds_total and
  1387.                 unique_entries[round_number_index][anevent[round_number_index]] >= round_number):
  1388.                 #(unique_entries[total_rounds_index][anevent[total_rounds_index]] != rounds_total or
  1389.                 #unique_entries[round_number_index][anevent[round_number_index]] != round_number)):
  1390.  
  1391.                 rkey = str(int(unique_entries[round_number_index][anevent[round_number_index]]))# + '.' + \
  1392.                 #       str(int(unique_entries[total_rounds_index][anevent[total_rounds_index]]))
  1393.                            
  1394.                 if not possible_following_events.has_key(rkey):
  1395.                     possible_following_events[rkey] = list()
  1396.  
  1397.                 possible_following_events[rkey].append(aneventID)
  1398.  
  1399.                 #possible_following_events[aneventID] = unique_entries[title_index][anevent[title_index]]
  1400.  
  1401.         best_final = dict()
  1402.  
  1403.         akeys = possible_following_events.keys()
  1404.  
  1405.         akeys.sort()
  1406.  
  1407.         for akey in akeys:
  1408.            
  1409.             best_score = 0
  1410.  
  1411.             best_final[akey] = list()
  1412.  
  1413.             for aneventID in possible_following_events[akey]:
  1414.                
  1415.                 title = unique_entries[title_index][events_byID[aneventID][title_index]]
  1416.  
  1417.                 maximum_match = max(map(lambda s:sum(map(lambda x,y:x == y,title,event_title[s:])),range(len(event_title))))
  1418.                 maximum_match = max(maximum_match,
  1419.                                     max(map(lambda s:sum(map(lambda x,y:x == y,title[s:],event_title)),range(len(title)))))
  1420.  
  1421.                 #print '\t',maximum_match,title
  1422.  
  1423.                 if maximum_match > best_score:
  1424.                     best_final[akey] = list()
  1425.                     best_score = maximum_match
  1426.                 if maximum_match == best_score:
  1427.                 #if maximum_match >= 5:
  1428.                     best_final[akey].append(aneventID)
  1429.  
  1430.         #print best_final
  1431.  
  1432.         #best_final_events = list()
  1433.        
  1434.         akeys = best_final.keys()
  1435.  
  1436.         akeys.sort()
  1437.  
  1438.         for akey in akeys:
  1439.            
  1440.             events_following[eventID].append(best_final[akey])
  1441.  
  1442.  
  1443.  
  1444.  
  1445. ident_indices = [title_index,is_tournament_index,can_register,round_number_index,total_rounds_index,
  1446.               desc_index,type_index,system_index,rules_index,company_index]
  1447.  
  1448. time_indices = [start_index,end_index,modified_index]
  1449.  
  1450. line = ''
  1451. command = ''
  1452.  
  1453. foundevents = dict()
  1454.  
  1455. schedule = list()
  1456. #event_priority = list()
  1457.  
  1458. list_start_offset = 0
  1459.  
  1460. solved_events = None
  1461.  
  1462. registered_events = list()
  1463.  
  1464. showevents = list()
  1465.  
  1466. #print unique_entries[can_register]
  1467.  
  1468. while not command == 'quit':
  1469.     line = raw_input(">")
  1470.  
  1471.     linesplit = mysplit(line)
  1472.     #print linesplit
  1473.     command = linesplit[0].lower()
  1474.     arguments = linesplit[1:]
  1475.  
  1476.     startindex = 0
  1477.     endindex = -1
  1478.    
  1479.     if len(arguments) == 1:
  1480.         if '-' in arguments[0]:
  1481.             spl_arguments = arguments[0].split('-')
  1482.             if len(spl_arguments) == 2 and spl_arguments[0].isdigit() and spl_arguments[1].isdigit():
  1483.                 startindex = int(spl_arguments[0])
  1484.                 endindex = int(spl_arguments[1])
  1485.         elif arguments[0] == 'all':
  1486.             startindex = 1
  1487.             endindex = len(foundevents.keys())+1
  1488.         elif arguments[0].isdigit():
  1489.             startindex = int(arguments[0])
  1490.             endindex = startindex
  1491.     elif len(arguments) == 3:
  1492.         if arguments[0].isdigit() and arguments[1].lower() in ['-','to'] and arguments[2].isdigit():
  1493.             startindex = int(arguments[0])
  1494.             endindex = int(arguments[2])
  1495.  
  1496.     if command == 'find':
  1497.         foundevents = find_events(arguments)
  1498.         foundeventkeys = foundevents.keys()
  1499.  
  1500.         #if len(foundeventkeys) > 30:
  1501.         #    showevents = foundeventkeys[:30]
  1502.         if len(foundeventkeys) == 0:
  1503.             print 'No matching events.'
  1504.             showevents = list()
  1505.         else:
  1506.             showevents = foundeventkeys
  1507.             showevents.sort(key = lambda eventID:unique_entries[start_index][events_byID[foundevents[eventID][0]][start_index]])
  1508.  
  1509.         index = 1
  1510.  
  1511.         for eventkey in showevents[:30]:
  1512.             events = foundevents[eventkey]
  1513.             eventkey_int = map(int,eventkey.split())
  1514.             print '#'+str(index)+':',unique_entries[title_index][eventkey_int[title_index]],
  1515.             if len(events) == 1:
  1516.                 print
  1517.             else:
  1518.                 print '('+str(len(events))+' events)'
  1519.             #for eventID in events:
  1520.             #    print '\t',eventID
  1521.             #print
  1522.             index = index + 1
  1523.            
  1524.         if len(foundeventkeys) > 30:
  1525.             print len(foundeventkeys)-30,'more events found, type "more" to see more,'
  1526.         print '"add <number>" to add an event to your schedule, "browse" for detailed info'
  1527.            
  1528.  
  1529.         list_start_offset = 0
  1530.     elif command == 'more':
  1531.         list_start_offset += 30
  1532.         if list_start_offset > len(showevents):
  1533.             print 'No more events to show'
  1534.         else:
  1535.             for eventkey in showevents[list_start_offset:list_start_offset+30]:
  1536.                 events = foundevents[eventkey]
  1537.                 eventkey_int = map(int,eventkey.split())
  1538.                 print '#'+str(index)+':',unique_entries[title_index][eventkey_int[title_index]],
  1539.                 if len(events) == 1:
  1540.                     print
  1541.                 else:
  1542.                     print '('+str(len(events))+' events)'
  1543.                 #for eventID in events:
  1544.                 #    print '\t',eventID
  1545.                 #print
  1546.                 index = index + 1
  1547.            
  1548.         if len(foundeventkeys) > list_start_offset+30:
  1549.             print len(foundeventkeys)-(list_start_offset+30),'more events found, type "more" to see more.'
  1550.         print '"add <number>" to add an event to your schedule, "browse" for detailed info'
  1551.  
  1552.     elif command == 'browse':
  1553.         list_start_offset = 0
  1554.  
  1555.         done = False
  1556.  
  1557.         while not done:
  1558.             if list_start_offset >= len(foundeventkeys):
  1559.                 done = True
  1560.             else:
  1561.                 eventkey = showevents[list_start_offset]
  1562.                 events = foundevents[eventkey]
  1563.                 eventkey_int = map(int,eventkey.split())
  1564.                 print
  1565.                
  1566.                 print_nicely_formatted(unique_entries[title_index][eventkey_int[title_index]],80)
  1567.  
  1568.                 print_nicely_formatted(unique_entries[desc_index][eventkey_int[desc_index]],80)
  1569.  
  1570.                 if eventkey_int[long_desc_index] >= 0:
  1571.                
  1572.                     print_nicely_formatted(unique_entries[long_desc_index][eventkey_int[long_desc_index]],80)
  1573.  
  1574.                 #print unique_entries[desc_index][eventkey_int[desc_index]]
  1575.  
  1576.                 if len(events) == 1:
  1577.                     event_ID = events[0]
  1578.                     print event_ID,
  1579.                     this_event = events_byID[event_ID]
  1580.                     event_start = unique_entries[start_index][this_event[start_index]]
  1581.                     event_end = unique_entries[end_index][this_event[end_index]]
  1582.                     print time.strftime('%A %I:%M%p',event_start),'-',
  1583.                     if time.strftime('%A',event_start) == time.strftime('%A',event_end):
  1584.                         print time.strftime('%I:%M%p',event_end)
  1585.                     else:
  1586.                         print time.strftime('%A %I:%M%p',event_end)
  1587.                
  1588.                 else:
  1589.                     print '('+str(len(events))+' events)'
  1590.  
  1591.                 #print location_index,room_index,table_index
  1592.                 #print eventkey_int[location_index],eventkey_int[room_index],eventkey_int[table_index]
  1593.  
  1594.                 if eventkey_int[location_index] != -1:
  1595.                     print unique_entries[location_index][eventkey_int[location_index]],
  1596.                     if eventkey_int[room_index] != -1:
  1597.                         print unique_entries[room_index][eventkey_int[room_index]],
  1598.                         if eventkey_int[table_index] != -1:
  1599.                             print unique_entries[table_index][eventkey_int[table_index]]
  1600.                    
  1601.                 if eventkey_int[system_index] != -1:
  1602.                     print unique_entries[system_index][eventkey_int[system_index]],
  1603.                     if eventkey_int[rules_index] != -1:
  1604.                         print unique_entries[rules_index][eventkey_int[rules_index]]+',',
  1605.                    
  1606.                 if eventkey_int[company_index] != -1:
  1607.                     print unique_entries[company_index][eventkey_int[company_index]]+',',
  1608.                     if eventkey_int[gm_index] != -1:
  1609.                         print unique_entries[gm_index][eventkey_int[gm_index]],
  1610.                        
  1611.                 print
  1612.                
  1613.                 if eventkey_int[cost_index] != -1:
  1614.                     print 'Event cost:',
  1615.                     print str(unique_entries[cost_index][eventkey_int[cost_index]]) + ',',
  1616.  
  1617.                 tickets_remaining = 0
  1618.  
  1619.                 for event_ID in events:
  1620.                    
  1621.                     this_event = events_byID[event_ID]
  1622.                     tickets_remaining = tickets_remaining + unique_entries[tickets_available_index][this_event[tickets_available_index]]
  1623.                    
  1624.                 print int(tickets_remaining),
  1625.                 print "tickets remaining"
  1626.                
  1627.                 list_start_offset = list_start_offset + 1
  1628.  
  1629.                 already_have = False
  1630.  
  1631.                 for s in schedule:
  1632.                     if len(s[1]) == len(events) and all(map(lambda e:e in s[1],events)):
  1633.                         already_have = True
  1634.  
  1635.                 #schedule = filter(lambda s:eventID not in s[1],schedule)
  1636.  
  1637.                 if already_have:
  1638.                     print 'Already in schedule, moving on...'
  1639.                 else:
  1640.  
  1641.                     reply = raw_input("Add/continue?")
  1642.                    
  1643.                     if reply.lower().startswith('n') or reply.lower().startswith('q'):
  1644.                         done = True
  1645.                     elif reply.lower().startswith('y') or reply.lower().startswith('q'):
  1646.                         priority = raw_input('Priority for '+unique_entries[title_index][eventkey_int[title_index]]+'?')
  1647.  
  1648.                         if priority.isdigit():
  1649.                             priority = int(priority)
  1650.                             if priority < 0:
  1651.                                 priority = 0
  1652.                             elif priority > 10:
  1653.                                 priority = 10
  1654.                             schedule.append((priority,foundevents[eventkey]))
  1655.  
  1656.                             #schedule.append((priority,unique_entries[title_index][eventkey_int[title_index]]))
  1657.                            
  1658.                             #event_priority.append(priority)
  1659.                            
  1660.                         if events_following.has_key(events[0]):
  1661.                             print "Note:",unique_entries[title_index][eventkey_int[title_index]],
  1662.                             print "is start of a tournament, will attempt to link rest of tournament events to it."
  1663.    
  1664.            
  1665.     elif command == 'show':
  1666.         for i in range(startindex - 1,endindex):
  1667.             if i >= 0 and i < len(showevents):
  1668.                 eventkey = map(int,showevents[i].split())
  1669.                 events = foundevents[showevents[i]]
  1670.                 #eventkey = map(int,foundevents.keys()[i].split())
  1671.                 for j in range(len(eventkey)):
  1672.                     if eventkey[j] > -1 and j not in time_indices:
  1673.                         print column_titles[j] + ':',unique_entries[j][eventkey[j]]
  1674.                 for eventID in events:
  1675.                     print '\t',eventID,
  1676.                     print time.strftime('%A %I:%M%p',unique_entries[start_index][events_byID[eventID][start_index]]),'-',
  1677.                     print time.strftime('%A %I:%M%p',unique_entries[end_index][events_byID[eventID][end_index]])
  1678.                 print
  1679.                    
  1680.                     #print eventkey
  1681.     elif command in ['add','got']:
  1682.         if len(arguments)>0 and events_byID.has_key(arguments[0]):
  1683.             eventID = arguments[0]
  1684.             priority = raw_input('Priority for '+eventID+'?')
  1685.  
  1686.             if priority.isdigit():
  1687.  
  1688.                 schedule = filter(lambda s:eventID not in s[1],schedule)                    
  1689.                    
  1690.                 priority = int(priority)
  1691.                 if priority < 0:
  1692.                     priority = 0
  1693.                 elif priority > 10:
  1694.                     priority = 10
  1695.                 schedule.append((priority,[eventID]))
  1696.  
  1697.                 if events_following.has_key(eventID):
  1698.                     print "Note:",eventID,
  1699.                     print " is start of a tournament, will attempt to link rest of tournament events to it."
  1700.         else:            
  1701.             for i in range(startindex - 1,endindex):
  1702.                 if i >= 0 and i < len(foundevents.keys()):
  1703.                     eventkey_int = map(int,showevents[i].split())
  1704.                     priority = raw_input('Priority for '+unique_entries[title_index][eventkey_int[title_index]]+'?')
  1705.  
  1706.                     if priority.isdigit():
  1707.                         priority = int(priority)
  1708.                         if priority < 0:
  1709.                             priority = 0
  1710.                         elif priority > 10:
  1711.                             priority = 10
  1712.                         schedule.append((priority,foundevents[showevents[i]]))
  1713.                        
  1714.                     if events_following.has_key(foundevents[showevents[i]][0]):
  1715.                         print "Note:",unique_entries[title_index][eventkey_int[title_index]],
  1716.                         print "is start of a tournament, will attempt to link rest of tournament events to it."
  1717.                
  1718.     elif command == 'list':
  1719.         index = 1
  1720.  
  1721.         schedule.sort(reverse = True)
  1722.  
  1723.  
  1724.         for index in range(len(schedule)):
  1725.  
  1726.             events = schedule[index][1]
  1727.             print '#'+str(index+1)+':',
  1728.             print unique_entries[title_index][events_byID[events[0]][title_index]],
  1729.             if len(events) > 1:
  1730.                 print '('+str(len(events))+' events)',
  1731.             else:
  1732.                 print events[0],
  1733.             print schedule[index][0]
  1734.                
  1735.  
  1736.                
  1737.     elif command in ['change']:
  1738.                  
  1739.         if startindex <= endindex:
  1740.             changing_events = schedule[startindex - 1:endindex]
  1741.             schedule = schedule[:startindex - 1]+schedule[endindex:]
  1742.  
  1743.             for anevent_info in changing_events:
  1744.            
  1745.                 anevent = events_byID[anevent_info[1][0]]
  1746.                 priority = raw_input('Priority for '+unique_entries[title_index][anevent[title_index]]+'?')
  1747.  
  1748.                 newevent_info = anevent_info
  1749.  
  1750.                 if priority.isdigit():
  1751.                     priority = int(priority)
  1752.                     if priority < 0:
  1753.                         priority = 0
  1754.                     elif priority > 10:
  1755.                         priority = 10
  1756.                     newevent_info = (priority,anevent_info[1])
  1757.  
  1758.                 schedule.append(newevent_info)
  1759.  
  1760.     elif command in ['combine','merge']:
  1761.         if startindex <= endindex:
  1762.            
  1763.             combinedevents = list()
  1764.             priority = schedule[startindex][0]
  1765.  
  1766.             for anevent_info in schedule[startindex - 1:endindex]:
  1767.                 combinedevents = combinedevents + anevent_info[1]
  1768.  
  1769.             schedule = schedule[:startindex - 1]+schedule[endindex:]
  1770.  
  1771.             newevent_info = (priority,combinedevents)
  1772.  
  1773.             schedule.append(newevent_info)
  1774.    
  1775.        
  1776.     elif command in ['del','remove']:
  1777.         if len(arguments)>0 and events_byID.has_key(arguments[0]):
  1778.             eventID = arguments[0]
  1779.             schedule = map(lambda s:(s[0],filter(lambda e:e != eventID,s[1])),schedule)
  1780.             #print schedule
  1781.             schedule = filter(lambda s:len(s[1])>0,schedule)
  1782.                    
  1783.         elif startindex <= endindex:
  1784.             schedule = schedule[:startindex - 1]+schedule[endindex:]
  1785.         #event_priority = event_priority[:startindex - 1]+event_priority[endindex:]
  1786.        
  1787.     elif command == 'solve':
  1788.  
  1789.         registered_events = list()
  1790.  
  1791.         solved_events = None
  1792.            
  1793.         all_solved_events = solve_schedule(schedule)
  1794.  
  1795.         if startindex > endindex:
  1796.  
  1797.             if all_solved_events and len(all_solved_events) > 0:
  1798.                 solved_events = all_solved_events[0][1]
  1799.                    
  1800.             if solved_events != None:
  1801.  
  1802.                 print 'Schedules calculated.'
  1803.  
  1804.                 print
  1805.  
  1806.                 reply = raw_input('Proceed to registration?')
  1807.  
  1808.                 if reply.lower().startswith('y'):
  1809.  
  1810.                     events_remaining = True
  1811.  
  1812.                     while events_remaining and all_solved_events != None:
  1813.                        
  1814.                         print "Calculating wish list..."
  1815.                         print
  1816.  
  1817.                         fail_check_events = list()
  1818.                         #fail_check_list = list()
  1819.                        
  1820.                         #schedules_tocheck = [all_solved_events[0][1]]
  1821.  
  1822.                         fully_solved_schedules = list()
  1823.  
  1824.                         #while len(schedules_tocheck) > 0:
  1825.                         for a_schedule in all_solved_events:
  1826.                             #for a_schedule in schedules_tocheck:
  1827.                             these_fail_check_events = list()
  1828.                                
  1829.                             for eventID in a_schedule[1]:
  1830.                                 if not eventID in fail_check_events+registered_events:
  1831.                                     thisevent = events_byID[eventID]
  1832.                                     if (int(float(unique_entries[cost_index][thisevent[cost_index]])) > 0 and
  1833.                                         not unique_entries[can_register][thisevent[can_register]].lower().startswith('no')):
  1834.                                         these_fail_check_events.append(eventID)
  1835.                                        
  1836.                                 #these_fail_check_events.sort(key = lambda e:
  1837.                                 #                        int(float(unique_entries[tickets_available_index][events_byID[e][tickets_available_index]])))
  1838.  
  1839.                             if len(these_fail_check_events) == 0:
  1840.                                 fully_solved_schedules.append(a_schedule)
  1841.                             else:
  1842.                                 these_fail_check_events.sort(key = lambda e:max(map(lambda s:(e in s[1]) and len(s[1]),schedule)))
  1843.  
  1844.                                 #these_fail_check_events.reverse()
  1845.  
  1846.                                 for eventID in these_fail_check_events:
  1847.                                     #print eventID
  1848.                                     fail_check_events.append(eventID)
  1849.  
  1850.                         fully_solved_schedules.sort(reverse = True)
  1851.  
  1852.                         solved_events = fully_solved_schedules[0][1]
  1853.  
  1854.                         if fully_solved_schedules[0] == all_solved_events[0]:
  1855.                             fail_check_events = list()
  1856.  
  1857.                         if len(registered_events) > 0:
  1858.  
  1859.                             print 'Registered events:'
  1860.  
  1861.                             for eventID in registered_events:
  1862.                                 print eventID+' ('+unique_entries[title_index][events_byID[eventID][title_index]]+')'
  1863.  
  1864.                             print
  1865.  
  1866.                         if len(fail_check_events) > 0:
  1867.  
  1868.                             event_priority = 1
  1869.  
  1870.                             fail_check_events = fail_check_events[:20]
  1871.  
  1872.                             print 'Wish list is as follows:'
  1873.                                        
  1874.                             for eventID in fail_check_events:
  1875.                                 print event_priority,eventID+' ('+unique_entries[title_index][events_byID[eventID][title_index]]+')'
  1876.                                 event_priority = event_priority + 1
  1877.                                 #print unique_entries[can_register][events_byID[eventID][can_register]]
  1878.                                
  1879.                             print 'Enter wish list in registration site now and submit form.'
  1880.  
  1881.                             print
  1882.  
  1883.                             #full_events = list()
  1884.  
  1885.                             for eventID in fail_check_events:
  1886.                                            
  1887.                                 reply = raw_input('Did we get '+eventID+'?')
  1888.                                            
  1889.                                 if reply.lower().startswith('y'):
  1890.                                     registered_events.append(eventID)
  1891.                                     #schedule = filter(lambda s:eventID not in s[1],schedule)
  1892.                                     #schedule.append((10,[eventID]))
  1893.                                 else:
  1894.                                     schedule = map(lambda s:(s[0],filter(lambda e:e != eventID,s[1])),schedule)
  1895.                                     schedule = filter(lambda s:len(s[1]) > 0,schedule)
  1896.                                    
  1897.                             print
  1898.                             print 'Recalculating schedule now...'
  1899.                             print
  1900.                             solved_events = None
  1901.                
  1902.                             all_solved_events = solve_schedule(schedule)
  1903.  
  1904.                             if all_solved_events and len(all_solved_events) > 0:
  1905.                                 solved_events = all_solved_events[0][1]
  1906.  
  1907.                         else:
  1908.                             events_remaining = False
  1909.                                      
  1910.             if solved_events != None:
  1911.  
  1912.                 drop_events = list()
  1913.  
  1914.                 for eventID in registered_events:
  1915.                     if not eventID in solved_events:
  1916.                         drop_events.append(eventID)
  1917.  
  1918.                 if len(drop_events) > 0:
  1919.  
  1920.                     print 'Now remove the following events from your cart:'
  1921.                                            
  1922.                     for eventID in drop_events:
  1923.                         print eventID
  1924.                         registered_events.remove(eventID)
  1925.  
  1926.                     reply = raw_input('(Press Enter when finished)')
  1927.  
  1928.                     print
  1929.                    
  1930.                 solved_events.sort(key = lambda eventID:unique_entries[start_index][events_byID[eventID][start_index]])
  1931.  
  1932.                 last_day = None
  1933.                    
  1934.                 for eventID in solved_events:
  1935.                     if eventID in registered_events:
  1936.                         schedule = filter(lambda s:eventID not in s[1],schedule)
  1937.                         schedule.append((10,[eventID]))
  1938.                    
  1939.                     thisevent = events_byID[eventID]
  1940.                     start_time = unique_entries[start_index][thisevent[start_index]]
  1941.                     end_time = unique_entries[end_index][thisevent[end_index]]
  1942.                     if last_day != time.strftime('%A',start_time):
  1943.                         print
  1944.                         print time.strftime('%A %d %B %Y',start_time)
  1945.                         print
  1946.                     last_day = time.strftime('%A',start_time)
  1947.                    
  1948.                     print_nicely_formatted(eventID + ': ' + unique_entries[title_index][thisevent[title_index]],80)
  1949.                    
  1950.                     whenst = time.strftime('%A %I:%M%p',start_time) + '-'
  1951.                            
  1952.                     if time.strftime('%A',end_time) != last_day:
  1953.                         whenst = whenst + time.strftime('%A %I:%M%p',end_time)
  1954.                     else:
  1955.                         whenst = whenst + time.strftime('%I:%M%p',end_time)
  1956.  
  1957.                     wherest = ' '.join([unique_entries[location_index][thisevent[location_index]],
  1958.                                         unique_entries[room_index][thisevent[room_index]],
  1959.                                         unique_entries[table_index][thisevent[table_index]]])
  1960.  
  1961.                     print_nicely_formatted(whenst + ', ' + wherest,80)
  1962.  
  1963.                     event_desc = unique_entries[desc_index][thisevent[desc_index]]
  1964.  
  1965.                     print_nicely_formatted(event_desc,80)
  1966.                    
  1967.                     whost = ''
  1968.                     #print whost
  1969.  
  1970.                     if len(unique_entries[gm_index][thisevent[gm_index]]) > 0:
  1971.                         whost = whost + unique_entries[gm_index][thisevent[gm_index]] + ', '
  1972.                     #print whost,unique_entries[company_index][thisevent[company_index]]
  1973.                     whost = whost + unique_entries[company_index][thisevent[company_index]]
  1974.                     whost = ' '.join(map(lambda s:s.capitalize(),whost.split()))
  1975.                     if unique_entries[cost_index][thisevent[cost_index]] > 0:
  1976.                         whost = whost + ' $'+str(unique_entries[cost_index][thisevent[cost_index]])
  1977.                    
  1978.                     print_nicely_formatted(whost,80)
  1979.                    
  1980.                     #print unique_entries[webaddress_index][thisevent[webaddress_index]],
  1981.                     #print unique_entries[email_index][thisevent[email_index]]
  1982.                                
  1983.                     #print 'Tickets available:',
  1984.                     #print unique_entries[tickets_available_index][thisevent[tickets_available_index]],
  1985.                     #print 'Event cost:',
  1986.                     #print unique_entries[cost_index][thisevent[cost_index]]
  1987.                            
  1988.                     print
  1989.                            
  1990.                     #if events_following.has_key(eventID):
  1991.                     #    print events_following[eventID]
  1992.                 print
  1993.             else:
  1994.                 print "Unable to solve schedule - incompatible mandatory events!  Remove some or reduce priority below 10."
  1995.         else:
  1996.  
  1997.             if all_solved_events and len(all_solved_events) > 0:
  1998.            
  1999.                 print 'Schedules calculated.'
  2000.  
  2001.                 print
  2002.  
  2003.                 for solved_event_info in all_solved_events[startindex - 1:endindex]:
  2004.                     solved_events = solved_event_info[1]
  2005.  
  2006.                     solved_events.sort(key = lambda eventID:unique_entries[start_index][events_byID[eventID][start_index]])
  2007.  
  2008.                     print 'Score:',solved_event_info[0]
  2009.  
  2010.                     for eventID in solved_events:
  2011.                         if eventID in registered_events:
  2012.                             schedule = filter(lambda s:eventID not in s[1],schedule)
  2013.                             schedule.append((10,[eventID]))
  2014.                        
  2015.                         thisevent = events_byID[eventID]
  2016.                         start_time = unique_entries[start_index][thisevent[start_index]]
  2017.                         end_time = unique_entries[end_index][thisevent[end_index]]
  2018.                        
  2019.                         whenst = time.strftime('%A %I:%M%p',start_time) + '-'
  2020.                                
  2021.                         whenst = whenst + time.strftime('%A %I:%M%p',end_time)
  2022.  
  2023.                         wherest = ' '.join([unique_entries[location_index][thisevent[location_index]],
  2024.                                             unique_entries[room_index][thisevent[room_index]],
  2025.                                             unique_entries[table_index][thisevent[table_index]]])
  2026.  
  2027.                         if len(unique_entries[title_index][thisevent[title_index]]) > 25:
  2028.  
  2029.                             print_nicely_formatted(whenst + ' ' + eventID + ': ' + unique_entries[title_index][thisevent[title_index]][:22] + '..., ' + wherest,80)
  2030.                         else:
  2031.                             print_nicely_formatted(whenst + ' ' + eventID + ': ' + unique_entries[title_index][thisevent[title_index]] + ', ' + wherest,80)
  2032.                            
  2033.                        
  2034.                     print                    
  2035.                
  2036.             else:
  2037.                 print "Unable to solve schedule - incompatible mandatory events!  Remove some or reduce priority below 10."
  2038.  
  2039.  
  2040.     elif command == 'save':
  2041.         if len(arguments) > 0:
  2042.                    
  2043.             print 'Saving to disk...'
  2044.  
  2045.             outfile = file(mydir + '/' + arguments[0] + '_schedule.pcl','w')
  2046.  
  2047.             pickle.dump(schedule,outfile)
  2048.  
  2049.             outfile.close()
  2050.         else:
  2051.             print "Not saved, file name needed"
  2052.  
  2053.     elif command == 'load':
  2054.         if len(arguments) > 0:
  2055.                
  2056.             print 'Loading from disk...'
  2057.            
  2058.  
  2059.             try:
  2060.                 infile = file(mydir + '/' + arguments[0] + '_schedule.pcl','r')
  2061.  
  2062.                 schedule = pickle.load(infile)
  2063.  
  2064.                 infile.close()
  2065.  
  2066.                 schedule = map(lambda s:(s[0],filter(lambda e:events_byID.has_key(e),s[1])),schedule)
  2067.  
  2068.                 schedule = filter(lambda s:len(s[1])>0,schedule)
  2069.  
  2070.             except IOError:
  2071.  
  2072.                 print arguments[0] + '_schedule.pcl not found.'
  2073.  
  2074.                 schedule = list()
  2075.  
  2076.                
  2077.        
  2078.         else:
  2079.             print "Not loaded, file name needed"
  2080.                
  2081.     elif command == '?' or command == 'help':
  2082.         if len(arguments) == 0:
  2083.             print "Commands:"
  2084.             print
  2085.             print "quit - exits this program"
  2086.             print "find <keywords> - searches the list of events for matches"
  2087.             print "more - lists next 30 found events"
  2088.             print "browse - views list of found events in detail one by one"
  2089.             print "show # - shows full details on one event"
  2090.             print "add # - adds an event from found event list to wishlist"
  2091.             print "list - shows your current wishlist"
  2092.             print "change # - changes the priority of an item on your wishlist"
  2093.             print "merge # - combines two items on wishlist into single item"
  2094.             print "del # - removes an item from your wishlist"
  2095.             print "solve - solves for best schedules, optionally proceeds to registration"
  2096.             print "save <filename> - saves current wishlist to a file"
  2097.             print "load <filename> - loads current wishlist from a file"
  2098.             print "help <command> - more detailed information on that command"
  2099.             print
  2100.             print "Commands are not case-sensitive"
  2101.         elif arguments[0] == 'find':
  2102.             print 'save <keywords>'
  2103.             print
  2104.             print 'This searches the list of events according to keywords'
  2105.             print 'Accepted keywords are any, all, on, in, at, by, before, after, type, not, age'
  2106.             print
  2107.             print 'Keyword functions:'
  2108.             print
  2109.             print 'Any, All - followed by a word this searches for all events which contain that word in their'
  2110.             print 'title or description.  For example, "Find all NASCRAG".  You can also omit the keyword for'
  2111.             print 'this case and just type "Find NASCRAG"/'
  2112.             print
  2113.             print 'on - searches for events by day'
  2114.             print '   for example, "find on saturday"'
  2115.             print
  2116.             print 'in - searches for events by location'
  2117.             print '   for example, "find in hyatt"'
  2118.             print
  2119.             print 'by - searches for events by company or group'
  2120.             print '   for example, "find by gamebase7"'
  2121.             print
  2122.             print 'before - searches for events which take place before a certain time'
  2123.             print '   for example, "find before 10pm"'
  2124.             print
  2125.             print 'after - searches for events which take place after a certain time'
  2126.             print '   for example, "find after 10am"'
  2127.             print
  2128.             print 'type - searches by the prefix/type code of the event'
  2129.             print '   for example, "find type RPGA"'
  2130.             print
  2131.             print 'not - inverts action of following keywords'
  2132.             print '   for example, "find not on sunday"'
  2133.             print
  2134.             print 'age - searches by event age restriction'
  2135.             print '   for example, "find age 21+"'
  2136.             print
  2137.             print 'Multiple keyword searches can be combines into a single search line'
  2138.             print '   for example, "find sparks by gamebase7 after 1pm not on thursday"'
  2139.             print
  2140.             print 'This command will return a numbered list of all events matching the search terms'
  2141.             print 'and will display the first 30 matches'
  2142.         elif arguments[0] == 'more':
  2143.             print 'more'
  2144.             print
  2145.             print 'The command Find will only show the first 30 event matches'
  2146.             print 'Typing "more" will then show the next 30 matches'
  2147.         elif arguments[0] == 'browse':
  2148.             print 'browse'
  2149.             print
  2150.             print 'After running the find command to generate a list of matches, the browse command'
  2151.             print 'will show each matching event one by one in detail, and for each one give the option to add'
  2152.             print 'that event to your wish list'
  2153.             print
  2154.             print 'When you add an item to your wish list, you will be asked for a priority number, which'
  2155.             print 'should be a number from 1-10.  A priority of 10 indicates a must-have event - the script'
  2156.             print 'will reject any calendar which does not include that event.  Lower priority events will'
  2157.             print 'be added as possible in order of their priority number'
  2158.         elif arguments[0] == 'show':
  2159.             print 'show #'
  2160.             print
  2161.             print 'After running the find command to generate a list of matches, the show command will'
  2162.             print 'give you all the details of an item on the list.'
  2163.         elif arguments[0] == 'add':
  2164.             print 'show #'
  2165.             print
  2166.             print 'After running the find command to generate a list of matches, the add command will'
  2167.             print 'allow you to add a single entry from the list to your wishlist.'
  2168.             print
  2169.             print 'When you add an item to your wish list, you will be asked for a priority number, which'
  2170.             print 'should be a number from 1-10.  A priority of 10 indicates a must-have event - the script'
  2171.             print 'will reject any calendar which does not include that event.  Lower priority events will'
  2172.             print 'be added as possible in order of their priority number'
  2173.         elif arguments[0] == 'list':
  2174.             print 'list'
  2175.             print
  2176.             print 'This command shows your wishlist so far, giving you an index list of event name,'
  2177.             print 'event number or number of event slots, and priority'
  2178.         elif arguments[0] == 'change':
  2179.             print 'change #'
  2180.             print
  2181.             print 'After running the list command, this command allows you to change the priority of'
  2182.             print 'any entry on the wishlist.'
  2183.         elif arguments[0] == 'merge':
  2184.             print 'merge #'
  2185.             print
  2186.             print 'This is a semi-experimental command which allows you to combine two items on your wishlist'
  2187.             print 'This is used primarily for merging two items which are the same event but weren\'t properly'
  2188.             print 'combined by the catelog parses.  To use this, add both the events you want to combine to'
  2189.             print 'your wishlist, giving them both the same priority so they will show up as adjacent items.'
  2190.             print 'Then use the merge command to join them, for example merge 4-5 if they are items 4 and 5.'
  2191.             print 'This can also be used when you have a situation where you want to go to either event A or'
  2192.             print 'event B but not both, by merging them into a single event with multiple slots.'
  2193.         elif arguments[0] == 'del':
  2194.             print 'del #'
  2195.             print
  2196.             print 'After running the list command, this command allows you to remove any one item from your'
  2197.             print 'wishlist.'
  2198.         elif arguments[0] == 'solve':
  2199.             print 'solve'
  2200.             print
  2201.             print 'This command attempts to derive an optimal schedule from your wishlist. This command takes'
  2202.             print 'into account all of the events you have selected, and the priority which you have assigned'
  2203.             print 'to each one.  It then builds a list of all possible schedule combinations and then ranks'
  2204.             print 'them by desirability.   When doing so it attempts to get in as many events as possible, but'
  2205.             print 'also prefers events in the afternoon or evening over those very late or early, and when'
  2206.             print 'possible tries to give you at least 15 minutes between events.'
  2207.             print
  2208.             print 'After the schedules are produced, you will be given the option to proceed to registration.'
  2209.             print 'The script does not fill out the Gencon registration page for you, you have to do that'
  2210.             print 'manually.'
  2211.             print 'However, it will give you a list of event IDs to enter.  Do not be alarmed if you see'
  2212.             print 'muliple conflicting events in the event ID list - the script takes a greedy approach where'
  2213.             print 'it has you register for all event slots you might want, then depending on which ones you get'
  2214.             print 'has you drop some of them later.  Just follow the instructions the script prints out, and'
  2215.             print 'follow the prompts to tell the script which slots you actually managed to get.  When that is'
  2216.             print 'done, the script will generate a finished schedule for you to copy and print out.'
  2217.             print
  2218.             print 'The script does not instruct you to register for free events that do not requie pre-reg,'
  2219.             print 'such as seminars.  You should probably register for them anyway afterwards.'
  2220.             print
  2221.             print 'The script attempts to take tournament structure into account.  If you register for the'
  2222.             print 'first part of a tournament, it will attempt to find the other parts of the tournament and'
  2223.             print 'add them to your schedule.  This doesn\'t always work.'
  2224.             print
  2225.             print 'If you answer no to the prompt to proceed to registration, the script will then just print'
  2226.             print 'out your optimal schedule - the one you\'ll have if you manage to get every event you try to'
  2227.             print 'register for.'
  2228.            
  2229.         elif arguments[0] == 'save':
  2230.             print 'save <filename>'
  2231.             print
  2232.             print 'This command immedately saves the current wishlist to a file indicated by the filename'
  2233.             print 'This overwrites any existing file of that name without warning.'
  2234.         elif arguments[0] == 'load':
  2235.             print 'save <filename>'
  2236.             print
  2237.             print 'This command immedately loads the wishlist from a file indicated by the filename'
  2238.             print 'This overwrites the curent wishlist without warning.'
  2239.         else:
  2240.             print 'No help available for',arguments[0]
  2241.        
  2242.        
  2243.     elif command == 'quit' or command == '':
  2244.         pass
  2245.     else:
  2246.         print 'Unrecognized command:',command
RAW Paste Data
Top