def index(): db = get_db() if request.method == "POST": date = request.form["date"] parse_date = datetime.strptime(date, "%Y-%m-%d") database_date = datetime.strftime(parse_date, "%Y%m%d") db.execute("insert into log_date (entry_date) values (?)", [database_date]) db.commit() cur = db.execute( "select log_date.entry_date, sum(food.protein) as protein, sum(food.carbohydrates) as carbohydrates, sum(food.fat) as fat, sum(food.calories) as calories from log_date left join food_date on food_date.log_date_id = log_date.id left join food on food.id = food_date.food_id group by log_date.id order by log_date.entry_date desc" ) results = cur.fetchall() date_results = [] for i in results: single_date = {} single_date["entry_date"] = i["entry_date"] single_date["protein"] = i["protein"] single_date["carbohydrates"] = i["carbohydrates"] single_date["fat"] = i["fat"] single_date["calories"] = i["calories"] d = datetime.strptime(str(i["entry_date"]), "%Y%m%d") single_date["html_date"] = datetime.strftime(d, "%B %d, %Y") date_results.append(single_date) return render_template("home.html", results=date_results)
async def delete_avatar(driver_id: int): """ Delete a driver's profile picture """ try: file_location = __get_avatar_path(driver_id) except SecurityException: raise HTTPException( status_code=404, detail=f"No avatar found for driver with id {driver_id}") # Update driver profile to clear image URL data = {"id": driver_id, "profilePic": ""} driver = schemas.DriverUpdate(**data) db = next(get_db()) updated_driver = crud.update_driver(db, driver) if not updated_driver: raise HTTPException(status_code=404, detail=f"No driver found with id {driver_id}") # Update active driver cache update_driver_cache(updated_driver) # Delete the image file remove(file_location) return {"success": "image removed"}
async def get_driver_stats(driver_id: int): """ Get overall stats for a driver: - Track time - Records held - Track with most records - TODO laps turned, max speed, favorite tracks """ db = next(get_db()) track_time = crud.get_driver_by_id(db, driver_id).trackTime laptimes = [ time for time in crud.get_laptimes(db) if time.driverId == driver_id ] records_held = len(laptimes) track_map = Counter(getattr(time, 'trackName') for time in laptimes) favorite_track = "" if track_map: favorite_track = max(track_map, key=track_map.get) return schemas.DriverStats( **{ "trackTime": track_time, "recordsHeld": records_held, "favoriteTrack": favorite_track })
async def upload_avatar(driver_id: int, profile_pic: UploadFile = File(...)): """ Upload a new driver profile picture """ try: file_location = __get_avatar_path(driver_id) except SecurityException: raise HTTPException( status_code=400, detail=f"Invalid request for driver with id {driver_id}") # Update driver profile with link to new avatar image data = {"id": driver_id, "profilePic": f"/avatars/{driver_id}"} driver = schemas.DriverUpdate(**data) db = next(get_db()) updated_driver = crud.update_driver(db, driver) if not updated_driver: raise HTTPException(status_code=404, detail=f"No driver found with id {driver_id}") # Update active driver cache update_driver_cache(updated_driver) # Save the image file with open(file_location, "wb+") as file_object: shutil.copyfileobj(profile_pic.file, file_object) return {"success": "image upload completed"}
async def delete_driver(driver_id: int): """ Delete a driver """ db = next(get_db()) result = crud.delete_driver_by_id(db, driver_id) return result
async def create_driver(driver: schemas.DriverCreate): """ Create a new driver """ db = next(get_db()) new_driver = crud.create_driver(db, driver) return new_driver
async def get_drivers(skip: int = 0, limit: int = -1): """ Get all drivers """ db = next(get_db()) drivers = crud.get_drivers(db, skip=skip, limit=limit) return drivers
async def get_controllers(skip: int = 0, limit: int = -1): """ Get all WLED light controllers """ db = next(get_db()) controllers = crud.get_light_controllers(db, skip=skip, limit=limit) return controllers
async def update_quote(quote: schemas.Quote): """ Update a quote """ db = next(get_db()) updated_quote = crud.update_quote(db, quote) return updated_quote
async def partial_update_quote(quote: schemas.QuoteUpdate): """ Update a quote (partial update) """ db = next(get_db()) updated_quote = crud.update_quote(db, quote) return updated_quote
async def get_scores(skip: int = 0, limit: int = -1): """ Get the current best lap times """ db = next(get_db()) laptimes = crud.get_laptimes(db, skip=skip, limit=limit) return laptimes
async def delete_quote(quote: schemas.QuoteDelete): """ Delete a quote """ db = next(get_db()) result = crud.delete_quote(db, quote) return result
async def create_controller(controller: schemas.LightControllerCreate): """ Create a new WLED light controller """ db = next(get_db()) new_controller = crud.create_light_controller(db, controller) return new_controller
async def get_random_quote(): """ Get a random racing quote """ db = next(get_db()) quote = crud.get_random_quote(db) return quote
async def get_quotes(skip: int = 0, limit: int = -1): """ Get all racing quotes """ db = next(get_db()) quotes = crud.get_quotes(db, skip=skip, limit=limit) return quotes
async def get_controller_settings(controllerId: int, driverId: int): """ Get controller settings linked to a driver profile """ db = next(get_db()) controller_settings = crud.get_controller_settings(db, controllerId, driverId) return controller_settings
async def delete_controller(controller: schemas.LightControllerDelete): """ Delete a light controller """ db = next(get_db()) result = crud.delete_light_controller(db, controller) return result
async def delete_controller(settings: schemas.LightControllerSettingsDelete): """ Delete settings for a light controller """ db = next(get_db()) result = crud.delete_light_controller(db, settings) return result
async def update_controller(controller: schemas.LightControllerUpdate): """ Update controller information """ db = next(get_db()) updated_controller = crud.update_light_controller(db, controller) return updated_controller
async def create_quote(quote: schemas.QuoteCreate): """ Create a new quote """ db = next(get_db()) new_quote = crud.create_quote(db, quote) return new_quote
async def update_driver(driver: schemas.DriverUpdate): """ Update driver information """ db = next(get_db()) updated_driver = crud.update_driver(db, driver) update_driver_cache(updated_driver) return updated_driver
async def update_controller_settings(db, controller_settings: schemas.LightControllerSettingsUpdate): """ Update settings profile for a light controller """ db = next(get_db()) new_controller_settings = crud.update_controller_settings( db, controller_settings ) return new_controller_settings
async def create_controller_settings(controller_settings: schemas.LightControllerSettingsCreate): """ Create a settings profile for a light controller """ db = next(get_db()) new_controller_settings = crud.create_controller_settings( db, controller_settings ) return new_controller_settings
async def create_score(laptime: schemas.LapTimeCreate): """ Log a new lap time. Only gets commited if it's a personal best. """ db = next(get_db()) new_laptime = crud.create_laptime(db, laptime) # Update redis key for streaming set_session_best_lap(new_laptime) return new_laptime
def init_quotes(): """ Initialize the quotes table with JSON data """ db = next(get_db()) quote_count = db.query(Quote).count() if quote_count == 0: path = os.path.dirname(os.path.realpath(__file__)) data = json.load(open(os.path.join(path, "quotes.json"))) crud.batch_create_quote(db, data)
async def set_active_driver(self, driver: schemas.ActiveDriverCreate): """ Select the active driver """ db = next(get_db()) crud.delete_active_driver(db) new_active_driver = crud.set_active_driver(db, driver) self.queue_manager.put("active_driver", new_active_driver.driver) # Update cache for worker threads self.__update_driver_cache(new_active_driver.driver) return new_active_driver.driver
def food(): db = get_db() if request.method == "POST": carbs = int(request.form["carbohydrates"]) fat = int(request.form["fat"]) protein = int(request.form["protein"]) name = request.form["food-name"] calories = protein * 4 + carbs * 4 + fat * 9 db.execute( "insert into food (name,protein,carbohydrates,fat,calories) values (?,?,?,?,?)", [name, protein, carbs, fat, calories], ) db.commit() return redirect("/food") else: cur = db.execute("select name,protein,carbohydrates,fat,calories from food") res = cur.fetchall() return render_template("add_food.html", res=res)
def get_active_driver_from_cache(): """ Get the active driver from cache. Tries the Redis cache first. If it is empty, check the database. """ redis_store = get_redis_store() try: active_driver = json.loads(redis_store.get("active_driver")) except (redis.exceptions.ConnectionError, TypeError): db = next(get_db()) active_driver_object = crud.get_active_driver(db) if active_driver_object: active_driver = active_driver_object.driver else: # No active driver, empty response return None return active_driver
def view(date): db = get_db() cur = db.execute("select id, entry_date from log_date where entry_date = ?", [date]) date_result = cur.fetchone() if request.method == "POST": selected = request.form["selected_food"] db.execute( "insert into food_date (food_id,log_date_id) values (?,?)", [selected, date_result["id"]], ) db.commit() selected_date = datetime.strftime(helper_date(date_result), "%B %d %Y") food_cur = db.execute("select id, name from food") res_food = food_cur.fetchall() log_cur = db.execute( "select food.name, food.protein, food.carbohydrates, food.fat, food.calories from log_date join food_date on food_date.log_date_id = log_date.id join food on food.id = food_date.food_id where log_date.entry_date = ?", [date], ) log_res = log_cur.fetchall() day_total = {"protein": 0, "carbohydrates": 0, "fat": 0, "calories": 0} for food in log_res: day_total["protein"] += food["protein"] day_total["carbohydrates"] += food["carbohydrates"] day_total["fat"] += food["fat"] day_total["calories"] += food["calories"] return render_template( "day.html", entry_date=date_result["entry_date"], selected_date=selected_date, res_food=res_food, log_res=log_res, day_total=day_total, )
def run(self): # Get the active driver and their track time db = next(get_db()) active_driver_object = crud.get_active_driver(db) active_driver = None best_lap_time = 0 track_time = 0 if active_driver_object: active_driver = active_driver_object.driver track_time = active_driver.trackTime self.log.info('Logging data for ' + active_driver.name) else: self.log.info('No driver selected. Lap times will not be recorded.') # Continue parsing data until ordered to stop while self.active: try: # Get data from the stream latest = self.data_stream.latest() latest_raw = self.data_stream.latest(raw=True) # Check for updates from the API updated_driver = self.queue_manager.get('active_driver') pending_task = self.queue_manager.get('tasks') if updated_driver: active_driver = updated_driver track_time = updated_driver.trackTime self.log.info('Setting active driver to ' + active_driver.name) if pending_task == 'latest': self.queue_manager.put('iracing_data_latest', latest) if pending_task == 'latest_raw': self.queue_manager.put('iracing_data_latest', latest_raw) if pending_task == 'stream': self.queue_manager.put('iracing_data_stream', latest) if pending_task == 'stream_raw': self.queue_manager.put('iracing_data_stream', latest_raw) if not self.data_stream.is_active or not latest['is_on_track']: best_lap_time = 0 # Update the driver's track time if active_driver and active_driver.trackTime < math.floor(track_time): self.log.info('Updating track time for ' + active_driver.name) active_driver = crud.update_driver(db, DriverUpdate( id=active_driver.id, trackTime=track_time )) # Stop the stream and wait if self.controller.is_connected: self.controller.stop() self.log.info('iRacing data lost - waiting') self.data_stream.restart() sleep(1) continue else: # Re-establish connection if not self.controller.is_connected: self.log.info('Reconnecting') self.controller.reconnect() # Check for car swaps if self.rpm_strip.redline != latest['redline']: self.rpm_strip.set_redline(latest['redline']) self.log.debug('Setting redline to new value: ' + str(latest['redline'])) if self.rpm_strip.idle_rpm != latest['idle_rpm']: self.rpm_strip.set_idle_rpm(latest['idle_rpm']) self.log.debug('Setting idle RPM to new value: ' + str(latest['idle_rpm'])) # Get the RPM and update the light controller self.rpm_strip.set_rpm(latest['rpm']) self.controller.update(self.rpm_strip.to_color_list()) # Log the best lap time if latest['best_lap_time'] > 0 and (best_lap_time == 0 or latest['best_lap_time'] < best_lap_time): best_lap_time = latest['best_lap_time'] if active_driver: self.log.info('Setting new best lap time for ' + active_driver.name) new_record = LapTimeCreate( car=latest['car_name'], trackName=latest['track_name'], trackConfig=latest['track_config'] or '', time=latest['best_lap_time'], driverId=active_driver.id ) new_laptime = crud.create_laptime(db, new_record) # Update Redis key for streaming self.redis_store.set('session_best_lap', schemas.LapTime(**new_laptime.__dict__).json()) # Update Redis keys self.redis_store.set('session_data', json.dumps(latest)) self.redis_store.set('session_data_raw', json.dumps(latest_raw)) self.log.debug(latest) track_time += 1/self.framerate sleep(1/self.framerate) except KeyboardInterrupt: self.log.info('Keyboard interrupt received - exiting') self.stop() except KeyError: self.log.error('Required data not found - stopping iRacing stream') self.data_stream.stop() except ConnectionResetError: self.log.error('iRacing refused connection') self.data_stream.stop() except ConnectionError: self.log.error('Redis server refused connection') except Exception: self.log.exception('Unhandled condition') self.data_stream.stop()