def __init__(self): super().__init__() # Keep a list of event objects (ID and name) self.events = [] # Event results are categorized, for example "Professional Couple American Smooth" # Keep a list of those categories. self.categories = [] # save the competition ID in order to request results for a given dancer self.comp_id = None # get access to format_name self.hld = Heatlist_Dancer()
def open(self, fieldfile): '''Begin the process of reading heatsheet data from the common file format.''' self.filedata = fieldfile self.filedata.open(mode="rt") line = self.filedata.readline().decode().strip() self.comp_name = line.split(":")[1] #print(self.comp_name) # read past the line that says Dancers: line = self.filedata.readline().decode().strip() while True: line = self.filedata.readline().decode().strip() if line == "Heats": break else: d = Heatlist_Dancer() d.load_from_file(line) #d = Dancer(fields[0], fields[1]) self.dancers.append(d) # close the file self.filedata.close()
def open(self, comp): '''This method obtains the name of the competition and a list of all the dancers.''' #extract comp name and comp_id from URL url = comp.heatsheet_url start_pos = url.find("cyi=") + len("cyi=") self.comp_id = url[start_pos:] # open this URL to obtain a list of dancers in JSON format url = "http://ndcapremier.com/feed/heatlists/?cyi=" + self.comp_id response = requests.get(url) data = json.loads(response.text) print(len(data['Result'])) for c in data['Result']: d = Heatlist_Dancer() d.load_from_ndca_premier_feed(c) d.comp = comp d.alias = None try: code_num = int(d.code) if d.code != "0": self.dancers.append(d) except: print("Invalid competitor " + d.name + " " + d.code) self.build_heatlist_error(comp, Heatlist_Error.NO_CODE_FOUND, dancer_name=d.name)
def open(self, comp): '''This method obtains the name of the competition and a list of all the dancers.''' #extract comp name and comp_id from URL url = comp.heatsheet_url start_pos = url.find("cyi=") + len("cyi=") self.comp_id = url[start_pos:] #self.comp_name = self.get_comp_name(self.comp_id) # open this URL to obtain a list of dancers url = "http://www.ndcapremier.com/scripts/competitors.asp?cyi=" + self.comp_id print(url) response = requests.get(url) competitors = response.text.split("</a>") for c in range(len(competitors) - 1): if 'class="team"' in competitors[c]: continue safe = html.unescape(competitors[c]) d = Heatlist_Dancer() d.load_from_ndca_premier(safe) d.comp = comp d.alias = None try: code_num = int(d.code) if d.code != "0": self.dancers.append(d) except: print("Invalid competitor " + d.name + " " + d.code) self.build_heatlist_error(comp, Heatlist_Error.NO_CODE_FOUND, dancer_name=d.name)
def build_heatlist_dancer(self, name): dancers = Heatlist_Dancer.objects.filter(name=name) if dancers.count() > 0: d = dancers.first() else: d = Heatlist_Dancer() d.name = name d.code = "LATE" d.save() return d
def load_dancers(request, comp_id): if not request.user.is_superuser: return render(request, 'rankings/permission_denied.html') comp_objects = Comp.objects.filter(pk=comp_id) if len(comp_objects) == 1: comp = comp_objects[0] #if Heatlist_Dancer.objects.count() > 0: # Heatlist_Dancer.objects.all().delete() if Unmatched_Heat_Entry.objects.count() > 0: Unmatched_Heat_Entry.objects.all().delete() if comp.heatsheet_file: heatlist = FileBasedHeatlist() heatlist.open(comp.heatsheet_file) else: if comp.url_data_format == Comp.COMP_MNGR: heatlist = CompMngrHeatlist() elif comp.url_data_format == Comp.NDCA_PREM: heatlist = NdcaPremHeatlist() elif comp.url_data_format == Comp.NDCA_FEED: heatlist = NdcaPremFeedHeatlist() elif comp.url_data_format == Comp.O2CM: heatlist = O2cmHeatlist() else: # CompOrganizer for now heatlist = CompOrgHeatlist() heatlist.open(comp) # add special "dancer" for partnerless events d = Heatlist_Dancer() d.name = "{No, Partner}" d.code = "0" d.comp = comp heatlist.dancers.append(d) for d in heatlist.dancers: in_database = Heatlist_Dancer.objects.filter(name=d.name, comp=comp) if in_database.count() == 0: d.save() comp.process_state = Comp.DANCERS_LOADED comp.save() return redirect("comps:resolve_dancers", comp.id)
def open(self, comp): '''This method obtains the name of the competition and a list of all the dancers.''' #extract comp name from URL url = comp.heatsheet_url print(comp.heatsheet_url) response = requests.get(url, timeout=5.0) lines = response.text.splitlines() for l in lines: if "var cmid" in l: # this line is in this format" # var cmid = "beachbash2019"; # extract the name from between the quotes self.comp_name = l.split('= "')[1][:-2] print(self.comp_name) break end_pos = url.find("/pages") # save this string for later use self.base_url = url[: end_pos] + "/scripts/heatlist_scrape.php?comp=" + self.comp_name print(self.base_url) # open the base URL to extract a list of dancers response = requests.get(self.base_url, timeout=5.0) competitors = response.text.split("},") print("Competitors = " + str(len(competitors))) for c in range(len(competitors)): start_pos = competitors[c].find('"id') d = Heatlist_Dancer() d.load_from_comp_org(competitors[c][start_pos:]) d.comp = comp d.alias = None try: code_num = int(d.code) if d.code != "0": self.dancers.append(d) else: print("Invalid competitor " + d.name + " " + d.code) self.build_heatlist_error(comp, Heatlist_Error.NO_CODE_FOUND, dancer_name=d.name) except: print("Invalid competitor " + d.name + " " + d.code) self.build_heatlist_error(comp, Heatlist_Error.NO_CODE_FOUND, dancer_name=d.name)
def aliases_for_dancer(request, hld_pk): if not request.user.is_superuser: return render(request, 'rankings/permission_denied.html') # get the heatlist dancer and the dancer by alias heatlist_dancer = get_object_or_404(Heatlist_Dancer, pk=hld_pk) dancer = get_object_or_404(Dancer, pk=heatlist_dancer.alias.id) dancer_aliases = Heatlist_Dancer.objects.filter( alias=heatlist_dancer.alias) all_comps = Comp.objects.all().order_by('-start_date') comps_for_dancer = list() for comp in all_comps: # if dancer's name has been corrected after this comp's start date, quit loop if comp.start_date < dancer.name_fix_date: break # if the dancer was in this comp if Heat_Entry.objects.filter(heat__comp=comp).filter( Q(couple__dancer_1=dancer) | Q(couple__dancer_2=dancer)).count() > 0: # and had an alias in that comp matches = dancer_aliases.filter(comp=comp) # add the alias to the list if matches.count() > 0: comps_for_dancer.append(matches.first()) else: # add a "no name alias" to the list no_name_hld = Heatlist_Dancer() no_name_hld.name = "" no_name_hld.code = "No Code" no_name_hld.alias = dancer no_name_hld.comp = comp comps_for_dancer.append(no_name_hld) paginator = Paginator(comps_for_dancer, 16) page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) return render(request, 'rankings/alias_dancers.html', { 'page_obj': page_obj, 'level': 1 })
def open(self, comp): '''This method obtains the name of the competition and a list of all the dancers.''' #extract comp name and comp_id from URL url = comp.heatsheet_url start_pos = url.find("event=") + len("event=") self.comp_id = url[start_pos:] self.comp_name = self.comp_id # open this URL to obtain a list of dancers response = requests.get(url) competitors = response.text.split("</OPTION>") #print(competitors[0]) # get the URL from the <form> tag if "<form" in competitors[0]: self.find_url(competitors[0]) #print(self.url) # get payload fields from the input tag if "<input" in competitors[-1]: self.find_payload_field(competitors[-1]) #print(self.payload) for c in range(1,len(competitors) - 1): safe = html.unescape(competitors[c]) d = Heatlist_Dancer() d.load_from_o2cm(safe) d.comp = comp d.alias = None try: code_num = int(d.code) if d.code != "0": self.dancers.append(d) except: print("Invalid competitor", d.name, d.code) self.build_heatlist_error(comp, Heatlist_Error.NO_CODE_FOUND, dancer_name=d.name)
class NdcaPremResults(Results_Processor): '''This class processes the results from the NDCA Premier site...''' def __init__(self): super().__init__() # Keep a list of event objects (ID and name) self.events = [] # Event results are categorized, for example "Professional Couple American Smooth" # Keep a list of those categories. self.categories = [] # save the competition ID in order to request results for a given dancer self.comp_id = None # get access to format_name self.hld = Heatlist_Dancer() def get_comp_name(self, comp_id): '''This method obtains the name of the competition based on the ID.''' url = "http://www.ndcapremier.com/scripts/compyears.asp?cyi=" + comp_id response = requests.get(url) lines = response.text.splitlines() # the comp name is enclosed in an HTML tag for l in lines: start_pos = l.find("<comp_name>") if start_pos > -1: start_pos += len("<comp_name>") end_pos = l.find("</comp_name>") comp_name = l[start_pos:end_pos] break return comp_name def temp_result(self, rounds, accum_value): '''This method builds a temporary result string based on the round that the couple was eliminated and the number of recall votes''' if rounds == "S": return "Semis-" + accum_value elif rounds == "Q": return "quarters-" + accum_value elif rounds == "R3": return "round 3-" + accum_value elif rounds == "R2" or rounds == "R32": return "round 2-" + accum_value else: return "round 1-" + accum_value def process_couple(self, entries, couple_field, result_str): # find the couple's shirt number sub_fields = couple_field.split(" & ") first_space = sub_fields[0].find(" ") shirt_number = sub_fields[0][:first_space] # find the names of the couple and format them dancer_name_list = list() dancer_name = sub_fields[0][first_space + 1:] for s in range(1, len(dancer_name.split())): dancer_name_list.append( self.hld.format_name(orig_name=dancer_name, simple=False, split_on=s)) if len(dancer_name_list) == 0: dancer_name_list.append(dancer_name) partner_name_list = list() partner_name = sub_fields[1] for s in range(1, len(partner_name.split())): partner_name_list.append( self.hld.format_name(orig_name=partner_name, simple=False, split_on=s)) if len(partner_name_list) == 0: partner_name_list.append(partner_name) # look for this couple in the entries and add the result and shirt number for entry in entries: if str(entry.couple.dancer_1) in dancer_name_list or str(entry.couple.dancer_2) in dancer_name_list or \ str(entry.couple.dancer_1) in partner_name_list or str(entry.couple.dancer_2) in partner_name_list: entry.shirt_number = shirt_number if len(entry.result) == 0: entry.result = result_str else: print(str(entry) + " result not empty") res_error = Result_Error() res_error.comp = entry.heat.comp res_error.heat = entry.heat res_error.couple = entry.couple res_error.error = Result_Error.TWO_RESULTS_FOR_COUPLE res_error.save() break else: # couple not found, create a late entry print("Could not find " + partner_name + " and " + dancer_name) couple_names = [dancer_name_list[0], partner_name_list[0]] self.build_late_entry(self.heat, shirt_number, couple_names, result_str) def update_scoring(self, e): '''This method updates the result and points for a given entry, e.''' if (e.points is None or e.points == 0) and len(e.result) > 0: if e.result.startswith("S"): accum_value = e.result[len("Semis-"):] e.result = "Semis" placement = -2 elif e.result.startswith("q"): accum_value = e.result[len("quarters-"):] e.result = "quarters" placement = -1 elif e.result.startswith("round 3-"): accum_value = e.result[len("round 3-"):] e.result = "round 3" placement = -3 elif e.result.startswith("round 2-"): accum_value = e.result[len("round 2-"):] e.result = "round 2" placement = -5 elif e.result.startswith("round 1-"): accum_value = e.result[len("round 1-"):] e.result = "round 1" placement = -10 else: try: placement = int(e.result) accum_value = 0 except: return None e.points = calc_points(self.heat.base_value, placement, num_competitors=self.entries_in_event, rounds=self.heat.rounds, accum=int(accum_value)) #print(str(e.couple) + " finish " + e.result + " for " + str(e.points) + " points") e.save() return e.result else: return None def process_scoresheet_for_event(self, entries, event): '''This is the method that requests and processes the scoresheet for a particular event. On the NDCA Premier site, the scoresheets are organized by event, not by dancer name.''' # on the NDCA Premier site, the Final round comes first. looking_for_final_round = True looking_for_final_summary = False looking_for_final_dance = False looking_for_result_column = False looking_for_recall_column = False looking_for_finalists = False looking_for_quarterfinal = False looking_for_prelim_round = False process_finalists = False looking_for_semifinal = False self.entries_in_event = 0 self.heat = entries.first().heat # build the URL based on comp ID and event ID url = "http://www.ndcapremier.com/scripts/results.asp?cyi=" + self.comp_id + "&event=" + event.id # get the number of dances in this event. For example W,T,F is 3 dances. num_dances = event.name.count(",") + 1 # request the scoresheet and split the response into lines response = requests.get(url) lines = response.text.splitlines() i = 0 # loop through all the lines while i < len(lines): l = lines[i] if looking_for_final_round: if 'class="roundHeader"' in l: # once the find the title with the final results, look for the summary. looking_for_final_summary = True looking_for_final_round = False else: i += 1 elif looking_for_final_summary: if "Final Summary" in l: # once the summary header is found, look for the result columen looking_for_final_summary = False looking_for_result_column = True col_count = 0 else: i += 1 elif looking_for_result_column: fields = l.split("</th>") # count the number of columns until the result column is found col_count += len(fields) - 1 if "Final Result" in l: # once the result column is found, process each finalist looking_for_result_column = False looking_for_finalists = True else: i += 1 elif looking_for_recall_column: # when looking for recalls, determine the number of columns fields = l.split("</th>") recall_column = len(fields) - 2 accum_column = recall_column - 1 i += 1 looking_for_recall_column = False # start looking for couples that were eliminated in the current round looking_for_eliminations = True elif looking_for_finalists: # skip the first field, it closes out the previous header row rows = fields[-1].split("</tr>")[1:] # once the closing table tag is found we have one row per couple if "</table>" in rows[-1]: rows = rows[:-1] looking_for_finalists = False # after processing the final results, look for possible semifinal looking_for_semifinal = True else: i += 1 # loop through all the couples for r in rows: # split the row into columns fields = r.split("</td>") # get the couple name and number from the first column couple_field = fields[0].split("<td>")[1] # get the result info from the last column result_place = fields[col_count - 1].split("<td>")[1] self.entries_in_event += 1 # process this couple self.process_couple(entries, couple_field, result_place) elif looking_for_semifinal: # if we find a semifinal, set the rounds and look for the results of this round if 'class="roundHeader"' in l: print("Found semi-final") self.heat.rounds = "S" looking_for_semifinal = False looking_for_final_dance = True dance_count = 0 else: i += 1 elif looking_for_quarterfinal: # if we find a quarter final, set the rounds and look for the results of this round if 'class="roundHeader"' in l: print("Found quarter-final") self.heat.rounds = "Q" looking_for_quarterfinal = False looking_for_final_dance = True dance_count = 0 else: i += 1 elif looking_for_prelim_round: # if we find an earlier round, set the rounds and look for the results of this round if 'class="roundHeader">Third' in l: print("Found Third Round") self.heat.rounds = "R3" looking_for_prelim_round = False looking_for_final_dance = True dance_count = 0 elif 'class="roundHeader">Second' in l: print("Found Second Round") if self.heat.rounds != "R3": self.heat.rounds = "R2" else: self.heat.rounds = "R32" looking_for_prelim_round = False looking_for_final_dance = True dance_count = 0 elif 'class="roundHeader">First' in l: print("Found First Round") if self.heat.rounds == "R32": self.heat.rounds = "R321" elif self.heat.rounds == "R2": self.heat.rounds = "R21" else: self.heat.rounds = "R1" looking_for_prelim_round = False looking_for_final_dance = True dance_count = 0 else: i += 1 elif looking_for_final_dance: if 'class="eventResults"' in l: dance_count += 1 # TODO: some prelim rounds may not dance all the dances. Need to handle this. if dance_count == num_dances: looking_for_final_dance = False looking_for_recall_column = True i += 1 elif looking_for_eliminations: # once we find the results of an early round, look for earlier rounds if "</table>" in l: looking_for_eliminations = False if self.heat.rounds == "S": looking_for_quarterfinal = True elif self.heat.rounds == "Q": looking_for_prelim_round = True elif self.heat.rounds == "R3": looking_for_prelim_round = True elif self.heat.rounds == "R2": looking_for_prelim_round = True else: # process the result of the next couple fields = l.split("</td>") # get the couple name and shirt number couple_field = fields[0].split("<td>")[1] # determine if the couple was recalled recall_place = fields[recall_column].split("<td>")[1] if recall_place != "Recall": # if the couple was not recalled determine how many votes they got accum_value = fields[accum_column].split("<td>")[1] result_str = self.temp_result(self.heat.rounds, accum_value) # process this couple self.process_couple(entries, couple_field, result_str) i += 1 else: i += 1 # entire scoresheet was processed # for each entry in the event, extract the recall votes and calculate the points event_result = None for e in entries: temp_result = self.update_scoring(e) if event_result is None: event_result = temp_result for late_entry in self.late_entries: temp_result = self.update_scoring(late_entry) if temp_result is not None: print("LATE ENTRY SCORING: " + late_entry.result + " " + str(late_entry.points)) if event_result is None: event_result = temp_result return event_result def determine_heat_results(self, entries): '''This method obtains the results for all entries in the event.''' # process the scoresheet for each of those events. for entry in entries: if entry.points is None or entry.points == 0: event_name = entries.first().heat.info for event in self.events: if event.name == event_name: #print("Processing " + event.name) event_result = self.process_scoresheet_for_event( entries, event) if event_result is not None: for entry in entries: if entry.points is None: entry.result = "DNP" return event_result else: print("ERROR: Could not find event " + event_name) heat = entries.first().heat res_error = Result_Error() res_error.comp = heat.comp res_error.heat = heat res_error.error = Result_Error.HEAT_NOT_FOUND res_error.save() return "No Change" else: # all entries have results already return "No change" def open(self, url): '''This method opens the results page for a competition on the NDCA Premier site It extracts all the event names and associated IDs.''' #extract comp name and comp_id from URL start_pos = url.find("cyi=") + len("cyi=") self.comp_id = url[start_pos:] self.comp_name = self.get_comp_name(self.comp_id) # request that page url = "http://www.ndcapremier.com/scripts/event_categories.asp?cyi=" + self.comp_id response = requests.get(url) # split the response into event categories categories = response.text.split("</a>") for cat_link in categories: if len(cat_link) > 0: start_pos = cat_link.find("style=") + len("style=") + 1 end_pos = cat_link.find('">', start_pos) category = cat_link[start_pos:end_pos] self.categories.append(category) # build a list of events, by looping through the event categories. for cat in self.categories: url = "http://www.ndcapremier.com/scripts/event_list.asp?cyi=" + self.comp_id + "&cat=" + cat response = requests.get(url) event_lines = response.text.split("</a>") for e in event_lines: if len(e) > 0: event = NdcaPremEvent(e) #print(event.name + " " + event.id) self.events.append(event)