@rine-kit/pubg-intelligence 0.0.0-stage → 0.1.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/dist/src/analytics.d.ts +176 -0
  3. package/dist/src/analytics.js +431 -0
  4. package/dist/src/analytics.js.map +1 -0
  5. package/dist/src/assistant.d.ts +87 -0
  6. package/dist/src/assistant.js +310 -0
  7. package/dist/src/assistant.js.map +1 -0
  8. package/dist/src/battle.d.ts +280 -0
  9. package/dist/src/battle.js +1249 -0
  10. package/dist/src/battle.js.map +1 -0
  11. package/dist/src/combat-long.d.ts +42 -0
  12. package/dist/src/combat-long.js +146 -0
  13. package/dist/src/combat-long.js.map +1 -0
  14. package/dist/src/combat-quality.d.ts +101 -0
  15. package/dist/src/combat-quality.js +253 -0
  16. package/dist/src/combat-quality.js.map +1 -0
  17. package/dist/src/evaluation-fixtures.d.ts +13 -0
  18. package/dist/src/evaluation-fixtures.js +144 -0
  19. package/dist/src/evaluation-fixtures.js.map +1 -0
  20. package/dist/src/evaluation-replay.d.ts +5 -0
  21. package/dist/src/evaluation-replay.js +107 -0
  22. package/dist/src/evaluation-replay.js.map +1 -0
  23. package/dist/src/evaluation.d.ts +140 -0
  24. package/dist/src/evaluation.js +180 -0
  25. package/dist/src/evaluation.js.map +1 -0
  26. package/dist/src/experiment-store.d.ts +56 -0
  27. package/dist/src/experiment-store.js +159 -0
  28. package/dist/src/experiment-store.js.map +1 -0
  29. package/dist/src/field.d.ts +103 -0
  30. package/dist/src/field.js +298 -0
  31. package/dist/src/field.js.map +1 -0
  32. package/dist/src/fights.d.ts +89 -0
  33. package/dist/src/fights.js +238 -0
  34. package/dist/src/fights.js.map +1 -0
  35. package/dist/src/highlights.d.ts +44 -0
  36. package/dist/src/highlights.js +153 -0
  37. package/dist/src/highlights.js.map +1 -0
  38. package/dist/src/index.d.ts +24 -0
  39. package/dist/src/index.js +25 -0
  40. package/dist/src/index.js.map +1 -0
  41. package/dist/src/insights.d.ts +44 -0
  42. package/dist/src/insights.js +343 -0
  43. package/dist/src/insights.js.map +1 -0
  44. package/dist/src/intent.d.ts +40 -0
  45. package/dist/src/intent.js +119 -0
  46. package/dist/src/intent.js.map +1 -0
  47. package/dist/src/landing.d.ts +74 -0
  48. package/dist/src/landing.js +195 -0
  49. package/dist/src/landing.js.map +1 -0
  50. package/dist/src/lobby.d.ts +48 -0
  51. package/dist/src/lobby.js +209 -0
  52. package/dist/src/lobby.js.map +1 -0
  53. package/dist/src/match-insight.d.ts +165 -0
  54. package/dist/src/match-insight.js +542 -0
  55. package/dist/src/match-insight.js.map +1 -0
  56. package/dist/src/match-relative.d.ts +73 -0
  57. package/dist/src/match-relative.js +145 -0
  58. package/dist/src/match-relative.js.map +1 -0
  59. package/dist/src/match-story.d.ts +155 -0
  60. package/dist/src/match-story.js +636 -0
  61. package/dist/src/match-story.js.map +1 -0
  62. package/dist/src/profiles.d.ts +41 -0
  63. package/dist/src/profiles.js +136 -0
  64. package/dist/src/profiles.js.map +1 -0
  65. package/dist/src/raw-telemetry-archive.d.ts +29 -0
  66. package/dist/src/raw-telemetry-archive.js +340 -0
  67. package/dist/src/raw-telemetry-archive.js.map +1 -0
  68. package/dist/src/raw-telemetry-backfill.d.ts +28 -0
  69. package/dist/src/raw-telemetry-backfill.js +144 -0
  70. package/dist/src/raw-telemetry-backfill.js.map +1 -0
  71. package/dist/src/research.d.ts +89 -0
  72. package/dist/src/research.js +376 -0
  73. package/dist/src/research.js.map +1 -0
  74. package/dist/src/rhythm.d.ts +104 -0
  75. package/dist/src/rhythm.js +260 -0
  76. package/dist/src/rhythm.js.map +1 -0
  77. package/dist/src/streaks.d.ts +117 -0
  78. package/dist/src/streaks.js +367 -0
  79. package/dist/src/streaks.js.map +1 -0
  80. package/dist/src/style.d.ts +304 -0
  81. package/dist/src/style.js +1461 -0
  82. package/dist/src/style.js.map +1 -0
  83. package/dist/src/tactics.d.ts +88 -0
  84. package/dist/src/tactics.js +1221 -0
  85. package/dist/src/tactics.js.map +1 -0
  86. package/package.json +49 -3
  87. package/README.md +0 -3
