@aephia/atlas-kit 0.6.0-next.60 → 0.6.0-next.62

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 (43) hide show
  1. package/README.md +1 -1
  2. package/dist/internal/c4/scan-detection-codecs.d.ts +1 -1
  3. package/dist/internal/c4/scan-detection-codecs.d.ts.map +1 -1
  4. package/dist/internal/c4/scan-detection-codecs.js +1 -1
  5. package/dist/internal/c4/scan-detection-codecs.js.map +1 -1
  6. package/dist/internal/c4/scan-lifecycle.d.ts +28 -0
  7. package/dist/internal/c4/scan-lifecycle.d.ts.map +1 -1
  8. package/dist/internal/c4/scan-lifecycle.js +22 -0
  9. package/dist/internal/c4/scan-lifecycle.js.map +1 -1
  10. package/dist/internal/planning/fleet-respawn.d.ts +1 -1
  11. package/dist/internal/planning/scan-completion-guard.d.ts +43 -0
  12. package/dist/internal/planning/scan-completion-guard.d.ts.map +1 -0
  13. package/dist/internal/planning/scan-completion-guard.js +94 -0
  14. package/dist/internal/planning/scan-completion-guard.js.map +1 -0
  15. package/dist/internal/planning/scan-completion.d.ts +20 -0
  16. package/dist/internal/planning/scan-completion.d.ts.map +1 -0
  17. package/dist/internal/planning/scan-completion.js +220 -0
  18. package/dist/internal/planning/scan-completion.js.map +1 -0
  19. package/dist/internal/planning/xp-runtime.d.ts +1 -1
  20. package/dist/internal/planning/xp-runtime.d.ts.map +1 -1
  21. package/dist/internal/planning/xp-runtime.js +5 -3
  22. package/dist/internal/planning/xp-runtime.js.map +1 -1
  23. package/dist/planning/execution.d.ts.map +1 -1
  24. package/dist/planning/execution.js +4 -0
  25. package/dist/planning/execution.js.map +1 -1
  26. package/dist/planning/index.d.ts +3 -2
  27. package/dist/planning/index.d.ts.map +1 -1
  28. package/dist/planning/index.js +61 -5
  29. package/dist/planning/index.js.map +1 -1
  30. package/dist/scanning/actions/index.d.ts +64 -0
  31. package/dist/scanning/actions/index.d.ts.map +1 -1
  32. package/dist/scanning/actions/index.js +92 -0
  33. package/dist/scanning/actions/index.js.map +1 -1
  34. package/dist/scanning/index.d.ts +1 -0
  35. package/dist/scanning/index.d.ts.map +1 -1
  36. package/dist/scanning/index.js +1 -0
  37. package/dist/scanning/index.js.map +1 -1
  38. package/dist/scanning/odds.d.ts +111 -0
  39. package/dist/scanning/odds.d.ts.map +1 -0
  40. package/dist/scanning/odds.js +294 -0
  41. package/dist/scanning/odds.js.map +1 -0
  42. package/dist/scanning/signals.d.ts +2 -2
  43. package/package.json +1 -1
