@voltro/plugin-progression 0.0.0-stage → 0.87.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 (97) hide show
  1. package/CHANGELOG.md +24329 -0
  2. package/LICENSE +61 -0
  3. package/README.md +478 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9189 -0
  6. package/dist/achievementComponents.js +92 -0
  7. package/dist/achievementStore.js +603 -0
  8. package/dist/achievementTables.entity.js +98 -0
  9. package/dist/achievements.d.ts +188 -0
  10. package/dist/achievements.js +205 -0
  11. package/dist/capture.js +64 -0
  12. package/dist/cmsQuests.d.ts +91 -0
  13. package/dist/cmsQuests.js +83 -0
  14. package/dist/components.d.ts +172 -0
  15. package/dist/components.js +4 -0
  16. package/dist/curve.d.ts +27 -0
  17. package/dist/curve.js +38 -0
  18. package/dist/daily.d.ts +152 -0
  19. package/dist/daily.js +126 -0
  20. package/dist/dailyStore.js +421 -0
  21. package/dist/dailySystem.fixture.js +138 -0
  22. package/dist/dailyTables.entity.js +90 -0
  23. package/dist/declarationFixtures.js +143 -0
  24. package/dist/errors.d.ts +13 -0
  25. package/dist/errors.js +20 -0
  26. package/dist/index.d.ts +1833 -0
  27. package/dist/index.js +19 -0
  28. package/dist/pass.d.ts +186 -0
  29. package/dist/pass.js +122 -0
  30. package/dist/passRules.js +96 -0
  31. package/dist/passStore.js +485 -0
  32. package/dist/passTables.entity.js +96 -0
  33. package/dist/plugin.js +1086 -0
  34. package/dist/port.js +5 -0
  35. package/dist/progressionStore.js +706 -0
  36. package/dist/questComponents.js +163 -0
  37. package/dist/questPort.d.ts +126 -0
  38. package/dist/questPort.js +5 -0
  39. package/dist/questRefresh.js +56 -0
  40. package/dist/questRefresh.server.js +126 -0
  41. package/dist/questRerollJournal.js +77 -0
  42. package/dist/questStore.js +592 -0
  43. package/dist/questTables.entity.js +117 -0
  44. package/dist/quests.d.ts +142 -0
  45. package/dist/quests.js +153 -0
  46. package/dist/rank-app/schedules/progression.dispatchRankClosures.cron.tsx +19 -0
  47. package/dist/rank-app/workflows/progression.closeRankSeason.workflow.server.tsx +10 -0
  48. package/dist/rank-app/workflows/progression.closeRankSeason.workflow.tsx +1 -0
  49. package/dist/rankClosure.d.ts +69 -0
  50. package/dist/rankClosure.js +35 -0
  51. package/dist/rankClosure.server.js +139 -0
  52. package/dist/rankClosureWorkflow.d.ts +34 -0
  53. package/dist/rankClosureWorkflow.js +16 -0
  54. package/dist/rankReader.server.js +57 -0
  55. package/dist/rankRewardParent.server.js +65 -0
  56. package/dist/rankSeasons.d.ts +144 -0
  57. package/dist/rankSeasons.js +91 -0
  58. package/dist/rankStore.js +521 -0
  59. package/dist/rankSystem.fixture.js +170 -0
  60. package/dist/rankTables.entity.js +101 -0
  61. package/dist/ranks.d.ts +167 -0
  62. package/dist/ranks.js +219 -0
  63. package/dist/resourceStore.js +464 -0
  64. package/dist/resourceTables.entity.js +89 -0
  65. package/dist/resources.d.ts +105 -0
  66. package/dist/resources.js +60 -0
  67. package/dist/reward-app/schedules/progression.dispatchRewards.cron.tsx +19 -0
  68. package/dist/reward-app/workflows/progression.deliverReward.workflow.server.tsx +10 -0
  69. package/dist/reward-app/workflows/progression.deliverReward.workflow.tsx +1 -0
  70. package/dist/reward.d.ts +27 -0
  71. package/dist/reward.js +39 -0
  72. package/dist/rewardDelivery.d.ts +163 -0
  73. package/dist/rewardDelivery.js +38 -0
  74. package/dist/rewardDelivery.server.js +430 -0
  75. package/dist/rewardDeliveryRecord.js +48 -0
  76. package/dist/rewardDeliveryWorkflow.d.ts +36 -0
  77. package/dist/rewardDeliveryWorkflow.js +16 -0
  78. package/dist/rpc.d.ts +880 -0
  79. package/dist/rpc.js +498 -0
  80. package/dist/server.d.ts +2812 -0
  81. package/dist/server.js +21 -0
  82. package/dist/stats.js +45 -0
  83. package/dist/strategies.d.ts +131 -0
  84. package/dist/strategies.js +4 -0
  85. package/dist/systemFixtures.js +474 -0
  86. package/dist/tables.entity.js +155 -0
  87. package/dist/testing.d.ts +1566 -0
  88. package/dist/testing.js +11 -0
  89. package/dist/track.js +72 -0
  90. package/dist/tutorial.d.ts +157 -0
  91. package/dist/tutorial.js +110 -0
  92. package/dist/tutorialStore.js +496 -0
  93. package/dist/tutorialSystem.fixture.js +100 -0
  94. package/dist/tutorialTables.entity.js +91 -0
  95. package/dist/web.d.ts +363 -0
  96. package/dist/web.js +7 -0
  97. package/package.json +167 -4
