@idlekit/cli 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/main.js +762 -386
- package/dist/main.js.map +21 -16
- package/dist/runtime/workers/entry.js +365 -7
- package/dist/runtime/workers/entry.js.map +12 -9
- package/package.json +2 -2
|
@@ -8198,7 +8198,7 @@ var init_validate = __esm(() => {
|
|
|
8198
8198
|
OFFLINE_ACTORS = new Set(["player", "automation"]);
|
|
8199
8199
|
});
|
|
8200
8200
|
|
|
8201
|
-
// ../../node_modules/.bun/typia@
|
|
8201
|
+
// ../../node_modules/.bun/typia@15.1.0+367f7514c87f1df1/node_modules/typia/lib/internal/_validateReport.mjs
|
|
8202
8202
|
var _validateReport = (array) => {
|
|
8203
8203
|
const isAncestor = (ancestor, descendant) => descendant === ancestor || descendant.startsWith(`${ancestor}.`) || descendant.startsWith(`${ancestor}[`);
|
|
8204
8204
|
const reportable = (path) => {
|
|
@@ -8223,7 +8223,7 @@ var _validateReport = (array) => {
|
|
|
8223
8223
|
};
|
|
8224
8224
|
var init__validateReport = () => {};
|
|
8225
8225
|
|
|
8226
|
-
// ../../node_modules/.bun/typia@
|
|
8226
|
+
// ../../node_modules/.bun/typia@15.1.0+367f7514c87f1df1/node_modules/typia/lib/internal/_createStandardSchema.mjs
|
|
8227
8227
|
var _createStandardSchema = (fn) => Object.assign(fn, { "~standard": {
|
|
8228
8228
|
version: 1,
|
|
8229
8229
|
vendor: "typia",
|
|
@@ -18125,7 +18125,7 @@ var init_checks3 = __esm(() => {
|
|
|
18125
18125
|
FAIL_ON = ["error", "warn", "inconclusive", "unsupported"];
|
|
18126
18126
|
});
|
|
18127
18127
|
|
|
18128
|
-
// ../../node_modules/.bun/typia@
|
|
18128
|
+
// ../../node_modules/.bun/typia@15.1.0+367f7514c87f1df1/node_modules/typia/lib/internal/_accessExpressionAsString.mjs
|
|
18129
18129
|
var _accessExpressionAsString = (str) => variable(str) ? `.${str}` : `[${JSON.stringify(str)}]`, variable = (str) => reserved(str) === false && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/g.test(str), reserved = (str) => RESERVED.has(str), RESERVED;
|
|
18130
18130
|
var init__accessExpressionAsString = __esm(() => {
|
|
18131
18131
|
RESERVED = /* @__PURE__ */ new Set([
|
|
@@ -18672,7 +18672,7 @@ var init_judge = __esm(() => {
|
|
|
18672
18672
|
// ../core/dist/sim/analysis/flow.js
|
|
18673
18673
|
var init_flow = () => {};
|
|
18674
18674
|
|
|
18675
|
-
// ../../node_modules/.bun/typia@
|
|
18675
|
+
// ../../node_modules/.bun/typia@15.1.0+367f7514c87f1df1/node_modules/typia/lib/internal/_isTypeUint32.mjs
|
|
18676
18676
|
var _isTypeUint32 = (value) => Math.floor(value) === value && MINIMUM <= value && value <= MAXIMUM, MINIMUM = 0, MAXIMUM;
|
|
18677
18677
|
var init__isTypeUint32 = __esm(() => {
|
|
18678
18678
|
MAXIMUM = 2 ** 32 - 1;
|
|
@@ -19020,6 +19020,363 @@ var init_jevAdvisory = __esm(() => {
|
|
|
19020
19020
|
init__createStandardSchema();
|
|
19021
19021
|
});
|
|
19022
19022
|
|
|
19023
|
+
// ../core/dist/ltv/projection.js
|
|
19024
|
+
function clamp012(v) {
|
|
19025
|
+
if (v < 0)
|
|
19026
|
+
return 0;
|
|
19027
|
+
if (v > 1)
|
|
19028
|
+
return 1;
|
|
19029
|
+
return v;
|
|
19030
|
+
}
|
|
19031
|
+
function deriveMonetizationConfig(scenario) {
|
|
19032
|
+
const m = scenario.monetization;
|
|
19033
|
+
const q = (m?.uncertainty?.quantiles ?? [0.5, 0.9]).filter((x) => typeof x === "number");
|
|
19034
|
+
const quantiles = q.length > 0 ? [...new Set(q)].sort((a, b) => a - b) : [0.5, 0.9];
|
|
19035
|
+
return {
|
|
19036
|
+
cohorts: {
|
|
19037
|
+
baseUsers: m?.cohorts?.baseUsers ?? 1
|
|
19038
|
+
},
|
|
19039
|
+
retention: {
|
|
19040
|
+
d1: m?.retention?.d1 ?? 0.42,
|
|
19041
|
+
d7: m?.retention?.d7 ?? 0.2,
|
|
19042
|
+
d30: m?.retention?.d30 ?? 0.09,
|
|
19043
|
+
d90: m?.retention?.d90 ?? 0.04,
|
|
19044
|
+
longTailDailyDecay: m?.retention?.longTailDailyDecay ?? 0.02
|
|
19045
|
+
},
|
|
19046
|
+
revenue: {
|
|
19047
|
+
payerConversion: m?.revenue?.payerConversion ?? 0.03,
|
|
19048
|
+
arppuDaily: m?.revenue?.arppuDaily ?? 0.7,
|
|
19049
|
+
adArpDau: m?.revenue?.adArpDau ?? 0.02,
|
|
19050
|
+
platformFeeRate: m?.revenue?.platformFeeRate ?? 0.3,
|
|
19051
|
+
grossMarginRate: m?.revenue?.grossMarginRate ?? 0.92,
|
|
19052
|
+
progressionRevenueLift: m?.revenue?.progressionRevenueLift ?? 0.4,
|
|
19053
|
+
progressionLogSpan: m?.revenue?.progressionLogSpan ?? 6
|
|
19054
|
+
},
|
|
19055
|
+
acquisition: {
|
|
19056
|
+
cpi: m?.acquisition?.cpi ?? 0
|
|
19057
|
+
},
|
|
19058
|
+
uncertainty: {
|
|
19059
|
+
enabled: m?.uncertainty?.enabled ?? false,
|
|
19060
|
+
draws: m?.uncertainty?.draws ?? 300,
|
|
19061
|
+
quantiles,
|
|
19062
|
+
seed: m?.uncertainty?.seed,
|
|
19063
|
+
sigma: {
|
|
19064
|
+
retention: m?.uncertainty?.sigma?.retention ?? 0.08,
|
|
19065
|
+
conversion: m?.uncertainty?.sigma?.conversion ?? 0.12,
|
|
19066
|
+
arppu: m?.uncertainty?.sigma?.arppu ?? 0.2,
|
|
19067
|
+
ad: m?.uncertainty?.sigma?.ad ?? 0.15
|
|
19068
|
+
},
|
|
19069
|
+
correlation: {
|
|
19070
|
+
retentionConversion: m?.uncertainty?.correlation?.retentionConversion ?? 0,
|
|
19071
|
+
retentionArppu: m?.uncertainty?.correlation?.retentionArppu ?? 0,
|
|
19072
|
+
retentionAd: m?.uncertainty?.correlation?.retentionAd ?? 0,
|
|
19073
|
+
conversionArppu: m?.uncertainty?.correlation?.conversionArppu ?? 0,
|
|
19074
|
+
conversionAd: m?.uncertainty?.correlation?.conversionAd ?? 0,
|
|
19075
|
+
arppuAd: m?.uncertainty?.correlation?.arppuAd ?? 0
|
|
19076
|
+
}
|
|
19077
|
+
}
|
|
19078
|
+
};
|
|
19079
|
+
}
|
|
19080
|
+
function retentionAtDay(ret, day) {
|
|
19081
|
+
if (day <= 0)
|
|
19082
|
+
return 1;
|
|
19083
|
+
if (day <= 1)
|
|
19084
|
+
return ret.d1;
|
|
19085
|
+
if (day <= 7)
|
|
19086
|
+
return ret.d1 + (ret.d7 - ret.d1) * (day - 1) / 6;
|
|
19087
|
+
if (day <= 30)
|
|
19088
|
+
return ret.d7 + (ret.d30 - ret.d7) * (day - 7) / 23;
|
|
19089
|
+
if (day <= 90)
|
|
19090
|
+
return ret.d30 + (ret.d90 - ret.d30) * (day - 30) / 60;
|
|
19091
|
+
const extra = day - 90;
|
|
19092
|
+
return clamp012(ret.d90 * Math.exp(-ret.longTailDailyDecay * extra));
|
|
19093
|
+
}
|
|
19094
|
+
function progressionFactor(startWorthLog10, endWorthLog10, span) {
|
|
19095
|
+
if (!Number.isFinite(startWorthLog10) || !Number.isFinite(endWorthLog10) || !Number.isFinite(span) || span <= 0) {
|
|
19096
|
+
return 0;
|
|
19097
|
+
}
|
|
19098
|
+
return clamp012((endWorthLog10 - startWorthLog10) / span);
|
|
19099
|
+
}
|
|
19100
|
+
function estimateLtvPerUser(args) {
|
|
19101
|
+
const { config, horizonDays } = args;
|
|
19102
|
+
const progression = clamp012(args.progression);
|
|
19103
|
+
const arppuDaily = config.revenue.arppuDaily * (1 + progression * config.revenue.progressionRevenueLift);
|
|
19104
|
+
const adArpDau = config.revenue.adArpDau * (1 + progression * config.revenue.progressionRevenueLift * 0.5);
|
|
19105
|
+
const payerConversion = config.revenue.payerConversion;
|
|
19106
|
+
const fullDays = Math.floor(Math.max(0, horizonDays));
|
|
19107
|
+
const remainder = Math.max(0, horizonDays - fullDays);
|
|
19108
|
+
let gross = 0;
|
|
19109
|
+
for (let day = 1;day <= fullDays; day++) {
|
|
19110
|
+
const active = retentionAtDay(config.retention, day);
|
|
19111
|
+
gross += active * (payerConversion * arppuDaily + adArpDau);
|
|
19112
|
+
}
|
|
19113
|
+
if (remainder > 0) {
|
|
19114
|
+
const active = retentionAtDay(config.retention, fullDays + 1);
|
|
19115
|
+
gross += remainder * active * (payerConversion * arppuDaily + adArpDau);
|
|
19116
|
+
}
|
|
19117
|
+
const net = gross * (1 - config.revenue.platformFeeRate) * config.revenue.grossMarginRate;
|
|
19118
|
+
const ltv = net - config.acquisition.cpi;
|
|
19119
|
+
return {
|
|
19120
|
+
cumulativeGrossRevenuePerUser: gross,
|
|
19121
|
+
cumulativeNetRevenuePerUser: net,
|
|
19122
|
+
cumulativeLtvPerUser: ltv
|
|
19123
|
+
};
|
|
19124
|
+
}
|
|
19125
|
+
|
|
19126
|
+
// ../core/dist/ltv/uncertainty.js
|
|
19127
|
+
function clamp013(v) {
|
|
19128
|
+
if (v < 0)
|
|
19129
|
+
return 0;
|
|
19130
|
+
if (v > 1)
|
|
19131
|
+
return 1;
|
|
19132
|
+
return v;
|
|
19133
|
+
}
|
|
19134
|
+
function clampCorrelation(v) {
|
|
19135
|
+
if (!Number.isFinite(v))
|
|
19136
|
+
return 0;
|
|
19137
|
+
if (v < -1)
|
|
19138
|
+
return -1;
|
|
19139
|
+
if (v > 1)
|
|
19140
|
+
return 1;
|
|
19141
|
+
return v;
|
|
19142
|
+
}
|
|
19143
|
+
function randNormal(rng) {
|
|
19144
|
+
const u1 = Math.max(0.000000000001, rng());
|
|
19145
|
+
const u2 = Math.max(0.000000000001, rng());
|
|
19146
|
+
return Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
|
|
19147
|
+
}
|
|
19148
|
+
function buildCorrelationMatrix(base) {
|
|
19149
|
+
const rc = clampCorrelation(base.retentionConversion);
|
|
19150
|
+
const ra = clampCorrelation(base.retentionArppu);
|
|
19151
|
+
const rd = clampCorrelation(base.retentionAd);
|
|
19152
|
+
const ca = clampCorrelation(base.conversionArppu);
|
|
19153
|
+
const cd = clampCorrelation(base.conversionAd);
|
|
19154
|
+
const ad = clampCorrelation(base.arppuAd);
|
|
19155
|
+
return [
|
|
19156
|
+
[1, rc, ra, rd],
|
|
19157
|
+
[rc, 1, ca, cd],
|
|
19158
|
+
[ra, ca, 1, ad],
|
|
19159
|
+
[rd, cd, ad, 1]
|
|
19160
|
+
];
|
|
19161
|
+
}
|
|
19162
|
+
function withOffDiagonalScale(matrix, alpha) {
|
|
19163
|
+
return matrix.map((row, i) => row.map((v, j) => {
|
|
19164
|
+
if (i === j)
|
|
19165
|
+
return 1;
|
|
19166
|
+
return v * alpha;
|
|
19167
|
+
}));
|
|
19168
|
+
}
|
|
19169
|
+
function cholesky4(matrix) {
|
|
19170
|
+
const n = 4;
|
|
19171
|
+
const l = Array.from({ length: n }, () => Array.from({ length: n }, () => 0));
|
|
19172
|
+
for (let i = 0;i < n; i++) {
|
|
19173
|
+
for (let j = 0;j <= i; j++) {
|
|
19174
|
+
let sum = 0;
|
|
19175
|
+
for (let k = 0;k < j; k++) {
|
|
19176
|
+
sum += (l[i]?.[k] ?? 0) * (l[j]?.[k] ?? 0);
|
|
19177
|
+
}
|
|
19178
|
+
if (i === j) {
|
|
19179
|
+
const val = (matrix[i]?.[i] ?? 0) - sum;
|
|
19180
|
+
if (val <= 0.000000001)
|
|
19181
|
+
return null;
|
|
19182
|
+
l[i][j] = Math.sqrt(val);
|
|
19183
|
+
} else {
|
|
19184
|
+
const denom = l[j]?.[j] ?? 0;
|
|
19185
|
+
if (Math.abs(denom) < 0.000000001)
|
|
19186
|
+
return null;
|
|
19187
|
+
l[i][j] = ((matrix[i]?.[j] ?? 0) - sum) / denom;
|
|
19188
|
+
}
|
|
19189
|
+
}
|
|
19190
|
+
}
|
|
19191
|
+
return l;
|
|
19192
|
+
}
|
|
19193
|
+
function multiplyLowerTriangular(l, z) {
|
|
19194
|
+
const out = [0, 0, 0, 0];
|
|
19195
|
+
for (let i = 0;i < 4; i++) {
|
|
19196
|
+
let sum = 0;
|
|
19197
|
+
for (let j = 0;j <= i; j++) {
|
|
19198
|
+
sum += (l[i]?.[j] ?? 0) * (z[j] ?? 0);
|
|
19199
|
+
}
|
|
19200
|
+
out[i] = sum;
|
|
19201
|
+
}
|
|
19202
|
+
return out;
|
|
19203
|
+
}
|
|
19204
|
+
function sampleCorrelatedNormals(rng, corr) {
|
|
19205
|
+
const z = [randNormal(rng), randNormal(rng), randNormal(rng), randNormal(rng)];
|
|
19206
|
+
const matrix = buildCorrelationMatrix(corr);
|
|
19207
|
+
let l = cholesky4(matrix);
|
|
19208
|
+
let alpha = 0.99;
|
|
19209
|
+
while (!l && alpha > 0.000001) {
|
|
19210
|
+
l = cholesky4(withOffDiagonalScale(matrix, alpha));
|
|
19211
|
+
alpha *= 0.8;
|
|
19212
|
+
}
|
|
19213
|
+
if (!l) {
|
|
19214
|
+
return {
|
|
19215
|
+
retention: z[0] ?? 0,
|
|
19216
|
+
conversion: z[1] ?? 0,
|
|
19217
|
+
arppu: z[2] ?? 0,
|
|
19218
|
+
ad: z[3] ?? 0
|
|
19219
|
+
};
|
|
19220
|
+
}
|
|
19221
|
+
const c = multiplyLowerTriangular(l, z);
|
|
19222
|
+
return {
|
|
19223
|
+
retention: c[0] ?? 0,
|
|
19224
|
+
conversion: c[1] ?? 0,
|
|
19225
|
+
arppu: c[2] ?? 0,
|
|
19226
|
+
ad: c[3] ?? 0
|
|
19227
|
+
};
|
|
19228
|
+
}
|
|
19229
|
+
function applyLogNormalShock(mean, sigma, z) {
|
|
19230
|
+
if (sigma <= 0)
|
|
19231
|
+
return mean;
|
|
19232
|
+
return mean * Math.exp(sigma * z - 0.5 * sigma * sigma);
|
|
19233
|
+
}
|
|
19234
|
+
function makeUncertainConfig(base, rng) {
|
|
19235
|
+
const shock = sampleCorrelatedNormals(rng, base.uncertainty.correlation);
|
|
19236
|
+
const d1 = clamp013(applyLogNormalShock(base.retention.d1, base.uncertainty.sigma.retention, shock.retention));
|
|
19237
|
+
const d7 = Math.min(d1, clamp013(applyLogNormalShock(base.retention.d7, base.uncertainty.sigma.retention, shock.retention)));
|
|
19238
|
+
const d30 = Math.min(d7, clamp013(applyLogNormalShock(base.retention.d30, base.uncertainty.sigma.retention, shock.retention)));
|
|
19239
|
+
const d90 = Math.min(d30, clamp013(applyLogNormalShock(base.retention.d90, base.uncertainty.sigma.retention, shock.retention)));
|
|
19240
|
+
return {
|
|
19241
|
+
...base,
|
|
19242
|
+
retention: {
|
|
19243
|
+
...base.retention,
|
|
19244
|
+
d1,
|
|
19245
|
+
d7,
|
|
19246
|
+
d30,
|
|
19247
|
+
d90
|
|
19248
|
+
},
|
|
19249
|
+
revenue: {
|
|
19250
|
+
...base.revenue,
|
|
19251
|
+
payerConversion: clamp013(applyLogNormalShock(base.revenue.payerConversion, base.uncertainty.sigma.conversion, shock.conversion)),
|
|
19252
|
+
arppuDaily: Math.max(0, applyLogNormalShock(base.revenue.arppuDaily, base.uncertainty.sigma.arppu, shock.arppu)),
|
|
19253
|
+
adArpDau: Math.max(0, applyLogNormalShock(base.revenue.adArpDau, base.uncertainty.sigma.ad, shock.ad))
|
|
19254
|
+
}
|
|
19255
|
+
};
|
|
19256
|
+
}
|
|
19257
|
+
function quantileFromSorted(sorted, q) {
|
|
19258
|
+
if (sorted.length === 0)
|
|
19259
|
+
return 0;
|
|
19260
|
+
const idx = Math.max(0, Math.min(sorted.length - 1, Math.floor((sorted.length - 1) * q)));
|
|
19261
|
+
return sorted[idx] ?? 0;
|
|
19262
|
+
}
|
|
19263
|
+
function estimateLtvDistribution(args) {
|
|
19264
|
+
const rng = mulberry32(args.seed);
|
|
19265
|
+
const grossSamples = [];
|
|
19266
|
+
const netSamples = [];
|
|
19267
|
+
const ltvSamples = [];
|
|
19268
|
+
const draws = Math.max(1, args.draws);
|
|
19269
|
+
for (let i = 0;i < draws; i++) {
|
|
19270
|
+
const sampled = makeUncertainConfig(args.config, rng);
|
|
19271
|
+
const point = estimateLtvPerUser({
|
|
19272
|
+
config: sampled,
|
|
19273
|
+
horizonDays: args.horizonDays,
|
|
19274
|
+
progression: args.progression
|
|
19275
|
+
});
|
|
19276
|
+
grossSamples.push(point.cumulativeGrossRevenuePerUser);
|
|
19277
|
+
netSamples.push(point.cumulativeNetRevenuePerUser);
|
|
19278
|
+
ltvSamples.push(point.cumulativeLtvPerUser);
|
|
19279
|
+
}
|
|
19280
|
+
const avg = (arr) => arr.reduce((a, b) => a + b, 0) / Math.max(1, arr.length);
|
|
19281
|
+
const sortedLtv = [...ltvSamples].sort((a, b) => a - b);
|
|
19282
|
+
const byQuantile = {};
|
|
19283
|
+
for (const q of args.quantiles) {
|
|
19284
|
+
byQuantile[`q${Math.round(q * 100)}`] = quantileFromSorted(sortedLtv, q);
|
|
19285
|
+
}
|
|
19286
|
+
return {
|
|
19287
|
+
mean: {
|
|
19288
|
+
cumulativeGrossRevenuePerUser: avg(grossSamples),
|
|
19289
|
+
cumulativeNetRevenuePerUser: avg(netSamples),
|
|
19290
|
+
cumulativeLtvPerUser: avg(ltvSamples)
|
|
19291
|
+
},
|
|
19292
|
+
quantiles: byQuantile
|
|
19293
|
+
};
|
|
19294
|
+
}
|
|
19295
|
+
var init_uncertainty = () => {};
|
|
19296
|
+
|
|
19297
|
+
// ../core/dist/ltv/public.js
|
|
19298
|
+
function assertMonetization(monetization) {
|
|
19299
|
+
const valid = validateScenarioV1({
|
|
19300
|
+
schemaVersion: 1,
|
|
19301
|
+
unit: { code: "LTV" },
|
|
19302
|
+
policy: { mode: "drop" },
|
|
19303
|
+
model: { id: "ltv-input", version: 1 },
|
|
19304
|
+
initial: { wallet: { unit: "LTV", amount: "0" } },
|
|
19305
|
+
clock: { stepSec: 1, durationSec: 1 },
|
|
19306
|
+
monetization
|
|
19307
|
+
});
|
|
19308
|
+
if (!valid.ok)
|
|
19309
|
+
throw new RangeError(valid.issues.map((issue) => issue.message).join("; "));
|
|
19310
|
+
}
|
|
19311
|
+
function assertQuantileValues(quantiles) {
|
|
19312
|
+
if (quantiles.length === 0)
|
|
19313
|
+
throw new RangeError("quantiles must be nonempty and in 0..1");
|
|
19314
|
+
for (const q of quantiles) {
|
|
19315
|
+
if (!Number.isFinite(q) || q < 0 || q > 1)
|
|
19316
|
+
throw new RangeError("quantiles must be nonempty and in 0..1");
|
|
19317
|
+
}
|
|
19318
|
+
}
|
|
19319
|
+
function assertConfig(config) {
|
|
19320
|
+
const { retention, ...other } = config;
|
|
19321
|
+
for (const day of ["d1", "d7", "d30", "d90"]) {
|
|
19322
|
+
if (!Number.isFinite(retention[day]) || retention[day] < 0 || retention[day] > 1) {
|
|
19323
|
+
throw new RangeError(`retention.${day} must be finite and in 0..1`);
|
|
19324
|
+
}
|
|
19325
|
+
}
|
|
19326
|
+
if (!Number.isFinite(retention.longTailDailyDecay) || retention.longTailDailyDecay < 0) {
|
|
19327
|
+
throw new RangeError("retention.longTailDailyDecay must be finite and >= 0");
|
|
19328
|
+
}
|
|
19329
|
+
const { quantiles, ...uncertainty } = other.uncertainty;
|
|
19330
|
+
assertQuantileValues(quantiles);
|
|
19331
|
+
assertMonetization({ ...other, uncertainty });
|
|
19332
|
+
}
|
|
19333
|
+
function deriveMonetizationConfig2(scenario) {
|
|
19334
|
+
assertMonetization(scenario.monetization ?? {});
|
|
19335
|
+
const config = deriveMonetizationConfig(scenario);
|
|
19336
|
+
assertConfig(config);
|
|
19337
|
+
return config;
|
|
19338
|
+
}
|
|
19339
|
+
function assertPoint(args) {
|
|
19340
|
+
assertConfig(args.config);
|
|
19341
|
+
if (!Number.isFinite(args.horizonDays) || args.horizonDays < 0 || args.horizonDays > 36500) {
|
|
19342
|
+
throw new RangeError("horizonDays must be finite and in 0..36500");
|
|
19343
|
+
}
|
|
19344
|
+
if (!Number.isFinite(args.progression))
|
|
19345
|
+
throw new RangeError("progression must be finite");
|
|
19346
|
+
}
|
|
19347
|
+
function finiteResult(result) {
|
|
19348
|
+
if (!Object.values(result).every((value) => typeof value === "number" && Number.isFinite(value))) {
|
|
19349
|
+
throw new RangeError("LTV calculation overflowed; reduce the input magnitudes");
|
|
19350
|
+
}
|
|
19351
|
+
return result;
|
|
19352
|
+
}
|
|
19353
|
+
function estimateLtvPerUser2(args) {
|
|
19354
|
+
assertPoint(args);
|
|
19355
|
+
return finiteResult(estimateLtvPerUser(args));
|
|
19356
|
+
}
|
|
19357
|
+
function estimateLtvDistribution2(args) {
|
|
19358
|
+
assertPoint(args);
|
|
19359
|
+
if (!Number.isSafeInteger(args.draws) || args.draws < 1 || args.draws > 1e5 || args.draws * Math.max(1, Math.ceil(args.horizonDays)) > 1e7) {
|
|
19360
|
+
throw new RangeError("draws must be 1..100000 and draws \xD7 ceil(horizonDays) at most 10000000");
|
|
19361
|
+
}
|
|
19362
|
+
if (!Number.isFinite(args.seed))
|
|
19363
|
+
throw new RangeError("seed must be finite");
|
|
19364
|
+
if (args.quantiles.length > 101)
|
|
19365
|
+
throw new RangeError("quantiles exceed the 101 distinct percent keys");
|
|
19366
|
+
assertQuantileValues(args.quantiles);
|
|
19367
|
+
if (new Set(args.quantiles.map((q) => Math.round(q * 100))).size !== args.quantiles.length) {
|
|
19368
|
+
throw new RangeError("quantiles must be nonempty, in 0..1 and have distinct rounded percent keys");
|
|
19369
|
+
}
|
|
19370
|
+
const result = estimateLtvDistribution(args);
|
|
19371
|
+
finiteResult(result.mean);
|
|
19372
|
+
finiteResult(result.quantiles);
|
|
19373
|
+
return result;
|
|
19374
|
+
}
|
|
19375
|
+
var init_public = __esm(() => {
|
|
19376
|
+
init_validate();
|
|
19377
|
+
init_uncertainty();
|
|
19378
|
+
});
|
|
19379
|
+
|
|
19023
19380
|
// ../core/dist/index.js
|
|
19024
19381
|
var init_dist2 = __esm(() => {
|
|
19025
19382
|
init_types();
|
|
@@ -19085,6 +19442,7 @@ var init_dist2 = __esm(() => {
|
|
|
19085
19442
|
init_judge();
|
|
19086
19443
|
init_flow();
|
|
19087
19444
|
init_jevAdvisory();
|
|
19445
|
+
init_public();
|
|
19088
19446
|
});
|
|
19089
19447
|
|
|
19090
19448
|
// src/errors.ts
|
|
@@ -19291,7 +19649,7 @@ var init_bun = __esm(() => {
|
|
|
19291
19649
|
var require_package = __commonJS(function(exports, module) {
|
|
19292
19650
|
module.exports = {
|
|
19293
19651
|
name: "@idlekit/cli",
|
|
19294
|
-
version: "0.
|
|
19652
|
+
version: "0.5.1",
|
|
19295
19653
|
description: "Bun-first idk CLI for idle game scenario validation, simulation, tuning, and reporting.",
|
|
19296
19654
|
license: "MIT",
|
|
19297
19655
|
type: "module",
|
|
@@ -19344,7 +19702,7 @@ var require_package = __commonJS(function(exports, module) {
|
|
|
19344
19702
|
"@clack/prompts": "1.8.1",
|
|
19345
19703
|
"@gunshi/plugin-completion": "0.37.3",
|
|
19346
19704
|
"@gunshi/plugin-suggestion": "0.37.3",
|
|
19347
|
-
"@idlekit/core": "0.
|
|
19705
|
+
"@idlekit/core": "0.5.0",
|
|
19348
19706
|
ajv: "^8.20.0",
|
|
19349
19707
|
gunshi: "0.37.3",
|
|
19350
19708
|
"proper-lockfile": "4.1.2",
|
|
@@ -21163,4 +21521,4 @@ export {
|
|
|
21163
21521
|
workerEntryMarker
|
|
21164
21522
|
};
|
|
21165
21523
|
|
|
21166
|
-
//# debugId=
|
|
21524
|
+
//# debugId=36317EC36EA8D6E664756E2164756E21
|