diff --git a/apiserver/src/data/repos.py b/apiserver/src/data/repos.py index 0e7337f..6547770 100644 --- a/apiserver/src/data/repos.py +++ b/apiserver/src/data/repos.py @@ -1,5 +1,5 @@ from ..core.models import RepoTemplate -from .models import Prefix, Ticket, Count, Basket +from .models import Prefix, Ticket, Count, Basket, WinnerByBasket class PrefixRepo(RepoTemplate): @@ -120,3 +120,39 @@ class BasketRepo(RepoTemplate): SET description = EXCLUDED.description""", (b.prefix, b.basket_id, b.description, b.winning_ticket)) self.conn.commit() return {"detail": "Baskets posted successfully."} + +class DrawingRepo(RepoTemplate): + """The repo that controls the drawing system.""" + + def get_all_winners(self): + """Gets all winners of baskets.""" + self.cur.execute("SELECT * FROM winners_by_basket ORDER BY prefix, basket_id") + results = self.cur.fetchall() + return [WinnerByBasket(*r) for r in results] + + def get_prefix_winners(self, prefix: str): + """Gets winners of a prefix of baskets.""" + self.cur.execute("SELECT * FROM winners_by_basket WHERE prefix = ? ORDER BY basket_id", (prefix,)) + results = self.cur.fetchall() + return [WinnerByBasket(*r) for r in results] + + def get_one_winner(self, prefix: str, b_id: int): + """Gets one winner.""" + self.cur.execute("SELECT * FROM winners_by_basket WHERE prefix = ? AND basket_id = ?", (prefix, b_id)) + result = self.cur.fetchone() + return WinnerByBasket(*result) + + def get_range_winners(self, prefix: str, r_start: int, r_end: int): + """Gets a range of winners.""" + self.cur.execute("SELECT * FROM winners_by_basket WHERE prefix = ? AND basket_id BETWEEN ? AND ?", (prefix, r_start, r_end)) + results = self.cur.fetchall() + return [WinnerByBasket(*r) for r in results] + + def post_winners(self, bs: list[Basket]): + """Posts a range of winners.""" + for b in bs: + self.cur.execute("""INSERT INTO baskets (prefix, basket_id, winning_ticket) + VALUES (?, ?, ?) ON CONFLICT (prefix, basket_id) DO UPDATE SET + winning_ticket = EXCLUDED.winning_ticket""", (b.prefix, b.basket_id, b.winning_ticket)) + self.conn.commit() + return {"detail": "Winners posted successfully."} diff --git a/apiserver/src/data/routers.py b/apiserver/src/data/routers.py index 1062920..0630912 100644 --- a/apiserver/src/data/routers.py +++ b/apiserver/src/data/routers.py @@ -1,47 +1,60 @@ -from fastapi import APIRouter, Header, status, HTTPException +from fastapi import APIRouter, Header, HTTPException, status -from .repos import PrefixRepo, TicketRepo, CountsRepo, BasketRepo -from .models import Prefix, Ticket, Basket from ..core.auth import AuthRepo +from .models import Basket, Prefix, Ticket +from .repos import BasketRepo, CountsRepo, DrawingRepo, PrefixRepo, TicketRepo prefix_router = APIRouter(prefix="/api/prefix") -inv_numbers_ex = HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="After last / has to be either an integer or range of integers (such as 1-20).") +inv_numbers_ex = HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="After last / has to be either an integer or range of integers (such as 1-20).", +) + @prefix_router.get("") def get_all_prefixes(tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return PrefixRepo().get_prefixes() + @prefix_router.get("/{prefix}") def get_one_prefix(prefix: str, tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return PrefixRepo().get_one_prefix(prefix) + @prefix_router.post("") def post_one_prefix(prefix: Prefix, tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return PrefixRepo().post_prefix(prefix) + @prefix_router.delete("") def del_one_prefix(prefix: str = "", tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return PrefixRepo().del_prefix(prefix) + ticket_router = APIRouter(prefix="/api/tickets") + @ticket_router.get("") def get_all_tickets(tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return TicketRepo().get_all_tickets() + @ticket_router.get("/{prefix}") def get_prefix_tickets(prefix: str, tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return TicketRepo().get_prefix_tickets(prefix) + @ticket_router.get("/{prefix}/{s_id}") -def get_ticket_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")) -> Ticket | list[Ticket]: +def get_ticket_scope( + prefix: str, s_id: str, tam_auth_key: str = Header("") +) -> Ticket | list[Ticket]: AuthRepo().verify_key(tam_auth_key) if "-" in s_id: l_id = s_id.split("-", maxsplit=2) @@ -57,32 +70,41 @@ def get_ticket_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")) -> raise inv_numbers_ex return TicketRepo().get_one_ticket(prefix, i_id) + @ticket_router.post("") def post_tickets(ts: list[Ticket], tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return TicketRepo().post_tickets(ts) + counts_router = APIRouter(prefix="/api/counts") + @counts_router.get("") def get_counts(tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return CountsRepo().get_counts() + basket_router = APIRouter(prefix="/api/baskets") + @basket_router.get("") def get_all_baskets(tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return BasketRepo().get_all_baskets() + @basket_router.get("/{prefix}") def get_prefix_baskets(prefix: str, tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return BasketRepo().get_prefix_baskets(prefix) + @basket_router.get("/{prefix}/{s_id}") -def get_basket_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")) -> Basket | list[Basket]: +def get_basket_scope( + prefix: str, s_id: str, tam_auth_key: str = Header("") +) -> Basket | list[Basket]: AuthRepo().verify_key(tam_auth_key) if "-" in s_id: l_id = s_id.split("-", maxsplit=2) @@ -98,7 +120,47 @@ def get_basket_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")) -> raise inv_numbers_ex return BasketRepo().get_one_baskets(prefix, i_id) + @basket_router.post("") def post_baskets(bs: list[Basket], tam_auth_key: str = Header("")): AuthRepo().verify_key(tam_auth_key) return BasketRepo().post_baskets(bs) + + +drawing_router = APIRouter(prefix="/api/winners") + + +@drawing_router.get("") +def get_all_drawing(tam_auth_key: str = Header("")): + AuthRepo().verify_key(tam_auth_key) + return DrawingRepo().get_all_winners() + + +@drawing_router.get("/{prefix}") +def get_prefix_drawing(prefix: str, tam_auth_key: str = Header("")): + AuthRepo().verify_key(tam_auth_key) + return DrawingRepo().get_prefix_winners(prefix) + + +@drawing_router.get("/{prefix}/{s_id}") +def get_drawing_scope(prefix: str, s_id: str, tam_auth_key: str = Header("")): + AuthRepo().verify_key(tam_auth_key) + if "-" in s_id: + try: + r_id = s_id.split("-", maxsplit=2) + r_start, r_end = int(r_id[0]), int(r_id[1]) + except ValueError: + raise inv_numbers_ex + return DrawingRepo().get_range_winners(prefix, r_start, r_end) + else: + try: + i_id = int(s_id) + except ValueError: + raise inv_numbers_ex + return DrawingRepo().get_one_winner(prefix, i_id) + + +@drawing_router.post("") +def post_winners(bs: list[Basket], tam_auth_key: str = Header("")): + AuthRepo().verify_key(tam_auth_key) + return DrawingRepo().post_winners(bs) diff --git a/apiserver/src/routers.py b/apiserver/src/routers.py index bbc72b3..6d3603c 100644 --- a/apiserver/src/routers.py +++ b/apiserver/src/routers.py @@ -9,3 +9,4 @@ def append_routers(app: FastAPI): app.include_router(routers.ticket_router) app.include_router(routers.counts_router) app.include_router(routers.basket_router) + app.include_router(routers.drawing_router)