Exemplo n.º 1
0
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)
Exemplo n.º 2
0
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"}
Exemplo n.º 3
0
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
        })
Exemplo n.º 4
0
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"}
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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
Exemplo n.º 9
0
async def update_quote(quote: schemas.Quote):
    """
    Update a quote
    """
    db = next(get_db())
    updated_quote = crud.update_quote(db, quote)

    return updated_quote
Exemplo n.º 10
0
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
Exemplo n.º 11
0
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
Exemplo n.º 12
0
async def delete_quote(quote: schemas.QuoteDelete):
    """
    Delete a quote
    """
    db = next(get_db())
    result = crud.delete_quote(db, quote)

    return result
Exemplo n.º 13
0
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
Exemplo n.º 14
0
async def get_random_quote():
    """
    Get a random racing quote
    """
    db = next(get_db())
    quote = crud.get_random_quote(db)

    return quote
Exemplo n.º 15
0
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
Exemplo n.º 16
0
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
Exemplo n.º 17
0
async def delete_controller(controller: schemas.LightControllerDelete):
    """
    Delete a light controller
    """
    db = next(get_db())
    result = crud.delete_light_controller(db, controller)

    return result
Exemplo n.º 18
0
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
Exemplo n.º 19
0
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
Exemplo n.º 20
0
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
Exemplo n.º 21
0
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
Exemplo n.º 22
0
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
Exemplo n.º 23
0
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
Exemplo n.º 24
0
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
Exemplo n.º 25
0
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)
Exemplo n.º 26
0
    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
Exemplo n.º 27
0
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)
Exemplo n.º 28
0
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
Exemplo n.º 29
0
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,
    )
Exemplo n.º 30
0
    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()