Add events
This commit is contained in:
174
backend/app/schemas/event.py
Normal file
174
backend/app/schemas/event.py
Normal file
@@ -0,0 +1,174 @@
|
||||
from datetime import datetime
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import Literal
|
||||
|
||||
from app.models.event import EventType
|
||||
from app.schemas.user import UserPublic
|
||||
|
||||
|
||||
# Event type literals for Pydantic
|
||||
EventTypeLiteral = Literal[
|
||||
"golden_hour",
|
||||
"common_enemy",
|
||||
"double_risk",
|
||||
"jackpot",
|
||||
"swap",
|
||||
"rematch",
|
||||
]
|
||||
|
||||
|
||||
class EventCreate(BaseModel):
|
||||
type: EventTypeLiteral
|
||||
duration_minutes: int | None = Field(
|
||||
None,
|
||||
description="Duration in minutes. If not provided, uses default for event type."
|
||||
)
|
||||
challenge_id: int | None = Field(
|
||||
None,
|
||||
description="For common_enemy event - the challenge everyone will get"
|
||||
)
|
||||
|
||||
|
||||
class EventEffects(BaseModel):
|
||||
points_multiplier: float = 1.0
|
||||
drop_free: bool = False
|
||||
special_action: str | None = None # "swap", "rematch"
|
||||
description: str = ""
|
||||
|
||||
|
||||
class EventResponse(BaseModel):
|
||||
id: int
|
||||
type: EventTypeLiteral
|
||||
start_time: datetime
|
||||
end_time: datetime | None
|
||||
is_active: bool
|
||||
created_by: UserPublic | None
|
||||
data: dict | None
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ActiveEventResponse(BaseModel):
|
||||
event: EventResponse | None
|
||||
effects: EventEffects
|
||||
time_remaining_seconds: int | None = None
|
||||
|
||||
|
||||
class SwapRequest(BaseModel):
|
||||
target_participant_id: int
|
||||
|
||||
|
||||
class CommonEnemyLeaderboard(BaseModel):
|
||||
participant_id: int
|
||||
user: UserPublic
|
||||
completed_at: datetime | None
|
||||
rank: int | None
|
||||
bonus_points: int
|
||||
|
||||
|
||||
# Event descriptions and default durations
|
||||
EVENT_INFO = {
|
||||
EventType.GOLDEN_HOUR: {
|
||||
"name": "Золотой час",
|
||||
"description": "Все очки x1.5!",
|
||||
"default_duration": 45,
|
||||
"points_multiplier": 1.5,
|
||||
"drop_free": False,
|
||||
},
|
||||
EventType.COMMON_ENEMY: {
|
||||
"name": "Общий враг",
|
||||
"description": "Все получают одинаковый челлендж. Первые 3 получают бонус!",
|
||||
"default_duration": None, # Until all complete
|
||||
"points_multiplier": 1.0,
|
||||
"drop_free": False,
|
||||
},
|
||||
EventType.DOUBLE_RISK: {
|
||||
"name": "Двойной риск",
|
||||
"description": "Дропы бесплатны, но очки x0.5",
|
||||
"default_duration": 120,
|
||||
"points_multiplier": 0.5,
|
||||
"drop_free": True,
|
||||
},
|
||||
EventType.JACKPOT: {
|
||||
"name": "Джекпот",
|
||||
"description": "Следующий спин — сложный челлендж с x3 очками!",
|
||||
"default_duration": None, # 1 spin
|
||||
"points_multiplier": 3.0,
|
||||
"drop_free": False,
|
||||
},
|
||||
EventType.SWAP: {
|
||||
"name": "Обмен",
|
||||
"description": "Можно поменяться заданием с другим участником",
|
||||
"default_duration": 60,
|
||||
"points_multiplier": 1.0,
|
||||
"drop_free": False,
|
||||
"special_action": "swap",
|
||||
},
|
||||
EventType.REMATCH: {
|
||||
"name": "Реванш",
|
||||
"description": "Можно переделать проваленный челлендж за 50% очков",
|
||||
"default_duration": 240,
|
||||
"points_multiplier": 0.5,
|
||||
"drop_free": False,
|
||||
"special_action": "rematch",
|
||||
},
|
||||
}
|
||||
|
||||
# Bonus points for Common Enemy top 3
|
||||
COMMON_ENEMY_BONUSES = {
|
||||
1: 50,
|
||||
2: 30,
|
||||
3: 15,
|
||||
}
|
||||
|
||||
|
||||
class SwapCandidate(BaseModel):
|
||||
"""Participant available for assignment swap"""
|
||||
participant_id: int
|
||||
user: UserPublic
|
||||
challenge_title: str
|
||||
challenge_description: str
|
||||
challenge_points: int
|
||||
challenge_difficulty: str
|
||||
game_title: str
|
||||
|
||||
|
||||
# Two-sided swap confirmation schemas
|
||||
SwapRequestStatusLiteral = Literal["pending", "accepted", "declined", "cancelled"]
|
||||
|
||||
|
||||
class SwapRequestCreate(BaseModel):
|
||||
"""Request to swap assignment with another participant"""
|
||||
target_participant_id: int
|
||||
|
||||
|
||||
class SwapRequestChallengeInfo(BaseModel):
|
||||
"""Challenge info for swap request display"""
|
||||
title: str
|
||||
description: str
|
||||
points: int
|
||||
difficulty: str
|
||||
game_title: str
|
||||
|
||||
|
||||
class SwapRequestResponse(BaseModel):
|
||||
"""Response for a swap request"""
|
||||
id: int
|
||||
status: SwapRequestStatusLiteral
|
||||
from_user: UserPublic
|
||||
to_user: UserPublic
|
||||
from_challenge: SwapRequestChallengeInfo
|
||||
to_challenge: SwapRequestChallengeInfo
|
||||
created_at: datetime
|
||||
responded_at: datetime | None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class MySwapRequests(BaseModel):
|
||||
"""User's incoming and outgoing swap requests"""
|
||||
incoming: list[SwapRequestResponse]
|
||||
outgoing: list[SwapRequestResponse]
|
||||
Reference in New Issue
Block a user