@@ -0,0 +1,57 @@
1
+ import { progressionError as e } from "./errors.js";
2
+ import { captureArguments as t, identifier as n, integer as r, list as i, object as a } from "./capture.js";
3
+ import { captureRankRating as o, defineRankLadder as s, resolveRank as c, resolveRankStrategies as l } from "./ranks.js";
4
+ import { Effect as u } from "effect";
5
+ //#region src/rankReader.server.ts
6
+ var d = (t) => {
7
+ let n = a(t);
8
+ if (typeof n.myRating != "function") throw e("invalid_input");
9
+ let r = n.myRating;
10
+ return Object.freeze({ read: (n, i) => u.try({
11
+ try: () => r.call(t, n, i),
12
+ catch: () => e("unavailable")
13
+ }).pipe(u.flatten, u.mapError(() => e("unavailable")), u.flatMap((t) => u.try({
14
+ try: () => o(t, i),
15
+ catch: () => e("invalid_record")
16
+ }))) });
17
+ }, f = (d) => {
18
+ let f = a(d, [
19
+ "ladders",
20
+ "source",
21
+ "strategies",
22
+ "now"
23
+ ]), p = Object.freeze(i(f.ladders, 64).map((e) => s(e))), m = a(f.source), h = f.now ?? Date.now, g = l(f.strategies);
24
+ if (!p.length || new Set(p.map((e) => e.id)).size !== p.length || typeof m.read != "function" || typeof h != "function") throw e("invalid_input");
25
+ let _ = m.read, v = h;
26
+ return Object.freeze({ mine: (i) => {
27
+ try {
28
+ let a = t(i);
29
+ if (a.type !== "user") throw e("forbidden");
30
+ return n(a.id), n(a.tenantId), u.gen(function* () {
31
+ let t = /* @__PURE__ */ new Map();
32
+ for (let n of p) t.has(n.rating) || t.set(n.rating, yield* u.flatMap(u.try({
33
+ try: () => _.call(m, a, n.rating),
34
+ catch: () => e("unavailable")
35
+ }).pipe(u.flatten), (t) => u.try({
36
+ try: () => o(t, n.rating),
37
+ catch: () => e("invalid_record")
38
+ })));
39
+ return yield* u.try({
40
+ try: () => {
41
+ let e = r(v(), 0, 864e13);
42
+ return Object.freeze(p.map((n) => c({
43
+ ladder: n,
44
+ rating: t.get(n.rating),
45
+ at: e
46
+ }, g)));
47
+ },
48
+ catch: () => e("invalid_record")
49
+ });
50
+ });
51
+ } catch {
52
+ return u.fail(e("forbidden"));
53
+ }
54
+ } });
55
+ };
56
+ //#endregion
57
+ export { f as makeRankReader, d as ratingSourceFromLeaderboards };
@@ -0,0 +1,65 @@
1
+ import { progressionError as e } from "./errors.js";
2
+ import { identifier as t, integer as n, object as r } from "./capture.js";
3
+ import { capturePlayerRank as i, captureRankRating as a, defineRankLadder as o } from "./ranks.js";
4
+ import { captureReward as s } from "./reward.js";
5
+ import { acceptRankObservation as c, closeRankSeasonState as l, defineRankSeason as u, initialRankSeasonState as d } from "./rankSeasons.js";
6
+ import { questHash as f } from "./questStore.js";
7
+ import { rankDefinitionsTable as p, rankLedgerTable as m, rankOperationsTable as h } from "./rankTables.entity.js";
8
+ import { and as g, eq as _, queryFor as v } from "@voltro/database";
9
+ //#region src/rankRewardParent.server.ts
10
+ var y = (e, ...t) => e + f(t).slice(0, 56), b = (e) => n(e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN, 0, 864e13), x = async (x, S, C, w, T) => {
11
+ let E = r(w.receipt, [
12
+ "operationId",
13
+ "kind",
14
+ "after",
15
+ "rewardsQueued",
16
+ "at"
17
+ ]), D = t(S.seasonId), O = n(r(E.after).version, 1, 1e6), k = b(S.createdAt), A = (await x.query(v(p).where(_("id", y("prd_", C.tenantId, D, String(O)))).limit(1).descriptor))[0];
18
+ if (!A || A.tenantId !== C.tenantId || A.seasonId !== D || E.kind !== "close" || E.at !== k) throw e("invalid_record");
19
+ let j = r(A.config, ["season", "ladder"]), M = o(j.ladder), N = u(j.season, M), P = t(A.rulesVersion);
20
+ if (N.id !== D || N.version !== O) throw e("invalid_record");
21
+ let F = await x.query(v(m).where(g(_("tenantId", C.tenantId), _("ownerKey", C.ownerKey), _("seasonId", D))).orderBy("sequence", "asc").limit(100001).descriptor), I = await x.query(v(h).where(g(_("tenantId", C.tenantId), _("ownerKey", C.ownerKey))).limit(100001).descriptor);
22
+ if (!F.length || F.length > 1e5 || I.length > 1e5) throw e("limit_exceeded");
23
+ let L = new Map(I.map((e) => [String(e.id), e])), R = /* @__PURE__ */ new Set(), z = d(N), B = 0, V = null;
24
+ for (let o of F) {
25
+ let s = r(o.intent, [
26
+ "request",
27
+ "rating",
28
+ "rank",
29
+ "resetScore"
30
+ ]), u = r(s.request, [
31
+ "seasonId",
32
+ "kind",
33
+ "requestId"
34
+ ]), d = b(o.at), p = t(o.operationId), m = L.get(p);
35
+ if (o.tenantId !== C.tenantId || o.ownerId !== C.ownerId || o.ownerKey !== C.ownerKey || o.seasonId !== D || u.seasonId !== D || u.kind !== "observe" && u.kind !== "close" || o.id !== y("prl_", p) || p !== y("pro_", C.tenantId, C.ownerId, t(u.requestId)) || !m || m.state !== "committed" || m.linkedOperationId !== null || m.tenantId !== C.tenantId || m.ownerKey !== C.ownerKey || m.digest !== f({
36
+ tenant: C.tenantId,
37
+ owner: C.ownerId,
38
+ request: u
39
+ }) || f(m.intent) !== f(u) || f(o.before) !== f(z)) throw e("invalid_record");
40
+ B = n(o.sequence, B + 1, n(T, 1, 2147483647));
41
+ let h;
42
+ if (u.kind === "observe") {
43
+ let t = a(s.rating, M.rating), n = i(s.rank, M, P);
44
+ if (s.resetScore !== null || n.games !== t.games || n.ratingUpdatedAt !== t.updatedAt || n.observedAt !== d) throw e("invalid_record");
45
+ h = y("pri_", C.tenantId, C.ownerId, D, "observe", f(t)), z = c(N, M, z, n, P);
46
+ } else {
47
+ if (s.rating !== null || s.rank !== null) throw e("invalid_record");
48
+ h = y("pri_", C.tenantId, C.ownerId, D, "close", ""), z = l(N, M, z, d, s.resetScore, P), V = p;
49
+ }
50
+ let g = r(m.receipt, [
51
+ "operationId",
52
+ "kind",
53
+ "after",
54
+ "rewardsQueued",
55
+ "at"
56
+ ]), _ = u.kind === "close" && z.highest ? N.rewards[z.highest.tierIndex].length : 0;
57
+ if (o.claimKey !== h || m.claimKey !== h || R.has(h) || f(o.after) !== f(z) || f(g.after) !== f(z) || g.operationId !== p || g.kind !== u.kind || g.at !== d || b(m.at) !== d || g.rewardsQueued !== _) throw e("invalid_record");
58
+ R.add(h);
59
+ }
60
+ if (V !== w.id || !z.highest || z.closedAt !== k || f(E.after) !== f(z)) throw e("invalid_record");
61
+ let H = N.rewards[z.highest.tierIndex], U = H.findIndex((e, n) => y("prr_", t(w.id), String(n)) === S.id);
62
+ if (U < 0 || E.rewardsQueued !== H.length || f(s(S.reward)) !== f(H[U])) throw e("invalid_record");
63
+ };
64
+ //#endregion
65
+ export { x as admitRankRewardParent };
@@ -0,0 +1,144 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { PluginPrivacyTarget } from '@voltro/protocol';
4
+ import { Schema } from 'effect';
5
+ import { Subject } from '@voltro/protocol';
6
+ import { YieldableError } from 'effect/Cause';
7
+
8
+ export declare const acceptRankObservation: (season: RankSeason, ladder: RankLadder, beforeInput: RankSeasonState, rankInput: PlayerRank, rulesVersion: string) => RankSeasonState;
9
+
10
+ export declare const captureRankSeasonState: (input: unknown, season: RankSeason, ladder: RankLadder, rulesVersion: string) => RankSeasonState;
11
+
12
+ export declare const closeRankSeasonState: (season: RankSeason, ladder: RankLadder, beforeInput: RankSeasonState, at: number, resetScore: number | null, rulesVersion: string) => RankSeasonState;
13
+
14
+ export declare const defineRankSeason: (input: RankSeasonDefinition | RankSeason, ladder: RankLadder) => RankSeason;
15
+
16
+ export declare const initialRankSeasonState: (season: RankSeason) => RankSeasonState;
17
+
18
+ declare interface PlayerRank {
19
+ readonly ladderId: string;
20
+ readonly version: number;
21
+ readonly pool: string;
22
+ readonly games: number;
23
+ readonly placementsRemaining: number;
24
+ readonly rawScore: number;
25
+ readonly score: number;
26
+ readonly grade: RankGrade | null;
27
+ readonly ratingUpdatedAt: number | null;
28
+ readonly observedAt: number;
29
+ readonly rulesVersion: string;
30
+ }
31
+
32
+ declare class ProgressionError extends ProgressionError_base {
33
+ }
34
+
35
+ declare const ProgressionError_base: Schema.Class<ProgressionError, Schema.TaggedStruct<"ProgressionError", {
36
+ readonly code: Schema.Literals<readonly ["invalid_input", "invalid_record", "invalid_curve", "invalid_reward", "invalid_track", "invalid_stat", "overflow", "insufficient_resource", "forbidden", "conflict", "erased", "not_found", "limit_exceeded", "unavailable"]>;
37
+ }>, YieldableError>;
38
+
39
+ declare type ProgressionReward = {
40
+ readonly kind: 'currency';
41
+ readonly currency: string;
42
+ readonly amount: string;
43
+ } | {
44
+ readonly kind: 'item';
45
+ readonly itemId: string;
46
+ readonly qty: number;
47
+ } | {
48
+ readonly kind: 'xp';
49
+ readonly trackId: string;
50
+ readonly amount: string;
51
+ };
52
+
53
+ export declare interface RankCloseInput extends RankObserveInput {
54
+ readonly tenantId: string;
55
+ readonly ownerId: string;
56
+ }
57
+
58
+ declare interface RankDecayDefinition {
59
+ readonly afterDays: number;
60
+ readonly perDay: number;
61
+ readonly floor: number;
62
+ }
63
+
64
+ declare interface RankGrade {
65
+ readonly index: number;
66
+ readonly tier: string;
67
+ readonly tierIndex: number;
68
+ readonly division: number;
69
+ }
70
+
71
+ declare interface RankLadder {
72
+ readonly id: string;
73
+ readonly version: number;
74
+ readonly rating: string;
75
+ readonly tiers: readonly string[];
76
+ readonly divisions: number;
77
+ readonly thresholds: readonly number[];
78
+ readonly placements: number;
79
+ readonly confidence: number;
80
+ readonly decay: RankDecayDefinition | null;
81
+ readonly softReset: RankResetDefinition | null;
82
+ }
83
+
84
+ export declare interface RankObserveInput {
85
+ readonly seasonId: string;
86
+ readonly requestId: string;
87
+ }
88
+
89
+ export declare class RankPort extends RankPort_base {
90
+ }
91
+
92
+ declare const RankPort_base: Context.ServiceClass<RankPort, "@voltro/RankPort", RankSeasonService>;
93
+
94
+ declare interface RankResetDefinition {
95
+ readonly target: number;
96
+ readonly retain: number;
97
+ }
98
+
99
+ export declare interface RankSeason {
100
+ readonly id: string;
101
+ readonly version: number;
102
+ readonly ladderId: string;
103
+ readonly from: number;
104
+ readonly until: number;
105
+ readonly rewards: readonly (readonly ProgressionReward[])[];
106
+ }
107
+
108
+ export declare interface RankSeasonDefinition {
109
+ readonly id: string;
110
+ readonly version?: number;
111
+ readonly ladderId: string;
112
+ readonly from: number;
113
+ readonly until: number;
114
+ readonly rewards: readonly (readonly ProgressionReward[])[];
115
+ }
116
+
117
+ export declare interface RankSeasonReceipt {
118
+ readonly operationId: string;
119
+ readonly kind: 'observe' | 'close';
120
+ readonly after: RankSeasonState;
121
+ readonly rewardsQueued: number;
122
+ readonly at: number;
123
+ }
124
+
125
+ export declare interface RankSeasonService {
126
+ readonly observe: (subject: Subject, input: RankObserveInput) => Effect.Effect<RankSeasonReceipt, ProgressionError>;
127
+ readonly close: (subject: Subject, input: RankCloseInput) => Effect.Effect<RankSeasonReceipt, ProgressionError>;
128
+ readonly mine: (subject: Subject) => Effect.Effect<readonly RankSeasonState[], ProgressionError>;
129
+ readonly exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<unknown, ProgressionError>;
130
+ readonly eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, ProgressionError>;
131
+ }
132
+
133
+ export declare interface RankSeasonState {
134
+ readonly seasonId: string;
135
+ readonly version: number;
136
+ readonly ladderId: string;
137
+ readonly observations: number;
138
+ readonly last: PlayerRank | null;
139
+ readonly highest: RankGrade | null;
140
+ readonly closedAt: number | null;
141
+ readonly resetScore: number | null;
142
+ }
143
+
144
+ export { }
@@ -0,0 +1,91 @@
1
+ import { progressionError as e } from "./errors.js";
2
+ import { identifier as t, integer as n, list as r, object as i } from "./capture.js";
3
+ import { capturePlayerRank as a } from "./ranks.js";
4
+ import { captureRewards as o } from "./reward.js";
5
+ import { Context as s } from "effect";
6
+ //#region src/rankSeasons.ts
7
+ var c = (a, s) => {
8
+ let c = i(a, [
9
+ "id",
10
+ "version",
11
+ "ladderId",
12
+ "from",
13
+ "until",
14
+ "rewards"
15
+ ]), l = n(c.from, 0, 864e13 - 1), u = n(c.until, l + 1, 864e13), d = Object.freeze(r(c.rewards, s.tiers.length).map((e) => o(e, 64)));
16
+ if (c.ladderId !== s.id || d.length !== s.tiers.length) throw e("invalid_input");
17
+ return Object.freeze({
18
+ id: t(c.id),
19
+ version: n(c.version ?? 1, 1, 1e6),
20
+ ladderId: s.id,
21
+ from: l,
22
+ until: u,
23
+ rewards: d
24
+ });
25
+ }, l = (e) => Object.freeze({
26
+ seasonId: e.id,
27
+ version: e.version,
28
+ ladderId: e.ladderId,
29
+ observations: 0,
30
+ last: null,
31
+ highest: null,
32
+ closedAt: null,
33
+ resetScore: null
34
+ }), u = (t, r, o, s) => {
35
+ let c = i(t, [
36
+ "seasonId",
37
+ "version",
38
+ "ladderId",
39
+ "observations",
40
+ "last",
41
+ "highest",
42
+ "closedAt",
43
+ "resetScore"
44
+ ]), l = n(c.observations, 0, 2147483647);
45
+ if (c.seasonId !== r.id || c.version !== r.version || c.ladderId !== o.id) throw e("invalid_record");
46
+ let u = c.last === null ? null : a(c.last, o, s), d = c.closedAt === null ? null : n(c.closedAt, r.until, 864e13);
47
+ if (!!l != (u !== null) || u && (u.observedAt < r.from || u.observedAt >= r.until)) throw e("invalid_record");
48
+ let f = null;
49
+ if (c.highest !== null) {
50
+ if (!u || (f = a({
51
+ ...u,
52
+ games: Math.max(u.games, o.placements),
53
+ placementsRemaining: 0,
54
+ ratingUpdatedAt: u.ratingUpdatedAt ?? u.observedAt,
55
+ grade: c.highest
56
+ }, o, s).grade, u.grade && f.index < u.grade.index)) throw e("invalid_record");
57
+ } else if (u?.grade) throw e("invalid_record");
58
+ if (u && u.placementsRemaining > 0 && f !== null) throw e("invalid_record");
59
+ let p = c.resetScore === null ? null : c.resetScore;
60
+ if (p !== null && (d === null || u === null || typeof p != "number" || !Number.isFinite(p) || Math.abs(p) > 1e9 || Object.is(p, -0)) || d !== null && u !== null && p === null) throw e("invalid_record");
61
+ return Object.freeze({
62
+ seasonId: r.id,
63
+ version: r.version,
64
+ ladderId: o.id,
65
+ observations: l,
66
+ last: u,
67
+ highest: f,
68
+ closedAt: d,
69
+ resetScore: p
70
+ });
71
+ }, d = (t, r, i, o, s) => {
72
+ let c = u(i, t, r, s), l = a(o, r, s);
73
+ if (c.closedAt !== null || l.observedAt < t.from || l.observedAt >= t.until || c.last && (l.observedAt < c.last.observedAt || l.games < c.last.games || (l.ratingUpdatedAt ?? 0) < (c.last.ratingUpdatedAt ?? 0))) throw e("conflict");
74
+ let d = l.grade && (c.highest === null || l.grade.index > c.highest.index) ? l.grade : c.highest;
75
+ return u({
76
+ ...c,
77
+ observations: n(c.observations + 1, 1, 2147483647),
78
+ last: l,
79
+ highest: d
80
+ }, t, r, s);
81
+ }, f = (t, r, i, a, o, s) => {
82
+ let c = u(i, t, r, s);
83
+ if (c.closedAt !== null) throw e("conflict");
84
+ return u({
85
+ ...c,
86
+ closedAt: n(a, t.until, 864e13),
87
+ resetScore: o
88
+ }, t, r, s);
89
+ }, p = class extends s.Service()("@voltro/RankPort") {};
90
+ //#endregion
91
+ export { p as RankPort, d as acceptRankObservation, u as captureRankSeasonState, f as closeRankSeasonState, c as defineRankSeason, l as initialRankSeasonState };