lct-18: профиль курсанта — радар, история попыток, дельта
Работа над ошибками становится измеримым циклом: посмотрел разбор → попробовал снова → увидел дельту по оценке, времени опроса и добытым фактам. В отчёт занятия добавлена сводка числами — время опроса, факты, подсказки, коды ошибок. Без неё дельту пришлось бы вытаскивать разбором текста метрик («94 с»), а это путь к тихим ошибкам. Радар — среднее по попыткам: одна неудачная попытка не определяет курсанта. Проверено сквозным тестом на живой базе: два занятия одного курсанта дают две попытки и посчитанную дельту. Проверка доступности базы в тесте была ложной — синхронного драйвера в проекте нет, и тест молча пропускался.
This commit is contained in:
parent
57f4c858b6
commit
38082e2af3
8 changed files with 412 additions and 0 deletions
|
|
@ -70,6 +70,51 @@ export const useSessions = (params: { trainee?: string; group?: string; mode?: S
|
|||
});
|
||||
};
|
||||
|
||||
export interface TraineeInfo {
|
||||
id: string;
|
||||
name: string;
|
||||
group: string | null;
|
||||
}
|
||||
|
||||
export interface Attempt {
|
||||
session_id: string;
|
||||
scenario_id: string;
|
||||
mode: SessionMode;
|
||||
attempt: number;
|
||||
created_at: string;
|
||||
score: number | null;
|
||||
interview_ms: number | null;
|
||||
facts_got: number | null;
|
||||
facts_required: number | null;
|
||||
hints: number | null;
|
||||
codes: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface Profile {
|
||||
trainee: TraineeInfo;
|
||||
attempts: Attempt[];
|
||||
competencies: Record<string, number>;
|
||||
deltas: {
|
||||
scenario_id: string;
|
||||
from_attempt: number;
|
||||
to_attempt: number;
|
||||
score: number | null;
|
||||
interview_ms: number | null;
|
||||
facts_got: number | null;
|
||||
}[];
|
||||
hints_total: number;
|
||||
}
|
||||
|
||||
export const useTrainees = () =>
|
||||
useQuery({ queryKey: ["trainees"], queryFn: () => request<TraineeInfo[]>("/api/trainees") });
|
||||
|
||||
export const useProfile = (traineeId: string | null) =>
|
||||
useQuery({
|
||||
queryKey: ["profile", traineeId],
|
||||
queryFn: () => request<Profile>(`/api/trainees/${traineeId}/profile`),
|
||||
enabled: Boolean(traineeId),
|
||||
});
|
||||
|
||||
export const useCreateSession = () =>
|
||||
useMutation({
|
||||
mutationFn: (body: { scenario_id: string; mode: SessionMode; trainee?: string; group?: string }) =>
|
||||
|
|
|
|||
Loading…
Reference in a new issue