def update_scoring(self, e):
     '''This method updates the result and points for a given entry, e.'''
     if e.points is None 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
예제 #2
0
    def process_response(self, entries, e):
        '''This routine processes the response returned by the form submittal.
           It is the scoresheet results for a single dancer.
           We use this to extract the results of the heat we are interested in .'''

        # determine heat to search for in the scoresheet
        if e.heat.heat_number == 0:
            heat_string = e.heat.extra
        elif len(e.heat.extra) > 0 and e.heat.extra[0] != '[':
            heat_string = str(e.heat.heat_number) + e.heat.extra
        else:
            heat_string = str(e.heat.heat_number)

        # save the level of the event (e.g. Open vs. Rising Star, Bronze, Silver, Gold, etc.)
        level = e.heat.base_value

        # set the rounds indicator to finals, until proven otherwise
        rounds = "F"

        # find the beginning of the JSON data
        if self.response.text[0] == "{":
            start_pos = 0
        else:
            start_pos = self.response.text.find("{")

        try:
            json_data = json.loads(self.response.text[start_pos:])
        except:
            print("Unable to parse scoresheet - " + str(e.heat))
            return

        if json_data['Status'] == 0:
            # no results for this competitor
            print("No scoresheet")
            return

        # search all the events on this dancer's scoresheet
        for ev in json_data['Result']['Events']:
            # once we find the heat we want
            if ev['Heat'] == heat_string:
                for r in ev['Rounds']:
                    if r['Name'] == "Final":
                        # process final round results
                        self.entries_in_event = 0
                        # don't process Solo - keep looking for heat_string
                        if r['Scoring_Method'] == "Solos":
                            continue
                        # loop through all the competitors in this heat
                        for c in r['Summary']['Competitors']:
                            self.entries_in_event += 1
                            for entry in entries:
                                # find matching entry by shirt number
                                if str(entry.shirt_number) == c['Bib']:
                                    # This Result list is length 1, unless there are tiebreakers, so use the last item
                                    result_str = c['Result'][-1]
                                    if len(entry.result) == 0:
                                        entry.result = result_str
                                        break
                                    elif entry.result == result_str:
                                        break
                                    else:
                                        print(
                                            str(entry.heat.heat_number) +
                                            " Same number - new result: " +
                                            " " + str(entry.couple.dancer_1) +
                                            " " + str(entry.couple.dancer_2) +
                                            " " + entry.result + " " +
                                            result_str)
                                        entry.result = result_str
                                        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:  # late entry in final
                                if 'Participants' in c:
                                    couple_names = self.get_couple_names(
                                        c['Participants'])
                                else:
                                    couple_names = []
                                if len(couple_names) == 2:
                                    self.build_late_entry(
                                        entry.heat,
                                        shirt_number=c['Bib'],
                                        result=c['Result'][-1],
                                        couple_names=couple_names)
                                else:
                                    entry.result = result_str
                                    res_error = Result_Error()
                                    res_error.comp = entry.heat.comp
                                    res_error.heat = entry.heat
                                    res_error.couple = None
                                    res_error.error = Result_Error.LATE_ENTRY
                                    res_error.save()

                        # now we know the number of entries, calculate points
                        for e in entries:
                            if e.points is None and len(e.result) > 0:
                                e.points = calc_points(
                                    level,
                                    int(e.result),
                                    num_competitors=self.entries_in_event,
                                    rounds=rounds)
                            if e.points is not None:
                                #print(e, e.result, e.points)
                                e.save()

                        for late_entry in self.late_entries:
                            if late_entry.points is None:
                                late_entry.points = calc_points(
                                    level,
                                    int(late_entry.result),
                                    num_competitors=self.entries_in_event,
                                    rounds=rounds)
                                late_entry.save()

                    else:  # process early rounds, looking for those who were eliminated
                        if r['Name'] == "Semi-Final":
                            if rounds == "F":
                                rounds = "S"
                            result_index = -2
                            temp_result = "Semis"
                        elif r['Name'] == "Quarter-Final":
                            if rounds == "F":
                                rounds = "Q"
                            result_index = -1
                            temp_result = "quarters"
                        elif r['Name'] == "Round 1":
                            if rounds == "F":
                                rounds = "R1"
                            result_index = -10
                            temp_result = "round 1"
                        elif r['Name'] == "Round 2":
                            if rounds == "F" or rounds == "R1":
                                rounds = "R21"
                            result_index = -5
                            temp_result = "round 2"
                        elif r['Name'] == "Round 3":
                            if rounds == "F" or rounds == "R1" or rounds == "R21":
                                rounds = "R321"
                            result_index = -3
                            temp_result = "round 3"
                        else:
                            print("Unknown Round")
                            print(r)
                            xxx()
                        for c in r['Summary']['Competitors']:
                            if c['Recalled'] == 0:
                                for entry in entries:
                                    if str(entry.shirt_number) == c['Bib']:
                                        if len(
                                                entry.result
                                        ) == 0 or entry.result == temp_result:
                                            # If the couple was not recalled, their result is the round
                                            # in which they were eliminated
                                            entry.result = temp_result

                                            # Lookup their points, and exit the loop
                                            entry.points = calc_points(
                                                level,
                                                result_index,
                                                rounds=rounds,
                                                accum=c['Total'])
                                            break
                                        else:
                                            res_error = Result_Error()
                                            res_error.comp = e.heat.comp
                                            res_error.heat = e.heat
                                            res_error.couple = e.couple
                                            res_error.error = Result_Error.TWO_RESULTS_FOR_COUPLE
                                            res_error.save()
                                            entry.result = temp_result
                                            break

                                else:  # late entry
                                    try:
                                        couple_names = self.get_couple_names(
                                            c['Participants'])
                                        if len(couple_names) == 2:
                                            points = calc_points(
                                                level,
                                                result_index,
                                                rounds=rounds,
                                                accum=c['Total'])
                                            self.build_late_entry(
                                                entry.heat,
                                                shirt_number=c['Bib'],
                                                result=temp_result,
                                                couple_names=couple_names,
                                                points=points)
                                        else:
                                            print("error in late entry names")
                                            xxx()
                                    except:
                                        print("error in late entry names")
    def process_scoresheet_for_event(self, entries, url):
        '''This is the method that requests and processes the scoresheet for a
           particular heat'''

        # on the o2cm site, we only handle final rounds at this time
        looking_for_final_round = True
        looking_for_score_column = False
        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
        looking_for_eliminations = False
        process_finalists = False
        looking_for_semifinal = False
        # on the o2cm site, the couple names are listed separately from the heat results
        looking_for_couple_names = False

        self.entries_in_event = 0
        # for e in entries:
        #     print(e)
        self.heat = entries.first().heat

        # 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="h4"' in l:
                    # once the find the title with the final results, look for the score column or summary.
                    looking_for_score_column = True
                    num_scores = 0
                    total_score = 0
                    looking_for_final_round = False
                    #print("Found Final results")
                else:
                    i += 1
            elif looking_for_score_column:
                if 'class=h3' in l:
                    if "Score" in l:
                        next_row = False
                        rows = l.split("</tr>")
                        for r in rows:
                            if next_row:
                                fields = r.split("</td>")
                                score_column = len(fields) - 4
                                score = float(fields[score_column][len("<td>"):])
                                num_scores += 1
                                total_score += score
                                break
                            if "Score" in r:
                                next_row = True

                        i += 1
                    else:
                        looking_for_score_column = False
                        looking_for_final_summary = True
                elif "Couples" in l:
                    e = entries[0]
                    e.result = 1
                    avg_score = total_score / num_scores
                    e.points = round(calc_points(self.heat.base_value, placement=1, num_competitors=1, score=avg_score), 2)
                    #print(str(e), total_score, avg_score, e.points)
                    e.save()
                    return 1
                    i += 1
                else:
                    i += 1
            elif looking_for_final_summary:
                if 'class=h3' in l and "Summary" in l:
                    # once the summary header is found, look for the result columen
                    looking_for_final_summary = False
                    looking_for_result_column = True
                    #print("Found Summary")
                    col_count = 0
                else:
                    i += 1
            elif looking_for_result_column:
                #print(l)
                rows = l.split("</tr>")
                fields = rows[0].split("</td>")
                # count the number of columns until the result column is found
                if "Res" in l:
                    # once the result column is found, process each finalist
                    col_count = len(fields) - 2
                    #print("Found Results in Column", col_count)
                    looking_for_result_column = False
                    looking_for_finalists = True
                    results = list()
                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:
                rows = l.split("</tr>")
                # 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
                    #print("Found last finalist")
                    looking_for_couple_names = True
                    i += 1
                    # 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>")
                    #print(fields)
                    if len(fields) == col_count + 1:
                        # get the couple name and number from the first column
                        couple_field = fields[0].split("t1b>")[1]
                        # get the result info from the last column
                        result_field = fields[col_count-1].split("<td>")[1]
                        # try:
                        #     result_place = int(result_field)
                        # except:
                        #     result_place = None
                        #print("Couple:", couple_field, "Result:", result_field)
                        entry={}
                        entry["couple"] = couple_field
                        entry["result"] = result_field
                        #print(entry)
                        results.append(entry)
                        self.entries_in_event += 1


            elif looking_for_couple_names:
                if 'class=t1b>Couples' in l:
                    #print("Found start of couple list")
                    #print(l)
                    rows = l.split("<tr>")
                    for r in rows:
                        if 'class=t1b>Judges' in r:
                            looking_for_couple_names = False
                            break
                        elif 'individual.asp' in r:
                            # this row has a couple number and names
                            cols = r.split("</td>")
                            # find the shirt number of this couple to match with results
                            start_pos = cols[0].find("t1b>") + len("t1b>")
                            number = cols[0][start_pos:]
                            # extract the couple names
                            couple_names = cols[1].split(",")
                            dancer_name = self.find_name_from_couple_table(couple_names[0])
                            partner_name = self.find_name_from_couple_table(couple_names[1])
                            # match the shirt number with the results found earlier
                            for e in results:
                                if e["couple"] == number:
                                    e["dancer"] = dancer_name
                                    e["partner"] = partner_name
                                    #print(e)
                                    self.process_couple(entries, dancer_name, partner_name, e["couple"], e["result"])
                                    break
                i += 1

            # 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 = "R32"
            #         else:
            #             self.heat.rounds = "R2"
            #         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 process_response(self, entries, e):
        '''This routine processes the response returned by the form submittal.
           It is the scoresheet results for a single dancer.
           We use this to extract the results of the heat we are interested in .'''
        # Build the string to find the results for the heat we want.
        # For example: Pro Heat 5:
        heat_string = e.heat.get_category_display() + " "
        # if the heat number is 0, leave it out
        if e.heat.heat_number != 0:
            heat_string += str(e.heat.heat_number)

        # if extra field was TBD or BOBR, there may be more than one, so include the heat info field
        if e.heat.extra in ["TBD", "BOBR"]:
            heat_string += e.heat.extra + ": " + e.heat.info
        elif len(e.heat.extra) > 0 and e.heat.extra[0].isalpha():
            # if the extra field is a single character, include it (Heat 123A:)
            heat_string += e.heat.extra[0] + ":"
        else:  # need the colon directly after the number, to distinguish 5 from 51, etc.
            heat_string += ":"

        heat_info_from_scoresheet = None

        # If there are parenthesis in the heat info, the heat has multiple dances
        # For example (W/T/F).
        # At this point, we only care about the final results of the heat, not the
        # individual dances.
        if e.heat.multi_dance():
            event = "Multi-Dance"
        else:
            event = "Single Dance"

        # save the level of the event (e.g. Open vs. Rising Star, Bronze, Silver, Gold, etc.)
        level = e.heat.base_value

        # set the rounds indicator to finals, until proven otherwise
        rounds = "F"

        # these are state variables to keep track of where we are in the parsing
        looking_for_recall_column = False
        looking_for_result_column = False
        looking_for_eliminations = False
        looking_for_finalists = False
        result = None

        # split the response into separate lines so we can loop through them
        lines = self.response.text.splitlines()
        for line in lines:
            # the result column is the last in the table, but there is one
            # column per judge, and we don't know how many judges there are
            if looking_for_result_column:
                # find the start of a table row
                if "<tr>" in line:
                    count = 0
                # If we have found the result column, save which column it is
                # and change the state to looking_for_finalists
                elif "<td>" in line and "Result" in line:
                    result_column = count
                    looking_for_finalists = True
                    looking_for_result_column = False
                    self.entries_in_event = 0
                    count = 0
                # skip past this column, it is not the last
                elif "<td>" in line:
                    count += 1

            # If we are processing the preliminary round results,
            # we look for the Recall column in the results of the last dance.
            # The logic is basically the same as looking for results, except
            # when we find that column, the next state is looking_for_eliminations
            elif looking_for_recall_column:
                if "<tr>" in line:
                    count = 0
                # this should only be true on sheets that don't identify the semi-final heat
                elif "<td>" in line and "Result" in line:
                    looking_for_recall_column = False
                    result = "Finals"
                elif "<td>" in line and "Recall" in line:
                    recall_column = count
                    accum_column = recall_column - 1
                    looking_for_eliminations = True
                    looking_for_recall_column = False
                    count = 0
                    if rounds == "F":
                        temp_result = "Semis"
                        result_index = -2
                        rounds = "S"
                        print("Found Semis unexpectedly")
                        res_error = Result_Error()
                        res_error.comp = e.heat.comp
                        res_error.heat = e.heat
                        res_error.error = Result_Error.UNEXPECTED_EARLY_ROUND
                        res_error.save()
                elif "<td>" in line:
                    count += 1

            # If we are processing the preliminary round results,
            # we want to know which entries were not recalled to the next round.
            elif looking_for_eliminations:
                if "<td>" in line:
                    if count == 0:
                        # This is the first column, get the competitor information.
                        # This could be any of the entries in this heat, not necessarily
                        # the dancer we used to submit the form
                        current_competitor = self.get_table_data(line)
                        count += 1

                    elif count == accum_column:
                        # This column indicates how many recall votes a couple received.
                        # If the couple was not recalled, this number affects their points for the heat.
                        try:
                            accum = int(self.get_table_data(line))
                        except:
                            accum = 0
                        count += 1
                    elif count == recall_column:
                        # If the data indicates the couple was recalled, we can ignore them,
                        # as we will get their results in the next round.
                        # If the couple was not recalled, we need to capture those results
                        if self.get_table_data(line) != "Recall":

                            # extract the shirt number from the scoresheet
                            #couple_names = self.get_couple_names(current_competitor)
                            shirt_number = self.get_shirt_number(
                                current_competitor)

                            # try to find this couple from the scoresheet in the original heat report
                            for e in entries:

                                if e.shirt_number == shirt_number:
                                    if len(e.result) == 0:
                                        # If the couple was not recalled, their result is the round
                                        # in which they were eliminated
                                        e.result = temp_result

                                        # Lookup their points, and exit the loop
                                        e.points = calc_points(level,
                                                               result_index,
                                                               rounds=rounds,
                                                               accum=accum)
                                        break

                                    elif e.result == temp_result:
                                        break
                                    else:
                                        print(
                                            str(e.heat.heat_number) +
                                            " Same shirt # - new result: " +
                                            str(e.couple) + " " + e.result +
                                            " " + temp_result + " " +
                                            str(accum))
                                        res_error = Result_Error()
                                        res_error.comp = e.heat.comp
                                        res_error.heat = e.heat
                                        res_error.couple = e.couple
                                        res_error.error = Result_Error.TWO_RESULTS_FOR_COUPLE
                                        res_error.save()
                                        e.result = temp_result

                            # If we get here, we didn't find an entry on the heatsheet that matches
                            # this line on the scoresheet. This is the dreaded late entry.
                            else:
                                # Build a structure for the late entry couple with the results
                                couple_names = self.get_couple_names(
                                    current_competitor)
                                points = calc_points(level,
                                                     result_index,
                                                     rounds=rounds,
                                                     accum=accum)
                                self.build_late_entry(
                                    e.heat,
                                    shirt_number=shirt_number,
                                    result=temp_result,
                                    couple_names=couple_names,
                                    points=points)

                        # reset the count to prepare for the next line of the scoresheet
                        count = 0

                    else:
                        # skip this column, it is not the recall column
                        count += 1

                elif "</table>" in line:
                    # once we get to the end of the table, there are no more entries to process
                    looking_for_eliminations = False

            # When we are looking for finalists, the logic is similar to looking for eliminations
            elif looking_for_finalists:
                num_competitors = len(entries)
                if "<td>" in line:
                    if count == 0:
                        current_competitor = self.get_table_data(line)
                        self.entries_in_event += 1
                        count += 1
                    elif count == result_column:
                        # When we get to the result column, we want to extract the number that indicates
                        # the finishing position of this couple in this heat.
                        # Need to check for non-digit, as the result could include a tiebreaker rule
                        # For example: 3(R11) means they finished in 3rd place.
                        result_field = self.get_table_data(line)
                        index = 0
                        while index < len(result_field) and result_field[
                                index] in string.digits:
                            index += 1
                        result_place = int(result_field[:index])

                        #couple_names = self.get_couple_names(current_competitor)
                        shirt_number = self.get_shirt_number(
                            current_competitor)

                        # loop through all entries on the heatsheet to find a match
                        for e in entries:

                            if e.shirt_number == shirt_number:
                                if len(e.result) == 0:
                                    e.result = str(result_place)
                                    break
                                elif e.result == str(result_place):
                                    break
                                else:
                                    print(
                                        str(e.heat.heat_number) +
                                        " Same number - new result: " + " " +
                                        str(e.couple.dancer_1) + " " +
                                        str(e.couple.dancer_2) + " " +
                                        e.result + " " + str(result_place))
                                    e.result = str(result_place)
                                    res_error = Result_Error()
                                    res_error.comp = e.heat.comp
                                    res_error.heat = e.heat
                                    res_error.couple = e.couple
                                    res_error.error = Result_Error.TWO_RESULTS_FOR_COUPLE
                                    res_error.save()
                                    break

                        else:  # this code runs when competitor not found in heat
                            couple_names = self.get_couple_names(
                                current_competitor)
                            if len(couple_names) > 1:
                                self.build_late_entry(
                                    e.heat,
                                    shirt_number=shirt_number,
                                    result=str(result_place),
                                    couple_names=couple_names)
                            else:
                                print("Error in couple " + " " +
                                      str(couple_names))

                        # reset for next line of the scoresheet
                        count = 0

                    else:  # skip past this column
                        count += 1

                # When we see the closing table tag, we are done with this heat.
                elif "</table>" in line:
                    looking_for_finalists = False
                    for e in entries:
                        if e.points is None and len(e.result) > 0:
                            e.points = calc_points(
                                level,
                                int(e.result),
                                num_competitors=self.entries_in_event,
                                rounds=rounds)
                        if e.points is not None:
                            #print(e, e.result, e.points)
                            e.save()
                    for late_entry in self.late_entries:
                        if late_entry.points is None:
                            late_entry.points = calc_points(
                                level,
                                int(late_entry.result),
                                num_competitors=self.entries_in_event,
                                rounds=rounds)
                            late_entry.save()
                            #print("LATE ENTRY SCORING: " + late_entry.result + " " + str(late_entry.points))
                    break

            # We get here if we aren't in any of the "looking" states
            # Note: These scoresheets list the preliminary rounds first, ending with the final round

            # If this check is true, we found first round results for this heat
            elif heat_string in line and "First Round" in line and (
                    "<p>" in line or "<h3>" in line):
                temp_result = "round 1"  # indicate which round we are in
                result_index = -10  # use this to pull values from the points table
                rounds = "R1"
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "First Round")
                looking_for_recall_column = True  # enter the next state

            # If this check is true, we found second round results for this heat
            elif heat_string in line and "Second Round" in line and (
                    "<p>" in line or "<h3>" in line):
                temp_result = "round 2"  # indicate which round we are in
                result_index = -5  # use this to pull values from the points table
                rounds = "R21"
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "Second Round")
                looking_for_recall_column = True  # enter the next state

            # If this check is true, we found third round results for this heat
            elif heat_string in line and "Third Round" in line and (
                    "<p>" in line or "<h3>" in line):
                temp_result = "round 3"  # indicate which round we are in
                result_index = -53  # use this to pull values from the points table
                rounds = "R321"
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "Third Round")
                looking_for_recall_column = True  # enter the next state

            # If this check is true, we found quarter-final results for this heat
            elif heat_string in line and "QUARTER" in line.upper(
            ) and "FINAL" in line.upper() and ("<p>" in line
                                               or "<h3>" in line):
                temp_result = "quarters"  # indicate which round we are in
                result_index = -1  # use this to pull values from the points table
                #print("Found Quarterfinals")
                # if we haven't seen a prelim round, set rounds indicator to quarters
                if rounds == "F":
                    rounds = "Q"
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "Quarter-final")
                looking_for_recall_column = True  # enter the next state

            # If this check is true, we found Semi-final results for this heat
            elif heat_string in line and "SEMI-FINAL" in line.upper() and (
                    "<p>" in line or "<h3>" in line):
                temp_result = "Semis"
                result_index = -2
                #print("Found Semifinals")
                if rounds == "F":
                    rounds = "S"
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "Semi-final")
                looking_for_recall_column = True

            # If this check is true, we found the Final results for this heat
            elif heat_string in line and ("<p>" in line or "<h3>"
                                          in line):  # and "Final" in line:
                #print("Found " + heat_string)
                heat_info_from_scoresheet = self.get_heat_info(
                    line, heat_string, "Final")
                # if this is a single dance event, we can look for the results now
                if event == "Single Dance":
                    result = "Finals"
                    #print("Found Finals - single dance")
                    looking_for_result_column = True
                else:
                    looking_for_recall_column = True  # this may not be the final on some websites

            # If this is the Final of a Multi-Dance event, we process the Final Summary
            elif result == "Finals" and "Final summary" in line and (
                    "<p>" in line or "<h3>" in line):
                if event == "Multi-Dance":
                    #print("Found Finals")
                    looking_for_result_column = True

            elif "Place" in line and "<th>" in line:
                print("Found a table header with Place " + line)

        # Return which level of results we were able to find on this dancer's scoresheet
        # If they were eliminated before the finals, the final results will not appear,
        # and the calling routine will have to try another dancer to get those.
        return result