@@ -0,0 +1,343 @@
1
+ import { newcombeDifference, wilsonInterval, median, } from './analytics.js';
2
+ import { DISTANCE_GAP_POINTS, ZONE_MIN_SAMPLES, } from './field.js';
3
+ import { FIGHT_MIN_GROUP } from './fights.js';
4
+ export const INSIGHT_RULE_VERSION = 'highlight-rules-v1';
5
+ export const INSIGHT_MAX = 6;
6
+ export const INSIGHT_MAP_MIN_MATCHES = 15;
7
+ export const INSIGHT_REVIVE_MIN_KNOCKS = 15;
8
+ export const INSIGHT_DEATH_MIN = 30;
9
+ export const INSIGHT_RECENT_MATCHES = 20;
10
+ const pct = (value, digits = 0) => value === null ? '—' : `${(value * 100).toFixed(digits)}%`;
11
+ const interval = (rate) => rate.low === null || rate.high === null
12
+ ? '区间不足'
13
+ : `95% 区间 ${pct(rate.low)}–${pct(rate.high)}`;
14
+ /** Orders warnings first, then good news, then context, and keeps the list short enough to read. */
15
+ export function rankInsights(insights, max = INSIGHT_MAX) {
16
+ const weight = { warn: 0, good: 1, info: 2 };
17
+ return insights
18
+ .sort((left, right) => weight[left.tone] - weight[right.tone] || left.id.localeCompare(right.id))
19
+ .slice(0, max);
20
+ }
21
+ export function buildPerformanceInsights(input) {
22
+ const insights = [];
23
+ for (const member of input.lineups.members) {
24
+ if (member.withMatches < 5 ||
25
+ member.withoutMatches < 5 ||
26
+ !member.difference.significant ||
27
+ member.difference.delta === null)
28
+ continue;
29
+ const delta = member.difference.delta;
30
+ insights.push({
31
+ id: `member-${member.id}`,
32
+ tone: delta > 0 ? 'good' : 'warn',
33
+ title: `${member.name} ${delta > 0 ? '在场时前十率明显更高' : '在场时前十率明显更低'}`,
34
+ detail: `在场 ${pct(member.withTop10.rate)}(${member.withMatches} 场)对比缺席 ${pct(member.withoutTop10.rate)}(${member.withoutMatches} 场),差 ${delta >= 0 ? '+' : ''}${(delta * 100).toFixed(0)} 个百分点。这是相关性,不等于个人贡献。`,
35
+ evidence: `差值 95% 区间 ${(member.difference.low * 100).toFixed(0)} 到 ${(member.difference.high * 100).toFixed(0)}pt`,
36
+ });
37
+ }
38
+ const rankedMaps = input.maps.filter((map) => map.rankedMatches >= INSIGHT_MAP_MIN_MATCHES);
39
+ const totalTrials = input.maps.reduce((sum, map) => sum + map.top10.trials, 0);
40
+ const totalSuccess = input.maps.reduce((sum, map) => sum + map.top10.successes, 0);
41
+ for (const map of rankedMaps) {
42
+ const rest = wilsonInterval(totalSuccess - map.top10.successes, totalTrials - map.top10.trials);
43
+ const difference = newcombeDifference(map.top10, rest);
44
+ if (!difference.significant || difference.delta === null)
45
+ continue;
46
+ insights.push({
47
+ id: `map-${map.mapName}`,
48
+ tone: difference.delta > 0 ? 'good' : 'warn',
49
+ title: `${map.label}前十率${difference.delta > 0 ? '明显高于' : '明显低于'}其他地图`,
50
+ detail: `${map.label} ${pct(map.top10.rate)}(${map.rankedMatches} 场)对比其他地图 ${pct(rest.rate)},中位名次 ${map.medianPlacement === null ? '未知' : `#${map.medianPlacement}`}。`,
51
+ evidence: `差值 95% 区间 ${(difference.low * 100).toFixed(0)} 到 ${(difference.high * 100).toFixed(0)}pt`,
52
+ });
53
+ }
54
+ for (const player of input.squad.players) {
55
+ const damage = player.metrics.find((metric) => metric.key === 'damage');
56
+ if (!damage ||
57
+ damage.form === 'steady' ||
58
+ damage.form === 'insufficient' ||
59
+ damage.formZ === null)
60
+ continue;
61
+ insights.push({
62
+ id: `form-${player.id}`,
63
+ tone: damage.form === 'hot' ? 'good' : 'warn',
64
+ title: `${player.name} 近 5 场伤害${damage.form === 'hot' ? '明显高于' : '明显低于'}自己的常态`,
65
+ detail: `此前基线中位 ${Math.round(damage.baselineMedian ?? 0)},近 5 场均值 ${Math.round(damage.recentMean ?? 0)}。`,
66
+ evidence: `稳健 z = ${damage.formZ.toFixed(1)}(|z| ≥ 1.5 才标记)`,
67
+ });
68
+ }
69
+ const recent = input.series.slice(-INSIGHT_RECENT_MATCHES);
70
+ const before = input.series.slice(0, -INSIGHT_RECENT_MATCHES);
71
+ const rate = (items) => {
72
+ const ranked = items.filter((point) => point.placement !== null);
73
+ return wilsonInterval(ranked.filter((point) => point.placement <= 10).length, ranked.length);
74
+ };
75
+ if (recent.length >= INSIGHT_RECENT_MATCHES && before.length >= 30) {
76
+ const recentRate = rate(recent);
77
+ const beforeRate = rate(before);
78
+ const difference = newcombeDifference(recentRate, beforeRate);
79
+ if (difference.significant && difference.delta !== null) {
80
+ insights.push({
81
+ id: 'recent-top10',
82
+ tone: difference.delta > 0 ? 'good' : 'warn',
83
+ title: `近 ${INSIGHT_RECENT_MATCHES} 场前十率${difference.delta > 0 ? '明显回升' : '明显下滑'}`,
84
+ detail: `近 ${INSIGHT_RECENT_MATCHES} 场 ${pct(recentRate.rate)} 对比此前 ${pct(beforeRate.rate)}。`,
85
+ evidence: `差值 95% 区间 ${(difference.low * 100).toFixed(0)} 到 ${(difference.high * 100).toFixed(0)}pt`,
86
+ });
87
+ }
88
+ const recentDamage = median(recent.map((point) => point.damage));
89
+ const beforeDamage = median(before.map((point) => point.damage));
90
+ if (recentDamage !== null &&
91
+ beforeDamage !== null &&
92
+ beforeDamage > 0 &&
93
+ Math.abs(recentDamage / beforeDamage - 1) >= 0.3) {
94
+ const change = recentDamage / beforeDamage - 1;
95
+ insights.push({
96
+ id: 'recent-damage',
97
+ tone: change > 0 ? 'good' : 'warn',
98
+ title: `近 ${INSIGHT_RECENT_MATCHES} 场人均伤害中位数${change > 0 ? '上升' : '下降'} ${Math.abs(change * 100).toFixed(0)}%`,
99
+ detail: `中位数 ${Math.round(recentDamage)} 对比此前 ${Math.round(beforeDamage)}(用中位数,避免个别爆发场次拉偏)。`,
100
+ evidence: `${recent.length} 场对 ${before.length} 场;变化 ≥ 30% 才提示`,
101
+ });
102
+ }
103
+ }
104
+ return rankInsights(insights);
105
+ }
106
+ export function buildCombatInsights(input) {
107
+ const { combat, deaths, landing } = input;
108
+ const insights = [];
109
+ const revive = combat.revive;
110
+ if (revive.knocked >= INSIGHT_REVIVE_MIN_KNOCKS &&
111
+ revive.reviveRate.high !== null &&
112
+ revive.reviveRate.high < 0.4) {
113
+ const finish = combat.finish.finishRate.rate;
114
+ insights.push({
115
+ id: 'revive-weak',
116
+ tone: 'warn',
117
+ title: `队员倒地后只有 ${pct(revive.reviveRate.rate)} 被救起`,
118
+ detail: `${revive.knocked} 次倒地中救起 ${revive.revived} 次、被补掉 ${revive.killed} 次${finish === null ? '' : `;对比我们补掉对手的 ${pct(finish)},救援是明显短板`}。`,
119
+ evidence: `${interval(revive.reviveRate)},样本 ${revive.knocked} 次`,
120
+ });
121
+ }
122
+ if (deaths.deaths >= INSIGHT_DEATH_MIN &&
123
+ deaths.afterKnock.rate.low !== null &&
124
+ deaths.afterKnock.rate.low > 0.5) {
125
+ insights.push({
126
+ id: 'death-after-knock',
127
+ tone: 'warn',
128
+ title: `${pct(deaths.afterKnock.rate.rate)} 的淘汰发生在倒地之后`,
129
+ detail: `${deaths.deaths} 次淘汰里有 ${deaths.afterKnock.count} 次是先倒地再被补掉。倒地后的封烟、拉人或爬走有机会改变结果。`,
130
+ evidence: interval(deaths.afterKnock.rate),
131
+ });
132
+ }
133
+ const first = combat.firstKnock;
134
+ if (first.forUs + first.againstUs >= 20 &&
135
+ first.ourRate.low !== null &&
136
+ first.ourRate.high !== null) {
137
+ if (first.ourRate.low > 0.5) {
138
+ insights.push({
139
+ id: 'first-knock',
140
+ tone: 'good',
141
+ title: `首倒占比 ${pct(first.ourRate.rate)},开战更常是我方先手`,
142
+ detail: `${first.forUs + first.againstUs} 次有明确首倒的交战里我方先倒地对手 ${first.forUs} 次。`,
143
+ evidence: interval(first.ourRate),
144
+ });
145
+ }
146
+ else if (first.ourRate.high < 0.5) {
147
+ insights.push({
148
+ id: 'first-knock',
149
+ tone: 'warn',
150
+ title: `首倒占比只有 ${pct(first.ourRate.rate)},开战更常被对手先手`,
151
+ detail: `${first.forUs + first.againstUs} 次有明确首倒的交战里对手先倒地我方 ${first.againstUs} 次。`,
152
+ evidence: interval(first.ourRate),
153
+ });
154
+ }
155
+ }
156
+ const lead = combat.leadConversion;
157
+ if (lead.held + lead.lost >= 20 && lead.heldRate.rate !== null && lead.heldRate.rate < 0.8) {
158
+ insights.push({
159
+ id: 'lead-lost',
160
+ tone: 'info',
161
+ title: `先手优势有 ${pct(1 - lead.heldRate.rate)} 被追平或反超`,
162
+ detail: `我方首倒后,${lead.lost} 次被对手把倒地数追平或反超(共 ${lead.held + lead.lost} 次)。`,
163
+ evidence: interval(lead.heldRate),
164
+ });
165
+ }
166
+ if (combat.groups >= 30 &&
167
+ combat.thirdParty.againstRate.rate !== null &&
168
+ combat.thirdParty.againstRate.rate >= 0.3) {
169
+ insights.push({
170
+ id: 'third-party',
171
+ tone: 'info',
172
+ title: `${pct(combat.thirdParty.againstRate.rate)} 的交战出现第三方介入候选`,
173
+ detail: `${combat.groups} 次交战里有 ${combat.thirdParty.againstUs} 次时间重叠的第三队接触;这只是候选,不代表对方意图。`,
174
+ evidence: interval(combat.thirdParty.againstRate),
175
+ });
176
+ }
177
+ const topStage = [...deaths.stages].sort((left, right) => right.deaths - left.deaths)[0];
178
+ if (deaths.deaths >= INSIGHT_DEATH_MIN &&
179
+ topStage &&
180
+ topStage.stage !== '未知' &&
181
+ topStage.share >= 0.5) {
182
+ insights.push({
183
+ id: 'death-stage',
184
+ tone: 'info',
185
+ title: `${pct(topStage.share)} 的淘汰集中在${topStage.stage}`,
186
+ detail: `${deaths.deaths} 次淘汰里 ${topStage.deaths} 次发生在${topStage.stage}阶段(按淘汰时剩余队伍数划分)。`,
187
+ evidence: `样本 ${deaths.deaths} 次`,
188
+ });
189
+ }
190
+ const map = landing.maps.find((item) => item.matchesWithLanding >= 6);
191
+ if (map && map.topCellRepeatRate !== null && map.topCellRepeatRate >= 0.5) {
192
+ insights.push({
193
+ id: `landing-${map.mapName}`,
194
+ tone: 'info',
195
+ title: `${map.label}落点集中:${pct(map.topCellRepeatRate)} 的场次落在 ${map.cells[0].cell} 格`,
196
+ detail: `${map.matchesWithLanding} 场有落点记录,队内成员落点距小队中心中位 ${map.medianSpreadMeters === null ? '未知' : `${Math.round(map.medianSpreadMeters)}m`}。`,
197
+ evidence: `样本 ${map.matchesWithLanding} 场`,
198
+ });
199
+ }
200
+ return rankInsights(insights);
201
+ }
202
+ export const FIELD_INSIGHT_MAX = 10;
203
+ const points = (value) => `${value >= 0 ? '+' : ''}${(value * 100).toFixed(0)}pt`;
204
+ export function buildFieldInsights(input) {
205
+ const { fights, distance, zone, landing, roles } = input;
206
+ const insights = [];
207
+ const decided = (bucket) => bucket.wins + bucket.losses;
208
+ const initiative = fights.initiatorEdge;
209
+ if (initiative.significant && initiative.delta !== null) {
210
+ const us = fights.byInitiator[0];
211
+ const them = fights.byInitiator[1];
212
+ insights.push({
213
+ id: 'fight-initiator',
214
+ tone: initiative.delta > 0 ? 'good' : 'warn',
215
+ title: initiative.delta > 0
216
+ ? `先手开火的交战胜率明显更高:${pct(us.winRate.rate)} 对 ${pct(them.winRate.rate)}`
217
+ : `先手开火反而更吃亏:${pct(us.winRate.rate)} 对 ${pct(them.winRate.rate)}`,
218
+ detail: `我方先手 ${decided(us)} 场分出胜负,对方先手 ${decided(them)} 场;先手 = 交战中第一次有效伤害的发起方。`,
219
+ evidence: `差 ${points(initiative.delta)},区间 ${(initiative.low * 100).toFixed(0)} 到 ${(initiative.high * 100).toFixed(0)}pt`,
220
+ });
221
+ }
222
+ const third = fights.thirdPartyEdge;
223
+ if (third.significant && third.delta !== null) {
224
+ const withThird = fights.byThirdParty[0];
225
+ const duel = fights.byThirdParty[1];
226
+ insights.push({
227
+ id: 'fight-third-party',
228
+ tone: third.delta > 0 ? 'good' : 'warn',
229
+ title: third.delta < 0
230
+ ? `有第三方介入时胜率降到 ${pct(withThird.winRate.rate)}(两队对战 ${pct(duel.winRate.rate)})`
231
+ : `有第三方介入时胜率反而更高 ${pct(withThird.winRate.rate)}`,
232
+ detail: `${decided(withThird)} 场有第三方候选、${decided(duel)} 场两队对战。第三方只是时间重叠的候选。`,
233
+ evidence: `差 ${points(third.delta)},区间 ${(third.low * 100).toFixed(0)} 到 ${(third.high * 100).toFixed(0)}pt`,
234
+ });
235
+ }
236
+ for (const stage of fights.byStage) {
237
+ if (decided(stage) < FIGHT_MIN_GROUP || stage.key === '未知')
238
+ continue;
239
+ const restWins = fights.overall.wins - stage.wins;
240
+ const restLosses = fights.overall.losses - stage.losses;
241
+ if (restWins + restLosses < FIGHT_MIN_GROUP)
242
+ continue;
243
+ const difference = newcombeDifference(stage.winRate, wilsonInterval(restWins, restWins + restLosses));
244
+ if (!difference.significant || difference.delta === null)
245
+ continue;
246
+ insights.push({
247
+ id: `fight-stage-${stage.key}`,
248
+ tone: difference.delta > 0 ? 'good' : 'warn',
249
+ title: `${stage.label}阶段的交战胜率${difference.delta > 0 ? '明显偏高' : '明显偏低'}:${pct(stage.winRate.rate)}`,
250
+ detail: `该阶段 ${decided(stage)} 场分出胜负,其余阶段合计 ${pct(wilsonInterval(restWins, restWins + restLosses).rate)}。`,
251
+ evidence: `差 ${points(difference.delta)},区间 ${(difference.low * 100).toFixed(0)} 到 ${(difference.high * 100).toFixed(0)}pt`,
252
+ });
253
+ }
254
+ if (distance.longRangeGap !== null && Math.abs(distance.longRangeGap) >= DISTANCE_GAP_POINTS) {
255
+ const dealt = distance.bands.slice(2).reduce((sum, band) => sum + (band.dealtShare ?? 0), 0);
256
+ const taken = distance.bands.slice(2).reduce((sum, band) => sum + (band.takenShare ?? 0), 0);
257
+ insights.push({
258
+ id: 'distance-gap',
259
+ tone: distance.longRangeGap > 0 ? 'warn' : 'good',
260
+ title: distance.longRangeGap > 0
261
+ ? `承受的远距离伤害(≥75m)占 ${pct(taken)},而我们打出的只占 ${pct(dealt)}`
262
+ : `我们的远距离输出(≥75m)占 ${pct(dealt)},高于承受的 ${pct(taken)}`,
263
+ detail: distance.longRangeGap > 0
264
+ ? '对手更常在远处消耗我们,这说明我们的交战距离偏近或缺少远程火力/掩体。'
265
+ : '我们更常占据远距离优势,近距离被动挨打的比例较低。',
266
+ evidence: `按枪械伤害统计,打出 ${Math.round(distance.totalDealt)}、承受 ${Math.round(distance.totalTaken)};差值需 ≥ ${DISTANCE_GAP_POINTS * 100}pt`,
267
+ });
268
+ }
269
+ const outside = [...zone.phases]
270
+ .filter((phase) => phase.samples >= ZONE_MIN_SAMPLES &&
271
+ phase.outsideRate.low !== null &&
272
+ phase.outsideRate.low > 0.15)
273
+ .sort((left, right) => (right.outsideRate.rate ?? 0) - (left.outsideRate.rate ?? 0))[0];
274
+ if (outside) {
275
+ insights.push({
276
+ id: `zone-outside-${outside.phase}`,
277
+ tone: 'warn',
278
+ title: `第 ${outside.phase} 圈有 ${pct(outside.outsideRate.rate)} 的时间在毒圈里`,
279
+ detail: `该圈共 ${outside.samples} 个位置样本,毒圈伤害合计 ${Math.round(outside.blueDamage)}。转圈偏晚会白白损血并被迫在不利位置交战。`,
280
+ evidence: interval(outside.outsideRate),
281
+ });
282
+ }
283
+ const lateEdge = zone.phases.filter((phase) => phase.phase >= 6 &&
284
+ phase.samples >= ZONE_MIN_SAMPLES &&
285
+ phase.binShares &&
286
+ phase.binShares[2] + phase.binShares[3] >= 0.6)[0];
287
+ if (lateEdge?.binShares) {
288
+ insights.push({
289
+ id: 'zone-late-edge',
290
+ tone: 'info',
291
+ title: `第 ${lateEdge.phase} 圈有 ${pct(lateEdge.binShares[2] + lateEdge.binShares[3])} 的时间贴着圈边或在圈外`,
292
+ detail: '决赛圈靠边更容易被两面夹击、也更容易被压缩空间;靠近圈中心通常有更多回旋余地。',
293
+ evidence: `样本 ${lateEdge.samples} 个位置点;圈边 = 距安全区中心 ≥ 85% 半径`,
294
+ });
295
+ }
296
+ if (zone.blueDamageShare !== null && zone.blueDamageShare >= 0.15 && zone.matches >= 20) {
297
+ insights.push({
298
+ id: 'zone-blue-damage',
299
+ tone: 'info',
300
+ title: `毒圈伤害占全部承伤的 ${pct(zone.blueDamageShare)}`,
301
+ detail: `${zone.matches} 场平均每场吃毒 ${Math.round(zone.blueDamagePerMatch ?? 0)} 点;这部分伤害本可以通过更早转圈或用载具避免。`,
302
+ evidence: `样本 ${zone.matches} 场`,
303
+ });
304
+ }
305
+ if (landing.contest.earlyWipeEdge.significant && (landing.contest.earlyWipeEdge.delta ?? 0) > 0) {
306
+ const [calm, , crowded] = landing.contest.buckets;
307
+ const top10 = landing.contest.top10Edge;
308
+ insights.push({
309
+ id: 'landing-contest',
310
+ tone: 'warn',
311
+ title: `落点附近有队伍争抢时,早崩率高出 ${points(landing.contest.earlyWipeEdge.delta)}`,
312
+ detail: `无争抢 ${calm.matches} 场早崩 ${pct(calm.earlyWipe.rate)};有争抢的场次更高${crowded.matches ? `(2 队及以上 ${crowded.matches} 场 ${pct(crowded.earlyWipe.rate)})` : ''}。但前十率${top10.delta === null ? '样本不足' : top10.significant ? `也有差异(${points(top10.delta)})` : `差异不显著(${points(top10.delta)})`}:争抢带来的主要是开局的翻车风险,不一定拉低最终名次。早崩 = 全队最长生存不足 7 分钟,争抢 = 500m 内有其他队降落。`,
313
+ evidence: `早崩差区间 ${(landing.contest.earlyWipeEdge.low * 100).toFixed(0)} 到 ${(landing.contest.earlyWipeEdge.high * 100).toFixed(0)}pt,共 ${landing.contest.matches} 场`,
314
+ });
315
+ }
316
+ for (const player of roles) {
317
+ for (const title of player.titles) {
318
+ const share = title === '开团手'
319
+ ? player.firstKnockShare
320
+ : title.startsWith('先锋盾')
321
+ ? player.firstDownedShare
322
+ : title === '救援担当'
323
+ ? player.reviveShare
324
+ : player.killShare;
325
+ insights.push({
326
+ id: `role-${player.accountId}-${title}`,
327
+ tone: 'info',
328
+ title: `${player.name}:${title}(占 ${pct(share)})`,
329
+ detail: title === '开团手'
330
+ ? '交战里第一个打倒对手的人最常是他。'
331
+ : title.startsWith('先锋盾')
332
+ ? '交战里第一个被打倒的人最常是他,说明他经常顶在最前面或被集火。'
333
+ : title === '救援担当'
334
+ ? '队内最多的救援来自他。'
335
+ : '队内最多的人头由他收割。',
336
+ evidence: `${player.fights} 次参与交战;占比 ≥ ${ROLE_TITLE_SHARE_TEXT} 才授予称号`,
337
+ });
338
+ }
339
+ }
340
+ return rankInsights(insights, FIELD_INSIGHT_MAX);
341
+ }
342
+ const ROLE_TITLE_SHARE_TEXT = '40%';
343
+ //# sourceMappingURL=insights.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.js","sourceRoot":"","sources":["../../src/insights.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import { type LanguageModel } from 'ai';
2
+ import { z } from 'zod';
3
+ export declare const ResearchIntentSchema: z.ZodObject<{
4
+ action: z.ZodEnum<{
5
+ trend: "trend";
6
+ summary: "summary";
7
+ player_comparison: "player_comparison";
8
+ map_breakdown: "map_breakdown";
9
+ telemetry_coverage: "telemetry_coverage";
10
+ unsupported: "unsupported";
11
+ }>;
12
+ metric: z.ZodNullable<z.ZodEnum<{
13
+ damage: "damage";
14
+ kills: "kills";
15
+ matches: "matches";
16
+ wins: "wins";
17
+ top10: "top10";
18
+ revives: "revives";
19
+ survival_time: "survival_time";
20
+ knocks: "knocks";
21
+ }>>;
22
+ groupBy: z.ZodNullable<z.ZodEnum<{
23
+ map: "map";
24
+ player: "player";
25
+ week: "week";
26
+ }>>;
27
+ }, z.core.$strict>;
28
+ export type ResearchIntent = z.infer<typeof ResearchIntentSchema>;
29
+ export type ResearchPlanSource = 'ai-sdk' | 'local-rule';
30
+ export interface ResearchPlan {
31
+ intent: ResearchIntent;
32
+ source: ResearchPlanSource;
33
+ }
34
+ export declare function redactSensitiveText(value: string): string;
35
+ export declare class NaturalLanguageResearchPlanner {
36
+ private readonly model?;
37
+ constructor(model?: Exclude<LanguageModel, string> | undefined);
38
+ plan(message: string): Promise<ResearchPlan>;
39
+ }
40
+ export declare function classifyResearchQuestion(message: string): ResearchIntent;
@@ -0,0 +1,119 @@
1
+ import { generateText, tool } from 'ai';
2
+ import { z } from 'zod';
3
+ export const ResearchIntentSchema = z
4
+ .object({
5
+ action: z.enum([
6
+ 'summary',
7
+ 'trend',
8
+ 'player_comparison',
9
+ 'map_breakdown',
10
+ 'telemetry_coverage',
11
+ 'unsupported',
12
+ ]),
13
+ metric: z
14
+ .enum(['damage', 'kills', 'knocks', 'revives', 'wins', 'top10', 'matches', 'survival_time'])
15
+ .nullable(),
16
+ groupBy: z.enum(['week', 'map', 'player']).nullable(),
17
+ })
18
+ .strict();
19
+ const DEFAULT_INTENT = { action: 'summary', metric: 'damage', groupBy: null };
20
+ export function redactSensitiveText(value) {
21
+ return value
22
+ .slice(0, 1200)
23
+ .replace(/(?<!\d)1[3-9]\d{9}(?!\d)/gu, '[手机号已隐藏]')
24
+ .replace(/(?:~\/|\/(?:Users|private|tmp|DATA|Volumes|var|home|workspace|mnt)\/)[^\s"'<>]+/giu, '[路径已隐藏]')
25
+ .replace(/\b(?:sk-[A-Za-z0-9]{20,}|gh[pousr]_[A-Za-z0-9_]{20,}|xox[baprs]-[A-Za-z0-9-]{20,}|Bearer\s+[A-Za-z0-9._-]{20,})\b/giu, '[凭据已隐藏]')
26
+ .replace(/\b(api[_ -]?key|access[_ -]?token|app[_ -]?secret|bot[_ -]?token|password)\s*[:=]\s*[^\s,;]+/giu, '$1=[凭据已隐藏]');
27
+ }
28
+ function localIntent(message) {
29
+ const text = message.normalize('NFKC').toLocaleLowerCase('zh-CN');
30
+ const metric = /胜率|吃鸡|冠军|夺冠|\bwin(?:s)?\b/iu.test(text)
31
+ ? 'wins'
32
+ : /前\s*十|前十率|top\s*10/iu.test(text)
33
+ ? 'top10'
34
+ : /救援|复活|\brevive(?:s)?\b/iu.test(text)
35
+ ? 'revives'
36
+ : /倒地|击倒|\bknock(?:s)?\b/iu.test(text)
37
+ ? 'knocks'
38
+ : /击杀|人头|\bkills?\b/iu.test(text)
39
+ ? 'kills'
40
+ : /生存|存活时长|\bsurvival\b/iu.test(text)
41
+ ? 'survival_time'
42
+ : /局数|多少场|比赛数|\bmatches\b/iu.test(text)
43
+ ? 'matches'
44
+ : 'damage';
45
+ if (/telemetry|缓存覆盖|事件缓存|解析缓存/iu.test(text)) {
46
+ return { action: 'telemetry_coverage', metric: null, groupBy: null };
47
+ }
48
+ if (/打法|playstyle/iu.test(text) &&
49
+ /(近\s*(?:\d+|[零一二两三四五六七八九十]+)?\s*(?:场|局)|最近|last\s+\d+|\bplayer_[0-9]{2}\b)/iu.test(text)) {
50
+ return { action: 'player_comparison', metric, groupBy: 'player' };
51
+ }
52
+ if (/按地图|地图.*(比较|表现|胜率|伤害|击杀)|map.*(breakdown|compare)/iu.test(text)) {
53
+ return { action: 'map_breakdown', metric, groupBy: 'map' };
54
+ }
55
+ if (/队员|成员|谁.*(高|低|最好|最多)|比较|对比|player.*compare/iu.test(text)) {
56
+ return { action: 'player_comparison', metric, groupBy: 'player' };
57
+ }
58
+ if (/趋势|变化|走势|逐周|每周|trend|over\s+time/iu.test(text)) {
59
+ return { action: 'trend', metric, groupBy: 'week' };
60
+ }
61
+ if (/复盘|总结|概况|整体|表现|分析|\bsummary\b/iu.test(text))
62
+ return DEFAULT_INTENT;
63
+ if (!text.trim())
64
+ return { action: 'unsupported', metric: null, groupBy: null };
65
+ if (/pubg|比赛|对局|小队|队伍|队员|伤害|击杀|倒地|地图|排名|吃鸡|前十|战绩|比赛数据/iu.test(text))
66
+ return DEFAULT_INTENT;
67
+ return { action: 'unsupported', metric: null, groupBy: null };
68
+ }
69
+ const INTENT_INSTRUCTIONS = [
70
+ 'Classify a PUBG squad research question into the one declared intent tool.',
71
+ 'Return slots only. Do not answer, calculate, select a player, infer dates, or invent facts.',
72
+ 'Use telemetry_coverage only for cache/parser coverage questions.',
73
+ 'Use player_comparison for comparing squad members and map_breakdown for map grouping.',
74
+ 'Use trend for change over time. Select groupBy week for trend, player for member comparison, map for map breakdown.',
75
+ 'Metric meanings: wins is placement 1; top10 is placement 1 through 10; damage is match-store damage.',
76
+ 'If the request is outside PUBG squad match research, return unsupported.',
77
+ ].join('\n');
78
+ export class NaturalLanguageResearchPlanner {
79
+ model;
80
+ constructor(model) {
81
+ this.model = model;
82
+ if (model && typeof model === 'string')
83
+ throw new TypeError('An explicit language model instance is required');
84
+ }
85
+ async plan(message) {
86
+ const normalized = redactSensitiveText(message.trim());
87
+ if (this.model && normalized) {
88
+ try {
89
+ const result = await generateText({
90
+ model: this.model,
91
+ system: INTENT_INSTRUCTIONS,
92
+ prompt: `Untrusted research question as JSON: ${JSON.stringify(normalized)}`,
93
+ tools: {
94
+ submit_research_intent: tool({
95
+ description: 'Return the bounded research intent slots.',
96
+ inputSchema: ResearchIntentSchema,
97
+ }),
98
+ },
99
+ toolChoice: { type: 'tool', toolName: 'submit_research_intent' },
100
+ temperature: 0,
101
+ maxOutputTokens: 180,
102
+ maxRetries: 0,
103
+ });
104
+ const call = result.toolCalls.find((item) => item.toolName === 'submit_research_intent');
105
+ const parsed = ResearchIntentSchema.safeParse(call?.input);
106
+ if (parsed.success)
107
+ return { intent: parsed.data, source: 'ai-sdk' };
108
+ }
109
+ catch {
110
+ // Local classification keeps the research page usable without a model.
111
+ }
112
+ }
113
+ return { intent: localIntent(normalized), source: 'local-rule' };
114
+ }
115
+ }
116
+ export function classifyResearchQuestion(message) {
117
+ return localIntent(message);
118
+ }
119
+ //# sourceMappingURL=intent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent.js","sourceRoot":"","sources":["../../src/intent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import { type NormalizedMatch } from '@rine-kit/pubg-domain';
2
+ import { type DifferenceEstimate, type RateEstimate } from './analytics.js';
3
+ export declare const LANDING_SCHEMA_VERSION: 1;
4
+ export declare const LANDING_EARLY_WIPE_SECONDS = 420;
5
+ export declare const LANDING_CELL_KM = 1;
6
+ export interface LandingSample {
7
+ playerRef: string;
8
+ xMeters: number;
9
+ yMeters: number;
10
+ /** One-kilometre grid label such as C5 (column from west, row from north); null on maps of unknown size. */
11
+ cell: string | null;
12
+ }
13
+ export declare function landingPlayerRef(accountId: string): string;
14
+ export declare function gridCell(xMeters: number, yMeters: number, mapName: string): string | null;
15
+ /** Reads LogParachuteLanding for the tracked squad; coordinates in telemetry are centimetres. */
16
+ export declare function extractLandings(payload: unknown, match: Pick<NormalizedMatch, 'mapName'>, memberIds: ReadonlySet<string>): LandingSample[];
17
+ export interface LandingMatchInput {
18
+ match: NormalizedMatch;
19
+ landings: readonly LandingSample[];
20
+ memberIds: ReadonlySet<string>;
21
+ /** Other teams that landed within the contest radius of the squad; null when unknown. */
22
+ contestedTeams?: number | null;
23
+ /** Named map area reported after landing. */
24
+ region?: string | null;
25
+ }
26
+ export interface LandingCellStats {
27
+ cell: string;
28
+ /** Most common named area for matches that used this cell. */
29
+ region: string | null;
30
+ matches: number;
31
+ share: number;
32
+ top10: RateEstimate;
33
+ medianPlacement: number | null;
34
+ earlyWipeRate: number | null;
35
+ averageDamage: number;
36
+ }
37
+ export interface LandingMapPreference {
38
+ mapName: string;
39
+ label: string;
40
+ sizeKm: number | null;
41
+ matches: number;
42
+ matchesWithLanding: number;
43
+ cells: LandingCellStats[];
44
+ /** Share of matches where the squad's main cell equals its most frequent main cell. */
45
+ topCellRepeatRate: number | null;
46
+ /** Median distance (m) between a member's landing and the squad centre. */
47
+ medianSpreadMeters: number | null;
48
+ points: Array<{
49
+ x: number;
50
+ y: number;
51
+ }>;
52
+ }
53
+ export interface ContestBucket {
54
+ key: string;
55
+ label: string;
56
+ matches: number;
57
+ top10: RateEstimate;
58
+ earlyWipe: RateEstimate;
59
+ medianPlacement: number | null;
60
+ }
61
+ export interface LandingContest {
62
+ matches: number;
63
+ buckets: ContestBucket[];
64
+ /** Early-wipe rate with at least one contesting team minus the rate with none. */
65
+ earlyWipeEdge: DifferenceEstimate;
66
+ top10Edge: DifferenceEstimate;
67
+ }
68
+ export interface LandingPreference {
69
+ schemaVersion: typeof LANDING_SCHEMA_VERSION;
70
+ maps: LandingMapPreference[];
71
+ contest: LandingContest;
72
+ notes: string[];
73
+ }
74
+ export declare function buildLandingPreference(inputs: readonly LandingMatchInput[]): LandingPreference;