File size: 3,533 Bytes
7bee6d4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from fastapi import Request, Response
from caainp_csm.plan_csm import PlanState, Constraints, Step
import json

COOKIE_KEY = "CAAINP-NAVIGATION-COOKIE"


def plan_to_dict(plan: PlanState) -> dict:
    """PlanState를 JSON 직렬화 가능한 dict로 변환"""
    return {
        "constraints": {
            "use_elevator_only": plan.constraints.use_elevator_only,
            "avoid_stairs": plan.constraints.avoid_stairs,
            "forbidden_nodes": plan.constraints.forbidden_nodes,
            "via_rooms": plan.constraints.via_rooms,
        },
        "steps": [
            {
                "step_id": s.step_id,
                "goal_type": s.goal_type,
                "goal_room": s.goal_room,
                "allowed_moves": s.allowed_moves,
                "description_ko": s.description_ko,
                "target_nodes": s.target_nodes,
                "route_nodes": s.route_nodes,
            }
            for s in plan.steps
        ],
        "current_step": plan.current_step,
        "steps_status": plan.steps_status,
        "step_targets": {str(k): v for k, v in plan.step_targets.items()},
        "in_target_count": plan.in_target_count,
    }


def dict_to_plan(data: dict) -> PlanState:
    """dict를 PlanState 객체로 복원"""
    constraints = Constraints(
        use_elevator_only=data["constraints"]["use_elevator_only"],
        avoid_stairs=data["constraints"]["avoid_stairs"],
        forbidden_nodes=data["constraints"]["forbidden_nodes"],
        via_rooms=data["constraints"]["via_rooms"],
    )
    
    steps = [
        Step(
            step_id=s["step_id"],
            goal_type=s["goal_type"],
            goal_room=s["goal_room"],
            allowed_moves=s["allowed_moves"],
            description_ko=s["description_ko"],
            target_nodes=s["target_nodes"],
            route_nodes=s["route_nodes"],
        )
        for s in data["steps"]
    ]
    
    # steps_status의 키를 int로 복원
    steps_status = {int(k): v for k, v in data["steps_status"].items()}
    # step_targets의 키를 int로 복원
    step_targets = {int(k): v for k, v in data["step_targets"].items()}
    
    return PlanState(
        constraints=constraints,
        steps=steps,
        current_step=data["current_step"],
        steps_status=steps_status,
        step_targets=step_targets,
        in_target_count=data["in_target_count"],
    )


def get_nav_state_from_cookie(request: Request) -> tuple[PlanState, int] | None:
    """쿠키에서 네비게이션 상태를 읽어서 반환"""
    cookies = dict(request.cookies)
    nav_state_cookie = cookies.get(COOKIE_KEY)
    
    if not nav_state_cookie:
        return None
    
    try:
        nav_state = json.loads(nav_state_cookie)
        plan_dict = nav_state.get("plan")
        prev_node = nav_state.get("prev_node")
        plan = dict_to_plan(plan_dict)
        return plan, prev_node
    except (json.JSONDecodeError, KeyError, TypeError):
        return None


def save_nav_state_to_cookie(response: Response, plan: PlanState, prev_node: int) -> None:
    """네비게이션 상태(plan, prev_node)를 쿠키에 저장"""
    nav_state = {
        "plan": plan_to_dict(plan),
        "prev_node": prev_node,
    }
    response.set_cookie(
        key=COOKIE_KEY,
        value=json.dumps(nav_state),
        max_age=3600,
        httponly=True,
        samesite="lax"
    )


def clear_nav_cookie(response: Response) -> None:
    """네비게이션 쿠키 삭제"""
    response.delete_cookie(COOKIE_KEY)