2024-07-24 22:53:56 +02:00
|
|
|
from typing import Union
|
2024-08-12 12:08:08 +02:00
|
|
|
from datetime import date, timedelta, datetime
|
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
from sqlmodel import Session
|
2024-08-16 10:13:47 +02:00
|
|
|
from threading import Thread
|
2024-08-08 18:13:01 +02:00
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
|
2024-08-12 12:08:08 +02:00
|
|
|
from fastapi import FastAPI, Depends
|
2024-08-08 16:35:06 +02:00
|
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
|
from contextlib import asynccontextmanager
|
2024-07-24 22:53:56 +02:00
|
|
|
|
2024-08-11 21:42:07 +02:00
|
|
|
from src.classes import boardgame_classes, play_classes, statistic_classes
|
2024-08-08 16:35:06 +02:00
|
|
|
from src.modules import data_connection
|
2024-08-12 12:08:08 +02:00
|
|
|
from src.filters import boardgame_filters, play_filters
|
2024-08-08 16:35:06 +02:00
|
|
|
|
2024-08-16 10:13:47 +02:00
|
|
|
is_refreshing = False
|
|
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
def get_session():
|
|
|
|
|
with Session(data_connection.get_db_engine()) as session:
|
|
|
|
|
yield session
|
|
|
|
|
|
|
|
|
|
def refresh_data():
|
2024-08-16 10:13:47 +02:00
|
|
|
global is_refreshing
|
|
|
|
|
|
|
|
|
|
is_refreshing = True
|
2024-08-15 11:07:11 +02:00
|
|
|
data_connection.delete_database()
|
2024-08-16 10:13:47 +02:00
|
|
|
data_connection.create_db_and_tables()
|
2024-08-15 11:07:11 +02:00
|
|
|
with Session(data_connection.get_db_engine()) as session:
|
|
|
|
|
data_connection.get_user_collection(session)
|
|
|
|
|
data_connection.get_user_owned_collection(session)
|
|
|
|
|
data_connection.get_user_wishlist_collection(session)
|
2024-08-16 10:13:47 +02:00
|
|
|
data_connection.get_plays(session)
|
|
|
|
|
|
|
|
|
|
is_refreshing = False
|
2024-08-15 11:07:11 +02:00
|
|
|
|
2024-08-08 16:35:06 +02:00
|
|
|
@asynccontextmanager
|
|
|
|
|
async def lifespan(app: FastAPI):
|
|
|
|
|
# Startup
|
2024-08-15 11:07:11 +02:00
|
|
|
#data_connection.delete_database()
|
2024-08-08 16:35:06 +02:00
|
|
|
data_connection.create_db_and_tables()
|
2024-08-15 11:07:11 +02:00
|
|
|
|
|
|
|
|
#refresh_data()
|
2024-08-08 16:35:06 +02:00
|
|
|
yield
|
|
|
|
|
# Shutdown
|
|
|
|
|
|
|
|
|
|
app = FastAPI(lifespan=lifespan)
|
|
|
|
|
|
|
|
|
|
origins = [
|
|
|
|
|
"http://127.0.0.1:8080",
|
|
|
|
|
"http://0.0.0.0:8080" #Will become something like 'bordspellen2.yarnecoppens.com'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
app.add_middleware(
|
|
|
|
|
CORSMiddleware,
|
|
|
|
|
allow_origins=origins,
|
|
|
|
|
allow_credentials=True,
|
|
|
|
|
allow_methods=["*"],
|
|
|
|
|
allow_headers=["*"],
|
|
|
|
|
)
|
2024-07-24 22:53:56 +02:00
|
|
|
|
2024-08-12 12:08:08 +02:00
|
|
|
#expansion filtering parameters
|
2024-08-15 11:18:27 +02:00
|
|
|
class BoardgameFilterParams(BaseModel):
|
2024-08-12 12:08:08 +02:00
|
|
|
filter_expansions_out: bool = False
|
|
|
|
|
only_expansions: bool = False
|
|
|
|
|
|
|
|
|
|
def do_filtering(self,boardgame_list):
|
|
|
|
|
if self.filter_expansions_out:
|
2024-08-15 11:18:27 +02:00
|
|
|
boardgame_list = boardgame_filters.filter_expansions_out(boardgame_list)
|
2024-08-12 12:08:08 +02:00
|
|
|
|
|
|
|
|
if self.only_expansions:
|
2024-08-15 11:18:27 +02:00
|
|
|
boardgame_list = boardgame_filters.filter_non_expansions_out(boardgame_list)
|
|
|
|
|
|
|
|
|
|
return boardgame_list
|
|
|
|
|
|
|
|
|
|
class PlayFilterParams(BaseModel):
|
|
|
|
|
filter_expansions_out: bool = False
|
|
|
|
|
only_expansions: bool = False
|
|
|
|
|
|
|
|
|
|
def do_filtering(self, play_list):
|
|
|
|
|
if self.filter_expansions_out:
|
|
|
|
|
play_list = play_filters.filter_expansions_out(play_list)
|
|
|
|
|
|
|
|
|
|
if self.only_expansions:
|
|
|
|
|
play_list = play_filters.filter_non_expansions_out(play_list)
|
|
|
|
|
|
|
|
|
|
return play_list
|
2024-08-12 12:08:08 +02:00
|
|
|
|
|
|
|
|
|
2024-07-24 22:53:56 +02:00
|
|
|
@app.get("/")
|
|
|
|
|
def read_root():
|
|
|
|
|
return {"Hello": "World"}
|
|
|
|
|
|
2024-08-16 10:13:47 +02:00
|
|
|
@app.get('/refresh')
|
|
|
|
|
def refresh():
|
|
|
|
|
if not is_refreshing:
|
|
|
|
|
Thread(target=refresh_data).start()
|
|
|
|
|
return {"Status": "Started refresh"}
|
|
|
|
|
else:
|
|
|
|
|
return {"Status": "Already refreshing"}
|
|
|
|
|
|
|
|
|
|
|
2024-08-13 10:35:25 +02:00
|
|
|
@app.get("/boardgame", response_model=Union[boardgame_classes.BoardGame, boardgame_classes.BoardGameExpansion])
|
2024-08-15 11:07:11 +02:00
|
|
|
def get_boardgame_by_id(id: int, session: Session = Depends(get_session)):
|
|
|
|
|
requested_boardgame: Union[boardgame_classes.BoardGame, boardgame_classes.BoardGameExpansion] = data_connection.get_boardgame(session, id)
|
2024-07-31 16:03:24 +02:00
|
|
|
return requested_boardgame
|
|
|
|
|
|
2024-08-08 18:41:18 +02:00
|
|
|
@app.get("/owned", response_model=list[Union[boardgame_classes.OwnedBoardGame, boardgame_classes.OwnedBoardGameExpansion]])
|
2024-08-15 11:18:27 +02:00
|
|
|
def get_owned_collection(query: BoardgameFilterParams = Depends(), session: Session = Depends(get_session)):
|
2024-08-15 11:07:11 +02:00
|
|
|
to_return_boardgames = data_connection.get_user_owned_collection(session)
|
2024-08-12 09:10:03 +02:00
|
|
|
|
2024-08-15 11:18:27 +02:00
|
|
|
to_return_boardgames = query.do_filtering(to_return_boardgames)
|
2024-08-12 09:10:03 +02:00
|
|
|
|
2024-08-16 10:13:47 +02:00
|
|
|
to_return_boardgames.sort(key=lambda x: x.name)
|
|
|
|
|
|
2024-08-11 19:58:22 +02:00
|
|
|
return to_return_boardgames
|
2024-08-01 10:35:51 +02:00
|
|
|
|
|
|
|
|
|
2024-08-08 18:41:18 +02:00
|
|
|
@app.get("/wishlist", response_model=list[Union[boardgame_classes.WishlistBoardGame, boardgame_classes.WishlistBoardGameExpansion]])
|
2024-08-15 11:18:27 +02:00
|
|
|
def get_wishlist_collection(priority: int = 0, query: BoardgameFilterParams = Depends(), session: Session = Depends(get_session)):
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
to_return_boardgames = data_connection.get_user_wishlist_collection(session, priority)
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:18:27 +02:00
|
|
|
to_return_boardgames = query.do_filtering(to_return_boardgames)
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-16 10:13:47 +02:00
|
|
|
to_return_boardgames.sort(key=lambda x: x.name)
|
|
|
|
|
|
2024-08-13 10:45:34 +02:00
|
|
|
return to_return_boardgames
|
2024-08-12 12:08:08 +02:00
|
|
|
|
2024-08-02 12:48:35 +02:00
|
|
|
|
2024-08-12 12:08:08 +02:00
|
|
|
@app.get("/plays", response_model=list[play_classes.PlayPublicWithPlayers])
|
2024-08-15 11:18:27 +02:00
|
|
|
def get_plays(query: PlayFilterParams = Depends(), boardgame_id: int = -1, session: Session = Depends(get_session)):
|
2024-08-12 20:11:34 +02:00
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
requested_plays = data_connection.get_plays(session)
|
2024-08-12 20:11:34 +02:00
|
|
|
|
2024-08-15 11:18:27 +02:00
|
|
|
requested_plays = query.do_filtering(requested_plays)
|
2024-08-12 20:23:05 +02:00
|
|
|
|
|
|
|
|
if boardgame_id > -1:
|
|
|
|
|
requested_plays = play_filters.filter_only_specific_boardgame(boardgame_id, requested_plays)
|
2024-08-11 21:27:59 +02:00
|
|
|
|
|
|
|
|
return requested_plays
|
|
|
|
|
|
|
|
|
|
|
2024-08-12 12:16:28 +02:00
|
|
|
@app.get('/players', response_model=list[play_classes.PlayPlayerPublic])
|
2024-08-15 11:07:11 +02:00
|
|
|
def get_players_from_play(play_id: int, session: Session = Depends(get_session)):
|
|
|
|
|
requested_players = data_connection.get_players_from_play(session, play_id)
|
2024-08-11 21:27:59 +02:00
|
|
|
|
2024-08-11 21:42:07 +02:00
|
|
|
return requested_players
|
|
|
|
|
|
2024-08-11 22:18:12 +02:00
|
|
|
@app.get('/statistics/amount_of_games', response_model=statistic_classes.NumberStatistic)
|
2024-08-15 11:18:27 +02:00
|
|
|
def get_amount_of_games(query: BoardgameFilterParams = Depends(), session: Session = Depends(get_session)):
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
owned_collection = data_connection.get_user_owned_collection(session)
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:21:33 +02:00
|
|
|
owned_collection = query.do_filtering(owned_collection)
|
2024-08-11 21:42:07 +02:00
|
|
|
|
|
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Amount of games in owned collection",
|
2024-08-13 10:45:34 +02:00
|
|
|
"result":len(owned_collection)
|
2024-08-11 21:42:07 +02:00
|
|
|
}
|
|
|
|
|
|
2024-08-11 22:18:12 +02:00
|
|
|
statistic_to_return = statistic_classes.NumberStatistic(**statistic_dict)
|
2024-08-11 21:52:36 +02:00
|
|
|
|
2024-08-11 22:18:12 +02:00
|
|
|
return statistic_to_return
|
|
|
|
|
|
2024-08-15 19:47:30 +02:00
|
|
|
@app.get('/statistics/total_collection_cost', response_model=statistic_classes.NumberStatistic)
|
|
|
|
|
def get_total_collection_cost(query: BoardgameFilterParams = Depends(), session: Session = Depends(get_session)):
|
|
|
|
|
|
|
|
|
|
owned_collection = data_connection.get_user_owned_collection(session)
|
|
|
|
|
|
|
|
|
|
owned_collection = query.do_filtering(owned_collection)
|
|
|
|
|
|
|
|
|
|
total_cost = sum([boardgame.price_paid for boardgame in owned_collection])
|
|
|
|
|
|
|
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Total cost of the owned collection",
|
|
|
|
|
"result":total_cost
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
statistic_to_return = statistic_classes.NumberStatistic(**statistic_dict)
|
|
|
|
|
|
|
|
|
|
return statistic_to_return
|
|
|
|
|
|
2024-08-11 22:52:15 +02:00
|
|
|
@app.get('/statistics/amount_of_games_over_time', response_model=statistic_classes.TimeLineStatistic)
|
2024-08-16 10:13:47 +02:00
|
|
|
def get_amount_of_games_over_time(query: BoardgameFilterParams = Depends(), day_step: int = 1, session: Session = Depends(get_session)):
|
2024-08-11 22:52:15 +02:00
|
|
|
|
2024-08-12 09:10:03 +02:00
|
|
|
def daterange(start_date: date, end_date: date, day_step):
|
2024-08-11 22:52:15 +02:00
|
|
|
days = int((end_date - start_date).days)
|
2024-08-12 09:10:03 +02:00
|
|
|
for n in range(0, days, day_step):
|
2024-08-11 22:52:15 +02:00
|
|
|
yield start_date + timedelta(n)
|
|
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
games_in_owned_collection = data_connection.get_user_owned_collection(session)
|
2024-08-11 22:52:15 +02:00
|
|
|
games_in_owned_collection.sort(key=lambda x: x.acquisition_date)
|
|
|
|
|
|
2024-08-12 09:18:43 +02:00
|
|
|
start_date = games_in_owned_collection[0].acquisition_date
|
|
|
|
|
|
2024-08-15 11:21:33 +02:00
|
|
|
games_in_owned_collection = query.do_filtering(games_in_owned_collection)
|
2024-08-12 09:18:43 +02:00
|
|
|
|
2024-08-11 22:52:15 +02:00
|
|
|
timeline_dict = {}
|
|
|
|
|
|
2024-08-12 09:18:43 +02:00
|
|
|
for current_date in daterange(start_date, date.today(), day_step):
|
2024-08-11 22:52:15 +02:00
|
|
|
games_in_collection_at_date = list(filter(lambda game: game.acquisition_date <= current_date, games_in_owned_collection))
|
|
|
|
|
timeline_dict[current_date] = len(games_in_collection_at_date)
|
|
|
|
|
|
|
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Amount of games in owned collection over time",
|
|
|
|
|
"result":timeline_dict
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
statistic_to_return = statistic_classes.TimeLineStatistic(**statistic_dict)
|
|
|
|
|
|
|
|
|
|
return statistic_to_return
|
|
|
|
|
|
2024-08-12 12:08:08 +02:00
|
|
|
@app.get('/statistics/games_played_per_year', response_model=statistic_classes.TimeLineStatistic)
|
2024-08-15 13:47:50 +02:00
|
|
|
def get_amount_of_games_played_per_year(query: PlayFilterParams = Depends(), session: Session = Depends(get_session)):
|
2024-08-15 11:07:11 +02:00
|
|
|
all_plays = data_connection.get_plays(session)
|
2024-08-12 12:08:08 +02:00
|
|
|
|
|
|
|
|
all_plays.sort(key= lambda x: x.play_date)
|
|
|
|
|
|
2024-08-15 11:21:33 +02:00
|
|
|
all_plays = query.do_filtering(all_plays)
|
2024-08-13 10:35:25 +02:00
|
|
|
|
2024-08-12 12:08:08 +02:00
|
|
|
all_played_boardgame_ids = []
|
|
|
|
|
|
|
|
|
|
for play in all_plays:
|
|
|
|
|
if play.boardgame_id not in all_played_boardgame_ids:
|
|
|
|
|
all_played_boardgame_ids.append(play.boardgame_id)
|
|
|
|
|
|
|
|
|
|
first_year_played = all_plays[0].play_date.year
|
|
|
|
|
current_year = datetime.now().year
|
|
|
|
|
|
|
|
|
|
years_plays_dict = {}
|
|
|
|
|
|
|
|
|
|
for year in range(first_year_played, current_year + 1):
|
|
|
|
|
plays_in_year = list(filter(lambda x: x.play_date.year == year, all_plays))
|
2024-08-14 22:19:56 +02:00
|
|
|
years_plays_dict[year] = len(plays_in_year)
|
2024-08-12 12:08:08 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Amount of games played per year",
|
|
|
|
|
"result":years_plays_dict
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
statistic_to_return = statistic_classes.TimeLineStatistic(**statistic_dict)
|
|
|
|
|
|
|
|
|
|
return statistic_to_return
|
|
|
|
|
|
2024-08-11 22:18:12 +02:00
|
|
|
|
2024-08-15 10:29:54 +02:00
|
|
|
@app.get('/statistics/most_expensive_games', response_model=statistic_classes.GamesStatistic)
|
2024-08-15 11:18:27 +02:00
|
|
|
def get_most_expensive_game(query: BoardgameFilterParams = Depends(), top_amount: int = 10, session: Session = Depends(get_session)):
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:07:11 +02:00
|
|
|
most_expensive_games: list[Union[boardgame_classes.OwnedBoardGame, boardgame_classes.OwnedBoardGameExpansion]] = data_connection.get_user_owned_collection(session)
|
2024-08-13 10:45:34 +02:00
|
|
|
|
2024-08-15 11:21:33 +02:00
|
|
|
most_expensive_games = query.do_filtering(most_expensive_games)
|
2024-08-11 22:18:12 +02:00
|
|
|
|
|
|
|
|
most_expensive_games.sort(key=lambda x: x.price_paid, reverse=True)
|
|
|
|
|
|
|
|
|
|
most_expensive_games = most_expensive_games[0:top_amount]
|
|
|
|
|
|
|
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Most expensive games",
|
|
|
|
|
"result":most_expensive_games
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-15 10:29:54 +02:00
|
|
|
statistic_to_return = statistic_classes.GamesStatistic(**statistic_dict)
|
2024-08-11 22:18:12 +02:00
|
|
|
|
|
|
|
|
return statistic_to_return
|
2024-08-15 10:29:54 +02:00
|
|
|
|
|
|
|
|
@app.get('/statistics/shelf_of_shame', response_model=statistic_classes.GamesStatistic)
|
2024-08-15 21:48:30 +02:00
|
|
|
def get_shelf_of_shame(query: BoardgameFilterParams = Depends(), top_amount: int = -1, session: Session = Depends(get_session)):
|
2024-08-15 13:47:50 +02:00
|
|
|
boardgames_in_collection = data_connection.get_user_collection(session)
|
|
|
|
|
|
|
|
|
|
owned_boardgames = data_connection.get_user_owned_collection(session)
|
|
|
|
|
|
|
|
|
|
#To make sure plays are loaded in
|
|
|
|
|
data_connection.get_plays(session)
|
|
|
|
|
|
|
|
|
|
owned_ids = [boardgame.id for boardgame in owned_boardgames]
|
|
|
|
|
|
|
|
|
|
owned_boardgames_in_collection = list(filter(lambda x: x.id in owned_ids, boardgames_in_collection))
|
|
|
|
|
|
|
|
|
|
owned_boardgames_in_collection = query.do_filtering(owned_boardgames_in_collection)
|
|
|
|
|
|
|
|
|
|
owned_boardgames_no_plays = list(filter(lambda x: len(x.plays) == 0, owned_boardgames_in_collection))
|
|
|
|
|
|
2024-08-16 10:13:47 +02:00
|
|
|
owned_boardgames_no_plays.sort(key=lambda x: x.name)
|
|
|
|
|
|
2024-08-15 13:47:50 +02:00
|
|
|
statistic_dict = {
|
|
|
|
|
"name":"Shelf of Shame",
|
|
|
|
|
"result":owned_boardgames_no_plays[0:top_amount]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
statistic_to_return = statistic_classes.GamesStatistic.model_validate(statistic_dict)
|
|
|
|
|
|
|
|
|
|
return statistic_to_return
|