kakaotalk-chat-analyzer 0.23.0 → 0.24.1

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.
Files changed (59) hide show
  1. package/README.md +1 -0
  2. package/dist/src/accumulator/aggregator-helpers.d.ts +127 -0
  3. package/dist/src/accumulator/aggregator-helpers.js +420 -0
  4. package/dist/src/accumulator/aggregator-helpers.js.map +1 -0
  5. package/dist/src/aggregator.d.ts +2 -0
  6. package/dist/src/aggregator.js +169 -496
  7. package/dist/src/aggregator.js.map +1 -1
  8. package/dist/src/analyze-pool.js +13 -2
  9. package/dist/src/analyze-pool.js.map +1 -1
  10. package/dist/src/cli.js +6 -2
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/dyad-matrix.js +10 -1
  13. package/dist/src/dyad-matrix.js.map +1 -1
  14. package/dist/src/event-spine.js +44 -26
  15. package/dist/src/event-spine.js.map +1 -1
  16. package/dist/src/gap-stats.js +2 -2
  17. package/dist/src/gap-stats.js.map +1 -1
  18. package/dist/src/keyword-counter.js +2 -0
  19. package/dist/src/keyword-counter.js.map +1 -1
  20. package/dist/src/keyword-tokenize.d.ts +3 -2
  21. package/dist/src/keyword-tokenize.js +7 -5
  22. package/dist/src/keyword-tokenize.js.map +1 -1
  23. package/dist/src/kiwi-keyword-pool.js +83 -33
  24. package/dist/src/kiwi-keyword-pool.js.map +1 -1
  25. package/dist/src/kiwi-tokenize-worker.js +50 -12
  26. package/dist/src/kiwi-tokenize-worker.js.map +1 -1
  27. package/dist/src/llm-cache.js +15 -3
  28. package/dist/src/llm-cache.js.map +1 -1
  29. package/dist/src/llm-deck-validate.d.ts +1 -0
  30. package/dist/src/llm-deck-validate.js +122 -5
  31. package/dist/src/llm-deck-validate.js.map +1 -1
  32. package/dist/src/llm-summarize.js +2 -4
  33. package/dist/src/llm-summarize.js.map +1 -1
  34. package/dist/src/memorable-moments.d.ts +2 -1
  35. package/dist/src/memorable-moments.js +50 -4
  36. package/dist/src/memorable-moments.js.map +1 -1
  37. package/dist/src/report-chart-util.js +15 -3
  38. package/dist/src/report-chart-util.js.map +1 -1
  39. package/dist/src/report-charts.d.ts +2 -2
  40. package/dist/src/report-charts.js +73 -129
  41. package/dist/src/report-charts.js.map +1 -1
  42. package/dist/src/report-head.d.ts +1 -1
  43. package/dist/src/report-head.js +1 -1
  44. package/dist/src/report-llm-deck.js +39 -17
  45. package/dist/src/report-llm-deck.js.map +1 -1
  46. package/dist/src/report-styles.d.ts +1 -1
  47. package/dist/src/report-styles.js +140 -16
  48. package/dist/src/report-styles.js.map +1 -1
  49. package/dist/src/report.js +22 -27
  50. package/dist/src/report.js.map +1 -1
  51. package/dist/src/stream-parser.d.ts +2 -1
  52. package/dist/src/stream-parser.js +11 -2
  53. package/dist/src/stream-parser.js.map +1 -1
  54. package/dist/src/toxicity-analyze.js +4 -1
  55. package/dist/src/toxicity-analyze.js.map +1 -1
  56. package/dist/src/types.d.ts +7 -0
  57. package/dist/src/version.d.ts +2 -2
  58. package/dist/src/version.js +1 -1
  59. package/package.json +8 -2
package/README.md CHANGED
@@ -262,6 +262,7 @@ cd kakaotalk-chat-analyzer && npm install && npm run build && npm test
262
262
 
263
263
  | 버전 | 요약 |
264
264
  |------|------|
265
+ | **0.24.1** | **리포트 인사이트 품질 강화** — 대화 근거 기반 핫토픽·기억나는 순간·LLM 서사 품질 게이트 · `kcachat` 0.1.78 |
265
266
  | **0.23.0** | **v3 통합 카드 시스템** — 리포트 레이아웃 전면 재설계 · 12개 CSS 토큰 · 5계층 카드 시스템 · OLED 글라스 6종 확장 · 히어로 재설계 · #s-charts 구조화 · 헤딩 계층 정비 · 컬러 토큰화 |
