Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ ENV DOCUMENT_BASE_PATH="/workspaces/WebWebWeb/test-assets/documents"
ENV ALBUM_BASE_PATH="/workspaces/WebWebWeb/test-assets/albums"
ENV ASSETS_BASE_PATH="/workspaces/WebWebWeb/test-assets/assets"
ENV MOOSE_GAME_TOKEN="sad_secret_key"
ENV ENCLOSE_MOOSE_TOKEN="happy_secret_key"

RUN mkdir -p "$DOCUMENT_BASE_PATH" \
"$ALBUM_BASE_PATH" \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/custom-tests-v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,5 @@ jobs:
TEST_REDIS_URL: redis://localhost:6379/0
ENVIRONMENT: "testing"
USER_MANAGER_SECRET: "test_secret"
ENCLOSE_MOOSE_TOKEN: "happy_secret_key"
run: pytest -v
53 changes: 53 additions & 0 deletions api_schemas/enclose_moose_level_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from pydantic import Field, model_validator
from datetime import datetime, date
from zoneinfo import ZoneInfo
from api_schemas.base_schema import BaseSchema
from api_schemas.enclose_moose_submission_schema import EncloseMooseSubmissionRead


class EncloseMooseLevelRead(BaseSchema):
level_id: str
release_date: date
day_index: int | None
name: str

encoded_grid: str
wall_budget: int

show_spoilers: bool = Field(default=False, exclude=True)

optimal_score: int | None = None
optimal_solution: set[int] | None = None
optimal_is_unique: bool | None = None

player_submission: EncloseMooseSubmissionRead | None = None
score_distribution: dict[int, int] | None = None

@model_validator(mode="after")
def redact_spoilers(self):
if not self.show_spoilers:
self.optimal_score = None
self.optimal_solution = None
self.optimal_is_unique = None
self.score_distribution = None

return self


class EncloseMooseLevelCreate(BaseSchema):
level_id: str
release_date: date = datetime.now(ZoneInfo("Europe/Stockholm")).date()
day_index: int | None = None
name: str

encoded_grid: str
wall_budget: int


class EncloseMooseLevelUpdate(BaseSchema):
release_date: date | None = None
day_index: int | None = None
name: str | None = None

encoded_grid: str | None = None
wall_budget: int | None = None
15 changes: 15 additions & 0 deletions api_schemas/enclose_moose_submission_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from api_schemas.base_schema import BaseSchema
from helpers.types import datetime


class EncloseMooseSubmissionRead(BaseSchema):
level_id: str
submission_time: datetime

player_id: int
player_score: int
player_solution: set[int]


class EncloseMooseSubmissionCreate(BaseSchema):
player_solution: set[int]
37 changes: 37 additions & 0 deletions db_models/enclose_moose_level_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from datetime import date
from helpers.constants import MAX_ENCLOSE_LEVEL_ID, MAX_ENCLOSE_LEVEL_NAME, MAX_ENCLOSE_GRID
from .base_model import BaseModel_DB
from sqlalchemy.orm import relationship, mapped_column, Mapped
from typing import TYPE_CHECKING, Optional
from sqlalchemy import JSON, String, Date

if TYPE_CHECKING:
from db_models.enclose_moose_submission_model import EncloseMooseSubmission_DB


class EncloseMooseLevel_DB(BaseModel_DB):
__tablename__ = "enclose_moose_level_table"

level_id: Mapped[str] = mapped_column(String(MAX_ENCLOSE_LEVEL_ID), primary_key=True)
release_date: Mapped[Optional[date]] = mapped_column(Date)
day_index: Mapped[Optional[int]] = mapped_column()
name: Mapped[str] = mapped_column(String(MAX_ENCLOSE_LEVEL_NAME))

encoded_grid: Mapped[str] = mapped_column(String(MAX_ENCLOSE_GRID))
wall_budget: Mapped[int] = mapped_column()

optimal_score: Mapped[int] = mapped_column()
optimal_solution: Mapped[list[int]] = mapped_column(JSON)
optimal_is_unique: Mapped[Optional[bool]] = mapped_column()

submissions: Mapped[list["EncloseMooseSubmission_DB"]] = relationship(
back_populates="level", cascade="all, delete-orphan", init=False
)

@property
def score_distribution(self):
score_distribution: dict[int, int] = {}
for submission in self.submissions:
score_distribution[submission.player_score] = score_distribution.get(submission.player_score, 0) + 1

return score_distribution
26 changes: 26 additions & 0 deletions db_models/enclose_moose_submission_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from helpers.constants import MAX_ENCLOSE_LEVEL_ID
from .base_model import BaseModel_DB
from sqlalchemy.orm import relationship, mapped_column, Mapped
from sqlalchemy import ForeignKey, JSON, String
from typing import TYPE_CHECKING
from helpers.types import datetime_utc

if TYPE_CHECKING:
from db_models.enclose_moose_level_model import EncloseMooseLevel_DB


class EncloseMooseSubmission_DB(BaseModel_DB):
__tablename__ = "enclose_moose_submission_table"

level_id: Mapped[str] = mapped_column(
String(MAX_ENCLOSE_LEVEL_ID),
ForeignKey("enclose_moose_level_table.level_id", ondelete="CASCADE"),
primary_key=True,
)
submission_time: Mapped[datetime_utc] = mapped_column()

player_id: Mapped[int] = mapped_column(primary_key=True)
player_score: Mapped[int] = mapped_column()
player_solution: Mapped[list[int]] = mapped_column(JSON)

level: Mapped["EncloseMooseLevel_DB"] = relationship(back_populates="submissions", init=False, viewonly=True)
6 changes: 6 additions & 0 deletions helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,9 @@
# Keyval, used for example for storing the links to different very important documents (e.g. reglementet)
MAX_KEYVAL_KEY = 100
MAX_KEYVAL_VALUE = 1000


# enclose.moose
MAX_ENCLOSE_LEVEL_ID = 100
MAX_ENCLOSE_LEVEL_NAME = 100
MAX_ENCLOSE_GRID = 10000
1 change: 1 addition & 0 deletions helpers/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def force_utc(date: datetime):
"Council",
"RoomBookings",
"Moosegame",
"EncloseMoose",
"MailAlias",
"GuildMeeting",
"Keyvals",
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ Mako==1.3.8
MarkupSafe==3.0.3
numpy==2.2.4
oauthlib==3.3.1
ortools==9.15.6755
packaging==23.2
pandas==2.2.3
passlib==1.7.4
Expand Down
3 changes: 3 additions & 0 deletions routes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .mail_alias_router import mail_alias_router
from .moose_game_router import moose_game_router
from .enclose_moose_router import enclose_moose_router
from .council_router import council_router
from .user_router import user_router
from .post_router import post_router
Expand Down Expand Up @@ -86,6 +87,8 @@

main_router.include_router(moose_game_router, prefix="/moose-game", tags=["moose-game"])

main_router.include_router(enclose_moose_router, prefix="/enclose-moose", tags=["enclose-moose"])

main_router.include_router(mail_alias_router, prefix="/mail-alias", tags=["mail-alias"])

main_router.include_router(access_serve_router, prefix="/access-serve", tags=["access serve"])
Expand Down
Loading
Loading