'):]
#print data
data = data[data.find('
')]
zipfileloc = zipfileloc.split('"')[1]
#print zipfileloc
while data.find('') > -1:
data = data[data.find(' | '):]
propertyname = data[data.find('>')+1:data.find(' | ')]
#print propertyname,
data = data[data.find('
'):]
propertyvalue = data[data.find('>')+1:data.find(' | ')]
#print propertyvalue
data = data[data.find(''):]
#data =
url = 'http://community.gencon.com' + zipfileloc
thisfilename = zipfileloc.split('/')
print thisfilename
thisfilename = thisfilename[len(thisfilename)-2]
#print thisfilename
#print filenames
if not thisfilename + '.zip' in filenames:
found = True
print 'Found new event catalog:',thisfilename
print 'Downloading it...'
urllib.urlretrieve(url,mydir + '/' + thisfilename + '.zip')
print 'Done. Decompressing and processing now.'
data = None
try:
zf = zipfile.ZipFile(mydir + '/' + thisfilename + '.zip','r')
files = zf.namelist()
data = ''
for filename in files:
if filename.endswith ('.csv') and filename.find('/') == -1 and filename.find('..') == -1:
zf.open(filename)
data = zf.read(filename)
zf.close()
except:
print 'Failed, unable to decompress.'
data = None
if data != None:
lines = data.split('\n')
lines = map(lambda x:x.rstrip('\r'),lines)
splitlines = map(mysplitcsv,lines)
column_titles = map(translate_UTF8,splitlines[0])
ll = len(column_titles)
proclines = list()
for line in splitlines[1:]:
if len(line) == ll:
fixedline = list()
for i in range(len(line)):
if 'room' in column_titles[i].lower():
fixedline.append(fix_location(translate_UTF8(line[i])))
else:
fixedline.append(translate_UTF8(line[i]))
proclines.append(fixedline)
#proclines.append(map(translate_UTF8,line))
#print
#print line
#print fixedline
columntypes = list()
unique_entries_by_category = dict()
#entries_as_shown_by_category = dict()
unique_to_as_shown_map_by_category = dict()
unique_to_as_shown_votes_by_category = dict()
for i in range(len(column_titles)):
lowtitle = column_titles[i].lower()
columntype = 'TEXT'
unique_contents = list()
nonefailedbool = True
anybool = False
nonefailedfloat = True
anynumeric = False
nonefaileddate = True
anydate = False
for line in proclines:
item = line[i].lower().strip(' ')
if nonefailedfloat and item != '':
try:
foo = float(item)
anynumeric = True
except ValueError:
nonefailedfloat = False
if nonefaileddate and item != '':
try:
foo = time.strptime(item,'%m/%d/%Y %H:%M')
anydate = True
except ValueError:
nonefaileddate = False
if nonefailedbool and item != '':
if (item == 'no' or item == 'yes' or
item == 'true' or item == 'false'):
anybool = True
else:
nonefailedbool = False
if not item in unique_contents:
unique_contents.append(item)
if nonefailedbool and anybool:
columntype = 'BOOL'
elif nonefailedfloat and anynumeric:
columntype = 'FLOAT'
elif nonefaileddate and anydate:
columntype = 'DATE'
elif len(unique_contents) == len(proclines):
columntype = 'ID'
else:
columntype = 'TEXT'
columntypes.append(columntype)
unique_entries_by_category[i] = list()
#entries_as_shown_by_category[i] = list()
unique_to_as_shown_map_by_category[i] = dict()
unique_to_as_shown_votes_by_category[i] = dict()
events_byID = dict()
for line in proclines:
#processed_event = list()
#eventID = None
for i in range(len(column_titles)):
shown_item = line[i]
if columntypes[i] == 'BOOL':
item = shown_item.lower()
if item == 'yes' or item == 'true':
item = True
else:
item = False
elif columntypes[i] == 'FLOAT':
if shown_item != '':
item = float(shown_item)
else:
item = 0.0
elif columntypes[i] == 'DATE':
if shown_item != '':
item = time.strptime(shown_item,'%m/%d/%Y %H:%M')
else:
item = 0
elif columntypes[i] == 'TEXT':
item = process_text_string(shown_item)
#if i == 4:
# print item[:20]+'... = '+shown_item[:20]+'...'
if columntypes[i] != 'ID':
if not item in unique_entries_by_category[i]:
unique_entries_by_category[i].append(item)
#if i == 4:
# print 'item not in unique_entries_by_category[i]'
if not unique_to_as_shown_map_by_category[i].has_key(item):
unique_to_as_shown_map_by_category[i][item] = list()
unique_to_as_shown_votes_by_category[i][item] = dict()
#if i == 4:
# print 'not unique_to_as_shown_map_by_category[i].has_key(item)'
if not shown_item in unique_to_as_shown_map_by_category[i][item]:
unique_to_as_shown_map_by_category[i][item].append(shown_item)
unique_to_as_shown_votes_by_category[i][item][shown_item] = 1
#if i == 4:
# print 'not shown_item in unique_to_as_shown_map_by_category[i][item]'
else:
unique_to_as_shown_votes_by_category[i][item][shown_item] += 1
#if i == 4:
# print 'unique_to_as_shown_votes_by_category[i][item][shown_item] =', unique_to_as_shown_votes_by_category[i][item][shown_item]
for i in range(len(column_titles)):
unique_entries_by_category[i].sort()
for item in unique_to_as_shown_map_by_category[i].keys():
bestscore = 0
bestsub = ''
for shown_item in unique_to_as_shown_map_by_category[i][item]:
if unique_to_as_shown_votes_by_category[i][item][shown_item] > bestscore:
bestsub = shown_item
bestscore = unique_to_as_shown_votes_by_category[i][item][shown_item]
#if i == 4:
#if len(unique_to_as_shown_map_by_category[i][item]) > 1:
#print item
#for shown_item in unique_to_as_shown_map_by_category[i][item]:
# print '\t',shown_item,unique_to_as_shown_votes_by_category[i][item][shown_item]
#print
#print bestsub
#print
unique_to_as_shown_map_by_category[i][item] = bestsub
for line in proclines:
processed_event = list()
eventID = None
for i in range(len(column_titles)):
shown_item = line[i]
if columntypes[i] == 'ID':
eventID = shown_item
elif columntypes[i] == 'BOOL':
item = shown_item.lower()
if item == 'yes' or item == 'true':
item = True
else:
item = False
elif columntypes[i] == 'FLOAT':
if shown_item != '':
item = float(shown_item)
else:
item = 0.0
elif columntypes[i] == 'DATE':
if shown_item != '':
item = time.strptime(shown_item,'%m/%d/%Y %H:%M')
else:
item = 0
elif columntypes[i] == 'TEXT':
item = process_text_string(shown_item)
if columntypes[i] != 'ID':
#if i == 4:
# print item,unique_entries_by_category[i].index(item)
item = unique_entries_by_category[i].index(item)
processed_event.append(item)
if eventID != None:
events_byID[eventID] = processed_event
unique_entries = list()
for i in range(len(column_titles)):
if columntypes[i] == 'TEXT':
mapped_unique = list()
for item in unique_entries_by_category[i]:
#if i == 4:
# print item,unique_to_as_shown_map_by_category[i][item]
mapped_unique.append(unique_to_as_shown_map_by_category[i][item])
unique_entries.append(mapped_unique)
#unique_entries.append(entries_as_shown_by_category[i])
elif columntypes[i] != 'ID':
unique_entries.append(unique_entries_by_category[i])
column_titles.remove(column_titles[columntypes.index('ID')])
columntypes.remove('ID')
print 'Saving to disk...'
outfile = file(mydir + '/' + thisfilename + '_processed.pcl','w')
pickle.dump(column_titles,outfile)
pickle.dump(columntypes,outfile)
pickle.dump(unique_entries,outfile)
pickle.dump(events_byID,outfile)
outfile.close()
print 'Done.'
else:
print 'Already have',thisfilename
if not found:
print "None found."
except IOError:
print "Unable to connect to Internet."
def print_nicely_formatted(text,linelength):
print text
return
i = 0
line = ''
for word in text.split():
if i + 1 + len(word) > linelength:
if len(line) < linelength:
increment = float(linelength) / (linelength - len(line) + 1)
line_words = line.split()
line = ''
index = increment
for aword in line_words:
if len(line) > 0:
while (len(line) + len(aword) >= int(index)) and (len(line) + len(aword)) < linelength:
line = line + ' '
index = index + increment
line = line + aword + ' '
while len(line) >= int(index):
line = line + ' '
index = index + increment
print line
line = word
i = len(word)
else:
if i > 0:
line = line + ' '
i = i + 1
line = line + word
i = i + len(word)
print line
UTF8translation = dict()
UTF8translation['\xe2\x80\x82'] = ' '
UTF8translation['\xe2\x80\x83'] = ' '
UTF8translation['\xe2\x80\x89'] = ' '
UTF8translation['\xe2\x80\x93'] = '-'
UTF8translation['\xe2\x80\x94'] = '--'
UTF8translation['\xe2\x80\x98'] = "'"
UTF8translation['\xe2\x80\x99'] = "'"
UTF8translation['\xe2\x80\x9A'] = "'"
UTF8translation['\xe2\x80\x9C'] = '"'
UTF8translation['\xe2\x80\x9D'] = '"'
UTF8translation['\xe2\x80\x9E'] = '"'
UTF8translation['\xe2\x80\xA0'] = '!'
UTF8translation['\xe2\x80\xA1'] = '!'
UTF8translation['\xe2\x80\xB0'] = '%o'
UTF8translation['\xe2\x80\xB9'] = '<'
UTF8translation['\xe2\x80\xBA'] = '>'
UTF8translation['\xe2\x80\xAC'] = 'E'
UTF8translation['\xe2\x80\xA2'] = '*'
UTF8translation['\xe2\x80\xA6'] = '...'
UTF8translation['\xe2\x80\xB2'] = "'"
UTF8translation['\xe2\x80\xB3'] = '"'
UTF8translation['\xe2\x80\xBE'] = '-'
UTF8translation['\xe2\x81\x84'] = '/'
print 'Welcome to Andrew\'s Gencon 2012 Schedule Solver'
print 'This software is an experimental tool for solving schedules with events'
print 'with many different slots, where there are large numbers of different combinations'
print 'possible. Only designed to work with the specific format of the Gencon 2012 csv'
print 'files. Use at your own risk.'
print
reply = raw_input("Download latest events from website?")
if reply.lower().startswith('y'):
#Get the calendar from the Gencon community site
get_catalog('http://community.gencon.com/files/folders/pmcompletecatalogs/default.aspx')
print 'Reading from disk...'
mydir = 'Catalogs'
filenames = listdir('.')
if not mydir in filenames:
mkdir(mydir)
filenames = listdir(mydir)
files = filter(lambda f:f.endswith('.pcl') and not f.endswith('schedule.pcl'),filenames)
files.sort()
column_titles = list()
unique_entries = dict()
events_byID = dict()
for fn in files:
print 'Loading from',fn
infile = file(mydir + '/' + fn,'r')
this_column_titles = pickle.load(infile)
this_columntypes = pickle.load(infile)
this_unique_entries = pickle.load(infile)
this_events_byID = pickle.load(infile)
infile.close()
for i in range(len(this_column_titles)):
ctitle = this_column_titles[i]
if not ctitle in column_titles:
column_titles.append(ctitle)
if not unique_entries.has_key(i):
unique_entries[i] = list()
for entry in this_unique_entries[i]:
if not entry in unique_entries[i]:
unique_entries[i].append(entry)
for eventID in this_events_byID:
processed_event = list()
this_file_event = this_events_byID[eventID]
for i in range(len(column_titles)):
item = this_unique_entries[i][this_file_event[i]]
processed_event.append(unique_entries[i].index(item))
events_byID[eventID] = processed_event
if len(events_byID) == 0:
print 'No events found.'
print 'Unable to do anything without a valid event file!'
exit(1)
print len(events_byID),'total events'
number_of_colums = len(column_titles)
is_tournament_index = None
can_register = None
round_number_index = None
total_rounds_index = None
start_index = None
end_index = None
title_index = None
desc_index = None
long_desc_index = None
type_index = None
system_index = None
rules_index = None
company_index = None
gm_index = None
email_index = None
webaddress_index = None
age_index = None
location_index = None
room_index = None
table_index = None
modified_index = None
tickets_available_index = None
cost_index = None
for i in range(number_of_colums):
if 'room' in column_titles[i].lower():
room_index = i
if 'modified' in column_titles[i].lower():
modified_index = i
if 'location' in column_titles[i].lower():
location_index = i
if 'table' in column_titles[i].lower():
table_index = i
if 'title' in column_titles[i].lower():
title_index = i
if 'short desc' in column_titles[i].lower():
desc_index = i
if 'long desc' in column_titles[i].lower():
long_desc_index = i
if 'start ' in column_titles[i].lower():
start_index = i
if 'end ' in column_titles[i].lower():
end_index = i
if 'round number' in column_titles[i].lower():
round_number_index = i
if 'total rounds' in column_titles[i].lower():
total_rounds_index = i
if 'cost' in column_titles[i].lower():
cost_index = i
if 'tourn' in column_titles[i].lower():
is_tournament_index = i
if 'regist' in column_titles[i].lower():
can_register = i
if 'type' in column_titles[i].lower():
type_index = i
if 'system' in column_titles[i].lower():
system_index = i
if 'rules' in column_titles[i].lower():
rules_index = i
if 'edition' in column_titles[i].lower():
edition_index = i
if 'group' in column_titles[i].lower():
company_index = i
if 'company' in column_titles[i].lower():
company_index = i
if 'gm' in column_titles[i].lower():
gm_index = i
if 'email' in column_titles[i].lower():
email_index = i
if 'web' in column_titles[i].lower():
webaddress_index = i
if 'tickets ava' in column_titles[i].lower():
tickets_available_index = i
if 'age ' in column_titles[i].lower():
age_index = i
print
print 'Event types found:'
for i in range(len(unique_entries[type_index])):
foo = len(filter(lambda e:events_byID[e][type_index] == i,events_byID.keys()))
foo = str(foo)
print ' ' * (5 - len(foo)),foo,
print unique_entries[type_index][i]
print
VIG_events = list()
tournament_prelim_events = list()
tournament_final_events = list()
tournament_generic_events = list()
nontournament_prelim_events = list()
nontournament_final_events = list()
nontournament_generic_events = list()
for eventID in events_byID.keys():
event = events_byID[eventID]
event_is_tournament = unique_entries[is_tournament_index][event[is_tournament_index]]
event_can_register = unique_entries[can_register][event[can_register]]
if 'VIG' in event_can_register:
VIG_events.append(eventID)
elif event_is_tournament:
if event_can_register.lower().startswith('yes'):
tournament_prelim_events.append(eventID)
elif 'generic' in event_can_register.lower():
tournament_generic_events.append(eventID)
else:
tournament_final_events.append(eventID)
else:
if event_can_register.lower().startswith('yes'):
nontournament_prelim_events.append(eventID)
elif 'generic' in event_can_register.lower():
nontournament_generic_events.append(eventID)
else:
nontournament_final_events.append(eventID)
events_canprereg = tournament_prelim_events + nontournament_prelim_events + nontournament_final_events
events_generic = tournament_generic_events + nontournament_generic_events
tournament_eventID = tournament_prelim_events + tournament_final_events + tournament_generic_events
tournament_eventID.sort()
events_following = dict()
for eventID in tournament_eventID:
#for eventID in events_byID.keys():
event = events_byID[eventID]
rounds_total = unique_entries[total_rounds_index][event[total_rounds_index]]
round_number = unique_entries[round_number_index][event[round_number_index]]
event_title = unique_entries[title_index][event[title_index]]
event_desc = unique_entries[desc_index][event[desc_index]]
if round_number < rounds_total:
event_system = event[system_index]
event_end = time.mktime(unique_entries[end_index][event[end_index]])
event_company = event[company_index]
#print unique_entries[system_index][event_system],
#print unique_entries[company_index][event_company]
#print
#print eventID
#print event_title
#print event_desc
#print round_number,
#print rounds_total
#print time.strftime('%A %I:%M%p',unique_entries[start_index][event[start_index]])
proc_title = ''
lastdigit = False
skip = 0
for c in event_desc.lower():
if c.isalnum() or c == ':':
proc_title = proc_title + c
if c.isdigit():
lastdigit = True
else:
lastdigit = False
elif c == ' ':
if not lastdigit:
proc_title = proc_title + ' '
elif c != '.':
proc_title = proc_title + ' '
lastdigit = False
proc_title = proc_title.split()
alldays = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday']
thisday = []
thistime = []
for item in proc_title:
if item in alldays and item not in thisday:
thisday.append(item)
elif item == 'noon' or item == '12noon':
thistime.append('12pm')
elif (item.endswith('am') or item.endswith('pm')) and item[0].isdigit():
thistime.append(item)
#if len(thisday) = 0:
# thisday = alldays
#print thisday,thistime
possible_following_events = dict()
events_following[eventID] = list()
#for aneventID in events_byID.keys():
#for aneventID in tournament_prelim_events + tournament_final_events + tournament_generic_events:
for aneventID in tournament_final_events + nontournament_final_events:
timeok = True
anevent = events_byID[aneventID]
if len(thisday) != 0:
timeok = False
for item in thisday:
timeok = timeok or item == time.strftime('%A',unique_entries[start_index][anevent[start_index]]).lower()
if timeok and len(thistime) != 0:
timeok = False
for item in thistime:
timeok = timeok or item == time.strftime('%I%p',unique_entries[start_index][anevent[start_index]]).lower().lstrip('0')
timeok = timeok or item == time.strftime('%I:%M%p',unique_entries[start_index][anevent[start_index]]).lower().lstrip('0')
if (timeok and anevent[system_index] == event_system and
anevent[company_index] == event_company and
time.mktime(unique_entries[start_index][anevent[start_index]]) >= event_end and
#(event_desc != unique_entries[desc_index][anevent[desc_index]] or
# event_title != unique_entries[title_index][anevent[title_index]]) and
unique_entries[round_number_index][anevent[round_number_index]] > round_number and
unique_entries[total_rounds_index][anevent[total_rounds_index]] == rounds_total and
unique_entries[round_number_index][anevent[round_number_index]] >= round_number):
#(unique_entries[total_rounds_index][anevent[total_rounds_index]] != rounds_total or
#unique_entries[round_number_index][anevent[round_number_index]] != round_number)):
rkey = str(int(unique_entries[round_number_index][anevent[round_number_index]]))# + '.' + \
# str(int(unique_entries[total_rounds_index][anevent[total_rounds_index]]))
if not possible_following_events.has_key(rkey):
possible_following_events[rkey] = list()
possible_following_events[rkey].append(aneventID)
#possible_following_events[aneventID] = unique_entries[title_index][anevent[title_index]]
best_final = dict()
akeys = possible_following_events.keys()
akeys.sort()
for akey in akeys:
best_score = 0
best_final[akey] = list()
for aneventID in possible_following_events[akey]:
title = unique_entries[title_index][events_byID[aneventID][title_index]]
maximum_match = max(map(lambda s:sum(map(lambda x,y:x == y,title,event_title[s:])),range(len(event_title))))
maximum_match = max(maximum_match,
max(map(lambda s:sum(map(lambda x,y:x == y,title[s:],event_title)),range(len(title)))))
#print '\t',maximum_match,title
if maximum_match > best_score:
best_final[akey] = list()
best_score = maximum_match
if maximum_match == best_score:
#if maximum_match >= 5:
best_final[akey].append(aneventID)
#print best_final
#best_final_events = list()
akeys = best_final.keys()
akeys.sort()
for akey in akeys:
events_following[eventID].append(best_final[akey])
ident_indices = [title_index,is_tournament_index,can_register,round_number_index,total_rounds_index,
desc_index,type_index,system_index,rules_index,company_index]
time_indices = [start_index,end_index,modified_index]
line = ''
command = ''
foundevents = dict()
schedule = list()
#event_priority = list()
list_start_offset = 0
solved_events = None
registered_events = list()
showevents = list()
#print unique_entries[can_register]
while not command == 'quit':
line = raw_input(">")
linesplit = mysplit(line)
#print linesplit
command = linesplit[0].lower()
arguments = linesplit[1:]
startindex = 0
endindex = -1
if len(arguments) == 1:
if '-' in arguments[0]:
spl_arguments = arguments[0].split('-')
if len(spl_arguments) == 2 and spl_arguments[0].isdigit() and spl_arguments[1].isdigit():
startindex = int(spl_arguments[0])
endindex = int(spl_arguments[1])
elif arguments[0] == 'all':
startindex = 1
endindex = len(foundevents.keys())+1
elif arguments[0].isdigit():
startindex = int(arguments[0])
endindex = startindex
elif len(arguments) == 3:
if arguments[0].isdigit() and arguments[1].lower() in ['-','to'] and arguments[2].isdigit():
startindex = int(arguments[0])
endindex = int(arguments[2])
if command == 'find':
foundevents = find_events(arguments)
foundeventkeys = foundevents.keys()
#if len(foundeventkeys) > 30:
# showevents = foundeventkeys[:30]
if len(foundeventkeys) == 0:
print 'No matching events.'
showevents = list()
else:
showevents = foundeventkeys
showevents.sort(key = lambda eventID:unique_entries[start_index][events_byID[foundevents[eventID][0]][start_index]])
index = 1
for eventkey in showevents[:30]:
events = foundevents[eventkey]
eventkey_int = map(int,eventkey.split())
print '#'+str(index)+':',unique_entries[title_index][eventkey_int[title_index]],
if len(events) == 1:
print
else:
print '('+str(len(events))+' events)'
#for eventID in events:
# print '\t',eventID
#print
index = index + 1
if len(foundeventkeys) > 30:
print len(foundeventkeys)-30,'more events found, type "more" to see more,'
print '"add
" to add an event to your schedule, "browse" for detailed info'
list_start_offset = 0
elif command == 'more':
list_start_offset += 30
if list_start_offset > len(showevents):
print 'No more events to show'
else:
for eventkey in showevents[list_start_offset:list_start_offset+30]:
events = foundevents[eventkey]
eventkey_int = map(int,eventkey.split())
print '#'+str(index)+':',unique_entries[title_index][eventkey_int[title_index]],
if len(events) == 1:
print
else:
print '('+str(len(events))+' events)'
#for eventID in events:
# print '\t',eventID
#print
index = index + 1
if len(foundeventkeys) > list_start_offset+30:
print len(foundeventkeys)-(list_start_offset+30),'more events found, type "more" to see more.'
print '"add " to add an event to your schedule, "browse" for detailed info'
elif command == 'browse':
list_start_offset = 0
done = False
while not done:
if list_start_offset >= len(foundeventkeys):
done = True
else:
eventkey = showevents[list_start_offset]
events = foundevents[eventkey]
eventkey_int = map(int,eventkey.split())
print
print_nicely_formatted(unique_entries[title_index][eventkey_int[title_index]],80)
print_nicely_formatted(unique_entries[desc_index][eventkey_int[desc_index]],80)
if eventkey_int[long_desc_index] >= 0:
print_nicely_formatted(unique_entries[long_desc_index][eventkey_int[long_desc_index]],80)
#print unique_entries[desc_index][eventkey_int[desc_index]]
if len(events) == 1:
event_ID = events[0]
print event_ID,
this_event = events_byID[event_ID]
event_start = unique_entries[start_index][this_event[start_index]]
event_end = unique_entries[end_index][this_event[end_index]]
print time.strftime('%A %I:%M%p',event_start),'-',
if time.strftime('%A',event_start) == time.strftime('%A',event_end):
print time.strftime('%I:%M%p',event_end)
else:
print time.strftime('%A %I:%M%p',event_end)
else:
print '('+str(len(events))+' events)'
#print location_index,room_index,table_index
#print eventkey_int[location_index],eventkey_int[room_index],eventkey_int[table_index]
if eventkey_int[location_index] != -1:
print unique_entries[location_index][eventkey_int[location_index]],
if eventkey_int[room_index] != -1:
print unique_entries[room_index][eventkey_int[room_index]],
if eventkey_int[table_index] != -1:
print unique_entries[table_index][eventkey_int[table_index]]
if eventkey_int[system_index] != -1:
print unique_entries[system_index][eventkey_int[system_index]],
if eventkey_int[rules_index] != -1:
print unique_entries[rules_index][eventkey_int[rules_index]]+',',
if eventkey_int[company_index] != -1:
print unique_entries[company_index][eventkey_int[company_index]]+',',
if eventkey_int[gm_index] != -1:
print unique_entries[gm_index][eventkey_int[gm_index]],
print
if eventkey_int[cost_index] != -1:
print 'Event cost:',
print str(unique_entries[cost_index][eventkey_int[cost_index]]) + ',',
tickets_remaining = 0
for event_ID in events:
this_event = events_byID[event_ID]
tickets_remaining = tickets_remaining + unique_entries[tickets_available_index][this_event[tickets_available_index]]
print int(tickets_remaining),
print "tickets remaining"
list_start_offset = list_start_offset + 1
already_have = False
for s in schedule:
if len(s[1]) == len(events) and all(map(lambda e:e in s[1],events)):
already_have = True
#schedule = filter(lambda s:eventID not in s[1],schedule)
if already_have:
print 'Already in schedule, moving on...'
else:
reply = raw_input("Add/continue?")
if reply.lower().startswith('n') or reply.lower().startswith('q'):
done = True
elif reply.lower().startswith('y') or reply.lower().startswith('q'):
priority = raw_input('Priority for '+unique_entries[title_index][eventkey_int[title_index]]+'?')
if priority.isdigit():
priority = int(priority)
if priority < 0:
priority = 0
elif priority > 10:
priority = 10
schedule.append((priority,foundevents[eventkey]))
#schedule.append((priority,unique_entries[title_index][eventkey_int[title_index]]))
#event_priority.append(priority)
if events_following.has_key(events[0]):
print "Note:",unique_entries[title_index][eventkey_int[title_index]],
print "is start of a tournament, will attempt to link rest of tournament events to it."
elif command == 'show':
for i in range(startindex - 1,endindex):
if i >= 0 and i < len(showevents):
eventkey = map(int,showevents[i].split())
events = foundevents[showevents[i]]
#eventkey = map(int,foundevents.keys()[i].split())
for j in range(len(eventkey)):
if eventkey[j] > -1 and j not in time_indices:
print column_titles[j] + ':',unique_entries[j][eventkey[j]]
for eventID in events:
print '\t',eventID,
print time.strftime('%A %I:%M%p',unique_entries[start_index][events_byID[eventID][start_index]]),'-',
print time.strftime('%A %I:%M%p',unique_entries[end_index][events_byID[eventID][end_index]])
print
#print eventkey
elif command in ['add','got']:
if len(arguments)>0 and events_byID.has_key(arguments[0]):
eventID = arguments[0]
priority = raw_input('Priority for '+eventID+'?')
if priority.isdigit():
schedule = filter(lambda s:eventID not in s[1],schedule)
priority = int(priority)
if priority < 0:
priority = 0
elif priority > 10:
priority = 10
schedule.append((priority,[eventID]))
if events_following.has_key(eventID):
print "Note:",eventID,
print " is start of a tournament, will attempt to link rest of tournament events to it."
else:
for i in range(startindex - 1,endindex):
if i >= 0 and i < len(foundevents.keys()):
eventkey_int = map(int,showevents[i].split())
priority = raw_input('Priority for '+unique_entries[title_index][eventkey_int[title_index]]+'?')
if priority.isdigit():
priority = int(priority)
if priority < 0:
priority = 0
elif priority > 10:
priority = 10
schedule.append((priority,foundevents[showevents[i]]))
if events_following.has_key(foundevents[showevents[i]][0]):
print "Note:",unique_entries[title_index][eventkey_int[title_index]],
print "is start of a tournament, will attempt to link rest of tournament events to it."
elif command == 'list':
index = 1
schedule.sort(reverse = True)
for index in range(len(schedule)):
events = schedule[index][1]
print '#'+str(index+1)+':',
print unique_entries[title_index][events_byID[events[0]][title_index]],
if len(events) > 1:
print '('+str(len(events))+' events)',
else:
print events[0],
print schedule[index][0]
elif command in ['change']:
if startindex <= endindex:
changing_events = schedule[startindex - 1:endindex]
schedule = schedule[:startindex - 1]+schedule[endindex:]
for anevent_info in changing_events:
anevent = events_byID[anevent_info[1][0]]
priority = raw_input('Priority for '+unique_entries[title_index][anevent[title_index]]+'?')
newevent_info = anevent_info
if priority.isdigit():
priority = int(priority)
if priority < 0:
priority = 0
elif priority > 10:
priority = 10
newevent_info = (priority,anevent_info[1])
schedule.append(newevent_info)
elif command in ['combine','merge']:
if startindex <= endindex:
combinedevents = list()
priority = schedule[startindex][0]
for anevent_info in schedule[startindex - 1:endindex]:
combinedevents = combinedevents + anevent_info[1]
schedule = schedule[:startindex - 1]+schedule[endindex:]
newevent_info = (priority,combinedevents)
schedule.append(newevent_info)
elif command in ['del','remove']:
if len(arguments)>0 and events_byID.has_key(arguments[0]):
eventID = arguments[0]
schedule = map(lambda s:(s[0],filter(lambda e:e != eventID,s[1])),schedule)
#print schedule
schedule = filter(lambda s:len(s[1])>0,schedule)
elif startindex <= endindex:
schedule = schedule[:startindex - 1]+schedule[endindex:]
#event_priority = event_priority[:startindex - 1]+event_priority[endindex:]
elif command == 'solve':
registered_events = list()
solved_events = None
all_solved_events = solve_schedule(schedule)
if startindex > endindex:
if all_solved_events and len(all_solved_events) > 0:
solved_events = all_solved_events[0][1]
if solved_events != None:
print 'Schedules calculated.'
print
reply = raw_input('Proceed to registration?')
if reply.lower().startswith('y'):
events_remaining = True
while events_remaining and all_solved_events != None:
print "Calculating wish list..."
print
fail_check_events = list()
#fail_check_list = list()
#schedules_tocheck = [all_solved_events[0][1]]
fully_solved_schedules = list()
#while len(schedules_tocheck) > 0:
for a_schedule in all_solved_events:
#for a_schedule in schedules_tocheck:
these_fail_check_events = list()
for eventID in a_schedule[1]:
if not eventID in fail_check_events+registered_events:
thisevent = events_byID[eventID]
if (int(float(unique_entries[cost_index][thisevent[cost_index]])) > 0 and
not unique_entries[can_register][thisevent[can_register]].lower().startswith('no')):
these_fail_check_events.append(eventID)
#these_fail_check_events.sort(key = lambda e:
# int(float(unique_entries[tickets_available_index][events_byID[e][tickets_available_index]])))
if len(these_fail_check_events) == 0:
fully_solved_schedules.append(a_schedule)
else:
these_fail_check_events.sort(key = lambda e:max(map(lambda s:(e in s[1]) and len(s[1]),schedule)))
#these_fail_check_events.reverse()
for eventID in these_fail_check_events:
#print eventID
fail_check_events.append(eventID)
fully_solved_schedules.sort(reverse = True)
solved_events = fully_solved_schedules[0][1]
if fully_solved_schedules[0] == all_solved_events[0]:
fail_check_events = list()
if len(registered_events) > 0:
print 'Registered events:'
for eventID in registered_events:
print eventID+' ('+unique_entries[title_index][events_byID[eventID][title_index]]+')'
print
if len(fail_check_events) > 0:
event_priority = 1
fail_check_events = fail_check_events[:20]
print 'Wish list is as follows:'
for eventID in fail_check_events:
print event_priority,eventID+' ('+unique_entries[title_index][events_byID[eventID][title_index]]+')'
event_priority = event_priority + 1
#print unique_entries[can_register][events_byID[eventID][can_register]]
print 'Enter wish list in registration site now and submit form.'
print
#full_events = list()
for eventID in fail_check_events:
reply = raw_input('Did we get '+eventID+'?')
if reply.lower().startswith('y'):
registered_events.append(eventID)
#schedule = filter(lambda s:eventID not in s[1],schedule)
#schedule.append((10,[eventID]))
else:
schedule = map(lambda s:(s[0],filter(lambda e:e != eventID,s[1])),schedule)
schedule = filter(lambda s:len(s[1]) > 0,schedule)
print
print 'Recalculating schedule now...'
print
solved_events = None
all_solved_events = solve_schedule(schedule)
if all_solved_events and len(all_solved_events) > 0:
solved_events = all_solved_events[0][1]
else:
events_remaining = False
if solved_events != None:
drop_events = list()
for eventID in registered_events:
if not eventID in solved_events:
drop_events.append(eventID)
if len(drop_events) > 0:
print 'Now remove the following events from your cart:'
for eventID in drop_events:
print eventID
registered_events.remove(eventID)
reply = raw_input('(Press Enter when finished)')
print
solved_events.sort(key = lambda eventID:unique_entries[start_index][events_byID[eventID][start_index]])
last_day = None
for eventID in solved_events:
if eventID in registered_events:
schedule = filter(lambda s:eventID not in s[1],schedule)
schedule.append((10,[eventID]))
thisevent = events_byID[eventID]
start_time = unique_entries[start_index][thisevent[start_index]]
end_time = unique_entries[end_index][thisevent[end_index]]
if last_day != time.strftime('%A',start_time):
print
print time.strftime('%A %d %B %Y',start_time)
print
last_day = time.strftime('%A',start_time)
print_nicely_formatted(eventID + ': ' + unique_entries[title_index][thisevent[title_index]],80)
whenst = time.strftime('%A %I:%M%p',start_time) + '-'
if time.strftime('%A',end_time) != last_day:
whenst = whenst + time.strftime('%A %I:%M%p',end_time)
else:
whenst = whenst + time.strftime('%I:%M%p',end_time)
wherest = ' '.join([unique_entries[location_index][thisevent[location_index]],
unique_entries[room_index][thisevent[room_index]],
unique_entries[table_index][thisevent[table_index]]])
print_nicely_formatted(whenst + ', ' + wherest,80)
event_desc = unique_entries[desc_index][thisevent[desc_index]]
print_nicely_formatted(event_desc,80)
whost = ''
#print whost
if len(unique_entries[gm_index][thisevent[gm_index]]) > 0:
whost = whost + unique_entries[gm_index][thisevent[gm_index]] + ', '
#print whost,unique_entries[company_index][thisevent[company_index]]
whost = whost + unique_entries[company_index][thisevent[company_index]]
whost = ' '.join(map(lambda s:s.capitalize(),whost.split()))
if unique_entries[cost_index][thisevent[cost_index]] > 0:
whost = whost + ' $'+str(unique_entries[cost_index][thisevent[cost_index]])
print_nicely_formatted(whost,80)
#print unique_entries[webaddress_index][thisevent[webaddress_index]],
#print unique_entries[email_index][thisevent[email_index]]
#print 'Tickets available:',
#print unique_entries[tickets_available_index][thisevent[tickets_available_index]],
#print 'Event cost:',
#print unique_entries[cost_index][thisevent[cost_index]]
print
#if events_following.has_key(eventID):
# print events_following[eventID]
print
else:
print "Unable to solve schedule - incompatible mandatory events! Remove some or reduce priority below 10."
else:
if all_solved_events and len(all_solved_events) > 0:
print 'Schedules calculated.'
print
for solved_event_info in all_solved_events[startindex - 1:endindex]:
solved_events = solved_event_info[1]
solved_events.sort(key = lambda eventID:unique_entries[start_index][events_byID[eventID][start_index]])
print 'Score:',solved_event_info[0]
for eventID in solved_events:
if eventID in registered_events:
schedule = filter(lambda s:eventID not in s[1],schedule)
schedule.append((10,[eventID]))
thisevent = events_byID[eventID]
start_time = unique_entries[start_index][thisevent[start_index]]
end_time = unique_entries[end_index][thisevent[end_index]]
whenst = time.strftime('%A %I:%M%p',start_time) + '-'
whenst = whenst + time.strftime('%A %I:%M%p',end_time)
wherest = ' '.join([unique_entries[location_index][thisevent[location_index]],
unique_entries[room_index][thisevent[room_index]],
unique_entries[table_index][thisevent[table_index]]])
if len(unique_entries[title_index][thisevent[title_index]]) > 25:
print_nicely_formatted(whenst + ' ' + eventID + ': ' + unique_entries[title_index][thisevent[title_index]][:22] + '..., ' + wherest,80)
else:
print_nicely_formatted(whenst + ' ' + eventID + ': ' + unique_entries[title_index][thisevent[title_index]] + ', ' + wherest,80)
print
else:
print "Unable to solve schedule - incompatible mandatory events! Remove some or reduce priority below 10."
elif command == 'save':
if len(arguments) > 0:
print 'Saving to disk...'
outfile = file(mydir + '/' + arguments[0] + '_schedule.pcl','w')
pickle.dump(schedule,outfile)
outfile.close()
else:
print "Not saved, file name needed"
elif command == 'load':
if len(arguments) > 0:
print 'Loading from disk...'
try:
infile = file(mydir + '/' + arguments[0] + '_schedule.pcl','r')
schedule = pickle.load(infile)
infile.close()
schedule = map(lambda s:(s[0],filter(lambda e:events_byID.has_key(e),s[1])),schedule)
schedule = filter(lambda s:len(s[1])>0,schedule)
except IOError:
print arguments[0] + '_schedule.pcl not found.'
schedule = list()
else:
print "Not loaded, file name needed"
elif command == '?' or command == 'help':
if len(arguments) == 0:
print "Commands:"
print
print "quit - exits this program"
print "find - searches the list of events for matches"
print "more - lists next 30 found events"
print "browse - views list of found events in detail one by one"
print "show # - shows full details on one event"
print "add # - adds an event from found event list to wishlist"
print "list - shows your current wishlist"
print "change # - changes the priority of an item on your wishlist"
print "merge # - combines two items on wishlist into single item"
print "del # - removes an item from your wishlist"
print "solve - solves for best schedules, optionally proceeds to registration"
print "save - saves current wishlist to a file"
print "load - loads current wishlist from a file"
print "help - more detailed information on that command"
print
print "Commands are not case-sensitive"
elif arguments[0] == 'find':
print 'save '
print
print 'This searches the list of events according to keywords'
print 'Accepted keywords are any, all, on, in, at, by, before, after, type, not, age'
print
print 'Keyword functions:'
print
print 'Any, All - followed by a word this searches for all events which contain that word in their'
print 'title or description. For example, "Find all NASCRAG". You can also omit the keyword for'
print 'this case and just type "Find NASCRAG"/'
print
print 'on - searches for events by day'
print ' for example, "find on saturday"'
print
print 'in - searches for events by location'
print ' for example, "find in hyatt"'
print
print 'by - searches for events by company or group'
print ' for example, "find by gamebase7"'
print
print 'before - searches for events which take place before a certain time'
print ' for example, "find before 10pm"'
print
print 'after - searches for events which take place after a certain time'
print ' for example, "find after 10am"'
print
print 'type - searches by the prefix/type code of the event'
print ' for example, "find type RPGA"'
print
print 'not - inverts action of following keywords'
print ' for example, "find not on sunday"'
print
print 'age - searches by event age restriction'
print ' for example, "find age 21+"'
print
print 'Multiple keyword searches can be combines into a single search line'
print ' for example, "find sparks by gamebase7 after 1pm not on thursday"'
print
print 'This command will return a numbered list of all events matching the search terms'
print 'and will display the first 30 matches'
elif arguments[0] == 'more':
print 'more'
print
print 'The command Find will only show the first 30 event matches'
print 'Typing "more" will then show the next 30 matches'
elif arguments[0] == 'browse':
print 'browse'
print
print 'After running the find command to generate a list of matches, the browse command'
print 'will show each matching event one by one in detail, and for each one give the option to add'
print 'that event to your wish list'
print
print 'When you add an item to your wish list, you will be asked for a priority number, which'
print 'should be a number from 1-10. A priority of 10 indicates a must-have event - the script'
print 'will reject any calendar which does not include that event. Lower priority events will'
print 'be added as possible in order of their priority number'
elif arguments[0] == 'show':
print 'show #'
print
print 'After running the find command to generate a list of matches, the show command will'
print 'give you all the details of an item on the list.'
elif arguments[0] == 'add':
print 'show #'
print
print 'After running the find command to generate a list of matches, the add command will'
print 'allow you to add a single entry from the list to your wishlist.'
print
print 'When you add an item to your wish list, you will be asked for a priority number, which'
print 'should be a number from 1-10. A priority of 10 indicates a must-have event - the script'
print 'will reject any calendar which does not include that event. Lower priority events will'
print 'be added as possible in order of their priority number'
elif arguments[0] == 'list':
print 'list'
print
print 'This command shows your wishlist so far, giving you an index list of event name,'
print 'event number or number of event slots, and priority'
elif arguments[0] == 'change':
print 'change #'
print
print 'After running the list command, this command allows you to change the priority of'
print 'any entry on the wishlist.'
elif arguments[0] == 'merge':
print 'merge #'
print
print 'This is a semi-experimental command which allows you to combine two items on your wishlist'
print 'This is used primarily for merging two items which are the same event but weren\'t properly'
print 'combined by the catelog parses. To use this, add both the events you want to combine to'
print 'your wishlist, giving them both the same priority so they will show up as adjacent items.'
print 'Then use the merge command to join them, for example merge 4-5 if they are items 4 and 5.'
print 'This can also be used when you have a situation where you want to go to either event A or'
print 'event B but not both, by merging them into a single event with multiple slots.'
elif arguments[0] == 'del':
print 'del #'
print
print 'After running the list command, this command allows you to remove any one item from your'
print 'wishlist.'
elif arguments[0] == 'solve':
print 'solve'
print
print 'This command attempts to derive an optimal schedule from your wishlist. This command takes'
print 'into account all of the events you have selected, and the priority which you have assigned'
print 'to each one. It then builds a list of all possible schedule combinations and then ranks'
print 'them by desirability. When doing so it attempts to get in as many events as possible, but'
print 'also prefers events in the afternoon or evening over those very late or early, and when'
print 'possible tries to give you at least 15 minutes between events.'
print
print 'After the schedules are produced, you will be given the option to proceed to registration.'
print 'The script does not fill out the Gencon registration page for you, you have to do that'
print 'manually.'
print 'However, it will give you a list of event IDs to enter. Do not be alarmed if you see'
print 'muliple conflicting events in the event ID list - the script takes a greedy approach where'
print 'it has you register for all event slots you might want, then depending on which ones you get'
print 'has you drop some of them later. Just follow the instructions the script prints out, and'
print 'follow the prompts to tell the script which slots you actually managed to get. When that is'
print 'done, the script will generate a finished schedule for you to copy and print out.'
print
print 'The script does not instruct you to register for free events that do not requie pre-reg,'
print 'such as seminars. You should probably register for them anyway afterwards.'
print
print 'The script attempts to take tournament structure into account. If you register for the'
print 'first part of a tournament, it will attempt to find the other parts of the tournament and'
print 'add them to your schedule. This doesn\'t always work.'
print
print 'If you answer no to the prompt to proceed to registration, the script will then just print'
print 'out your optimal schedule - the one you\'ll have if you manage to get every event you try to'
print 'register for.'
elif arguments[0] == 'save':
print 'save '
print
print 'This command immedately saves the current wishlist to a file indicated by the filename'
print 'This overwrites any existing file of that name without warning.'
elif arguments[0] == 'load':
print 'save '
print
print 'This command immedately loads the wishlist from a file indicated by the filename'
print 'This overwrites the curent wishlist without warning.'
else:
print 'No help available for',arguments[0]
elif command == 'quit' or command == '':
pass
else:
print 'Unrecognized command:',command