266
267
  | **0.22.6** | **프리미엄 리디자인** — 랜딩 페이지·리포트 CSS 전면 개편 · **글라스 2.0** 테마 · **벤토 그리드** 기능 카드 · **인터랙티브 마우스 트래킹** · 접근성 개선 (**focus-visible**, 대비 강화, reduced motion) · light theme 보완 |
267
268
  | **0.22.3** | **5개 신규 지표**(질문·독백·세션·피크일·도메인) · **3개 LLM 섹션 활성화**(관계·시대·그날) · **소셜 네트워크 그래프** · **감정 롤러코스터** · **토픽 트랜드** · 참여자 **10명+더보기** · 모바일 **ECharts 최적화** · 네비 번호 연속성 · `insightBullets` 버그 수정 |
@@ -0,0 +1,127 @@
1
+ /**
2
+ * ReportAggregator 헬퍼 함수 — aggregator.ts에서 추출한 순수 함수들.
3
+ * 클래스 상태에 의존하지 않으며 독립적으로 동작합니다.
4
+ */
5
+ import type { CountItem, ParsedDateParts, ParticipantRole, ParticipantStat, PrivacyMode } from "../types.js";
6
+ import { KeywordCounter } from "../keyword-counter.js";
7
+ export declare function round(value: number, decimals: number): number;
8
+ export declare function pad2(value: number): string;
9
+ export declare function medianSorted(sorted: number[]): number;
10
+ export declare function increment(map: Map<string, number>, key: string, amount?: number): void;
11
+ export declare function topCounts(map: Map<string, number>, limit: number): CountItem[];
12
+ export declare function buildSenderLabels(senders: string[], privacy: PrivacyMode): Map<string, string>;
13
+ export declare function normalizeToken(token: string): string;
14
+ export declare function getDomains(message: string): string[];
15
+ export declare function longestDateStreak(sortedYmd: string[]): number;
16
+ export declare function computeGini(counts: number[]): number | null;
17
+ export declare function maxSilenceGapDays(sortedYmd: string[]): number | null;
18
+ export declare function computeDensityFromSpan(first: ParsedDateParts | null, last: ParsedDateParts | null, total: number): number | null;
19
+ export declare function domainEntropyBits(domains: Map<string, number>): number | null;
20
+ export declare function computeRhythmScore(input: {
21
+ gini: number | null;
22
+ longestStreak: number;
23
+ density: number | null;
24
+ }): number;
25
+ interface MutableParticipantStat {
26
+ messages: number;
27
+ characters: number;
28
+ attachmentMessages: number;
29
+ linkMessages: number;
30
+ nightMessages: number;
31
+ maxConsecutive: number;
32
+ }
33
+ export declare function getParticipantStat(stats: Map<string, MutableParticipantStat>, sender: string): MutableParticipantStat;
34
+ export declare function computeTop3Share(stats: Map<string, MutableParticipantStat>, total: number): number;
35
+ export declare function computeDaypartPercents(hourly: number[], total: number): {
36
+ key: string;
37
+ label: string;
38
+ percent: number;
39
+ }[];
40
+ export declare function top1ShareFromCounts(keywords: {
41
+ count: number;
42
+ }[], totalMessages: number): number | null;
43
+ export declare function typeRichnessFromKeywords(keywords: {
44
+ label: string;
45
+ count: number;
46
+ }[], totalMessages: number): number | null;
47
+ export declare function splitMonthlyKeywordBuckets(buckets: Map<string, KeywordCounter>): {
48
+ headKeywords: CountItem[];
49
+ tailKeywords: CountItem[];
50
+ };
51
+ export declare function topDailyLinkSpikes(dailyLinks: Map<string, number>): {
52
+ date: string;
53
+ links: number;
54
+ }[];
55
+ export type RoomEventCounts = {
56
+ join: number;
57
+ leave: number;
58
+ deleted: number;
59
+ hidden: number;
60
+ kick: number;
61
+ slowModeOn: number;
62
+ slowModeOff: number;
63
+ subManager: number;
64
+ manager: number;
65
+ shopSearch: number;
66
+ photoBundle: number;
67
+ };
68
+ export declare function buildRoomEventStats(total: number, c: RoomEventCounts, shopExtra?: {
69
+ tagExtractions: number;
70
+ uniqueTags: number;
71
+ untaggedNotices: number;
72
+ }): import("../types.js").RoomEventStats;
73
+ export declare function buildParticipantRoles(participants: ParticipantStat[], laughBySender: Map<string, number>, shortBySender: Map<string, number>, aliases: Map<string, string>): ParticipantRole[];
74
+ export declare function formatDayMdHighlight(ymd: string): string;
75
+ export declare function buildHighlights(input: {
76
+ total: number;
77
+ topAlias: string | null;
78
+ topShare: number | null;
79
+ busiestWeekdayLabel: string | null;
80
+ peakHour: number | null;
81
+ medianReplyGapMinutes: number | null;
82
+ nightSharePercent: number;
83
+ longestStreak: number;
84
+ emojiMessages: number;
85
+ messagesWithAttachments: number;
86
+ weekendSharePercent: number;
87
+ participantGini: number | null;
88
+ replyGapP90Minutes: number | null;
89
+ maxSilenceBetweenActiveDays: number | null;
90
+ rhythmScore: number;
91
+ burstGapUnder1mPercent: number | null;
92
+ monologueMessagesPercent: number;
93
+ roomJoinMessages: number;
94
+ roomLeaveMessages: number;
95
+ roomDeletedMessages: number;
96
+ roomHiddenMessages: number;
97
+ roomKickMessages: number;
98
+ pureLaughMessages: number;
99
+ repeatedPhraseCount: number;
100
+ burstDays: {
101
+ date: string;
102
+ count: number;
103
+ }[];
104
+ activityArc: {
105
+ id: string;
106
+ label: string;
107
+ messages: number;
108
+ activeDays: number;
109
+ }[];
110
+ conversationPace: {
111
+ label: string;
112
+ emoji: string;
113
+ detail: string;
114
+ };
115
+ roomPulse: {
116
+ date: string;
117
+ join: number;
118
+ leave: number;
119
+ hidden: number;
120
+ kick: number;
121
+ newSenders: number;
122
+ }[];
123
+ lexicalTypeRichnessPercent: number | null;
124
+ speakerSwitchRatePer100: number;
125
+ }): string[];
126
+ export declare function inferRoomRelationship(honorific: import("../types.js").HonorificInsight): import("../types.js").RoomRelationship;
127
+ export {};
@@ -0,0 +1,420 @@
1
+ import { KeywordCounter } from "../keyword-counter.js";
2
+ import { maskPartialDisplayName } from "../analysis-labels.js";
3
+ import { partsToUtcMs } from "../date.js";
4
+ import { formatCompactNumber, formatReplyGapMinutes } from "../report-util.js";
5
+ /* ── 기본 유틸 ── */
6
+ export function round(value, decimals) {
7
+ const factor = 10 ** decimals;
8
+ return Math.round(value * factor) / factor;
9
+ }
10
+ export function pad2(value) {
11
+ return value.toString().padStart(2, "0");
12
+ }
13
+ export function medianSorted(sorted) {
14
+ if (sorted.length === 0)
15
+ return 0;
16
+ const mid = Math.floor(sorted.length / 2);
17
+ return sorted.length % 2 === 1 ? sorted[mid] : (sorted[mid - 1] + sorted[mid]) / 2;
18
+ }
19
+ export function increment(map, key, amount = 1) {
20
+ map.set(key, (map.get(key) ?? 0) + amount);
21
+ }
22
+ export function topCounts(map, limit) {
23
+ return [...map.entries()]
24
+ .map(([label, count]) => ({ label, count }))
25
+ .sort((a, b) => b.count - a.count || a.label.localeCompare(b.label))
26
+ .slice(0, limit);
27
+ }
28
+ /* ── 참여자·레이블 ── */
29
+ export function buildSenderLabels(senders, privacy) {
30
+ const unique = [...new Set(senders)];
31
+ if (privacy === "public-anonymous") {
32
+ const map = new Map();
33
+ unique.forEach((sender, i) => map.set(sender, `User ${String(i + 1).padStart(3, "0")}`));
34
+ return map;
35
+ }
36
+ const map = new Map();
37
+ const used = new Map();
38
+ for (const raw of unique) {
39
+ let base = maskPartialDisplayName(raw);
40
+ const n = (used.get(base) ?? 0) + 1;
41
+ used.set(base, n);
42
+ if (n > 1)
43
+ base = `${base}·${n}`;
44
+ map.set(raw, base);
45
+ }
46
+ return map;
47
+ }
48
+ export function normalizeToken(token) {
49
+ return /^[A-Za-z0-9_+-]+$/.test(token) ? token.toLowerCase() : token.trim();
50
+ }
51
+ /* ── URL·도메인 ── */
52
+ const URL_RE = /\bhttps?:\/\/[^\s<>"']+|www\.[^\s<>"']+/gi;
53
+ export function getDomains(message) {
54
+ const matches = message.match(URL_RE) ?? [];
55
+ const domains = [];
56
+ for (const match of matches) {
57
+ const urlText = match.startsWith("http") ? match : `https://${match}`;
58
+ try {
59
+ const url = new URL(urlText);
60
+ domains.push(url.hostname.toLowerCase().replace(/^www\./, ""));
61
+ }
62
+ catch {
63
+ continue;
64
+ }
65
+ }
66
+ return domains;
67
+ }
68
+ /* ── 통계·지표 ── */
69
+ export function longestDateStreak(sortedYmd) {
70
+ if (sortedYmd.length === 0)
71
+ return 0;
72
+ let best = 1;
73
+ let cur = 1;
74
+ for (let i = 1; i < sortedYmd.length; i += 1) {
75
+ const a = new Date(`${sortedYmd[i - 1]}T12:00:00Z`).getTime();
76
+ const b = new Date(`${sortedYmd[i]}T12:00:00Z`).getTime();
77
+ const diffDays = Math.round((b - a) / 86_400_000);
78
+ if (diffDays === 1) {
79
+ cur += 1;
80
+ best = Math.max(best, cur);
81
+ }
82
+ else {
83
+ cur = 1;
84
+ }
85
+ }
86
+ return best;
87
+ }
88
+ export function computeGini(counts) {
89
+ if (counts.length === 0)
90
+ return null;
91
+ const sorted = [...counts].sort((a, b) => a - b);
92
+ const n = sorted.length;
93
+ let sum = 0;
94
+ for (const x of sorted)
95
+ sum += x;
96
+ if (sum === 0)
97
+ return null;
98
+ let num = 0;
99
+ for (let i = 0; i < n; i += 1) {
100
+ num += (2 * i - n + 1) * sorted[i];
101
+ }
102
+ return round(num / (n * sum), 3);
103
+ }
104
+ export function maxSilenceGapDays(sortedYmd) {
105
+ if (sortedYmd.length < 2)
106
+ return null;
107
+ let best = 0;
108
+ for (let i = 1; i < sortedYmd.length; i += 1) {
109
+ const a = new Date(`${sortedYmd[i - 1]}T12:00:00Z`).getTime();
110
+ const b = new Date(`${sortedYmd[i]}T12:00:00Z`).getTime();
111
+ const diffDays = Math.round((b - a) / 86_400_000);
112
+ best = Math.max(best, Math.max(0, diffDays - 1));
113
+ }
114
+ return best;
115
+ }
116
+ export function computeDensityFromSpan(first, last, total) {
117
+ if (total === 0 || !first || !last)
118
+ return null;
119
+ const spanDays = Math.max(1, Math.floor((partsToUtcMs(last) - partsToUtcMs(first)) / 86_400_000) + 1);
120
+ return round(total / spanDays, 2);
121
+ }
122
+ export function domainEntropyBits(domains) {
123
+ let sum = 0;
124
+ for (const c of domains.values())
125
+ sum += c;
126
+ if (sum === 0)
127
+ return null;
128
+ let h = 0;
129
+ for (const c of domains.values()) {
130
+ if (c <= 0)
131
+ continue;
132
+ const p = c / sum;
133
+ h -= p * Math.log2(p);
134
+ }
135
+ return round(h, 2);
136
+ }
137
+ export function computeRhythmScore(input) {
138
+ const g = input.gini ?? 0.45;
139
+ const streakN = Math.min(1, input.longestStreak / 28);
140
+ const densityN = input.density != null ? Math.min(1, input.density / 40) : 0.25;
141
+ const score = 48 * (1 - Math.min(0.95, g)) + 32 * streakN + 20 * densityN;
142
+ return Math.max(0, Math.min(100, Math.round(score)));
143
+ }
144
+ export function getParticipantStat(stats, sender) {
145
+ const existing = stats.get(sender);
146
+ if (existing)
147
+ return existing;
148
+ const created = {
149
+ messages: 0, characters: 0, attachmentMessages: 0,
150
+ linkMessages: 0, nightMessages: 0, maxConsecutive: 0,
151
+ };
152
+ stats.set(sender, created);
153
+ return created;
154
+ }
155
+ export function computeTop3Share(stats, total) {
156
+ if (total === 0)
157
+ return 0;
158
+ const top3 = [...stats.values()]
159
+ .map((s) => s.messages).sort((a, b) => b - a).slice(0, 3)
160
+ .reduce((a, c) => a + c, 0);
161
+ return round((top3 / total) * 100, 1);
162
+ }
163
+ /* ── 시간대 ── */
164
+ export function computeDaypartPercents(hourly, total) {
165
+ const bands = [
166
+ { key: "dawn", label: "새벽(0~5시)", lo: 0, hi: 5 },
167
+ { key: "morning", label: "오전(6~11시)", lo: 6, hi: 11 },
168
+ { key: "afternoon", label: "오후(12~17시)", lo: 12, hi: 17 },
169
+ { key: "evening", label: "저녁(18~23시)", lo: 18, hi: 23 },
170
+ ];
171
+ if (total === 0)
172
+ return bands.map((b) => ({ key: b.key, label: b.label, percent: 0 }));
173
+ const raw = bands.map((b) => {
174
+ let c = 0;
175
+ for (let h = b.lo; h <= b.hi; h += 1)
176
+ c += hourly[h] ?? 0;
177
+ return { key: b.key, label: b.label, count: c };
178
+ });
179
+ const sum = raw.reduce((a, x) => a + x.count, 0) || 1;
180
+ let rounded = raw.map((x) => ({
181
+ key: x.key, label: x.label,
182
+ percent: round((x.count / sum) * 100, 1),
183
+ }));
184
+ const drift = 100 - rounded.reduce((a, x) => a + x.percent, 0);
185
+ if (Math.abs(drift) >= 0.05 && rounded.length > 0) {
186
+ const idx = rounded.reduce((best, x, i, arr) => (x.percent >= arr[best].percent ? i : best), 0);
187
+ rounded = rounded.map((x, i) => (i === idx ? { ...x, percent: round(x.percent + drift, 1) } : x));
188
+ }
189
+ return rounded;
190
+ }
191
+ /* ── 키워드 ── */
192
+ export function top1ShareFromCounts(keywords, totalMessages) {
193
+ if (keywords.length === 0 || totalMessages === 0)
194
+ return null;
195
+ const sum = keywords.reduce((a, k) => a + k.count, 0);
196
+ if (sum === 0)
197
+ return null;
198
+ return round((keywords[0].count / sum) * 100, 1);
199
+ }
200
+ export function typeRichnessFromKeywords(keywords, totalMessages) {
201
+ if (totalMessages === 0 || keywords.length === 0)
202
+ return null;
203
+ const tokenSum = keywords.reduce((a, k) => a + k.count, 0);
204
+ if (tokenSum === 0)
205
+ return null;
206
+ return round((keywords.length / tokenSum) * 100, 1);
207
+ }
208
+ export function splitMonthlyKeywordBuckets(buckets) {
209
+ const months = [...buckets.keys()].sort();
210
+ if (months.length < 2)
211
+ return { headKeywords: [], tailKeywords: [] };
212
+ const mid = Math.floor(months.length / 2);
213
+ const mergeMonths = (keys) => {
214
+ const acc = new KeywordCounter();
215
+ for (const k of keys) {
216
+ const b = buckets.get(k);
217
+ if (!b)
218
+ continue;
219
+ for (const item of b.topCounts(40))
220
+ acc.addHits(item.label, item.count);
221
+ }
222
+ return acc.topCounts(12);
223
+ };
224
+ return {
225
+ headKeywords: mergeMonths(months.slice(0, mid)),
226
+ tailKeywords: mergeMonths(months.slice(mid)),
227
+ };
228
+ }
229
+ export function topDailyLinkSpikes(dailyLinks) {
230
+ return [...dailyLinks.entries()]
231
+ .filter(([, c]) => c >= 3)
232
+ .sort((a, b) => b[1] - a[1])
233
+ .slice(0, 6)
234
+ .map(([date, links]) => ({ date, links }));
235
+ }
236
+ export function buildRoomEventStats(total, c, shopExtra) {
237
+ const sum = c.join + c.leave + c.deleted + c.hidden + c.kick +
238
+ c.slowModeOn + c.slowModeOff + c.subManager + c.manager +
239
+ c.shopSearch + c.photoBundle;
240
+ const pct = (n) => (total > 0 ? round((n / total) * 100, 2) : 0);
241
+ return {
242
+ joinCount: c.join, leaveCount: c.leave, deletedCount: c.deleted,
243
+ hiddenCount: c.hidden, kickCount: c.kick,
244
+ slowModeOnCount: c.slowModeOn, slowModeOffCount: c.slowModeOff,
245
+ subManagerCount: c.subManager, managerCount: c.manager,
246
+ shopSearchCount: c.shopSearch,
247
+ shopSearchTagExtractions: shopExtra?.tagExtractions ?? 0,
248
+ shopSearchUniqueTags: shopExtra?.uniqueTags ?? 0,
249
+ shopSearchUntaggedNotices: shopExtra?.untaggedNotices ?? 0,
250
+ photoBundleCount: c.photoBundle, total: sum,
251
+ joinSharePercent: pct(c.join), leaveSharePercent: pct(c.leave),
252
+ deletedSharePercent: pct(c.deleted), hiddenSharePercent: pct(c.hidden),
253
+ kickSharePercent: pct(c.kick),
254
+ };
255
+ }
256
+ /* ── 참여자 역할 ── */
257
+ export function buildParticipantRoles(participants, laughBySender, shortBySender, aliases) {
258
+ if (participants.length === 0)
259
+ return [];
260
+ const sortedByMessages = [...participants].sort((a, b) => b.messages - a.messages);
261
+ const avgLengthOverall = participants.reduce((sum, p) => sum + p.averageLength, 0) / participants.length;
262
+ const pickedRoles = new Set();
263
+ const results = [];
264
+ for (const p of participants) {
265
+ const rawAlias = [...aliases.entries()].find(([, a]) => a === p.alias)?.[0];
266
+ const laughCount = rawAlias ? (laughBySender.get(rawAlias) ?? 0) : 0;
267
+ const shortCount = rawAlias ? (shortBySender.get(rawAlias) ?? 0) : 0;
268
+ const msg = Math.max(p.messages, 1);
269
+ const laughRate = laughCount / msg;
270
+ const shortRate = shortCount / msg;
271
+ const nightRate = p.nightMessages / msg;
272
+ const attachRate = p.attachmentMessages / msg;
273
+ const linkRate = p.linkMessages / msg;
274
+ const rank = sortedByMessages.findIndex((x) => x.alias === p.alias);
275
+ const candidates = [];
276
+ if (rank === 0 && p.sharePercent >= 18) {
277
+ candidates.push({ role: "주도형", confidence: 0.92, reason: `메시지 비중 ${p.sharePercent}%로 대화 흐름을 가장 많이 만든 참여자`, score: p.sharePercent + 30 });
278
+ }
279
+ if (p.averageLength >= Math.max(28, avgLengthOverall * 1.45)) {
280
+ candidates.push({ role: "긴글러", confidence: 0.88, reason: `평균 ${p.averageLength}자로 긴 설명을 남기는 편`, score: p.averageLength });
281
+ }
282
+ if (laughRate >= 0.12 && laughCount >= 8) {
283
+ candidates.push({ role: "분위기 메이커", confidence: 0.86, reason: `웃음 반응이 ${Math.round(laughRate * 100)}%로 뚜렷함`, score: laughRate * 100 });
284
+ }
285
+ if (shortRate >= 0.22 && shortCount >= 12) {
286
+ candidates.push({ role: "리액션러", confidence: 0.84, reason: `짧은 응답 비중 ${Math.round(shortRate * 100)}%로 빠른 반응이 많음`, score: shortRate * 100 });
287
+ }
288
+ if (linkRate >= 0.08 && p.linkMessages >= 8) {
289
+ candidates.push({ role: "자료 공유자", confidence: 0.84, reason: `링크 포함 메시지 ${p.linkMessages}건으로 자료 공유 신호가 강함`, score: linkRate * 100 });
290
+ }
291
+ if (attachRate >= 0.1 && p.attachmentMessages >= 8) {
292
+ candidates.push({ role: "첨부 장인", confidence: 0.82, reason: `사진·파일 첨부 ${p.attachmentMessages}건으로 시각 자료 기여가 큼`, score: attachRate * 100 });
293
+ }
294
+ if (nightRate >= 0.25 && p.nightMessages >= 10) {
295
+ candidates.push({ role: "심야 상주자", confidence: 0.82, reason: `심야 메시지 ${p.nightMessages}건으로 늦은 시간 활동이 두드러짐`, score: nightRate * 100 });
296
+ }
297
+ if (p.maxConsecutive >= 10) {
298
+ candidates.push({ role: "연속 발화자", confidence: 0.82, reason: `최대 ${p.maxConsecutive}연속 발화로 한 번에 흐름을 길게 이어감`, score: p.maxConsecutive * 3 });
299
+ }
300
+ candidates.sort((a, b) => b.score - a.score);
301
+ const picked = candidates.find((c) => !pickedRoles.has(c.role));
302
+ if (!picked)
303
+ continue;
304
+ pickedRoles.add(picked.role);
305
+ results.push({ alias: p.alias, role: picked.role, confidence: picked.confidence, reason: picked.reason });
306
+ if (results.length >= 6)
307
+ break;
308
+ }
309
+ return results;
310
+ }
311
+ export function formatDayMdHighlight(ymd) {
312
+ const p = ymd.split("-");
313
+ if (p.length === 3)
314
+ return `${Number(p[1])}/${Number(p[2])}`;
315
+ return ymd;
316
+ }
317
+ export function buildHighlights(input) {
318
+ const out = [];
319
+ if (input.topAlias && input.topShare !== null && input.total > 0)
320
+ out.push(`가장 말이 많았던 분은 **${input.topAlias}** (전체의 **${input.topShare}%**).`);
321
+ if (input.busiestWeekdayLabel)
322
+ out.push(`요일별로는 **${input.busiestWeekdayLabel}**에 활동이 가장 활발했어요.`);
323
+ if (input.peakHour !== null)
324
+ out.push(`시간대는 **${input.peakHour}시**대에 메시지가 가장 몰렸습니다.`);
325
+ if (input.medianReplyGapMinutes !== null)
326
+ out.push(`연속 메시지 사이 간격의 중앙값은 **${formatReplyGapMinutes(input.medianReplyGapMinutes)}** 정도예요.`);
327
+ if (input.nightSharePercent > 0)
328
+ out.push(`심야(23~05시) 메시지 비중은 **${input.nightSharePercent}%**입니다.`);
329
+ if (input.longestStreak > 1)
330
+ out.push(`하루도 빠짐없이 이어진 최장 **${input.longestStreak}일** 연속 활동 기록이 있어요.`);
331
+ if (input.emojiMessages > 0)
332
+ out.push(`이모지·스티커 느낌의 메시지는 **${input.emojiMessages}**건 정도 감지됐어요.`);
333
+ if (input.messagesWithAttachments > 0)
334
+ out.push(`사진·파일·동영상 등 첨부가 들어간 메시지는 **${input.messagesWithAttachments}**건입니다.`);
335
+ if (input.total > 0 && input.weekendSharePercent > 0)
336
+ out.push(`주말(토·일) 메시지 비중은 **${input.weekendSharePercent}%**예요.`);
337
+ if (input.participantGini !== null && input.participantGini >= 0.35)
338
+ out.push(`참여도는 소수에게 조금 몰린 편이에요(지니 **${input.participantGini}** — 1에 가까울수록 쏠림).`);
339
+ if (input.replyGapP90Minutes !== null && input.replyGapP90Minutes >= 30)
340
+ out.push(`가끔 긴 침묵도 있어요 — 응답 간격 **상위 10%**가 약 **${input.replyGapP90Minutes}분** 이상입니다.`);
341
+ if (input.maxSilenceBetweenActiveDays !== null && input.maxSilenceBetweenActiveDays >= 7)
342
+ out.push(`활동일 사이 최대 **${input.maxSilenceBetweenActiveDays}일** 동안은 메시지가 끊긴 구간이 있었어요.`);
343
+ if (input.rhythmScore >= 65)
344
+ out.push(`종합 **리듬 점수**는 **${input.rhythmScore}/100** — 꾸준하고 균형 잡힌 페이스에 가깝습니다.`);
345
+ if (input.burstGapUnder1mPercent !== null && input.burstGapUnder1mPercent >= 40)
346
+ out.push(`응답 간격의 **${input.burstGapUnder1mPercent}%**가 1분 이내로, 실시간 대화 톤이 강해요.`);
347
+ if (input.monologueMessagesPercent >= 25)
348
+ out.push(`같은 사람 **3연속 이상** 메시지가 전체의 **${input.monologueMessagesPercent}%** — 긴 설명·정리 구간이 잦을 수 있어요.`);
349
+ const sysTotal = input.roomJoinMessages + input.roomLeaveMessages + input.roomDeletedMessages +
350
+ input.roomHiddenMessages + input.roomKickMessages;
351
+ if (sysTotal > 0) {
352
+ const parts = [
353
+ input.roomJoinMessages > 0 ? `들어옴 ${input.roomJoinMessages}` : "",
354
+ input.roomLeaveMessages > 0 ? `나감 ${input.roomLeaveMessages}` : "",
355
+ input.roomDeletedMessages > 0 ? `삭제 ${input.roomDeletedMessages}` : "",
356
+ input.roomHiddenMessages > 0 ? `가림 ${input.roomHiddenMessages}` : "",
357
+ input.roomKickMessages > 0 ? `강퇴 ${input.roomKickMessages}` : "",
358
+ ].filter(Boolean);
359
+ out.push(`카카오톡 **시스템·운영 알림** **${sysTotal}**건(${parts.join(" · ")}) — 본문 키워드와 분리했어요.`);
360
+ }
361
+ if (input.pureLaughMessages > 0)
362
+ out.push(`**ㅋㅋ만** 보낸 리액션 메시지는 **${input.pureLaughMessages}**건이에요.`);
363
+ if (input.repeatedPhraseCount >= 10)
364
+ out.push(`똑같은 문장이 **${input.repeatedPhraseCount}회** 반복된 복붙·환영 문구도 있어요.`);
365
+ if (input.burstDays.length > 0) {
366
+ const top = input.burstDays[0];
367
+ const labels = input.burstDays.slice(0, 3).map((d) => formatDayMdHighlight(d.date)).join(" · ");
368
+ out.push(`메시지가 평소보다 몰린 날 **${input.burstDays.length}일** — 최고는 **${formatDayMdHighlight(top.date)}**(${formatCompactNumber(top.count)}건). ${labels}`);
369
+ }
370
+ const head = input.activityArc.find((a) => a.id === "head");
371
+ const tail = input.activityArc.find((a) => a.id === "tail");
372
+ if (head && tail && head.messages > 0 && tail.messages > 0) {
373
+ const ratio = round(tail.messages / head.messages, 2);
374
+ if (ratio >= 1.25)
375
+ out.push(`마지막 7일이 처음 7일보다 **${ratio}배** 활발 — 대화가 뜨거워지는 구간이 있었어요.`);
376
+ else if (ratio <= 0.8)
377
+ out.push(`처음 7일이 마지막보다 더 붐볐어요(후반은 처음의 **${Math.round(ratio * 100)}%** 수준).`);
378
+ }
379
+ if (input.lexicalTypeRichnessPercent !== null && input.lexicalTypeRichnessPercent >= 18)
380
+ out.push(`본문 단어는 **${input.lexicalTypeRichnessPercent}%** 정도로 서로 다른 표현이 많이 섞였어요.`);
381
+ const pace = input.conversationPace;
382
+ out.push(`대화 템포는 **${pace.emoji} ${pace.label}** — ${pace.detail}`);
383
+ const peakHidden = [...input.roomPulse].sort((a, b) => b.hidden - a.hidden)[0];
384
+ if (peakHidden && peakHidden.hidden >= 5)
385
+ out.push(`가림 알림이 가장 많았던 날은 **${formatDayMdHighlight(peakHidden.date)}**(${peakHidden.hidden}건)이에요.`);
386
+ const peakJoin = [...input.roomPulse].sort((a, b) => b.join - a.join)[0];
387
+ if (peakJoin && peakJoin.join >= 20)
388
+ out.push(`입장이 가장 몰린 날은 **${formatDayMdHighlight(peakJoin.date)}** — **${peakJoin.join}**명 들어왔어요.`);
389
+ return out.slice(0, 14);
390
+ }
391
+ /* ── 관계 추론 ── */
392
+ export function inferRoomRelationship(honorific) {
393
+ const honorificCount = honorific.participants.filter((p) => p.dominantStyle === "honorific").length;
394
+ const casualCount = honorific.participants.filter((p) => p.dominantStyle === "casual").length;
395
+ const total = honorific.participants.length;
396
+ if (total === 0)
397
+ return { type: "mixed", description: "높임법 분석 데이터가 부족합니다.", evidence: [] };
398
+ const hRatio = honorificCount / total;
399
+ const cRatio = casualCount / total;
400
+ if (hRatio >= 0.7)
401
+ return {
402
+ type: "formal", description: "대부분 존칭을 사용하는 격식 있는 방입니다.",
403
+ evidence: [`${honorificCount}명 중 ${Math.round(hRatio * 100)}%가 존칭 사용`],
404
+ };
405
+ if (cRatio >= 0.7)
406
+ return {
407
+ type: "friendly", description: "친구나 동료처럼 편안한 반말을 주로 사용합니다.",
408
+ evidence: [`${casualCount}명 중 ${Math.round(cRatio * 100)}%가 반말 사용`],
409
+ };
410
+ if (honorificCount > 0 && casualCount > 0)
411
+ return {
412
+ type: "hierarchical", description: "존칭과 반말이 혼용되어 선후배/상하 관계가 있을 수 있습니다.",
413
+ evidence: [`존칭 사용자: ${honorificCount}명`, `반말 사용자: ${casualCount}명`],
414
+ };
415
+ return {
416
+ type: "mixed", description: "다양한 높임법 스타일이 혼재되어 있습니다.",
417
+ evidence: ["명확한 패턴을 찾을 수 없음"],
418
+ };
419
+ }
420
+ //# sourceMappingURL=aggregator-helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregator-helpers.js","sourceRoot":"","sources":["../../../src/accumulator/aggregator-helpers.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,7 @@ export declare class ReportAggregator {
57
57
  private readonly dailyPlanSignals;
58
58
  private readonly monthlyKeywordBuckets;
59
59
  private readonly dailyKeywordBuckets;
60
+ private readonly dailyContextSamples;
60
61
  private readonly dyads;
61
62
  private readonly dailySentimentCounters;
62
63
  private readonly senderHonorificCounts;
@@ -132,6 +133,7 @@ export declare class ReportAggregator {
132
133
  label: string;
133
134
  messageHits: number;
134
135
  }[]): void;
136
+ private collectDailyContextSample;
135
137
  consume(record: ChatRecord, opts?: {
136
138
  keywordsOnly?: boolean;
137
139
  skipKeywords?: boolean;