def _create_and_validate_classnames(self, trackname_obj, classnames): # Create all the required singleracedetail objects in the DB racenum_count = 1 for classname in classnames: classname[1] = self._create_racedetail(trackname_obj, classname[0], racenum_count) racenum_count += 1 database_cleanup.collapse_alias_classnames(models.SingleRaceDetails.objects.all()) # Validate that the names were collapse correctly. for classname in classnames: racedetail = models.SingleRaceDetails.objects.get(pk=classname[1]) self.assertEqual(classname[2], racedetail.racedata)
def collapse_alias_classnames(modeladmin, request, queryset): # For every SingleRaceDetails in the queryset we want # to see if it is an alias, if it is, than change # it to the official database_cleanup.collapse_alias_classnames(queryset)
def process_singlerace(race): ''' Insert the information in the singlerace object into the DB. Conditions - The trackname is already in the db. ''' # ==================================================== # Trackname # ==================================================== # Track - We assume it has already been validated that this is a known track. # NOTE - we do not want to be creating new tracks in this code, if the track # is new it probably means they are not uploading appropriately. track_obj = TrackName.objects.get(trackname=race.trackName) # ==================================================== # Get additional meta info for creating the race details # ==================================================== # Find race length racelength = _calculate_race_length(race.raceHeaderData) # Find Winning lap count maxlaps = 0; for racer in race.raceHeaderData: if (racer['Laps'] > maxlaps): maxlaps = racer['Laps'] # Parse this '10:32:24 PM 8/13/2011' timestruct = time.strptime(race.date, "%I:%M:%S %p %m/%d/%Y") # Format the time to get something like this '2012-01-04 20:20:20-01' formatedtime = time.strftime('%Y-%m-%d %H:%M:%S', timestruct) currenttime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # ==================================================== # Check for duplicates # ==================================================== # We want to stop if this race is already in the database test_objs = SingleRaceDetails.objects.filter( #trackkey=track_obj, # I dont want to accidentally upload results across tracks #racedata=race.raceClass, # This gets modified by the collapse names code. roundnumber=race.roundNumber, racenumber=race.raceNumber, racedate=formatedtime, racelength=racelength, winninglapcount=maxlaps, mainevent=race.mainEvent, maineventroundnum=race.mainEventRoundNum, maineventparsed=race.mainEventParsed) if (len(test_objs) != 0): # We want to tell the user since this not what they wanted. # We can be reasonably certain this file has already been uploaded. raise FileAlreadyUploadedError("File already uploaded") # ==================================================== # Insert Racers # ==================================================== # We want to add a new racerid if one does not already exist. for racer in race.raceHeaderData: racer_obj, created = RacerId.objects.get_or_create(racerpreferredname=racer['Driver']) racer['racer_obj'] = racer_obj # ==================================================== # Insert Race Details # ==================================================== details_obj = SingleRaceDetails(trackkey=track_obj, racedata=race.raceClass, roundnumber=race.roundNumber, racenumber=race.raceNumber, racedate=formatedtime, uploaddate=currenttime, racelength=racelength, winninglapcount=maxlaps, mainevent=race.mainEvent, maineventroundnum=race.mainEventRoundNum, maineventparsed=race.mainEventParsed) details_obj.save() # ==================================================== # Insert Race Laps # ==================================================== bulk_laptimes = [] # For each racer in the raceHeaderData for racer in race.raceHeaderData: # Upload each lap for this racer, their care number - 1 indicates # the index of their laps in the lapRowsTime list. index = racer['Car#'] - 1 # This would be a good place to check and see if there are enough laps, it # has been observed that the parser can fail to get everyone's lap data (another # pending bug). if index >= len(race.lapRowsTime): # I am going to try and move on, it is not totally un-expected that the race director # might mangle this part. SIMPLE - Racer in header, but no laps recorded. continue #raise FileUnableToParseError("This racer %s is missing his laps: %s" % (index, race.raceHeaderData)) for row in range(0, len(race.lapRowsTime[index])): # print "Debug: ", racer # print "Debug: ", lapRowsPosition[index] if (race.lapRowsPosition[index][row] == ''): race.lapRowsPosition[index][row] = None race.lapRowsTime[index][row] = None lap_obj = LapTimes(raceid=details_obj, racerid=racer['racer_obj'], racelap=row, raceposition=race.lapRowsPosition[index][row], racelaptime=race.lapRowsTime[index][row]) bulk_laptimes.append(lap_obj) #lap_obj.save() LapTimes.objects.bulk_create(bulk_laptimes) # ==================================================== # Insert Race Results # ==================================================== ''' Example of the data structure we will work with here: [{"Driver":"TOM WAGGONER", "Car#":"9", "Laps":"26", "RaceTime":"8:07.943", "Fast Lap":"17.063", "Behind":"6.008", "Final Position":9} , ...] ''' bulk_raceheader = [] for racer in race.raceHeaderData: if (racer['RaceTime'] == ''): racer['RaceTime'] = None else: # Convert the racetime to a datetime.time object, # this is required to ensure the microseconds are not # chopped off. racer['RaceTime'] = datetime.datetime.strptime(racer['RaceTime'], "%M:%S.%f") if (racer['Fast Lap'] == ''): racer['Fast Lap'] = None if (racer['Behind'] == ''): racer['Behind'] = None individual_result = SingleRaceResults(raceid=details_obj, racerid=racer['racer_obj'], carnum=racer['Car#'], lapcount=racer['Laps'], racetime=racer['RaceTime'], fastlap=racer['Fast Lap'], behind=racer['Behind'], finalpos=racer['Final Position']) #individual_result.save() bulk_raceheader.append(individual_result) SingleRaceResults.objects.bulk_create(bulk_raceheader) # TODO - I can see the following code being good stuff to log. # =============================================================== # Collapse alias racer names. # =============================================================== collapse_racer_names() # =============================================================== # Collapse class names. # =============================================================== # Note - this likely changed the race's name. collapse_alias_classnames(SingleRaceDetails.objects.filter(id__exact=details_obj.id)) return details_obj