/ components / paddock / telemetry / racing_stats.py
racing_stats.py
  1  from datetime import datetime, timedelta
  2  
  3  from django.db import connection
  4  from django.db.models import CharField, Count, Max, Q, Value
  5  
  6  from telemetry.models import FastLap, Game, Lap, Track
  7  
  8  
  9  class RacingStats:
 10      def __init__(self):
 11          pass
 12  
 13      def combos(self, type="", **kwargs):
 14          return self.driver_combos(type=type, **kwargs)
 15  
 16      def driver_combos(self, driver=None, range=30, type="circuit", **kwargs):
 17          filter = {}
 18          if driver is not None:
 19              filter["session__driver__name"] = driver
 20  
 21          # Calculate the start date based on the range
 22          start_date = datetime.now() - timedelta(days=range)
 23  
 24          laps = Lap.objects.filter(**filter)
 25          # Filter laps based on the end time within the range
 26          laps = laps.filter(session__end__gte=start_date)
 27          # group by game, track, and car
 28          if type == "circuit" or type == "":
 29              laps = laps.values(
 30                  "session__game__name", "track__name", "car__name", "session__game__id", "track__id", "car__id"
 31              )
 32              # annotate with count of laps, valid laps, and latest lap end time
 33              laps = laps.annotate(
 34                  lap_count=Count("id"), valid_lap_count=Count("id", filter=Q(valid=True)), latest_lap_end=Max("end")
 35              )
 36              if type == "circuit":
 37                  # exclude all rally games: Richard Burns Rally, Dirt Rally, Dirt Rally 2.0
 38                  laps = laps.exclude(session__game__name__in=["Richard Burns Rally", "Dirt Rally", "Dirt Rally 2.0"])
 39          elif type == "rally":
 40              laps = laps.values("session__game__name", "car__name", "session__game__id", "car__id", "track__game__id")
 41              # add a field called track__name with a hardcoded value of "Multiple"
 42              laps = laps.annotate(
 43                  track__name=Value("Multiple", output_field=CharField()),
 44                  track__id=Value(0, output_field=CharField()),
 45                  lap_count=Count("id"),
 46                  valid_lap_count=Count("id", filter=Q(valid=True)),
 47                  latest_lap_end=Max("end"),
 48              )
 49              # only include rally games: Richard Burns Rally, Dirt Rally, Dirt Rally 2.0
 50              laps = laps.filter(session__game__name__in=["Richard Burns Rally", "Dirt Rally", "Dirt Rally 2.0"])
 51          # order by latest lap end time
 52          laps = laps.order_by("-latest_lap_end")
 53  
 54          # show the sql of the query
 55          # print(laps.query)
 56  
 57          return laps
 58  
 59      def known_combos_list(self, game=None, track=None, car=None, **kwargs):
 60          laps = self.known_combos(game, track, car, **kwargs)
 61          for row in laps:
 62              yield row["track__game__name"], row["car__name"], row["track__name"], row["count"]
 63  
 64      def known_combos(self, game=None, track=None, car=None, **kwargs):
 65          filter = {}
 66          if game:
 67              filter["track__game__name"] = game
 68          if track:
 69              filter["track__name"] = track
 70          if car:
 71              filter["car__name"] = car
 72  
 73          filter["valid"] = True
 74          laps = Lap.objects.filter(**filter)
 75          # group by track and car and game
 76          laps = laps.values("track__name", "car__name", "track__game__name")
 77          laps = laps.annotate(count=Count("id"))
 78          laps = laps.order_by("track__game__name", "car__name", "track__name")
 79          return laps
 80  
 81      def fast_lap_values(self, game=None, track=None, car=None, **kwargs):
 82          filter = {}
 83          if game:
 84              filter["game__name"] = game
 85          if track:
 86              filter["track__name"] = track
 87          if car:
 88              filter["car__name"] = car
 89  
 90          filter["driver"] = None
 91  
 92          laps = FastLap.objects.filter(**filter)
 93          # group by track and car and game
 94          laps = laps.values("track__name", "car__name", "game__name")
 95          # laps = laps.annotate(count=Count("id"))
 96          laps = laps.order_by("game__name", "car__name", "track__name")
 97          return laps
 98          # for row in laps:
 99          #     yield row["track__game__name"], row["car__name"], row["track__name"], row["count"]
100  
101      def fast_laps(self, game=None, track=None, car=None, **kwargs):
102          filter = {}
103          filter["game__name"] = game
104          filter["track__name"] = track
105          filter["car__name"] = car
106  
107          laps = FastLap.objects.filter(**filter)
108          return laps
109  
110      def laps(self, game=None, track=None, car=None, driver=None, valid=None, **kwargs):
111          filter = {}
112          if game:
113              filter["track__game__name"] = game
114          if track:
115              filter["track__name"] = track
116          if car:
117              filter["car__name"] = car
118  
119          if valid is not None:
120              filter["valid"] = valid
121  
122          if driver is not None:
123              filter["session__driver__name"] = driver
124  
125          laps = Lap.objects.filter(**filter)
126          laps = laps.order_by("time")
127          # limit to 10
128          # laps = laps[:10]
129          return laps
130  
131          # for lap in laps:
132          #     yield lap
133  
134      def fast_laps_cursor(self, game=None, track=None, car=None, **kwargs):
135          where = []
136          filter_game = None
137          if game:
138              filter_game = Game.objects.get(name=game)
139          if track:
140              track = Track.objects.get(name=track)
141              where.append(f" track_id={track.pk}")
142          if car:
143              # get the first car with this name
144              car = filter_game.cars.filter(name=car).first()
145              where.append(f"car_id={car.pk}")
146  
147          where_clause = ""
148          if where:
149              where_clause = "where " + " and ".join(where)
150  
151          sql = f"select count(id) as c, track_id, car_id from telemetry_lap {where_clause} group by track_id, car_id"
152  
153          with connection.cursor() as cursor:
154              cursor.execute(sql)
155              rows = cursor.fetchall()
156  
157          return rows