Skip to content

Commit f6b1c9b

Browse files
feat: 점수 저장을 위한 game 도메인 생성, 점수 업데이트 로직 구현
1 parent 2d86e94 commit f6b1c9b

10 files changed

Lines changed: 95 additions & 8 deletions

File tree

src/configs/database.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import psycopg2
2-
from psycopg2.extras import RealDictCursor
2+
from psycopg2.extras import RealDictCursor, register_uuid
33

44
from src.configs import setting
55
from src.utils.logger import logger
66

7+
# UUID
8+
register_uuid()
9+
710

811
def get_db_connection():
912
"""

src/domains/game/__init__.py

Whitespace-only changes.

src/domains/game/dtos/__init__.py

Whitespace-only changes.

src/domains/game/dtos/game_dto.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from datetime import datetime
2+
from uuid import UUID
3+
from pydantic import BaseModel, Field
4+
5+
6+
class GameResponse(BaseModel):
7+
game_id: UUID = Field(..., description="게임 고유 ID")
8+
user_id: UUID = Field(..., description="사용자 ID")
9+
game_type: str = Field(..., description="게임 유형 (discoverex, magic-eye 등)")
10+
created_at: datetime = Field(..., description="생성 일시")
11+
12+
class Config:
13+
from_attributes = True

src/domains/game/game_service.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
from typing import Optional
2+
from uuid import UUID
3+
4+
from src.domains.game.dtos.game_dto import GameResponse
5+
from src.utils.load_sql import load_sql
6+
7+
8+
class GameService:
9+
"""
10+
게임 정보를 조회하고 관리하는 서비스 클래스입니다.
11+
"""
12+
13+
def __init__(self, cursor):
14+
self.cursor = cursor
15+
16+
def get_game_by_id(self, game_id: UUID) -> Optional[GameResponse]:
17+
"""
18+
주어진 game_id에 해당하는 게임 정보를 조회합니다.
19+
"""
20+
query = load_sql("domains/game", "get_game_by_id")
21+
self.cursor.execute(query, (game_id,))
22+
result = self.cursor.fetchone()
23+
if result:
24+
return GameResponse(**result)
25+
return None
26+
27+
def create_game(self, game_id: UUID, game_type: str, user_id: UUID) -> GameResponse:
28+
"""
29+
새로운 게임을 생성합니다.
30+
"""
31+
query = load_sql("domains/game", "create_game")
32+
self.cursor.execute(query, (game_id, user_id, game_type))
33+
result = self.cursor.fetchone()
34+
return GameResponse(**result)
35+
36+
def get_or_create_game(self, game_id: UUID, game_type: str, user_id: UUID) -> GameResponse:
37+
"""
38+
게임이 존재하면 조회하고, 없으면 새로 생성합니다.
39+
"""
40+
game = self.get_game_by_id(game_id)
41+
if game:
42+
return game
43+
44+
return self.create_game(game_id=game_id, game_type=game_type, user_id=user_id)

src/domains/game/queries/__init__.py

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
INSERT INTO game (game_id, user_id, game_type)
2+
VALUES (%s, %s, %s)
3+
RETURNING game_id, user_id, game_type, created_at;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
SELECT
2+
game_id,
3+
game_type
4+
FROM
5+
game
6+
WHERE
7+
game_id = %s;

src/domains/score/score_router.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from src.common.dtos.wrapped_response import WrappedResponse
99
from src.configs.database import get_db_cursor
1010
from src.domains.auth.auth_service import AuthService
11+
from src.domains.game.game_service import GameService # GameService 임포트
1112
from src.domains.score.dtos.score_dto import ScoreCreateRequest, ScoreResponse
1213
from src.domains.auth.utils.verify_token import verify_user
1314

@@ -19,6 +20,9 @@ def get_score_service(cursor=Depends(get_db_cursor)) -> ScoreService:
1920
def get_auth_service(cursor=Depends(get_db_cursor)) -> AuthService:
2021
return AuthService(cursor)
2122

23+
def get_game_service(cursor=Depends(get_db_cursor)) -> GameService: # GameService 의존성 제공자 추가
24+
return GameService(cursor)
25+
2226
@score_router.post(
2327
"/",
2428
status_code=status.HTTP_201_CREATED,
@@ -30,7 +34,8 @@ async def post_score(
3034
request: ScoreCreateRequest,
3135
user_info: dict = Depends(verify_user),
3236
score_service: ScoreService = Depends(get_score_service),
33-
auth_service: AuthService = Depends(get_auth_service)
37+
auth_service: AuthService = Depends(get_auth_service),
38+
game_service: GameService = Depends(get_game_service) # GameService 주입
3439
):
3540
# 1. 토큰에서 추출한 이메일로 DB 상의 사용자 정보를 확인
3641
email = user_info.get("email")
@@ -40,7 +45,11 @@ async def post_score(
4045
user_data = auth_service.handle_login_or_register(email=email, name=name)
4146

4247
# 3. 점수 기록
43-
result = score_service.register_score(user_id=user_data.user_id, request=request)
48+
result = score_service.register_score(
49+
user_id=user_data.user_id,
50+
request=request,
51+
game_service=game_service # game_service 전달
52+
)
4453

4554
return WrappedResponse(
4655
data=result,

src/domains/score/score_service.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import List, Optional
33
from uuid import UUID
44

5+
from src.domains.game.game_service import GameService
56
from src.domains.score.dtos.score_dto import ScoreCreateRequest, ScoreResponse
67
from src.utils.load_sql import load_sql
78

@@ -14,10 +15,17 @@ class ScoreService:
1415
def __init__(self, cursor):
1516
self.cursor = cursor
1617

17-
def register_score(self, user_id: UUID, request: ScoreCreateRequest) -> ScoreResponse:
18+
def register_score(self, user_id: UUID, request: ScoreCreateRequest, game_service: GameService) -> ScoreResponse:
1819
"""
1920
사용자의 게임 점수를 DB에 등록합니다.
2021
"""
22+
# 1. game_id 조회 또는 생성
23+
game_service.get_or_create_game(
24+
game_id=request.game_id,
25+
game_type=request.game_type,
26+
user_id=user_id
27+
)
28+
2129
query = load_sql("domains/score", "insert_score")
2230
self.cursor.execute(
2331
query,
@@ -27,10 +35,10 @@ def register_score(self, user_id: UUID, request: ScoreCreateRequest) -> ScoreRes
2735
return ScoreResponse(**result)
2836

2937
def get_user_scores(
30-
self,
31-
user_id: Optional[UUID] = None,
38+
self,
39+
user_id: Optional[UUID] = None,
3240
game_type: Optional[str] = None,
33-
start_date: Optional[datetime] = None,
41+
start_date: Optional[datetime] = None,
3442
end_date: Optional[datetime] = None
3543
) -> List[ScoreResponse]:
3644
"""
@@ -46,5 +54,5 @@ def get_user_scores(
4654
)
4755
self.cursor.execute(query, params)
4856
results = self.cursor.fetchall()
49-
57+
5058
return [ScoreResponse(**row) for row in results]

0 commit comments

Comments
 (0)