@readerseye2/cr_type 1.0.111 → 1.0.113
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/book/book-api.type.d.ts +15 -15
- package/dist/book/book-api.type.js +2 -2
- package/dist/book/book-log.type.d.ts +14 -14
- package/dist/book/book-log.type.js +2 -2
- package/dist/book/book.const.d.ts +274 -274
- package/dist/book/book.const.js +119 -119
- package/dist/book/legacy.book.type.d.ts +164 -164
- package/dist/book/legacy.book.type.js +41 -41
- package/dist/socket/index.d.ts +1 -1
- package/dist/socket/index.js +1 -1
- package/dist/socket/reading-section.types.d.ts +1 -127
- package/dist/socket/reading-section.types.js +1 -1
- package/dist/socket/socket-clientToServerEvents.type.d.ts +35 -27
- package/dist/socket/socket-serverToClientEvents.type.d.ts +70 -40
- package/dist/socket/socket-serverToClientEvents.type.js +0 -1
- package/dist/socket/unified-session.types.d.ts +304 -0
- package/dist/socket/unified-session.types.js +22 -0
- package/package.json +27 -27
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { ViewerSnapshot, SessionMeta, SessionStats } from './reading-section.types';
|
|
2
|
+
import type { ViewerEvent } from './viewer-events.types';
|
|
3
|
+
/** 청크 참조 정보 (meta.json 내) */
|
|
4
|
+
export interface ChunkRef {
|
|
5
|
+
start: number;
|
|
6
|
+
end: number;
|
|
7
|
+
key: string;
|
|
8
|
+
eventCount: number;
|
|
9
|
+
}
|
|
10
|
+
/** 통합 세션 상태 */
|
|
11
|
+
export type UnifiedSessionStatus = 'active' | 'ended';
|
|
12
|
+
/** 통합 세그먼트 상태 */
|
|
13
|
+
export type UnifiedSegmentStatus = 'active' | 'ended';
|
|
14
|
+
/**
|
|
15
|
+
* 시선 데이터 배치 (청크 내 포함)
|
|
16
|
+
* - ~30FPS의 x,y,t 데이터를 flat number[]로 압축
|
|
17
|
+
* - 30FPS × 10초 = 900샘플 = 2700숫자 (객체 대비 ~60% JSON 크기 절감)
|
|
18
|
+
*/
|
|
19
|
+
export interface GazeBatch {
|
|
20
|
+
/** 배치 시작 timestamp (ms) */
|
|
21
|
+
startTs: number;
|
|
22
|
+
/** 배치 종료 timestamp (ms) */
|
|
23
|
+
endTs: number;
|
|
24
|
+
/** 압축된 시선 샘플 [x0, y0, t0, x1, y1, t1, ...] (x,y: 0~1 정규화) */
|
|
25
|
+
samples: number[];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 통합 청크 파일 (S3: segments/{n}/chunks/{startTs}-{endTs}.json)
|
|
29
|
+
* - 10초 단위 이벤트 + 시선 데이터 묶음
|
|
30
|
+
* - snapshot: 청크 시작 시점의 뷰어 상태 (Seek 시 초기화용)
|
|
31
|
+
* - gazeData: 시선 추적 배치 데이터 (활성 시에만)
|
|
32
|
+
*/
|
|
33
|
+
export interface UnifiedChunkFile {
|
|
34
|
+
startTimestamp: number;
|
|
35
|
+
endTimestamp: number;
|
|
36
|
+
events: ViewerEvent[];
|
|
37
|
+
/** 청크 시작 시점의 뷰어 상태 (Seek 시 이 상태로 초기화 후 이벤트 재생) */
|
|
38
|
+
snapshot?: ViewerSnapshot;
|
|
39
|
+
/** 시선 추적 데이터 배치 (~30FPS, 활성 시에만 포함) */
|
|
40
|
+
gazeData?: GazeBatch[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* 통합 세그먼트 메타데이터
|
|
44
|
+
* - 하나의 섹션을 읽는 구간 (섹션 변경 시 새 세그먼트)
|
|
45
|
+
* - 세션 내에서 0, 1, 2... 순차 인덱스
|
|
46
|
+
*/
|
|
47
|
+
export interface UnifiedSegmentMeta {
|
|
48
|
+
/** 세그먼트 인덱스 (0부터) */
|
|
49
|
+
segmentIndex: number;
|
|
50
|
+
/** 상태 */
|
|
51
|
+
status: UnifiedSegmentStatus;
|
|
52
|
+
bookIdx: number;
|
|
53
|
+
bookTitle?: string;
|
|
54
|
+
sectionId: string;
|
|
55
|
+
sectionTitle?: string;
|
|
56
|
+
/** 세그먼트 시작 시간 (ms) */
|
|
57
|
+
startedAt: number;
|
|
58
|
+
/** 세그먼트 종료 시간 (ms), null이면 진행중 */
|
|
59
|
+
endedAt: number | null;
|
|
60
|
+
/** 마지막 업데이트 */
|
|
61
|
+
updatedAt: number;
|
|
62
|
+
chunks: ChunkRef[];
|
|
63
|
+
totalEvents: number;
|
|
64
|
+
totalGazeSamples?: number;
|
|
65
|
+
durationMs: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* 세그먼트 요약 정보 (manifest 내)
|
|
69
|
+
* - Seek 시 어떤 segment를 봐야 할지 판단
|
|
70
|
+
* - 전체 정보는 segments/{n}/meta.json 참조
|
|
71
|
+
*/
|
|
72
|
+
export interface UnifiedSegmentSummary {
|
|
73
|
+
/** 세그먼트 인덱스 (0부터, 시간순) */
|
|
74
|
+
segmentIndex: number;
|
|
75
|
+
/** 상태 */
|
|
76
|
+
status: UnifiedSegmentStatus;
|
|
77
|
+
bookIdx: number;
|
|
78
|
+
bookTitle?: string;
|
|
79
|
+
sectionId: string;
|
|
80
|
+
sectionTitle?: string;
|
|
81
|
+
/** 세그먼트 시작 timestamp (ms) */
|
|
82
|
+
startedAt: number;
|
|
83
|
+
/** 세그먼트 종료 timestamp (ms) - null이면 진행중 (Live) */
|
|
84
|
+
endedAt: number | null;
|
|
85
|
+
/** 세그먼트 길이 (ms) */
|
|
86
|
+
durationMs: number;
|
|
87
|
+
chunkCount: number;
|
|
88
|
+
eventCount: number;
|
|
89
|
+
/** meta.json S3 key */
|
|
90
|
+
metaKey: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 통합 세션 매니페스트
|
|
94
|
+
* - 뷰어 열림 → 닫힘까지가 하나의 세션
|
|
95
|
+
* - 섹션 변경은 세그먼트로 기록
|
|
96
|
+
* - 기존 ReadingSessionRecord + RecordingManifest 대체
|
|
97
|
+
*/
|
|
98
|
+
export interface UnifiedSessionManifest {
|
|
99
|
+
/** 세션 ID (UUID) */
|
|
100
|
+
sessionId: string;
|
|
101
|
+
/** 상태 */
|
|
102
|
+
status: UnifiedSessionStatus;
|
|
103
|
+
/** 스키마 버전 (구 포맷과 구분용, 항상 2) */
|
|
104
|
+
version: 2;
|
|
105
|
+
userId: number;
|
|
106
|
+
userType: 'parent' | 'child';
|
|
107
|
+
userName: string;
|
|
108
|
+
familyId: number;
|
|
109
|
+
/** 세션 시작 시간 (뷰어 열림, ms) */
|
|
110
|
+
startedAt: number;
|
|
111
|
+
/** 세션 종료 시간 (뷰어 닫힘, ms), null이면 진행중 */
|
|
112
|
+
endedAt: number | null;
|
|
113
|
+
/** 마지막 업데이트 */
|
|
114
|
+
updatedAt: number;
|
|
115
|
+
segments: UnifiedSegmentSummary[];
|
|
116
|
+
totalSegments: number;
|
|
117
|
+
totalChunks: number;
|
|
118
|
+
totalEvents: number;
|
|
119
|
+
/** 실제 활동 시간 합계 (ms, 세그먼트 간 갭 제외) */
|
|
120
|
+
totalDurationMs: number;
|
|
121
|
+
/** 세션 최초 스냅샷 */
|
|
122
|
+
initialSnapshot?: ViewerSnapshot;
|
|
123
|
+
/** 세션 최종 스냅샷 */
|
|
124
|
+
finalSnapshot?: ViewerSnapshot;
|
|
125
|
+
/** 구 포맷에서 변환된 경우 true */
|
|
126
|
+
migrated?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* 뷰어 열림 페이로드 (세션 시작 또는 세그먼트 추가)
|
|
130
|
+
* - isSectionChange=false: 새 세션 시작 (뷰어 최초 열림)
|
|
131
|
+
* - isSectionChange=true: 기존 세션 내 세그먼트 추가 (섹션 이동)
|
|
132
|
+
*/
|
|
133
|
+
export interface ViewerOpenPayload {
|
|
134
|
+
bookIdx: number;
|
|
135
|
+
sectionId: string;
|
|
136
|
+
snapshot: ViewerSnapshot;
|
|
137
|
+
meta?: SessionMeta;
|
|
138
|
+
/** true면 기존 세션 내에서 섹션 변경 (새 세그먼트 추가) */
|
|
139
|
+
isSectionChange?: boolean;
|
|
140
|
+
}
|
|
141
|
+
/** 뷰어 닫힘 페이로드 (세션 종료) */
|
|
142
|
+
export interface ViewerClosePayload {
|
|
143
|
+
durationMs?: number;
|
|
144
|
+
finalSnapshot?: ViewerSnapshot;
|
|
145
|
+
stats?: SessionStats;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* 시선 데이터 전송 페이로드
|
|
149
|
+
* - CR_app에서 1초 간격으로 버퍼링 후 전송
|
|
150
|
+
*/
|
|
151
|
+
export interface GazeDataPayload {
|
|
152
|
+
/** 압축된 시선 샘플 [x, y, t, x, y, t, ...] */
|
|
153
|
+
samples: number[];
|
|
154
|
+
/** 배치 시작 timestamp (ms) */
|
|
155
|
+
startTs: number;
|
|
156
|
+
/** 배치 종료 timestamp (ms) */
|
|
157
|
+
endTs: number;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* 통합 세션 정보 (실시간 활성 세션)
|
|
161
|
+
* - ReadingSessionInfo 대체
|
|
162
|
+
* - 현재 세그먼트 정보 포함
|
|
163
|
+
*/
|
|
164
|
+
export interface UnifiedSessionInfo {
|
|
165
|
+
sessionId: string;
|
|
166
|
+
userId: number;
|
|
167
|
+
userType: 'parent' | 'child';
|
|
168
|
+
userName?: string;
|
|
169
|
+
familyId: number;
|
|
170
|
+
startedAt: string;
|
|
171
|
+
snapshot: ViewerSnapshot;
|
|
172
|
+
lastEventAt?: string;
|
|
173
|
+
/** 현재 활성 세그먼트 정보 */
|
|
174
|
+
currentSegment: {
|
|
175
|
+
segmentIndex: number;
|
|
176
|
+
bookIdx: number;
|
|
177
|
+
bookTitle?: string;
|
|
178
|
+
sectionId: string;
|
|
179
|
+
sectionTitle?: string;
|
|
180
|
+
startedAt: number;
|
|
181
|
+
};
|
|
182
|
+
/** 세션 내 모든 세그먼트 요약 */
|
|
183
|
+
segments: UnifiedSegmentSummary[];
|
|
184
|
+
}
|
|
185
|
+
/** 세그먼트 변경 알림 (섹션 변경 시) */
|
|
186
|
+
export interface SessionSegmentChangedPayload {
|
|
187
|
+
sessionId: string;
|
|
188
|
+
/** 종료된 세그먼트 인덱스 */
|
|
189
|
+
oldSegmentIndex: number;
|
|
190
|
+
/** 새로 시작된 세그먼트 */
|
|
191
|
+
newSegment: {
|
|
192
|
+
segmentIndex: number;
|
|
193
|
+
bookIdx: number;
|
|
194
|
+
bookTitle?: string;
|
|
195
|
+
sectionId: string;
|
|
196
|
+
sectionTitle?: string;
|
|
197
|
+
startedAt: number;
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/** 세션 이력 목록 조회 요청 */
|
|
201
|
+
export interface SessionHistoryListPayload {
|
|
202
|
+
familyId?: number;
|
|
203
|
+
userId?: number;
|
|
204
|
+
date?: string;
|
|
205
|
+
limit?: number;
|
|
206
|
+
offset?: number;
|
|
207
|
+
}
|
|
208
|
+
/** 세션 이력 상세 조회 요청 */
|
|
209
|
+
export interface SessionHistoryGetPayload {
|
|
210
|
+
sessionId: string;
|
|
211
|
+
s3Key?: string;
|
|
212
|
+
}
|
|
213
|
+
/** 세션 이력 삭제 요청 */
|
|
214
|
+
export interface SessionHistoryDeletePayload {
|
|
215
|
+
sessionId: string;
|
|
216
|
+
s3Key?: string;
|
|
217
|
+
}
|
|
218
|
+
/** 통합 청크 조회 요청 (seek/재생용) */
|
|
219
|
+
export interface UnifiedChunksGetPayload {
|
|
220
|
+
sessionId: string;
|
|
221
|
+
segmentIndex: number;
|
|
222
|
+
/** 시작 timestamp (이 시점부터 청크 조회) */
|
|
223
|
+
fromTimestamp?: number;
|
|
224
|
+
/** 종료 timestamp (이 시점까지 청크 조회) */
|
|
225
|
+
toTimestamp?: number;
|
|
226
|
+
}
|
|
227
|
+
/** 통합 세그먼트 상세 조회 요청 */
|
|
228
|
+
export interface UnifiedSegmentGetPayload {
|
|
229
|
+
sessionId: string;
|
|
230
|
+
segmentIndex: number;
|
|
231
|
+
}
|
|
232
|
+
/** 세션 이력 목록 결과 */
|
|
233
|
+
export interface SessionHistoryListResult {
|
|
234
|
+
sessions: UnifiedSessionManifest[];
|
|
235
|
+
total: number;
|
|
236
|
+
hasMore: boolean;
|
|
237
|
+
}
|
|
238
|
+
/** 세션 이력 상세 결과 (재생용 — 전체 청크 포함) */
|
|
239
|
+
export interface SessionHistoryGetResult {
|
|
240
|
+
manifest: UnifiedSessionManifest;
|
|
241
|
+
/** 세그먼트별 전체 청크 (재생용) */
|
|
242
|
+
chunks?: UnifiedChunkFile[];
|
|
243
|
+
/** 청크에서 추출한 전체 이벤트 (편의용) */
|
|
244
|
+
events?: ViewerEvent[];
|
|
245
|
+
}
|
|
246
|
+
/** 청크 조회 결과 */
|
|
247
|
+
export interface UnifiedChunksResult {
|
|
248
|
+
sessionId: string;
|
|
249
|
+
segmentIndex: number;
|
|
250
|
+
chunks: UnifiedChunkFile[];
|
|
251
|
+
/** Seek 시 가장 가까운 스냅샷 (초기 상태 복원용) */
|
|
252
|
+
nearestSnapshot: ViewerSnapshot | null;
|
|
253
|
+
}
|
|
254
|
+
/** 세그먼트 상세 결과 */
|
|
255
|
+
export interface UnifiedSegmentResult {
|
|
256
|
+
sessionId: string;
|
|
257
|
+
segment: UnifiedSegmentMeta;
|
|
258
|
+
}
|
|
259
|
+
/** 세션 삭제 결과 */
|
|
260
|
+
export interface SessionHistoryDeleteResult {
|
|
261
|
+
sessionId: string;
|
|
262
|
+
success: boolean;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 활성 통합 세션 (서버 메모리)
|
|
266
|
+
* - 기존 ActiveRecording + SessionChunkState 대체
|
|
267
|
+
*/
|
|
268
|
+
export interface ActiveUnifiedSession {
|
|
269
|
+
sessionId: string;
|
|
270
|
+
s3Prefix: string;
|
|
271
|
+
userId: number;
|
|
272
|
+
userType: 'parent' | 'child';
|
|
273
|
+
userName: string;
|
|
274
|
+
familyId: number;
|
|
275
|
+
viewerSocketId: string;
|
|
276
|
+
startedAt: number;
|
|
277
|
+
currentSegment: ActiveUnifiedSegment | null;
|
|
278
|
+
completedSegments: UnifiedSegmentSummary[];
|
|
279
|
+
totalEvents: number;
|
|
280
|
+
subscribers: Set<string>;
|
|
281
|
+
chunkIntervalHandle: ReturnType<typeof setInterval> | null;
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 활성 세그먼트 (서버 메모리)
|
|
285
|
+
* - 하나의 섹션을 읽는 동안의 버퍼 상태
|
|
286
|
+
*/
|
|
287
|
+
export interface ActiveUnifiedSegment {
|
|
288
|
+
segmentIndex: number;
|
|
289
|
+
bookIdx: number;
|
|
290
|
+
bookTitle?: string;
|
|
291
|
+
sectionId: string;
|
|
292
|
+
sectionTitle?: string;
|
|
293
|
+
startedAt: number;
|
|
294
|
+
eventBuffer: ViewerEvent[];
|
|
295
|
+
gazeBuffer: GazeBatch[];
|
|
296
|
+
chunkStartTimestamp: number;
|
|
297
|
+
/** 현재 청크 시작 시점의 스냅샷 (청크에 포함됨) */
|
|
298
|
+
chunkStartSnapshot: ViewerSnapshot | null;
|
|
299
|
+
/** 가장 최근 스냅샷 (다음 청크의 시작 스냅샷으로 사용) */
|
|
300
|
+
lastSnapshot: ViewerSnapshot | null;
|
|
301
|
+
chunks: ChunkRef[];
|
|
302
|
+
totalEvents: number;
|
|
303
|
+
totalGazeSamples: number;
|
|
304
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// src/socket/unified-session.types.ts
|
|
3
|
+
// 통합 읽기 세션 시스템 타입 정의 (v2)
|
|
4
|
+
//
|
|
5
|
+
// 기존 ReadingSessionService + RecordingService를 하나로 통합
|
|
6
|
+
//
|
|
7
|
+
// 핵심 변경:
|
|
8
|
+
// - 세션 = 뷰어 열림~닫힘 (섹션 변경은 세그먼트)
|
|
9
|
+
// - 자동 녹화 (Admin recording:start 제거)
|
|
10
|
+
// - 시선 데이터(~30FPS) 청크에 배치 저장
|
|
11
|
+
// - Parent + Admin 동일한 subscribe 체계
|
|
12
|
+
//
|
|
13
|
+
// S3 경로:
|
|
14
|
+
// reading-sessions/{familyId}/{userId}/{YYYY-MM-DD}/{sessionId}/
|
|
15
|
+
// ├── manifest.json (UnifiedSessionManifest)
|
|
16
|
+
// └── segments/
|
|
17
|
+
// ├── 0/
|
|
18
|
+
// │ ├── meta.json (UnifiedSegmentMeta)
|
|
19
|
+
// │ └── chunks/{startTs}-{endTs}.json (UnifiedChunkFile)
|
|
20
|
+
// └── 1/
|
|
21
|
+
// └── ...
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
package/package.json
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@readerseye2/cr_type",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "CheckReading shared TypeScript types",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
"dist"
|
|
9
|
-
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"deploy_npm": "npm version patch && npm publish --access public",
|
|
12
|
-
"build": "tsc --project tsconfig.json",
|
|
13
|
-
"prepare": "npm run build"
|
|
14
|
-
},
|
|
15
|
-
"repository": {
|
|
16
|
-
"type": "git",
|
|
17
|
-
"url": "https://github.com/bnri/CR_type.git"
|
|
18
|
-
},
|
|
19
|
-
"author": "guripong",
|
|
20
|
-
"license": "MIT",
|
|
21
|
-
"publishConfig": {
|
|
22
|
-
"access": "public"
|
|
23
|
-
},
|
|
24
|
-
"devDependencies": {
|
|
25
|
-
"typescript": "^5.8.3"
|
|
26
|
-
}
|
|
27
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@readerseye2/cr_type",
|
|
3
|
+
"version": "1.0.113",
|
|
4
|
+
"description": "CheckReading shared TypeScript types",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"deploy_npm": "npm version patch && npm publish --access public",
|
|
12
|
+
"build": "tsc --project tsconfig.json",
|
|
13
|
+
"prepare": "npm run build"
|
|
14
|
+
},
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/bnri/CR_type.git"
|
|
18
|
+
},
|
|
19
|
+
"author": "guripong",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"access": "public"
|
|
23
|
+
},
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"typescript": "^5.8.3"
|
|
26
|
+
}
|
|
27
|
+
}
|