kakaotalk-chat-analyzer 0.22.6 → 0.24.0

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 (44) hide show
  1. package/README.md +3 -1
  2. package/dist/src/accumulator/aggregator-helpers.d.ts +127 -0
  3. package/dist/src/accumulator/aggregator-helpers.js +419 -0
  4. package/dist/src/accumulator/aggregator-helpers.js.map +1 -0
  5. package/dist/src/aggregator.js +6 -482
  6. package/dist/src/aggregator.js.map +1 -1
  7. package/dist/src/analyze-pool.js +13 -2
  8. package/dist/src/analyze-pool.js.map +1 -1
  9. package/dist/src/cli.js +6 -2
  10. package/dist/src/cli.js.map +1 -1
  11. package/dist/src/gap-stats.js +2 -2
  12. package/dist/src/gap-stats.js.map +1 -1
  13. package/dist/src/keyword-counter.js +2 -0
  14. package/dist/src/keyword-counter.js.map +1 -1
  15. package/dist/src/keyword-tokenize.d.ts +3 -2
  16. package/dist/src/keyword-tokenize.js +7 -5
  17. package/dist/src/keyword-tokenize.js.map +1 -1
  18. package/dist/src/kiwi-keyword-pool.js +83 -33
  19. package/dist/src/kiwi-keyword-pool.js.map +1 -1
  20. package/dist/src/kiwi-tokenize-worker.js +50 -12
  21. package/dist/src/kiwi-tokenize-worker.js.map +1 -1
  22. package/dist/src/llm-cache.js +15 -3
  23. package/dist/src/llm-cache.js.map +1 -1
  24. package/dist/src/report-charts.d.ts +2 -2
  25. package/dist/src/report-charts.js +212 -74
  26. package/dist/src/report-charts.js.map +1 -1
  27. package/dist/src/report-head.d.ts +1 -1
  28. package/dist/src/report-head.js +1 -1
  29. package/dist/src/report-innovation.js +5 -5
  30. package/dist/src/report-llm-deck.js +7 -7
  31. package/dist/src/report-story.js +5 -5
  32. package/dist/src/report-story.js.map +1 -1
  33. package/dist/src/report-styles.d.ts +1 -1
  34. package/dist/src/report-styles.js +1714 -1276
  35. package/dist/src/report-styles.js.map +1 -1
  36. package/dist/src/report-ux.js +1 -1
  37. package/dist/src/report.js +19 -19
  38. package/dist/src/report.js.map +1 -1
  39. package/dist/src/stream-parser.d.ts +2 -1
  40. package/dist/src/stream-parser.js +11 -2
  41. package/dist/src/stream-parser.js.map +1 -1
  42. package/dist/src/version.d.ts +2 -2
  43. package/dist/src/version.js +1 -1
  44. package/package.json +8 -2
package/README.md CHANGED
@@ -106,7 +106,7 @@ npx kcachat@latest "C:\경로\KakaoTalk_Chat_....csv"
106
106
 
107
107
  ## 리포트에서 볼 수 있는 것
108
108
 
109
- 브라우저만 있으면 되는 **단일 HTML**입니다. **대화 원문은 파일에 넣지 않습니다.** 상단 **섹션 메뉴**로 ⓪~⑥ 구역을 바로 이동할 수 있습니다.
109
+ 브라우저만 있으면 되는 **단일 HTML**입니다. **대화 원문은 파일에 넣지 않습니다.** 상단 **섹션 메뉴**로 ⓪~⑥ 구역을 바로 이동할 수 있으며, 모든 콘텐츠는 **v3 통합 카드 시스템**으로 일관되게 배치됩니다.
110
110
 
111
111
  | 구역 | 내용 |
112
112
  |------|------|
@@ -262,6 +262,8 @@ cd kakaotalk-chat-analyzer && npm install && npm run build && npm test
262
262
 
263
263
  | 버전 | 요약 |
264
264
  |------|------|
