Skip to content
This repository has been archived by the owner on Dec 12, 2024. It is now read-only.

Commit

Permalink
feat: added leaderboard
Browse files Browse the repository at this point in the history
  • Loading branch information
TatarinAlba committed Nov 30, 2024
1 parent d40424f commit 005b513
Show file tree
Hide file tree
Showing 193 changed files with 113 additions and 28 deletions.
6 changes: 0 additions & 6 deletions backend/src/api/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,6 @@ def generate_unique_operation_id(route: APIRoute) -> str:
app.mount(settings.static_mount_path, StaticFiles(directory=settings.static_directory), name="static")


from src.modules.events.routes import router as router_events # noqa: E402
from src.modules.notifies.routes import router as router_notify # noqa: E402
from src.modules.sports.routes import router as router_sports # noqa: E402
from src.modules.users.routes import router as router_users # noqa: E402

app.include_router(router_users)
app.include_router(router_events)
app.include_router(router_sports)
app.include_router(router_notify)
2 changes: 0 additions & 2 deletions backend/src/api/lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@

from src.config import settings
from src.logging_ import logger
from src.modules.notifies.repository import notification_repository
from src.modules.notifies.scheams import Filter
from src.storages.mongo import document_models


Expand Down
71 changes: 66 additions & 5 deletions backend/src/modules/users/repository.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
__all__ = ["user_repository"]

import datetime

from beanie import PydanticObjectId

from src.modules.users.schemas import CreateUser
from src.storages.mongo.users import User
from src.modules.users.schemas import CreateUser, LevelLeaderboardResp
from src.storages.mongo.users import User, LevelMetaInfo
from fastapi import HTTPException

# noinspection PyMethodMayBeStatic
Expand Down Expand Up @@ -33,9 +35,68 @@ async def exists(self, user_id: PydanticObjectId) -> bool:
async def is_banned(self, user_id: str | PydanticObjectId) -> bool:
return False

async def upsert_level_info(self, user_id: PydanticObjectId, level_name: str, time_passed: float, help_number_used: int, clicks_num: int) -> list[LevelMetaInfo] | None:
user = await User.get(user_id)

if user.level_passed is None:
user.level_passed = [LevelMetaInfo(
level_name = level_name,
time_passed = time_passed,
help_number_used = help_number_used,
clicks_num = clicks_num,
attempts = 1,
)]
await User.find_one(User.id == user.id).update(
{
"$set": {User.level_passed: user.level_passed}
}
)
return user.level_passed

found = False

for lvl in user.level_passed:
if lvl.level_name == level_name:
lvl.attempts += 1
if lvl.time_passed > time_passed:
lvl.time_passed = time_passed
found = True
break

if not found:
user.level_passed.append(LevelMetaInfo(
level_name = level_name,
time_passed = time_passed,
help_number_used = help_number_used,
clicks_num = clicks_num,
attempts = 1,
))

await User.find_one(User.id == user.id).update(
{
"$set": {User.level_passed: user.level_passed}
}
)
return user.level_passed

async def upsert_favorites(self, user_id: PydanticObjectId, favorite_items: list[PydanticObjectId]) -> list[PydanticObjectId]:
user = await User.find_one(User.id == user_id).update({"$set": {"favorites": list(set(favorite_items))}})
return favorite_items
async def get_levels_info(self, user_id: PydanticObjectId):
user = await User.get(user_id)
return user.level_passed

async def get_board_for_level(self, level_name: str) -> list[LevelLeaderboardResp]:
users = await User.find_all().to_list()
result: list[LevelLeaderboardResp] = []
for user in users:
if user.level_passed is None:
continue
for lvl in user.level_passed:
if lvl.level_name == level_name:
result.append(
LevelLeaderboardResp(
user_id = user.id,
lvlInfo = lvl,
)
)
return sorted(result, key=lambda x: x.lvlInfo.time_passed)

user_repository: UserRepository = UserRepository()
27 changes: 23 additions & 4 deletions backend/src/modules/users/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from src.api.dependencies import USER_AUTH
from src.api.exceptions import IncorrectCredentialsException
from src.modules.users.repository import user_repository
from src.modules.users.schemas import ViewUser, UpdateFavoriteReq
from src.modules.users.schemas import ViewUser, AddResultReq, LevelLeaderboardResp
from beanie import PydanticObjectId

