개선관리 요구사항과 Google 로그인을 완료

This commit is contained in:
Yun Chan 2026-08-28 16:07:09 +09:00
parent cc0a15b7c6
commit 2a39636163
112 changed files with 10166 additions and 527 deletions

View file

@ -6,9 +6,10 @@ import unittest
from unittest.mock import AsyncMock, patch
from .deps import Principal, Role
from . import session_read_model
from .routes import sessions
from .services import state_machine
from .services.persona import P1, P2
from .services.persona import P1, P2, P3
from .store import InProcSession, TurnRecord
@ -30,7 +31,7 @@ def _session(
created_at: float,
ended: bool = True,
) -> InProcSession:
persona = P2 if persona_code == P2.code else P1
persona = {P1.code: P1, P2.code: P2, P3.code: P3}.get(persona_code, P1)
state = state_machine.init_state(params=persona.openness_params())
state.stage = state_machine.Stage.EXPLORE
return InProcSession(
@ -70,6 +71,64 @@ def _session(
)
def _exposure_sessions(persona_codes: list[str]) -> list[InProcSession]:
return [
_session(
session_id=f"exposure-{index}",
session_no=index,
persona_code=persona_code,
score="neutral",
rapport=0.1,
technique="reflection",
created_at=float(index),
)
for index, persona_code in enumerate(persona_codes, start=1)
]
class TrainingExposureMetricTest(unittest.TestCase):
def test_zero_completed_sessions_is_insufficient(self) -> None:
metric = session_read_model.dashboard_training_exposure([])
self.assertEqual(metric.label, "판정 근거 부족")
self.assertEqual(metric.completed_sessions, 0)
self.assertIsNone(metric.dominant_share)
def test_one_completed_session_is_insufficient(self) -> None:
metric = session_read_model.dashboard_training_exposure(
_exposure_sessions([P1.code])
)
self.assertEqual(metric.label, "판정 근거 부족")
self.assertEqual(metric.dominant_share, 1.0)
def test_four_sessions_with_broad_exposure_is_balanced(self) -> None:
metric = session_read_model.dashboard_training_exposure(
_exposure_sessions([P1.code, P1.code, P2.code, P3.code])
)
self.assertEqual(metric.label, "균형")
self.assertEqual(metric.dominant_share, 0.5)
def test_dominant_share_at_seventy_five_percent_is_attention(self) -> None:
metric = session_read_model.dashboard_training_exposure(
_exposure_sessions([P1.code, P1.code, P1.code, P2.code])
)
self.assertEqual(metric.label, "훈련 집중 주의")
self.assertEqual(metric.dominant_sessions, 3)
self.assertEqual(metric.dominant_share, 0.75)
def test_tied_dominant_persona_is_deterministic_and_balanced(self) -> None:
metric = session_read_model.dashboard_training_exposure(
_exposure_sessions([P2.code, P1.code, P2.code, P1.code])
)
self.assertEqual(metric.label, "균형")
self.assertEqual(metric.dominant_persona_code, P1.code)
self.assertEqual(metric.dominant_share, 0.5)
class LearnerDashboardTest(unittest.IsolatedAsyncioTestCase):
async def test_dashboard_returns_personalized_growth_from_owned_sessions(self) -> None:
principal = _principal()
@ -150,6 +209,8 @@ class LearnerDashboardTest(unittest.IsolatedAsyncioTestCase):
self.assertEqual([row.persona_code for row in response.persona_progress], [P2.code, P1.code])
self.assertEqual(response.persona_progress[0].review_ready_sessions, 1)
self.assertEqual(response.persona_progress[1].sessions, 2)
self.assertEqual(response.training_exposure.label, "판정 근거 부족")
self.assertEqual(response.training_exposure.completed_sessions, 2)
self.assertEqual(response.achievements[0].state, "done")
self.assertEqual(response.achievements[1].state, "done")
self.assertEqual(len(response.recent_feedback), 3)