Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
2ae0e8b
added support for enclose.moose: created router, schemas and db_model…
MikaeldeVerdier Jul 31, 2026
c261153
minor improvement to default release_date
MikaeldeVerdier Jul 31, 2026
33d496f
tests (yay) for enclose_moose_router
MikaeldeVerdier Jul 31, 2026
7a98ec8
Added ENCLOSE_MOOSE_TOKEN to test workflow env
MikaeldeVerdier Jul 31, 2026
6435c64
minor improvement to bfs
MikaeldeVerdier Aug 3, 2026
f23d8a6
added get_all_submissions and admin_get_all_submissions routes; updat…
MikaeldeVerdier Aug 3, 2026
e142618
Separated LevelRead into InitialRead and UnlockedRead (before and aft…
MikaeldeVerdier Aug 4, 2026
ce37c07
removed initial and unlocked schemas and instead made spoiler fields …
MikaeldeVerdier Aug 4, 2026
2502eb2
added a separate flag for show_spoilers, otherwise admins couldn't se…
MikaeldeVerdier Aug 4, 2026
554e32f
fixed show_spoilers after submission
MikaeldeVerdier Aug 4, 2026
a0d6ed7
changed level_id to an autoincrementing integer
MikaeldeVerdier Aug 6, 2026
24d0bd3
Merge remote-tracking branch 'origin/main' into enclose_moose
MikaeldeVerdier Aug 11, 2026
35d7d10
added a seperate title for swedish/english
MikaeldeVerdier Aug 13, 2026
2cd8739
Merge remote-tracking branch 'origin/main' into enclose_moose
MikaeldeVerdier Aug 13, 2026
728dc49
Fix copy-paste error in tests, add foreignkey to player_id in submiss…
georgelgeback Aug 15, 2026
c29b179
Move leading newline check and fix broken local tests
georgelgeback Aug 15, 2026
cbf8db3
fixed requested changes
MikaeldeVerdier Aug 15, 2026
16f5e2a
Fix server error when sending None values for encoded grid or wall bu…
georgelgeback Aug 15, 2026
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
55 changes: 55 additions & 0 deletions api_schemas/enclose_moose_level_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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: int
release_date: date
day_index: int | None
name_sv: str
name_en: 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):
release_date: date = Field(default_factory=lambda: datetime.now(ZoneInfo("Europe/Stockholm")).date())
day_index: int | None = None
name_sv: str
name_en: str

encoded_grid: str
wall_budget: int


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

encoded_grid: str | None = None
wall_budget: int | None = None
Comment thread
georgelgeback marked this conversation as resolved.
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: int
submission_time: datetime

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


class EncloseMooseSubmissionCreate(BaseSchema):
player_solution: set[int]
38 changes: 38 additions & 0 deletions db_models/enclose_moose_level_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from datetime import date
from helpers.constants import 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 String, Date, JSON

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[int] = mapped_column(primary_key=True, init=False)
release_date: Mapped[Optional[date]] = mapped_column(Date)
day_index: Mapped[Optional[int]] = mapped_column()
name_sv: Mapped[str] = mapped_column(String(MAX_ENCLOSE_LEVEL_NAME))
name_en: 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
27 changes: 27 additions & 0 deletions db_models/enclose_moose_submission_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from .base_model import BaseModel_DB
from sqlalchemy.orm import relationship, mapped_column, Mapped
from sqlalchemy import ForeignKey, JSON
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[int] = mapped_column(
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(
ForeignKey("user_table.id", ondelete="CASCADE"),
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)
5 changes: 5 additions & 0 deletions helpers/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@
# 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_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 @@ -87,6 +88,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