router = APIRouter(
Expand Down Expand Up @@ -69,6 +69,25 @@ async def logout(request: Request) -> None:
request.session.clear()
return None

@router.put("/favorites")
async def update_favorites(user: USER_AUTH, req: UpdateFavoriteReq) -> list[PydanticObjectId]:
return await user_repository.upsert_favorites(user_id=user.user_id, favorite_items=req.favorite_ids)
@router.post(
"/result",
responses={200: {"description": "Result was added successfully"}}
)
async def add_result(request: AddResultReq, user: USER_AUTH):
"""
Add result to user; if not exist will create it
"""
return await user_repository.upsert_level_info(user.user_id, request.level_name, request.time_passed, request.help_number_used, request.clicks_num)

@router.get(
"/result"
)
async def get_results(user: USER_AUTH):
return await user_repository.get_levels_info(user.user_id)

@router.get(
"/result/{level_name}"
)
async def get_results_by_level_name(level_name: str) -> list[LevelLeaderboardResp]:
return await user_repository.get_board_for_level(level_name)
16 changes: 11 additions & 5 deletions backend/src/modules/users/schemas.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
__all__ = ["CreateUser", "ViewUser"]

import datetime

from beanie import PydanticObjectId

from src.pydantic_base import BaseSchema

from src.storages.mongo.users import LevelMetaInfo

class CreateUser(BaseSchema):
login: str
password: str

class AddResultReq(BaseSchema):
level_name: str
time_passed: float
help_number_used: int
clicks_num: int

class UpdateFavoriteReq(BaseSchema):
favorite_ids: list[PydanticObjectId]

class LevelLeaderboardResp(BaseSchema):
user_id: PydanticObjectId
lvlInfo: LevelMetaInfo

class ViewUser(BaseSchema):
id: PydanticObjectId
login: str
favorites: list[PydanticObjectId]


class UserAuthData(BaseSchema):
Expand Down
6 changes: 1 addition & 5 deletions backend/src/storages/mongo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,9 @@

from beanie import Document, View

from src.storages.mongo.events import Event
from src.storages.mongo.notifies import Notification
from src.storages.mongo.selection import Selection
from src.storages.mongo.sports import Sport
from src.storages.mongo.users import User

document_models = cast(
list[type[Document] | type[View] | str],
[User, Event, Sport, Notification, Selection],
[User],
)
13 changes: 12 additions & 1 deletion backend/src/storages/mongo/users.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
__all__ = ["User", "UserRole"]

import datetime

from enum import StrEnum

from beanie import PydanticObjectId
from pymongo import IndexModel

from src.pydantic_base import BaseSchema
from src.pydantic_base import BaseSchema, BaseModel
from src.storages.mongo.__base__ import CustomDocument


Expand All @@ -14,9 +16,18 @@ class UserRole(StrEnum):
ADMIN = "admin"


class LevelMetaInfo(BaseModel):
level_name: str
time_passed: float
help_number_used: int
clicks_num: int
attempts: int


class UserSchema(BaseSchema):
login: str
password_hash: str
level_passed: list[LevelMetaInfo] | None = None
role: UserRole = UserRole.DEFAULT


Expand Down
Binary file not shown.
Binary file removed backend/static/авиационные_гонки.png
Binary file not shown.
Binary file not shown.
Binary file removed backend/static/айкидо.png
Binary file not shown.
Binary file not shown.
Binary file removed backend/static/альпинизм.png
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file removed backend/static/армрестлинг.png
Binary file not shown.
Binary file removed backend/static/бадминтон.png
Binary file not shown.
Binary file removed backend/static/баскетбол.png
Binary file not shown.
Binary file removed backend/static/бейсбол.png
Binary file not shown.
Binary file removed backend/static/биатлон.png
Binary file not shown.
Binary file removed backend/static/бильярдный_спорт.png
Binary file not shown.
Binary file removed backend/static/бобслей.png
Binary file not shown.
Binary file removed backend/static/бодибилдинг.png
Binary file not shown.
Binary file removed backend/static/бокс.png
Binary file not shown.
Binary file removed backend/static/борьба_на_поясах.png
Binary file not shown.
Binary file removed backend/static/боулинг.png
Binary file not shown.
Binary file removed backend/static/брейкинг.png
Binary file not shown.
Binary file not shown.
Binary file removed backend/static/вертолетный_спорт.png
Binary file not shown.
Binary file not shown.
Binary file removed backend/static/водное_поло.png
Binary file not shown.
Binary file removed backend/static/воднолыжный_спорт.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/волейбол.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/гандбол.png
Diff not rendered.
Binary file removed backend/static/гиревой_спорт.png
Diff not rendered.
Binary file removed backend/static/го.png
Diff not rendered.
Binary file removed backend/static/гольф.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/горнолыжный_спорт.png
Diff not rendered.
Binary file removed backend/static/городошный_спорт.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/гребля_на_шлюпках.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/гребной_слалом.png
Diff not rendered.
Binary file removed backend/static/гребной_спорт.png
Diff not rendered.
Binary file removed backend/static/дартс.png
Diff not rendered.
Binary file removed backend/static/джиу-джитсу.png
Diff not rendered.
Binary file removed backend/static/дзюдо.png
Diff not rendered.
Binary file removed backend/static/ездовой_спорт.png
Diff not rendered.
Binary file removed backend/static/зимнее_плавание.png
Diff not rendered.
Binary file removed backend/static/каратэ.png
Diff not rendered.
Binary file removed backend/static/кендо.png
Diff not rendered.
Binary file removed backend/static/керешу.png
Diff not rendered.
Binary file removed backend/static/кикбоксинг.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/киокусинкай.png
Diff not rendered.
Binary file removed backend/static/киокушин.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/конный_спорт.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/корэш.png
Diff not rendered.
Binary file removed backend/static/кудо.png
Diff not rendered.
Binary file removed backend/static/кёрлинг.png
Diff not rendered.
Binary file removed backend/static/лапта.png
Diff not rendered.
Binary file removed backend/static/легкая_атлетика.png
Diff not rendered.
Binary file removed backend/static/лыжное_двоеборье.png
Diff not rendered.
Binary file removed backend/static/лыжные_гонки.png
Diff not rendered.
Binary file removed backend/static/мас-рестлинг.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/микрофутзал.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/муайтай.png
Diff not rendered.
Binary file removed backend/static/нарды.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/падел.png
Diff not rendered.
Binary file removed backend/static/парашютный_спорт.png
Diff not rendered.
Binary file removed backend/static/парусный_спорт.png
Diff not rendered.
Binary file removed backend/static/пауэрлифтинг.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/пилонный_спорт.png
Diff not rendered.
Binary file removed backend/static/плавание.png
Diff not rendered.
Binary file removed backend/static/планерный_спорт.png
Diff not rendered.
Binary file removed backend/static/подводный_спорт.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/полиатлон.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/прыжки_в_воду.png
Diff not rendered.
Binary file removed backend/static/прыжки_на_батуте.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/пулевая_стрельба.png
Diff not rendered.
Binary file removed backend/static/пэйнтбол.png
Diff not rendered.
Binary file removed backend/static/радиоспорт.png
Diff not rendered.
Binary file removed backend/static/рафтинг.png
Diff not rendered.
Binary file removed backend/static/регби.png
Diff not rendered.
Binary file removed backend/static/роллер_спорт.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/рукопашный_бой.png
Diff not rendered.
Binary file removed backend/static/рыболовный_спорт.png
Diff not rendered.
Binary file removed backend/static/сават.png
Diff not rendered.
Binary file removed backend/static/самбо.png
Diff not rendered.
Binary file removed backend/static/самолетный_спорт.png
Diff not rendered.
Binary file removed backend/static/санный_спорт.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/серфинг.png
Diff not rendered.
Binary file removed backend/static/силовой_экстрим.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/скалолазание.png
Diff not rendered.
Binary file removed backend/static/сквош.png
Diff not rendered.
Binary file removed backend/static/скейтбординг.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/сноуборд.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/софтбол.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/спорт_глухих.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/спорт_слепых.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/страйкбол.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/стрельба_из_лука.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/сумо.png
Diff not rendered.
Binary file removed backend/static/таврели.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/теннис.png
Diff not rendered.
Binary file removed backend/static/триатлон.png
Diff not rendered.
Binary file removed backend/static/тхэквондо.png
Diff not rendered.
Binary file removed backend/static/тхэквондо_гтф.png
Diff not rendered.
Binary file removed backend/static/тхэквондо_итф.png
Diff not rendered.
Binary file removed backend/static/тхэквондо_мфт.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/ушу.png
Diff not rendered.
Binary file removed backend/static/фехтование.png
Diff not rendered.
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/фитнес-аэробика.png
Diff not rendered.
Binary file removed backend/static/флорбол.png
Diff not rendered.
Binary file removed backend/static/фристайл.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/футбол.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/хапкидо.png
Diff not rendered.
Binary file removed backend/static/хапсагай.png
Diff not rendered.
Binary file removed backend/static/хоккей.png
Diff not rendered.
Binary file removed backend/static/хоккей_на_траве.png
Diff not rendered.
Binary file removed backend/static/хоккей_с_мячом.png
Diff not rendered.
Diff not rendered.
Binary file removed backend/static/хуреш.png
Diff not rendered.
Binary file removed backend/static/чир_спорт.png
Diff not rendered.
Binary file removed backend/static/шахматы.png
Diff not rendered.
Binary file removed backend/static/шашки.png
Diff not rendered.
Binary file removed backend/static/шодсанлат.png
Diff not rendered.
Diff not rendered.
Diff not rendered.

0 comments on commit 005b513

Please sign in to comment.