265
+ | **0.23.0** | **v3 통합 카드 시스템** — 리포트 레이아웃 전면 재설계 · 12개 CSS 토큰 · 5계층 카드 시스템 · OLED 글라스 6종 확장 · 히어로 재설계 · #s-charts 구조화 · 헤딩 계층 정비 · 컬러 토큰화 |
266
+ | **0.22.6** | **프리미엄 리디자인** — 랜딩 페이지·리포트 CSS 전면 개편 · **글라스 2.0** 테마 · **벤토 그리드** 기능 카드 · **인터랙티브 마우스 트래킹** · 접근성 개선 (**focus-visible**, 대비 강화, reduced motion) · light theme 보완 |
265
267
  | **0.22.3** | **5개 신규 지표**(질문·독백·세션·피크일·도메인) · **3개 LLM 섹션 활성화**(관계·시대·그날) · **소셜 네트워크 그래프** · **감정 롤러코스터** · **토픽 트랜드** · 참여자 **10명+더보기** · 모바일 **ECharts 최적화** · 네비 번호 연속성 · `insightBullets` 버그 수정 |
266
268
  | **0.22.2** | **JSON 필드명 노출** 버그 수정·LLM 출력 필터링 강화·리포트 렌더링 품질 개선 |
267
269
  | **0.22.1** | **LLM JSON Grammar Constraint** 핫픽스(Child Process)·**템플릿 잔여물 필터링**·**Few-shot 프롬프트**·리포트 출력 품질 개선 |
