@rine-kit/pubg-domain 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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/dist/config/default-team.json +27 -0
  4. package/dist/src/config/chicken-index.d.ts +9 -0
  5. package/dist/src/config/chicken-index.js +37 -0
  6. package/dist/src/config/chicken-index.js.map +1 -0
  7. package/dist/src/config/team.d.ts +22 -0
  8. package/dist/src/config/team.js +69 -0
  9. package/dist/src/config/team.js.map +1 -0
  10. package/dist/src/context/context-store.d.ts +40 -0
  11. package/dist/src/context/context-store.js +119 -0
  12. package/dist/src/context/context-store.js.map +1 -0
  13. package/dist/src/context/team-context.d.ts +13 -0
  14. package/dist/src/context/team-context.js +16 -0
  15. package/dist/src/context/team-context.js.map +1 -0
  16. package/dist/src/core.d.ts +23 -0
  17. package/dist/src/core.js +24 -0
  18. package/dist/src/core.js.map +1 -0
  19. package/dist/src/data/model.d.ts +123 -0
  20. package/dist/src/data/model.js +100 -0
  21. package/dist/src/data/model.js.map +1 -0
  22. package/dist/src/data/pubg-api-client.d.ts +59 -0
  23. package/dist/src/data/pubg-api-client.js +441 -0
  24. package/dist/src/data/pubg-api-client.js.map +1 -0
  25. package/dist/src/engine/query-engine.d.ts +20 -0
  26. package/dist/src/engine/query-engine.js +765 -0
  27. package/dist/src/engine/query-engine.js.map +1 -0
  28. package/dist/src/index.d.ts +27 -0
  29. package/dist/src/index.js +28 -0
  30. package/dist/src/index.js.map +1 -0
  31. package/dist/src/migration/importer.d.ts +35 -0
  32. package/dist/src/migration/importer.js +229 -0
  33. package/dist/src/migration/importer.js.map +1 -0
  34. package/dist/src/review/combat-scope.d.ts +11 -0
  35. package/dist/src/review/combat-scope.js +101 -0
  36. package/dist/src/review/combat-scope.js.map +1 -0
  37. package/dist/src/review/event-combination-engine.d.ts +17 -0
  38. package/dist/src/review/event-combination-engine.js +534 -0
  39. package/dist/src/review/event-combination-engine.js.map +1 -0
  40. package/dist/src/review/fight-detector.d.ts +4 -0
  41. package/dist/src/review/fight-detector.js +138 -0
  42. package/dist/src/review/fight-detector.js.map +1 -0
  43. package/dist/src/review/fight-integrity-validator.d.ts +13 -0
  44. package/dist/src/review/fight-integrity-validator.js +134 -0
  45. package/dist/src/review/fight-integrity-validator.js.map +1 -0
  46. package/dist/src/review/fun-candidate-generator.d.ts +9 -0
  47. package/dist/src/review/fun-candidate-generator.js +267 -0
  48. package/dist/src/review/fun-candidate-generator.js.map +1 -0
  49. package/dist/src/review/fun-event-generator.d.ts +8 -0
  50. package/dist/src/review/fun-event-generator.js +740 -0
  51. package/dist/src/review/fun-event-generator.js.map +1 -0
  52. package/dist/src/review/fun-intelligence.d.ts +13 -0
  53. package/dist/src/review/fun-intelligence.js +20 -0
  54. package/dist/src/review/fun-intelligence.js.map +1 -0
  55. package/dist/src/review/fun-ranker.d.ts +13 -0
  56. package/dist/src/review/fun-ranker.js +68 -0
  57. package/dist/src/review/fun-ranker.js.map +1 -0
  58. package/dist/src/review/heavy-weapon-intelligence.d.ts +5 -0
  59. package/dist/src/review/heavy-weapon-intelligence.js +215 -0
  60. package/dist/src/review/heavy-weapon-intelligence.js.map +1 -0
  61. package/dist/src/review/key-operation-detector.d.ts +3 -0
  62. package/dist/src/review/key-operation-detector.js +126 -0
  63. package/dist/src/review/key-operation-detector.js.map +1 -0
  64. package/dist/src/review/match-selector.d.ts +18 -0
  65. package/dist/src/review/match-selector.js +202 -0
  66. package/dist/src/review/match-selector.js.map +1 -0
  67. package/dist/src/review/review-analyzer.d.ts +2 -0
  68. package/dist/src/review/review-analyzer.js +652 -0
  69. package/dist/src/review/review-analyzer.js.map +1 -0
  70. package/dist/src/review/review-facts.d.ts +17 -0
  71. package/dist/src/review/review-facts.js +560 -0
  72. package/dist/src/review/review-facts.js.map +1 -0
  73. package/dist/src/review/review-share.d.ts +48 -0
  74. package/dist/src/review/review-share.js +37 -0
  75. package/dist/src/review/review-share.js.map +1 -0
  76. package/dist/src/review/selection-store.d.ts +25 -0
  77. package/dist/src/review/selection-store.js +80 -0
  78. package/dist/src/review/selection-store.js.map +1 -0
  79. package/dist/src/review/session-review.d.ts +72 -0
  80. package/dist/src/review/session-review.js +492 -0
  81. package/dist/src/review/session-review.js.map +1 -0
  82. package/dist/src/review/special-events.d.ts +3 -0
  83. package/dist/src/review/special-events.js +258 -0
  84. package/dist/src/review/special-events.js.map +1 -0
  85. package/dist/src/review/subgraph.d.ts +26 -0
  86. package/dist/src/review/subgraph.js +146 -0
  87. package/dist/src/review/subgraph.js.map +1 -0
  88. package/dist/src/review/supplemental-intelligence.d.ts +15 -0
  89. package/dist/src/review/supplemental-intelligence.js +431 -0
  90. package/dist/src/review/supplemental-intelligence.js.map +1 -0
  91. package/dist/src/review/team-damage.d.ts +8 -0
  92. package/dist/src/review/team-damage.js +180 -0
  93. package/dist/src/review/team-damage.js.map +1 -0
  94. package/dist/src/review/telemetry-events.d.ts +72 -0
  95. package/dist/src/review/telemetry-events.js +573 -0
  96. package/dist/src/review/telemetry-events.js.map +1 -0
  97. package/dist/src/review/telemetry.d.ts +86 -0
  98. package/dist/src/review/telemetry.js +266 -0
  99. package/dist/src/review/telemetry.js.map +1 -0
  100. package/dist/src/review/types.d.ts +501 -0
  101. package/dist/src/review/types.js +2 -0
  102. package/dist/src/review/types.js.map +1 -0
  103. package/dist/src/review/vehicle-intelligence.d.ts +3 -0
  104. package/dist/src/review/vehicle-intelligence.js +148 -0
  105. package/dist/src/review/vehicle-intelligence.js.map +1 -0
  106. package/dist/src/schema/query.d.ts +876 -0
  107. package/dist/src/schema/query.js +185 -0
  108. package/dist/src/schema/query.js.map +1 -0
  109. package/dist/src/schema/status.d.ts +66 -0
  110. package/dist/src/schema/status.js +49 -0
  111. package/dist/src/schema/status.js.map +1 -0
  112. package/dist/src/service/pubg-domain-service.d.ts +192 -0
  113. package/dist/src/service/pubg-domain-service.js +1598 -0
  114. package/dist/src/service/pubg-domain-service.js.map +1 -0
  115. package/dist/src/storage/repository-port.d.ts +84 -0
  116. package/dist/src/storage/repository-port.js +2 -0
  117. package/dist/src/storage/repository-port.js.map +1 -0
  118. package/dist/src/storage/sqlite-repository-adapter.d.ts +33 -0
  119. package/dist/src/storage/sqlite-repository-adapter.js +66 -0
  120. package/dist/src/storage/sqlite-repository-adapter.js.map +1 -0
  121. package/dist/src/storage/sqlite-repository.d.ts +73 -0
  122. package/dist/src/storage/sqlite-repository.js +652 -0
  123. package/dist/src/storage/sqlite-repository.js.map +1 -0
  124. package/dist/src/time/selector-resolver.d.ts +34 -0
  125. package/dist/src/time/selector-resolver.js +364 -0
  126. package/dist/src/time/selector-resolver.js.map +1 -0
  127. package/package.json +42 -3