@@ -0,0 +1,111 @@
1
+ import type { ScanPatternPolicySnapshot, ScanLootProfileSnapshot, ScanSignalSnapshot } from './signals.js';
2
+ type Policy = ScanPatternPolicySnapshot;
3
+ type Profile = ScanLootProfileSnapshot;
4
+ type Row = Profile['loot'][number];
5
+ type Focus = Row['category'];
6
+ type UnavailableReason = 'missing-policy' | 'missing-loot-profile' | 'unsupported-version' | 'unsupported-pattern' | 'unsupported-loot-layout' | 'game-mismatch' | 'inactive-policy' | 'inactive-loot-profile' | 'pattern-research-locked' | 'region-research-locked' | 'focus-not-allowed' | 'empty-weighted-pool' | 'signal-not-pending' | 'committed-configuration-mismatch';
7
+ type Exclusion = 'pattern' | 'rarity' | 'value-budget' | 'focus' | 'research' | 'not-committed';
8
+ type Provenance = Readonly<{
9
+ policy: Readonly<Pick<Policy, 'address' | 'game' | 'patternId' | 'revision' | 'contentFingerprint'>> | undefined;
10
+ lootProfile: Readonly<Pick<Profile, 'address' | 'game' | 'regionId' | 'revision' | 'contentFingerprint'>> | undefined;
11
+ signal: Readonly<Pick<ScanSignalSnapshot, 'address' | 'sequence'>> | undefined;
12
+ }>;
13
+ type Share = Readonly<{
14
+ cargo: Row['cargo'];
15
+ weight: bigint;
16
+ conditionalProbability: number;
17
+ perScanProbability: number;
18
+ }>;
19
+ /** Explicit eligibility knowledge for prospective client estimates. Empty tag arrays mean known none.
20
+ * Regional requirements must describe the supplied loot profile's region. Focus defaults to any.
21
+ * @example
22
+ * ```ts
23
+ * const options: ScanLootOddsOptions = { unlockedResearchTagIds: [12], requiredRegionResearchTagIds: [], exhaustionBasisPoints: 0 };
24
+ * ```
25
+ */
26
+ export interface ScanLootOddsOptions {
27
+ readonly unlockedResearchTagIds: readonly number[];
28
+ readonly requiredRegionResearchTagIds: readonly number[];
29
+ readonly exhaustionBasisPoints: number;
30
+ readonly focus?: Focus;
31
+ }
32
+ /** Client-derived selection estimates, never program-verified probabilities or recovery quantities.
33
+ * Unavailable results deliberately contain no probability fields. Conditional shares remain meaningful
34
+ * when contact probability is zero. Probabilities are numeric fractions from zero through one.
35
+ * @example
36
+ * ```ts
37
+ * declare const odds: ScanLootOdds;
38
+ * if (odds.status === 'available') console.log(odds.resources[0]?.perScanProbability);
39
+ * ```
40
+ */
41
+ export type ScanLootOdds = Readonly<{
42
+ kind: 'client-derived-estimate';
43
+ basis: 'prospective' | 'committed';
44
+ provenance: Provenance;
45
+ toJSON(): unknown;
46
+ }> & (Readonly<{
47
+ status: 'unavailable';
48
+ reasons: readonly UnavailableReason[];
49
+ }> | Readonly<{
50
+ status: 'available';
51
+ contactChanceBasisPoints: number;
52
+ contactProbability: number;
53
+ noContactProbability: number;
54
+ totalWeight: bigint;
55
+ eligibleRows: readonly (Share & Readonly<{
56
+ rowIndex: number;
57
+ }>)[];
58
+ excludedRows: readonly Readonly<{
59
+ rowIndex: number;
60
+ reasons: readonly Exclusion[];
61
+ }>[];
62
+ resources: readonly Share[];
63
+ }>);
64
+ /** Client-derived exhaustion from an explicit clock and retained recovery history.
65
+ * @example
66
+ * ```ts
67
+ * declare const exhaustion: ScanExhaustion;
68
+ * console.log(exhaustion.exhaustionBasisPoints, exhaustion.effectiveRecoveries);
69
+ * ```
70
+ */
71
+ export interface ScanExhaustion {
72
+ readonly kind: 'client-derived-estimate';
73
+ readonly exhaustionBasisPoints: number;
74
+ readonly effectiveRecoveries: number;
75
+ toJSON(): unknown;
76
+ }
77
+ /** Estimates prospective contact and cargo-selection odds using the fingerprinted client's eligibility rules.
78
+ * Requires explicit research and exhaustion knowledge. This is not full scan-launch readiness:
79
+ * permissions, costs, Fleet state, cooldown, target and recovery capacity are outside this calculation.
80
+ * @example
81
+ * ```ts
82
+ * declare const policy: ScanPatternPolicySnapshot, loot: ScanLootProfileSnapshot;
83
+ * const odds = deriveScanLootOdds(policy, loot, { unlockedResearchTagIds: [], requiredRegionResearchTagIds: [], exhaustionBasisPoints: 0 });
84
+ * ```
85
+ */
86
+ export declare function deriveScanLootOdds(policy: Policy | undefined, profile: Profile | undefined, options: ScanLootOddsOptions): ScanLootOdds;
87
+ /** Estimates a pending signal's recorded draw using its committed rows and contact chance.
88
+ * Revisions AND full fingerprints must match. Current activity, focus and research do not
89
+ * replace committed eligibility; terminal signals are not random forecasts.
90
+ * @example
91
+ * ```ts
92
+ * declare const signal: ScanSignalSnapshot, policy: ScanPatternPolicySnapshot, loot: ScanLootProfileSnapshot;
93
+ * const odds = deriveCommittedScanLootOdds(signal, policy, loot);
94
+ * ```
95
+ */
96
+ export declare function deriveCommittedScanLootOdds(signal: ScanSignalSnapshot | undefined, policy: Policy | undefined, profile: Profile | undefined): ScanLootOdds;
97
+ /** Applies the client exhaustion decay rule with explicit region and Unix seconds, without clock reads.
98
+ * An absent signal means known absence of recovery history, not an unknown/unread signal.
99
+ * Another region, disabled decay or a clock before the last recovery produce zero exhaustion.
100
+ * @example
101
+ * ```ts
102
+ * declare const policy: ScanPatternPolicySnapshot, signal: ScanSignalSnapshot | undefined;
103
+ * const exhaustion = deriveScanExhaustion(policy, signal, { regionId: 3, unixSeconds: 1_790_000_000n });
104
+ * ```
105
+ */
106
+ export declare function deriveScanExhaustion(policy: Policy, signal: ScanSignalSnapshot | undefined, options: Readonly<{
107
+ regionId: number;
108
+ unixSeconds: bigint;
109
+ }>): ScanExhaustion;
110
+ export {};
111
+ //# sourceMappingURL=odds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"odds.d.ts","sourceRoot":"","sources":["../../src/scanning/odds.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,294 @@
1
+ import { InvalidDerivationInputError } from '../client/errors.js';
2
+ import { attachJsonSerialization } from '../internal/json.js';
3
+ import { freezeResolvedSnapshot } from '../internal/resolved-snapshot.js';
4
+ const categories = [
5
+ 'any',
6
+ 'industrial',
7
+ 'technology',
8
+ 'tactical',
9
+ 'exotic',
10
+ ];
11
+ const rarities = [
12
+ 'common',
13
+ 'uncommon',
14
+ 'rare',
15
+ 'epic',
16
+ 'legendary',
17
+ 'anomalous',
18
+ ];
19
+ function finish(value) {
20
+ return freezeResolvedSnapshot(attachJsonSerialization(value));
21
+ }
22
+ function invalid(field, value) {
23
+ throw new InvalidDerivationInputError(field, typeof value === 'number' || typeof value === 'bigint' ? value : NaN, 'Supply valid current scanning snapshots and explicit research, exhaustion and clock inputs before estimating scan loot.');
24
+ }
25
+ function integer(field, value, maximum = 65535) {
26
+ if (!Number.isSafeInteger(value) || value < 0 || value > maximum)
27
+ invalid(field, value);
28
+ }
29
+ function exact(field, value, nonnegative = true) {
30
+ if (typeof value !== 'bigint' || (nonnegative && value < 0n))
31
+ invalid(field, value);
32
+ }
33
+ function tags(field, values) {
34
+ if (!Array.isArray(values))
35
+ invalid(field, values);
36
+ values.forEach((value) => integer(field, value));
37
+ }
38
+ function fingerprint(field, value) {
39
+ if (typeof value !== 'string' || !/^[0-9a-f]{64}$/.test(value))
40
+ invalid(field, value);
41
+ }
42
+ function configurations(policy, profile) {
43
+ const reasons = [];
44
+ if (!policy)
45
+ reasons.push('missing-policy');
46
+ if (!profile)
47
+ reasons.push('missing-loot-profile');
48
+ if (!policy || !profile)
49
+ return reasons;
50
+ if (policy.version !== 0 || profile.version !== 0)
51
+ reasons.push('unsupported-version');
52
+ if (!Number.isInteger(policy.patternId) ||
53
+ policy.patternId < 0 ||
54
+ policy.patternId > 4)
55
+ reasons.push('unsupported-pattern');
56
+ if (profile.loot.length > 64)
57
+ reasons.push('unsupported-loot-layout');
58
+ if (policy.game.address !== profile.game.address)
59
+ reasons.push('game-mismatch');
60
+ fingerprint('policy.contentFingerprint', policy.contentFingerprint);
61
+ fingerprint('lootProfile.contentFingerprint', profile.contentFingerprint);
62
+ integer('policy.revision', policy.revision, 0xffffffff);
63
+ integer('lootProfile.revision', profile.revision, 0xffffffff);
64
+ integer('lootProfile.regionId', profile.regionId);
65
+ for (const row of profile.loot) {
66
+ integer('loot.rollWeight', row.rollWeight, 0xffffffff);
67
+ integer('loot.cargo.id', row.cargo.id);
68
+ }
69
+ return reasons;
70
+ }
71
+ function provenance(policy, profile, signal) {
72
+ return {
73
+ policy: policy && {
74
+ address: policy.address,
75
+ game: { ...policy.game },
76
+ patternId: policy.patternId,
77
+ revision: policy.revision,
78
+ contentFingerprint: policy.contentFingerprint,
79
+ },
80
+ lootProfile: profile && {
81
+ address: profile.address,
82
+ game: { ...profile.game },
83
+ regionId: profile.regionId,
84
+ revision: profile.revision,
85
+ contentFingerprint: profile.contentFingerprint,
86
+ },
87
+ signal: signal && { address: signal.address, sequence: signal.sequence },
88
+ };
89
+ }
90
+ function result(basis, sources, reasons, profile, selected, excludedRows, chance) {
91
+ const base = {
92
+ kind: 'client-derived-estimate',
93
+ basis,
94
+ provenance: sources,
95
+ };
96
+ if (reasons.length)
97
+ return finish({ ...base, status: 'unavailable', reasons });
98
+ const totalWeight = selected.reduce((sum, index) => sum + BigInt(profile.loot[index].rollWeight), 0n);
99
+ if (totalWeight === 0n)
100
+ return finish({
101
+ ...base,
102
+ status: 'unavailable',
103
+ reasons: ['empty-weighted-pool'],
104
+ });
105
+ const shares = (cargo, weight) => ({
106
+ cargo: { ...cargo },
107
+ weight,
108
+ conditionalProbability: Number(weight) / Number(totalWeight),
109
+ perScanProbability: Number(weight * BigInt(chance)) / Number(totalWeight * 10000n),
110
+ });
111
+ const resourceWeights = new Map();
112
+ const eligibleRows = selected.map((rowIndex) => {
113
+ const row = profile.loot[rowIndex];
114
+ const weight = BigInt(row.rollWeight);
115
+ const previous = resourceWeights.get(row.cargo.id);
116
+ resourceWeights.set(row.cargo.id, {
117
+ cargo: row.cargo,
118
+ weight: (previous?.weight ?? 0n) + weight,
119
+ });
120
+ return { rowIndex, ...shares(row.cargo, weight) };
121
+ });
122
+ return finish({
123
+ ...base,
124
+ status: 'available',
125
+ totalWeight,
126
+ contactChanceBasisPoints: chance,
127
+ contactProbability: chance / 10000,
128
+ noContactProbability: (10000 - chance) / 10000,
129
+ eligibleRows,
130
+ excludedRows,
131
+ resources: [...resourceWeights.values()].map(({ cargo, weight }) => shares(cargo, weight)),
132
+ });
133
+ }
134
+ /** Estimates prospective contact and cargo-selection odds using the fingerprinted client's eligibility rules.
135
+ * Requires explicit research and exhaustion knowledge. This is not full scan-launch readiness:
136
+ * permissions, costs, Fleet state, cooldown, target and recovery capacity are outside this calculation.
137
+ * @example
138
+ * ```ts
139
+ * declare const policy: ScanPatternPolicySnapshot, loot: ScanLootProfileSnapshot;
140
+ * const odds = deriveScanLootOdds(policy, loot, { unlockedResearchTagIds: [], requiredRegionResearchTagIds: [], exhaustionBasisPoints: 0 });
141
+ * ```
142
+ */
143
+ export function deriveScanLootOdds(policy, profile, options) {
144
+ integer('exhaustionBasisPoints', options.exhaustionBasisPoints, 10000);
145
+ tags('unlockedResearchTagIds', options.unlockedResearchTagIds);
146
+ tags('requiredRegionResearchTagIds', options.requiredRegionResearchTagIds);
147
+ const focus = options.focus ?? 'any';
148
+ if (!categories.includes(focus))
149
+ invalid('focus', focus);
150
+ const reasons = configurations(policy, profile);
151
+ const sources = provenance(policy, profile);
152
+ if (reasons.length)
153
+ return result('prospective', sources, reasons, profile, [], [], 0);
154
+ const p = policy, l = profile;
155
+ integer('policy.contactChanceBasisPoints', p.contactChanceBasisPoints, 10000);
156
+ exact('policy.valueBudgetRaw', p.valueBudgetRaw);
157
+ integer('lootProfile.riskValueMultiplierBasisPoints', l.riskValueMultiplierBasisPoints, 65535);
158
+ tags('policy.requiredResearchTagIds', p.requiredResearchTagIds);
159
+ if (!rarities.includes(p.maximumRarity))
160
+ invalid('policy.maximumRarity', p.maximumRarity);
161
+ if (!Array.isArray(p.allowedFocusCategories) ||
162
+ p.allowedFocusCategories.some((category) => !categories.includes(category)))
163
+ invalid('policy.allowedFocusCategories', p.allowedFocusCategories);
164
+ if (p.status !== 'active')
165
+ reasons.push('inactive-policy');
166
+ if (l.status !== 'active')
167
+ reasons.push('inactive-loot-profile');
168
+ const unlocked = new Set(options.unlockedResearchTagIds);
169
+ if (!p.requiredResearchTagIds.every((tag) => unlocked.has(tag)))
170
+ reasons.push('pattern-research-locked');
171
+ if (!options.requiredRegionResearchTagIds.every((tag) => unlocked.has(tag)))
172
+ reasons.push('region-research-locked');
173
+ if (focus !== 'any' && !p.allowedFocusCategories.includes(focus))
174
+ reasons.push('focus-not-allowed');
175
+ const budget = (p.valueBudgetRaw * BigInt(l.riskValueMultiplierBasisPoints)) / 10000n;
176
+ const selected = [], excluded = [];
177
+ l.loot.forEach((row, rowIndex) => {
178
+ integer('loot.valueUnits', row.valueUnits);
179
+ tags('loot.supportedPatternIds', row.supportedPatternIds);
180
+ tags('loot.requiredResearchTagIds', row.requiredResearchTagIds);
181
+ if (!rarities.includes(row.rarity))
182
+ invalid('loot.rarity', row.rarity);
183
+ if (!categories.includes(row.category))
184
+ invalid('loot.category', row.category);
185
+ const exclusions = [];
186
+ if (!row.supportedPatternIds.includes(p.patternId))
187
+ exclusions.push('pattern');
188
+ if (rarities.indexOf(row.rarity) > rarities.indexOf(p.maximumRarity))
189
+ exclusions.push('rarity');
190
+ if (BigInt(row.valueUnits) > budget)
191
+ exclusions.push('value-budget');
192
+ if (focus !== 'any' && row.category !== 'any' && row.category !== focus)
193
+ exclusions.push('focus');
194
+ if (!row.requiredResearchTagIds.every((tag) => unlocked.has(tag)))
195
+ exclusions.push('research');
196
+ if (exclusions.length)
197
+ excluded.push({ rowIndex, reasons: exclusions });
198
+ else
199
+ selected.push(rowIndex);
200
+ });
201
+ const chance = Math.floor((p.contactChanceBasisPoints * (10000 - options.exhaustionBasisPoints)) /
202
+ 10000);
203
+ return result('prospective', sources, reasons, l, selected, excluded, chance);
204
+ }
205
+ /** Estimates a pending signal's recorded draw using its committed rows and contact chance.
206
+ * Revisions AND full fingerprints must match. Current activity, focus and research do not
207
+ * replace committed eligibility; terminal signals are not random forecasts.
208
+ * @example
209
+ * ```ts
210
+ * declare const signal: ScanSignalSnapshot, policy: ScanPatternPolicySnapshot, loot: ScanLootProfileSnapshot;
211
+ * const odds = deriveCommittedScanLootOdds(signal, policy, loot);
212
+ * ```
213
+ */
214
+ export function deriveCommittedScanLootOdds(signal, policy, profile) {
215
+ const reasons = configurations(policy, profile), sources = provenance(policy, profile, signal);
216
+ if (signal?.status !== 'pending-entropy')
217
+ reasons.push('signal-not-pending');
218
+ if (signal !== undefined &&
219
+ signal.version !== 0 &&
220
+ !reasons.includes('unsupported-version'))
221
+ reasons.push('unsupported-version');
222
+ if (reasons.length)
223
+ return result('committed', sources, reasons, profile, [], [], 0);
224
+ const attempt = signal.attempt;
225
+ if (!attempt)
226
+ invalid('signal.attempt', attempt);
227
+ fingerprint('attempt.policyContentFingerprint', attempt.policyContentFingerprint);
228
+ fingerprint('attempt.lootProfileContentFingerprint', attempt.lootProfileContentFingerprint);
229
+ if (signal.game.address !== policy.game.address ||
230
+ attempt.patternId !== policy.patternId ||
231
+ attempt.regionId !== profile.regionId ||
232
+ attempt.policyRevision !== policy.revision ||
233
+ attempt.lootProfileRevision !== profile.revision ||
234
+ attempt.policyContentFingerprint !== policy.contentFingerprint ||
235
+ attempt.lootProfileContentFingerprint !== profile.contentFingerprint)
236
+ return result('committed', sources, ['committed-configuration-mismatch'], profile, [], [], 0);
237
+ integer('attempt.contactChanceBasisPoints', attempt.contactChanceBasisPoints, 10000);
238
+ if (!Array.isArray(attempt.eligibleLootRowIndexes))
239
+ invalid('attempt.eligibleLootRowIndexes', attempt.eligibleLootRowIndexes);
240
+ const selected = new Set();
241
+ for (const index of attempt.eligibleLootRowIndexes) {
242
+ integer('attempt.eligibleLootRowIndexes', index, profile.loot.length - 1);
243
+ if (selected.has(index))
244
+ invalid('attempt.eligibleLootRowIndexes', index);
245
+ selected.add(index);
246
+ }
247
+ const excluded = profile.loot.flatMap((_, rowIndex) => selected.has(rowIndex)
248
+ ? []
249
+ : [{ rowIndex, reasons: ['not-committed'] }]);
250
+ return result('committed', sources, reasons, profile, [...selected], excluded, attempt.contactChanceBasisPoints);
251
+ }
252
+ /** Applies the client exhaustion decay rule with explicit region and Unix seconds, without clock reads.
253
+ * An absent signal means known absence of recovery history, not an unknown/unread signal.
254
+ * Another region, disabled decay or a clock before the last recovery produce zero exhaustion.
255
+ * @example
256
+ * ```ts
257
+ * declare const policy: ScanPatternPolicySnapshot, signal: ScanSignalSnapshot | undefined;
258
+ * const exhaustion = deriveScanExhaustion(policy, signal, { regionId: 3, unixSeconds: 1_790_000_000n });
259
+ * ```
260
+ */
261
+ export function deriveScanExhaustion(policy, signal, options) {
262
+ integer('regionId', options.regionId);
263
+ exact('unixSeconds', options.unixSeconds, false);
264
+ integer('policy.exhaustionPerRecoveryBasisPoints', policy.exhaustionPerRecoveryBasisPoints, 10000);
265
+ integer('policy.maximumExhaustionBasisPoints', policy.maximumExhaustionBasisPoints, 10000);
266
+ integer('policy.exhaustionDecaySeconds', policy.exhaustionDecaySeconds, 0xffffffff);
267
+ if (policy.version !== 0 ||
268
+ (signal !== undefined &&
269
+ (signal.version !== 0 || signal.game.address !== policy.game.address)))
270
+ invalid('scanning.versionOrGame', policy.version);
271
+ let effectiveRecoveries = 0;
272
+ if (signal !== undefined) {
273
+ const history = signal.recoveryHistory;
274
+ if (!history)
275
+ invalid('signal.recoveryHistory', history);
276
+ integer('recoveryHistory.lastRegionId', history.lastRegionId);
277
+ integer('recoveryHistory.consecutiveRecoveries', history.consecutiveRecoveries, 65535);
278
+ exact('recoveryHistory.lastRecoveryAtUnixSeconds', history.lastRecoveryAtUnixSeconds, false);
279
+ if (history.lastRegionId === options.regionId &&
280
+ policy.exhaustionDecaySeconds > 0 &&
281
+ options.unixSeconds >= history.lastRecoveryAtUnixSeconds) {
282
+ const decay = (options.unixSeconds - history.lastRecoveryAtUnixSeconds) /
283
+ BigInt(policy.exhaustionDecaySeconds);
284
+ const remaining = BigInt(history.consecutiveRecoveries) - decay;
285
+ effectiveRecoveries = remaining > 0n ? Number(remaining) : 0;
286
+ }
287
+ }
288
+ return finish({
289
+ kind: 'client-derived-estimate',
290
+ effectiveRecoveries,
291
+ exhaustionBasisPoints: Math.min(effectiveRecoveries * policy.exhaustionPerRecoveryBasisPoints, policy.maximumExhaustionBasisPoints),
292
+ });
293
+ }
294
+ //# sourceMappingURL=odds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"odds.js","sourceRoot":"","sources":["../../src/scanning/odds.ts"],"names":[],"mappings":"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"}
@@ -47,7 +47,7 @@ export type ScanSignalSnapshot = Immutable<Base<Omit<ScanSignalData, 'fleet' | '
47
47
  receipt: CargoRow<NonNullable<ScanSignalData['receipt']>> | undefined;
48
48
  }>;
49
49
  /** Current scan policy parameters. Basis points use 10,000 = 100%; XP stays exact raw units.
50
- * This focused projection intentionally omits value-budget and focus-mask fields.
50
+ * Value budgets and permitted focus categories support client-derived estimates.
51
51
  * @example
52
52
  * ```ts
53
53
  * declare const policy: ScanPatternPolicySnapshot;
@@ -58,7 +58,7 @@ export type ScanPatternPolicySnapshot = Immutable<Base<ScanPatternPolicyData> &
58
58
  kind: 'scanPatternPolicy';
59
59
  }>;
60
60
  /** Regional loot configuration, not a reward forecast. Weights are relative integers.
61
- * Quantity modes, pattern masks and value-budget eligibility are intentionally not projected.
61
+ * Pattern eligibility is translated to IDs; opaque quantity modes remain unprojected.
62
62
  * @example
63
63
  * ```ts
64
64
  * declare const profile: ScanLootProfileSnapshot;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aephia/atlas-kit",
3
- "version": "0.6.0-next.60",
3
+ "version": "0.6.0-next.62",
4
4
  "description": "Community-maintained non-custodial TypeScript SDK for Star Atlas SAGE C4.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Aephia contributors",