@@ -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,419 @@
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((s, p) => s + p.averageLength, 0) / participants.length;
262
+ const top25 = Math.ceil(participants.length * 0.25);
263
+ const top50 = Math.ceil(participants.length * 0.5);
264
+ const results = [];
265
+ for (const p of participants) {
266
+ const rawAlias = [...aliases.entries()].find(([, a]) => a === p.alias)?.[0];
267
+ const laughCount = rawAlias ? (laughBySender.get(rawAlias) ?? 0) : 0;
268
+ const shortCount = rawAlias ? (shortBySender.get(rawAlias) ?? 0) : 0;
269
+ const laughRate = p.messages > 0 ? (laughCount / p.messages) : 0;
270
+ const shortRate = p.messages > 0 ? (shortCount / p.messages) : 0;
271
+ const rank = sortedByMessages.findIndex((x) => x.alias === p.alias);
272
+ const isTop25 = rank < top25;
273
+ const isBottom50 = rank >= top50;
274
+ const isLong = p.averageLength >= avgLengthOverall * 1.2;
275
+ const isShort = p.averageLength <= avgLengthOverall * 0.7;
276
+ const isVeryLong = p.averageLength >= avgLengthOverall * 1.5;
277
+ let role;
278
+ let confidence;
279
+ let reason;
280
+ if (isTop25 && isLong) {
281
+ role = "리더";
282
+ confidence = 0.9;
283
+ reason = `메시지 수 상위(${p.messages}건)에 평균 길이(${p.averageLength}자)가 전체 평균(${avgLengthOverall.toFixed(1)}자)보다 긴 주도형 참여자`;
284
+ }
285
+ else if (laughRate > 0.15 || (isBottom50 && shortRate > 0.3)) {
286
+ role = "유머메이커";
287
+ confidence = 0.8;
288
+ reason = `웃음 표현 비율(${Math.round(laughRate * 100)}%)이 높거나 짧은 반응 메시지가 많은 분위기 메이커`;
289
+ }
290
+ else if (isBottom50 && isVeryLong) {
291
+ role = "조용한기여자";
292
+ confidence = 0.85;
293
+ reason = `메시지 수는 적지만 평균 길이(${p.averageLength}자)가 전체 평균(${avgLengthOverall.toFixed(1)}자)의 1.5배 이상인 깊이 있는 기여자`;
294
+ }
295
+ else if (isBottom50 && isShort) {
296
+ role = "방관자";
297
+ confidence = 0.8;
298
+ reason = `메시지 수가 적고 짧은 메시지(${p.averageLength}자) 위주로 주로 관찰하는 참여자`;
299
+ }
300
+ else {
301
+ role = "조력자";
302
+ confidence = 0.75;
303
+ reason = `균형 잡힌 메시지 수(${p.messages}건)와 길이(${p.averageLength}자)로 대화를 돕는 조력자`;
304
+ }
305
+ results.push({ alias: p.alias, role, confidence, reason });
306
+ }
307
+ return results;
308
+ }
309
+ /* ── 하이라이트 ── */
310
+ export function formatDayMdHighlight(ymd) {
311
+ const p = ymd.split("-");
312
+ if (p.length === 3)
313
+ return `${Number(p[1])}/${Number(p[2])}`;
314
+ return ymd;
315
+ }
316
+ export function buildHighlights(input) {
317
+ const out = [];
318
+ if (input.topAlias && input.topShare !== null && input.total > 0)
319
+ out.push(`가장 말이 많았던 분은 **${input.topAlias}** (전체의 **${input.topShare}%**).`);
320
+ if (input.busiestWeekdayLabel)
321
+ out.push(`요일별로는 **${input.busiestWeekdayLabel}**에 활동이 가장 활발했어요.`);
322
+ if (input.peakHour !== null)
323
+ out.push(`시간대는 **${input.peakHour}시**대에 메시지가 가장 몰렸습니다.`);
324
+ if (input.medianReplyGapMinutes !== null)
325
+ out.push(`연속 메시지 사이 간격의 중앙값은 **${formatReplyGapMinutes(input.medianReplyGapMinutes)}** 정도예요.`);
326
+ if (input.nightSharePercent > 0)
327
+ out.push(`심야(23~05시) 메시지 비중은 **${input.nightSharePercent}%**입니다.`);
328
+ if (input.longestStreak > 1)
329
+ out.push(`하루도 빠짐없이 이어진 최장 **${input.longestStreak}일** 연속 활동 기록이 있어요.`);
330
+ if (input.emojiMessages > 0)
331
+ out.push(`이모지·스티커 느낌의 메시지는 **${input.emojiMessages}**건 정도 감지됐어요.`);
332
+ if (input.messagesWithAttachments > 0)
333
+ out.push(`사진·파일·동영상 등 첨부가 들어간 메시지는 **${input.messagesWithAttachments}**건입니다.`);
334
+ if (input.total > 0 && input.weekendSharePercent > 0)
335
+ out.push(`주말(토·일) 메시지 비중은 **${input.weekendSharePercent}%**예요.`);
336
+ if (input.participantGini !== null && input.participantGini >= 0.35)
337
+ out.push(`참여도는 소수에게 조금 몰린 편이에요(지니 **${input.participantGini}** — 1에 가까울수록 쏠림).`);
338
+ if (input.replyGapP90Minutes !== null && input.replyGapP90Minutes >= 30)
339
+ out.push(`가끔 긴 침묵도 있어요 — 응답 간격 **상위 10%**가 약 **${input.replyGapP90Minutes}분** 이상입니다.`);
340
+ if (input.maxSilenceBetweenActiveDays !== null && input.maxSilenceBetweenActiveDays >= 7)
341
+ out.push(`활동일 사이 최대 **${input.maxSilenceBetweenActiveDays}일** 동안은 메시지가 끊긴 구간이 있었어요.`);
342
+ if (input.rhythmScore >= 65)
343
+ out.push(`종합 **리듬 점수**는 **${input.rhythmScore}/100** — 꾸준하고 균형 잡힌 페이스에 가깝습니다.`);
344
+ if (input.burstGapUnder1mPercent !== null && input.burstGapUnder1mPercent >= 40)
345
+ out.push(`응답 간격의 **${input.burstGapUnder1mPercent}%**가 1분 이내로, 실시간 대화 톤이 강해요.`);
346
+ if (input.monologueMessagesPercent >= 25)
347
+ out.push(`같은 사람 **3연속 이상** 메시지가 전체의 **${input.monologueMessagesPercent}%** — 긴 설명·정리 구간이 잦을 수 있어요.`);
348
+ const sysTotal = input.roomJoinMessages + input.roomLeaveMessages + input.roomDeletedMessages +
349
+ input.roomHiddenMessages + input.roomKickMessages;
350
+ if (sysTotal > 0) {
351
+ const parts = [
352
+ input.roomJoinMessages > 0 ? `들어옴 ${input.roomJoinMessages}` : "",
353
+ input.roomLeaveMessages > 0 ? `나감 ${input.roomLeaveMessages}` : "",
354
+ input.roomDeletedMessages > 0 ? `삭제 ${input.roomDeletedMessages}` : "",
355
+ input.roomHiddenMessages > 0 ? `가림 ${input.roomHiddenMessages}` : "",
356
+ input.roomKickMessages > 0 ? `강퇴 ${input.roomKickMessages}` : "",
357
+ ].filter(Boolean);
358
+ out.push(`카카오톡 **시스템·운영 알림** **${sysTotal}**건(${parts.join(" · ")}) — 본문 키워드와 분리했어요.`);
359
+ }
360
+ if (input.pureLaughMessages > 0)
361
+ out.push(`**ㅋㅋ만** 보낸 리액션 메시지는 **${input.pureLaughMessages}**건이에요.`);
362
+ if (input.repeatedPhraseCount >= 10)
363
+ out.push(`똑같은 문장이 **${input.repeatedPhraseCount}회** 반복된 복붙·환영 문구도 있어요.`);
364
+ if (input.burstDays.length > 0) {
365
+ const top = input.burstDays[0];
366
+ const labels = input.burstDays.slice(0, 3).map((d) => formatDayMdHighlight(d.date)).join(" · ");
367
+ out.push(`메시지가 평소보다 몰린 날 **${input.burstDays.length}일** — 최고는 **${formatDayMdHighlight(top.date)}**(${formatCompactNumber(top.count)}건). ${labels}`);
368
+ }
369
+ const head = input.activityArc.find((a) => a.id === "head");
370
+ const tail = input.activityArc.find((a) => a.id === "tail");
371
+ if (head && tail && head.messages > 0 && tail.messages > 0) {
372
+ const ratio = round(tail.messages / head.messages, 2);
373
+ if (ratio >= 1.25)
374
+ out.push(`마지막 7일이 처음 7일보다 **${ratio}배** 활발 — 대화가 뜨거워지는 구간이 있었어요.`);
375
+ else if (ratio <= 0.8)
376
+ out.push(`처음 7일이 마지막보다 더 붐볐어요(후반은 처음의 **${Math.round(ratio * 100)}%** 수준).`);
377
+ }
378
+ if (input.lexicalTypeRichnessPercent !== null && input.lexicalTypeRichnessPercent >= 18)
379
+ out.push(`본문 단어는 **${input.lexicalTypeRichnessPercent}%** 정도로 서로 다른 표현이 많이 섞였어요.`);
380
+ const pace = input.conversationPace;
381
+ out.push(`대화 템포는 **${pace.emoji} ${pace.label}** — ${pace.detail}`);
382
+ const peakHidden = [...input.roomPulse].sort((a, b) => b.hidden - a.hidden)[0];
383
+ if (peakHidden && peakHidden.hidden >= 5)
384
+ out.push(`가림 알림이 가장 많았던 날은 **${formatDayMdHighlight(peakHidden.date)}**(${peakHidden.hidden}건)이에요.`);
385
+ const peakJoin = [...input.roomPulse].sort((a, b) => b.join - a.join)[0];
386
+ if (peakJoin && peakJoin.join >= 20)
387
+ out.push(`입장이 가장 몰린 날은 **${formatDayMdHighlight(peakJoin.date)}** — **${peakJoin.join}**명 들어왔어요.`);
388
+ return out.slice(0, 14);
389
+ }
390
+ /* ── 관계 추론 ── */
391
+ export function inferRoomRelationship(honorific) {
392
+ const honorificCount = honorific.participants.filter((p) => p.dominantStyle === "honorific").length;
393
+ const casualCount = honorific.participants.filter((p) => p.dominantStyle === "casual").length;
394
+ const total = honorific.participants.length;
395
+ if (total === 0)
396
+ return { type: "mixed", description: "높임법 분석 데이터가 부족합니다.", evidence: [] };
397
+ const hRatio = honorificCount / total;
398
+ const cRatio = casualCount / total;
399
+ if (hRatio >= 0.7)
400
+ return {
401
+ type: "formal", description: "대부분 존칭을 사용하는 격식 있는 방입니다.",
402
+ evidence: [`${honorificCount}명 중 ${Math.round(hRatio * 100)}%가 존칭 사용`],
403
+ };
404
+ if (cRatio >= 0.7)
405
+ return {
406
+ type: "friendly", description: "친구나 동료처럼 편안한 반말을 주로 사용합니다.",
407
+ evidence: [`${casualCount}명 중 ${Math.round(cRatio * 100)}%가 반말 사용`],
408
+ };
409
+ if (honorificCount > 0 && casualCount > 0)
410
+ return {
411
+ type: "hierarchical", description: "존칭과 반말이 혼용되어 선후배/상하 관계가 있을 수 있습니다.",
412
+ evidence: [`존칭 사용자: ${honorificCount}명`, `반말 사용자: ${casualCount}명`],
413
+ };
414
+ return {
415
+ type: "mixed", description: "다양한 높임법 스타일이 혼재되어 있습니다.",
416
+ evidence: ["명확한 패턴을 찾을 수 없음"],
417
+ };
418
+ }
419
+ //# 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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"}