@@ -0,0 +1,258 @@
1
+ import { isRocketStats } from './heavy-weapon-intelligence.js';
2
+ import { dedupeRelevantCombatEvents, isTrackedOffensiveEvent, isTrackedReviveEvent, } from './combat-scope.js';
3
+ function sameWeapon(event, stats) {
4
+ const value = event.weaponId ?? event.itemId;
5
+ if (!value)
6
+ return false;
7
+ const canonical = value
8
+ .replace(/^Item_Weapon_/iu, '')
9
+ .replace(/^Weap/iu, '')
10
+ .replace(/_C$/iu, '');
11
+ return value === stats.weapon || canonical === stats.weapon || /panzer|rocket|rpg/i.test(value);
12
+ }
13
+ function pushEvent(events, value) {
14
+ events.push({ ...value, id: `special-${events.length + 1}` });
15
+ }
16
+ export function detectSpecialEvents(events, fights, heavyWeapons, vehicles, teamIds, fightIntegrityPass = true) {
17
+ const result = [];
18
+ const dedupedCombatIds = new Set(dedupeRelevantCombatEvents(events, teamIds).map((event) => event.id));
19
+ for (const fight of fightIntegrityPass ? fights : []) {
20
+ const fightEvents = events.filter((event) => fight.evidenceIds.includes(event.id));
21
+ for (const playerId of teamIds) {
22
+ const playerCombat = fightEvents.filter((event) => event.actorId === playerId && isTrackedOffensiveEvent(event, teamIds));
23
+ const playerKnocks = playerCombat.filter((event) => event.type === 'KNOCK');
24
+ const playerKills = playerCombat.filter((event) => event.type === 'KILL');
25
+ if (playerKnocks.length >= 2) {
26
+ pushEvent(result, {
27
+ type: 'MULTI_KNOCK',
28
+ playerId,
29
+ time: playerKnocks.at(-1)?.timeSeconds ?? null,
30
+ impact: `一波团战造成${playerKnocks.length}次倒地`,
31
+ impactScore: Math.max(520, fight.importanceScore / 2) + playerKnocks.length * 40,
32
+ facts: { knocks: playerKnocks.length, kills: playerKills.length, fightId: fight.id },
33
+ evidenceIds: playerKnocks.map((event) => event.id),
34
+ });
35
+ }
36
+ if (playerKills.length >= 2) {
37
+ pushEvent(result, {
38
+ type: 'CLUTCH',
39
+ playerId,
40
+ time: playerKills.at(-1)?.timeSeconds ?? null,
41
+ impact: `团战内完成${playerKills.length}次击杀`,
42
+ impactScore: Math.max(580, fight.importanceScore / 2) + playerKills.length * 60,
43
+ facts: {
44
+ kills: playerKills.length,
45
+ knocks: playerKnocks.length,
46
+ result: fight.result,
47
+ fightId: fight.id,
48
+ },
49
+ evidenceIds: playerKills.map((event) => event.id),
50
+ });
51
+ }
52
+ }
53
+ }
54
+ const revivesByPlayer = new Map();
55
+ for (const event of dedupeRelevantCombatEvents(events, teamIds)) {
56
+ if (!isTrackedReviveEvent(event, teamIds))
57
+ continue;
58
+ if (!event.actorId)
59
+ continue;
60
+ const bucket = revivesByPlayer.get(event.actorId) ?? [];
61
+ bucket.push(event);
62
+ revivesByPlayer.set(event.actorId, bucket);
63
+ }
64
+ for (const [playerId, playerEvents] of revivesByPlayer) {
65
+ if (playerEvents.length < 2)
66
+ continue;
67
+ pushEvent(result, {
68
+ type: 'REVIVE_CHAIN',
69
+ playerId,
70
+ time: playerEvents.at(-1)?.timeSeconds ?? null,
71
+ impact: `连续完成${playerEvents.length}次救援`,
72
+ impactScore: playerEvents.length * 120,
73
+ facts: { revives: playerEvents.length },
74
+ evidenceIds: playerEvents.map((event) => event.id),
75
+ });
76
+ }
77
+ for (const stats of heavyWeapons) {
78
+ if (!isRocketStats(stats))
79
+ continue;
80
+ const directWeaponEvents = events.filter((event) => event.actorId === stats.playerId && sameWeapon(event, stats));
81
+ const attackIds = new Set(directWeaponEvents.map((event) => event.attackId).filter((id) => Boolean(id)));
82
+ // A kill/destroy event without a weapon can still be attributed when the
83
+ // telemetry carries the same attackId as an observed rocket event. Time
84
+ // proximity alone is deliberately not used as a causal link.
85
+ const weaponEvents = events.filter((event) => event.actorId === stats.playerId &&
86
+ (sameWeapon(event, stats) || Boolean(event.attackId && attackIds.has(event.attackId))) &&
87
+ (!['DAMAGE', 'KNOCK', 'KILL'].includes(event.type) || dedupedCombatIds.has(event.id)));
88
+ const pickupEvents = weaponEvents.filter((event) => event.type === 'ITEM_ACQUIRE');
89
+ const shotEvents = weaponEvents.filter((event) => event.type === 'ATTACK' || event.type === 'THROWABLE_USE');
90
+ const damageEvents = weaponEvents.filter((event) => event.type === 'DAMAGE' && event.hit && isTrackedOffensiveEvent(event, teamIds));
91
+ const vehicleHitEvents = weaponEvents.filter((event) => event.type === 'VEHICLE_DAMAGE' &&
92
+ (event.vehicleDamage > 0 || event.damage > 0 || event.hit));
93
+ const killEvents = weaponEvents.filter((event) => event.type === 'KILL' && isTrackedOffensiveEvent(event, teamIds));
94
+ const knockEvents = weaponEvents.filter((event) => event.type === 'KNOCK' && isTrackedOffensiveEvent(event, teamIds));
95
+ const destroyEvents = weaponEvents.filter((event) => event.type === 'VEHICLE_DESTROY');
96
+ if (stats.pickupEvents > 0 && stats.shots === 0) {
97
+ pushEvent(result, {
98
+ type: 'ROCKET_UNUSED',
99
+ playerId: stats.playerId,
100
+ time: pickupEvents[0]?.timeSeconds ?? null,
101
+ impact: `拾取${stats.pickupEvents}次但没有发射`,
102
+ impactScore: 20,
103
+ facts: { pickupEvents: stats.pickupEvents, shots: stats.shots },
104
+ evidenceIds: stats.evidenceIds,
105
+ });
106
+ }
107
+ if (stats.hits > 0) {
108
+ // A rocket may expose only a knock/kill record. Those records count as a
109
+ // hit in HeavyWeaponStats when attackId correlation is reliable.
110
+ const hitEvents = [...damageEvents, ...vehicleHitEvents, ...knockEvents, ...killEvents];
111
+ pushEvent(result, {
112
+ type: 'ROCKET_HIT',
113
+ playerId: stats.playerId,
114
+ time: hitEvents[0]?.timeSeconds ?? null,
115
+ impact: `火箭筒产生${stats.hits}次命中记录`,
116
+ impactScore: 180 + stats.playerDamage,
117
+ facts: { shots: stats.shots, hits: stats.hits, playerDamage: stats.playerDamage },
118
+ evidenceIds: [
119
+ ...new Set(hitEvents.flatMap((event) => [
120
+ event.id,
121
+ ...shotEvents
122
+ .filter((attack) => attack.attackId !== null && attack.attackId === event.attackId)
123
+ .map((attack) => attack.id),
124
+ ])),
125
+ ],
126
+ });
127
+ }
128
+ if (stats.shots > 0 &&
129
+ stats.hits === 0 &&
130
+ stats.vehicleDamage <= 0 &&
131
+ stats.vehiclesDestroyed === 0 &&
132
+ // A weapon-labelled knock/kill is outcome evidence even when the source
133
+ // omitted attackId. It must not be called an all-miss.
134
+ stats.knocks === 0 &&
135
+ stats.kills === 0) {
136
+ pushEvent(result, {
137
+ type: 'ROCKET_MISS',
138
+ playerId: stats.playerId,
139
+ time: shotEvents[0]?.timeSeconds ?? null,
140
+ impact: `发射${stats.shots}次但没有检测到命中`,
141
+ impactScore: 35,
142
+ facts: { shots: stats.shots, hits: stats.hits },
143
+ evidenceIds: shotEvents.map((event) => event.id),
144
+ });
145
+ }
146
+ if (destroyEvents.length > 0) {
147
+ pushEvent(result, {
148
+ type: 'ROCKET_VEHICLE_DESTROY',
149
+ playerId: stats.playerId,
150
+ time: destroyEvents[0]?.timeSeconds ?? null,
151
+ impact: '火箭筒摧毁载具',
152
+ impactScore: 260,
153
+ facts: { vehiclesDestroyed: destroyEvents.length },
154
+ evidenceIds: destroyEvents.map((event) => event.id),
155
+ });
156
+ }
157
+ const killsByAttack = new Map();
158
+ for (const event of killEvents) {
159
+ if (!event.attackId || !attackIds.has(event.attackId))
160
+ continue;
161
+ const bucket = killsByAttack.get(event.attackId) ?? [];
162
+ bucket.push(event);
163
+ killsByAttack.set(event.attackId, bucket);
164
+ }
165
+ for (const [attackId, groupedKills] of killsByAttack) {
166
+ if (groupedKills.length < 2 || !shotEvents.some((event) => event.attackId === attackId))
167
+ continue;
168
+ pushEvent(result, {
169
+ type: 'ROCKET_MULTI_KILL',
170
+ playerId: stats.playerId,
171
+ time: groupedKills[0]?.timeSeconds ?? null,
172
+ impact: `一发火箭筒关联${groupedKills.length}次击杀`,
173
+ impactScore: 500 + groupedKills.length * 100,
174
+ facts: { attackId, kills: groupedKills.length },
175
+ evidenceIds: [
176
+ ...new Set([
177
+ ...shotEvents.filter((event) => event.attackId === attackId).map((event) => event.id),
178
+ ...groupedKills.map((event) => event.id),
179
+ ]),
180
+ ],
181
+ });
182
+ }
183
+ // A vehicle id plus a weapon-causal destroy event is required. Time
184
+ // proximity alone is intentionally insufficient for a multi-kill claim.
185
+ for (const destroy of destroyEvents) {
186
+ if (!destroy.vehicleId)
187
+ continue;
188
+ const causalShotEvents = shotEvents.filter((event) => event.attackId !== null &&
189
+ (event.attackId === destroy.attackId || event.vehicleId === destroy.vehicleId));
190
+ if (!causalShotEvents.length)
191
+ continue;
192
+ const vehicleAttackIds = new Set(weaponEvents
193
+ .filter((event) => event.vehicleId === destroy.vehicleId && event.attackId !== null)
194
+ .map((event) => event.attackId));
195
+ const vehicleKills = events.filter((event) => event.type === 'KILL' &&
196
+ event.actorId === stats.playerId &&
197
+ isTrackedOffensiveEvent(event, teamIds) &&
198
+ dedupedCombatIds.has(event.id) &&
199
+ event.vehicleId === destroy.vehicleId &&
200
+ (sameWeapon(event, stats) ||
201
+ (event.attackId !== null &&
202
+ (event.attackId === destroy.attackId || vehicleAttackIds.has(event.attackId)))));
203
+ if (vehicleKills.length < 2)
204
+ continue;
205
+ const causalEvents = weaponEvents.filter((event) => event.id === destroy.id ||
206
+ (event.vehicleId === destroy.vehicleId &&
207
+ (event.type === 'ATTACK' ||
208
+ event.type === 'THROWABLE_USE' ||
209
+ event.type === 'VEHICLE_DAMAGE')) ||
210
+ (destroy.attackId !== null && event.attackId === destroy.attackId));
211
+ pushEvent(result, {
212
+ type: 'ROCKET_VEHICLE_MULTI_KILL',
213
+ playerId: stats.playerId,
214
+ time: destroy.timeSeconds,
215
+ impact: `摧毁载具并关联${vehicleKills.length}次击杀`,
216
+ impactScore: 800 + vehicleKills.length * 150,
217
+ facts: { vehicleId: destroy.vehicleId, kills: vehicleKills.length, vehiclesDestroyed: 1 },
218
+ evidenceIds: [
219
+ ...new Set([
220
+ ...causalEvents.map((event) => event.id),
221
+ ...vehicleKills.map((event) => event.id),
222
+ ]),
223
+ ],
224
+ });
225
+ }
226
+ }
227
+ for (const vehicle of vehicles) {
228
+ if (vehicle.driveDistance >= 2000) {
229
+ pushEvent(result, {
230
+ type: 'VEHICLE_LONG_DRIVE',
231
+ playerId: vehicle.playerId,
232
+ time: null,
233
+ impact: `驾驶${Math.round(vehicle.driveDistance)}米`,
234
+ impactScore: Math.min(300, vehicle.driveDistance / 20),
235
+ facts: {
236
+ driveDistance: Math.round(vehicle.driveDistance),
237
+ maxSpeed: Math.round(vehicle.maxSpeed),
238
+ },
239
+ evidenceIds: vehicle.evidenceIds,
240
+ });
241
+ }
242
+ if (vehicle.vehiclesDestroyed > 0) {
243
+ pushEvent(result, {
244
+ type: 'VEHICLE_DESTROY',
245
+ playerId: vehicle.playerId,
246
+ time: null,
247
+ impact: `摧毁${vehicle.vehiclesDestroyed}辆载具`,
248
+ impactScore: vehicle.vehiclesDestroyed * 180,
249
+ facts: { vehiclesDestroyed: vehicle.vehiclesDestroyed },
250
+ evidenceIds: vehicle.evidenceIds,
251
+ });
252
+ }
253
+ }
254
+ return result.sort((left, right) => right.impactScore - left.impactScore ||
255
+ (left.time ?? Number.POSITIVE_INFINITY) - (right.time ?? Number.POSITIVE_INFINITY) ||
256
+ left.id.localeCompare(right.id));
257
+ }
258
+ //# sourceMappingURL=special-events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"special-events.js","sourceRoot":"","sources":["../../../src/review/special-events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { TeamConfig } from '../config/team.js';
2
+ import type { DataLayerResult } from '../data/model.js';
3
+ import type { MatchSelectionRecord, ReviewExecution } from './types.js';
4
+ import { TelemetryWorker } from './telemetry.js';
5
+ import type { CanonicalQuery } from '../schema/query.js';
6
+ import type { SessionContextRecord } from '../data/model.js';
7
+ export type { ReviewExecution } from './types.js';
8
+ export interface ReviewSubgraphOptions {
9
+ team: TeamConfig;
10
+ telemetryWorker?: TelemetryWorker;
11
+ }
12
+ export interface ReviewRequest {
13
+ query: CanonicalQuery;
14
+ data: DataLayerResult;
15
+ sessionId: string;
16
+ context: SessionContextRecord | null;
17
+ now: Date;
18
+ sourceMatchResultSetId?: string | null;
19
+ selection?: MatchSelectionRecord | null;
20
+ }
21
+ export declare class ReviewSubgraph {
22
+ private readonly team;
23
+ private readonly telemetryWorker;
24
+ constructor(options: ReviewSubgraphOptions);
25
+ execute(request: ReviewRequest): Promise<ReviewExecution>;
26
+ }
@@ -0,0 +1,146 @@
1
+ import { emptyMatchReviewFacts } from './review-facts.js';
2
+ import { resolveMatchCandidates } from './match-selector.js';
3
+ import { analyzeMatchReview } from './review-analyzer.js';
4
+ import { TelemetryWorker } from './telemetry.js';
5
+ function resultEvidence(candidate, query) {
6
+ return {
7
+ matchIds: candidate.map((item) => item.match.matchId),
8
+ playerIds: [
9
+ ...new Set(candidate.flatMap((item) => item.row.players?.map((player) => player.accountId) ?? [])),
10
+ ],
11
+ fields: ['matchId', 'createdAt', 'mapName', 'rank', 'kills', 'assists', 'damage'],
12
+ calculation: 'pubg_review_subgraph_v3_3',
13
+ selector: query.matchSelector ?? null,
14
+ };
15
+ }
16
+ function baseResult(request, status, candidates, selected) {
17
+ return {
18
+ queryId: request.query.queryId,
19
+ sessionId: request.sessionId,
20
+ status,
21
+ data: {
22
+ operation: 'review_match',
23
+ groupBy: 'match',
24
+ rows: selected ? [selected.row] : candidates.map((candidate) => candidate.row),
25
+ summary: {
26
+ periodLabel: request.query.selector.label ?? '复盘范围',
27
+ candidateCount: candidates.length,
28
+ ...(selected
29
+ ? { selectedMatchId: selected.match.matchId, selectedOrdinal: selected.ordinal }
30
+ : {}),
31
+ },
32
+ },
33
+ coverage: request.data.coverage,
34
+ source: request.data.source,
35
+ evidence: resultEvidence(candidates, request.query),
36
+ diagnostics: {
37
+ calculation: 'pubg_review_subgraph_v3_3',
38
+ telemetryRequested: Boolean(selected),
39
+ telemetryFetchedOnlyAfterUniqueMatch: true,
40
+ },
41
+ };
42
+ }
43
+ export class ReviewSubgraph {
44
+ team;
45
+ telemetryWorker;
46
+ constructor(options) {
47
+ this.team = options.team;
48
+ this.telemetryWorker = options.telemetryWorker ?? new TelemetryWorker({ team: this.team });
49
+ }
50
+ async execute(request) {
51
+ const resolution = resolveMatchCandidates(request.data.records, request.query, this.team, request.now, request.context);
52
+ let candidates = resolution.candidates;
53
+ let selected = resolution.selected;
54
+ if (request.selection) {
55
+ const selectedIndex = candidates.findIndex((candidate) => candidate.match.matchId === request.selection?.matchId);
56
+ const forced = selectedIndex >= 0 ? candidates[selectedIndex] : undefined;
57
+ if (forced) {
58
+ // The callback query narrows the ResultSet to one match. Rebind the
59
+ // candidate's ordinal from the selection record so the source Picker
60
+ // order survives that narrowing.
61
+ const rebound = { ...forced, ordinal: request.selection.ordinal };
62
+ candidates = candidates.map((candidate, index) => index === selectedIndex ? rebound : candidate);
63
+ selected = [rebound];
64
+ }
65
+ }
66
+ const pickerCandidates = resolution.selectionRequired
67
+ ? resolution.selector
68
+ ? resolution.selected
69
+ : resolution.candidates
70
+ : candidates;
71
+ if (selected.length === 0) {
72
+ return {
73
+ result: baseResult(request, 'MATCH_NOT_FOUND', candidates, null),
74
+ candidates: pickerCandidates,
75
+ selected: null,
76
+ matchSelector: resolution.selector,
77
+ sourceMatchResultSetId: request.sourceMatchResultSetId ?? null,
78
+ };
79
+ }
80
+ if (selected.length !== 1 || (resolution.selectionRequired && !request.selection)) {
81
+ return {
82
+ result: baseResult(request, 'MATCH_SELECTION_REQUIRED', pickerCandidates, null),
83
+ candidates: pickerCandidates,
84
+ selected: null,
85
+ matchSelector: resolution.selector,
86
+ sourceMatchResultSetId: request.sourceMatchResultSetId ?? null,
87
+ ...(resolution.selector?.type === 'ranked'
88
+ ? { rankedMetric: resolution.selector.metric }
89
+ : {}),
90
+ };
91
+ }
92
+ const target = selected[0];
93
+ if (!target) {
94
+ return {
95
+ result: baseResult(request, 'MATCH_NOT_FOUND', candidates, null),
96
+ candidates,
97
+ selected: null,
98
+ matchSelector: resolution.selector,
99
+ sourceMatchResultSetId: request.sourceMatchResultSetId ?? null,
100
+ };
101
+ }
102
+ const telemetry = await this.telemetryWorker.ensure(target.match, target.ordinal);
103
+ const facts = telemetry.facts ?? emptyMatchReviewFacts(target.match, this.team, target.ordinal);
104
+ const analysis = analyzeMatchReview(facts);
105
+ const review = {
106
+ schemaVersion: 1,
107
+ match: facts.match,
108
+ facts,
109
+ analysis,
110
+ telemetry: {
111
+ status: telemetry.status,
112
+ cacheStatus: telemetry.cacheStatus,
113
+ cacheLookup: telemetry.cacheLookup,
114
+ availability: telemetry.availability,
115
+ parserVersion: telemetry.parserVersion,
116
+ featureVersion: telemetry.featureVersion,
117
+ ...(telemetry.error ? { error: telemetry.error } : {}),
118
+ },
119
+ sourceMatchResultSetId: request.sourceMatchResultSetId ?? null,
120
+ };
121
+ const status = telemetry.status === 'UNAVAILABLE'
122
+ ? 'REVIEW_PARTIAL'
123
+ : facts.fightIntegrity.pass
124
+ ? 'OK'
125
+ : 'FIGHT_ANALYTICS_INVALID';
126
+ const result = baseResult(request, status, [target], target);
127
+ result.review = review;
128
+ result.diagnostics = {
129
+ ...result.diagnostics,
130
+ telemetryStatus: telemetry.status,
131
+ parserVersion: telemetry.parserVersion,
132
+ featureVersion: telemetry.featureVersion,
133
+ evidenceOnlyCommentary: true,
134
+ fightIntegrity: facts.fightIntegrity,
135
+ ...facts.fightIntegrity.diagnostics,
136
+ };
137
+ return {
138
+ result,
139
+ candidates,
140
+ selected: target,
141
+ matchSelector: resolution.selector,
142
+ sourceMatchResultSetId: request.sourceMatchResultSetId ?? null,
143
+ };
144
+ }
145
+ }
146
+ //# sourceMappingURL=subgraph.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subgraph.js","sourceRoot":"","sources":["../../../src/review/subgraph.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAO7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAqBjD,SAAS,cAAc,CAAC,SAAiC,EAAE,KAAqB;IAC9E,OAAO;QACL,QAAQ,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;QACrD,SAAS,EAAE;YACT,GAAG,IAAI,GAAG,CACR,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CACvF;SACF;QACD,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,CAAC;QACjF,WAAW,EAAE,2BAA2B;QACxC,QAAQ,EAAE,KAAK,CAAC,aAAa,IAAI,IAAI;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CACjB,OAAsB,EACtB,MAAkC,EAClC,UAAkC,EAClC,QAAqC;IAErC,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO;QAC9B,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,MAAM;QACN,IAAI,EAAE;YACJ,SAAS,EAAE,cAAc;YACzB,OAAO,EAAE,OAAO;YAChB,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC;YAC9E,OAAO,EAAE;gBACP,WAAW,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,IAAI,MAAM;gBACnD,cAAc,EAAE,UAAU,CAAC,MAAM;gBACjC,GAAG,CAAC,QAAQ;oBACV,CAAC,CAAC,EAAE,eAAe,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,QAAQ,CAAC,OAAO,EAAE;oBAChF,CAAC,CAAC,EAAE,CAAC;aACR;SACF;QACD,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,QAAQ;QAC/B,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM;QAC3B,QAAQ,EAAE,cAAc,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC;QACnD,WAAW,EAAE;YACX,WAAW,EAAE,2BAA2B;YACxC,kBAAkB,EAAE,OAAO,CAAC,QAAQ,CAAC;YACrC,oCAAoC,EAAE,IAAI;SAC3C;KACF,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,cAAc;IACR,IAAI,CAAa;IACjB,eAAe,CAAkB;IAElD,YAAY,OAA8B;QACxC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,IAAI,eAAe,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC7F,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,OAAsB;QAClC,MAAM,UAAU,GAAG,sBAAsB,CACvC,OAAO,CAAC,IAAI,CAAC,OAAO,EACpB,OAAO,CAAC,KAAK,EACb,IAAI,CAAC,IAAI,EACT,OAAO,CAAC,GAAG,EACX,OAAO,CAAC,OAAO,CAChB,CAAC;QACF,IAAI,UAAU,GAAG,UAAU,CAAC,UAAU,CAAC;QACvC,IAAI,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACnC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,aAAa,GAAG,UAAU,CAAC,SAAS,CACxC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,SAAS,EAAE,OAAO,CACtE,CAAC;YACF,MAAM,MAAM,GAAG,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1E,IAAI,MAAM,EAAE,CAAC;gBACX,oEAAoE;gBACpE,qEAAqE;gBACrE,iCAAiC;gBACjC,MAAM,OAAO,GAAG,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;gBAClE,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,EAAE,CAC/C,KAAK,KAAK,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAC9C,CAAC;gBACF,QAAQ,GAAG,CAAC,OAAO,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QACD,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB;YACnD,CAAC,CAAC,UAAU,CAAC,QAAQ;gBACnB,CAAC,CAAC,UAAU,CAAC,QAAQ;gBACrB,CAAC,CAAC,UAAU,CAAC,UAAU;YACzB,CAAC,CAAC,UAAU,CAAC;QACf,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO;gBACL,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,CAAC;gBAChE,UAAU,EAAE,gBAAgB;gBAC5B,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU,CAAC,QAAQ;gBAClC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,IAAI;aAC/D,CAAC;QACJ,CAAC;QACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,iBAAiB,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YAClF,OAAO;gBACL,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,0BAA0B,EAAE,gBAAgB,EAAE,IAAI,CAAC;gBAC/E,UAAU,EAAE,gBAAgB;gBAC5B,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU,CAAC,QAAQ;gBAClC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,IAAI;gBAC9D,GAAG,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,KAAK,QAAQ;oBACxC,CAAC,CAAC,EAAE,YAAY,EAAE,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE;oBAC9C,CAAC,CAAC,EAAE,CAAC;aACR,CAAC;QACJ,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO;gBACL,MAAM,EAAE,UAAU,CAAC,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,IAAI,CAAC;gBAChE,UAAU;gBACV,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,UAAU,CAAC,QAAQ;gBAClC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,IAAI;aAC/D,CAAC;QACJ,CAAC;QACD,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAClF,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,qBAAqB,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;QAChG,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAsB;YAChC,aAAa,EAAE,CAAC;YAChB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK;YACL,QAAQ;YACR,SAAS,EAAE;gBACT,MAAM,EAAE,SAAS,CAAC,MAAM;gBACxB,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,YAAY,EAAE,SAAS,CAAC,YAAY;gBACpC,aAAa,EAAE,SAAS,CAAC,aAAa;gBACtC,cAAc,EAAE,SAAS,CAAC,cAAc;gBACxC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACvD;YACD,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,IAAI;SAC/D,CAAC;QACF,MAAM,MAAM,GACV,SAAS,CAAC,MAAM,KAAK,aAAa;YAChC,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI;gBACzB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,yBAAyB,CAAC;QAClC,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QACvB,MAAM,CAAC,WAAW,GAAG;YACnB,GAAG,MAAM,CAAC,WAAW;YACrB,eAAe,EAAE,SAAS,CAAC,MAAM;YACjC,aAAa,EAAE,SAAS,CAAC,aAAa;YACtC,cAAc,EAAE,SAAS,CAAC,cAAc;YACxC,sBAAsB,EAAE,IAAI;YAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,GAAG,KAAK,CAAC,cAAc,CAAC,WAAW;SACpC,CAAC;QACF,OAAO;YACL,MAAM;YACN,UAAU;YACV,QAAQ,EAAE,MAAM;YAChB,aAAa,EAAE,UAAU,CAAC,QAAQ;YAClC,sBAAsB,EAAE,OAAO,CAAC,sBAAsB,IAAI,IAAI;SAC/D,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,15 @@
1
+ import type { ArmorBreakFact, EnvironmentStats, LootActivityStats, LootStats, RecoveryStats, StunGunStats, VehicleImpactFact, VehicleTrunkTransfer } from './types.js';
2
+ import type { NormalizedTelemetryEvent } from './telemetry-events.js';
3
+ export declare function extractStunGunStats(events: NormalizedTelemetryEvent[], teamIds: Set<string>): StunGunStats[];
4
+ export declare function extractRecoveryStats(events: NormalizedTelemetryEvent[], teamIds: Set<string>): RecoveryStats[];
5
+ export declare function extractLootStats(events: NormalizedTelemetryEvent[], teamIds: Set<string>): LootStats[];
6
+ /**
7
+ * Count item movement without pretending that every pickup is rare loot.
8
+ * Cosmetic fields use only explicit item-event metadata; kill/settlement
9
+ * payloads are deliberately not interpreted as pickup records.
10
+ */
11
+ export declare function extractLootActivityStats(events: NormalizedTelemetryEvent[], teamIds: Set<string>): LootActivityStats[];
12
+ export declare function extractVehicleTrunkTransfers(events: NormalizedTelemetryEvent[], teamIds: Set<string>): VehicleTrunkTransfer[];
13
+ export declare function extractEnvironmentStats(events: NormalizedTelemetryEvent[], teamIds: Set<string>): EnvironmentStats[];
14
+ export declare function extractArmorBreakFacts(events: NormalizedTelemetryEvent[], teamIds: Set<string>): ArmorBreakFact[];
15
+ export declare function extractVehicleImpactFacts(events: NormalizedTelemetryEvent[], teamIds: Set<string>): VehicleImpactFact[];