@orakl/shared 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 (56) hide show
  1. package/LICENSE +662 -0
  2. package/dist/analytics.d.ts +21 -0
  3. package/dist/analytics.js +21 -0
  4. package/dist/avatar-helpers.d.ts +46 -0
  5. package/dist/avatar-helpers.js +69 -0
  6. package/dist/avatars.d.ts +6 -0
  7. package/dist/avatars.js +138 -0
  8. package/dist/badges.d.ts +126 -0
  9. package/dist/badges.js +667 -0
  10. package/dist/constants/auth.constants.d.ts +26 -0
  11. package/dist/constants/auth.constants.js +94 -0
  12. package/dist/constants/feature-flags.constants.d.ts +138 -0
  13. package/dist/constants/feature-flags.constants.js +119 -0
  14. package/dist/constants/font.constants.d.ts +9 -0
  15. package/dist/constants/font.constants.js +14 -0
  16. package/dist/constants/lobby.constants.d.ts +2 -0
  17. package/dist/constants/lobby.constants.js +438 -0
  18. package/dist/constants/patterns.constants.d.ts +4 -0
  19. package/dist/constants/patterns.constants.js +4 -0
  20. package/dist/constants/theme.constants.d.ts +24 -0
  21. package/dist/constants/theme.constants.js +69 -0
  22. package/dist/env.d.ts +3 -0
  23. package/dist/env.js +5 -0
  24. package/dist/font.d.ts +4 -0
  25. package/dist/font.js +8 -0
  26. package/dist/history-range.d.ts +13 -0
  27. package/dist/history-range.js +29 -0
  28. package/dist/index.d.ts +23 -0
  29. package/dist/index.js +26 -0
  30. package/dist/lobby.d.ts +16 -0
  31. package/dist/lobby.js +50 -0
  32. package/dist/manage-questions.d.ts +52 -0
  33. package/dist/manage-questions.js +26 -0
  34. package/dist/math.d.ts +27 -0
  35. package/dist/math.js +30 -0
  36. package/dist/murmurhash.d.ts +9 -0
  37. package/dist/murmurhash.js +52 -0
  38. package/dist/pricing.d.ts +32 -0
  39. package/dist/pricing.js +32 -0
  40. package/dist/profile-tabs.d.ts +8 -0
  41. package/dist/profile-tabs.js +18 -0
  42. package/dist/quiz-routes.d.ts +28 -0
  43. package/dist/quiz-routes.js +65 -0
  44. package/dist/sanitize.d.ts +38 -0
  45. package/dist/sanitize.js +109 -0
  46. package/dist/schemas/question.schema.d.ts +1 -0
  47. package/dist/schemas/question.schema.js +1 -0
  48. package/dist/solo-entitlements.d.ts +28 -0
  49. package/dist/solo-entitlements.js +56 -0
  50. package/dist/theme.d.ts +39 -0
  51. package/dist/theme.js +139 -0
  52. package/dist/types/auth.d.ts +143 -0
  53. package/dist/types/auth.js +28 -0
  54. package/dist/utils.d.ts +50 -0
  55. package/dist/utils.js +133 -0
  56. package/package.json +45 -0
@@ -0,0 +1,126 @@
1
+ import type { BadgeAward, BadgeId, BadgeMode, BadgeRunParams } from "@orakl/protocol";
2
+ export type { BadgeAward, BadgeId, BadgeMode, BadgeRunParams, } from "@orakl/protocol";
3
+ export interface BadgeMeta {
4
+ id: BadgeId;
5
+ label: string;
6
+ /** Static one-line description (used on the trials tally). */
7
+ description: string;
8
+ icon: string;
9
+ /** Which modes can award this badge (ADR 0018 mode tags). */
10
+ modes: readonly BadgeMode[];
11
+ }
12
+ /** Display order, most prestigious first. */
13
+ export declare const BADGE_ORDER: BadgeId[];
14
+ export declare const BADGES: Record<BadgeId, BadgeMeta>;
15
+ /**
16
+ * Mode context for a run. Solo runs carry the solo mode (normal/endless);
17
+ * multiplayer runs carry the final ranking data that drives Victor/Podium and
18
+ * the full-game Flawless rule.
19
+ */
20
+ export type BadgeContext = {
21
+ kind: "solo";
22
+ mode: "normal" | "endless";
23
+ } | {
24
+ kind: "multiplayer";
25
+ /** Distinct final rank (1 = winner; see `distinctRanks`). */
26
+ rank: number;
27
+ /** Heroes who took part (the field Victor topped). */
28
+ heroCount: number;
29
+ /** Questions in the whole game — Flawless requires acing all of them. */
30
+ totalQuestions: number;
31
+ /** This player's final score (a 0-score field can't crown a Victor). */
32
+ score: number;
33
+ /** Questions actually served in this game. */
34
+ questionsServed: number;
35
+ };
36
+ export interface BadgeInput {
37
+ context: BadgeContext;
38
+ difficulty: "all" | "easy" | "medium" | "hard";
39
+ /**
40
+ * Questions in the player's log. In multiplayer this includes recorded
41
+ * misses: every unanswered round during the player's hero tenure (timeout,
42
+ * disconnect, quit) counts as a miss.
43
+ */
44
+ totalAnswered: number;
45
+ correctCount: number;
46
+ /** Session-wide tab-away events. 0 means the player never left the trial. */
47
+ tabAwayCount: number;
48
+ /** Peak consecutive-correct streak. */
49
+ maxStreak: number;
50
+ /** Per-question timer (ms) — the clock each answer is measured against. */
51
+ timerDurationMs: number;
52
+ /** Mean time-to-answer (ms) across the run. */
53
+ timeToAnswerAvgMs: number;
54
+ /**
55
+ * Best "faster than most" reading this run: the highest % of prior correct
56
+ * solvers any single answer beat on time. Null when no question had enough
57
+ * samples to judge. Drives the Faster-than-most badge (US #11).
58
+ */
59
+ fasterThanMaxPercent: number | null;
60
+ /**
61
+ * Total times the player switched a selection before committing, across the
62
+ * run. 0 means every answer was committed first-try (sure-handed). Undefined
63
+ * when the client didn't report changes (legacy) — the badge then can't award.
64
+ */
65
+ answerChanges?: number;
66
+ /**
67
+ * The player's consecutive-days-played streak as of this run (signed-in only).
68
+ * Drives the Devotee badge; undefined for guests / when not computed.
69
+ */
70
+ consecutiveDays?: number;
71
+ results: Array<{
72
+ timeToAnswerMs: number;
73
+ categoryId: string;
74
+ isCorrect: boolean;
75
+ /** Difficulty band of this question (for the per-difficulty Polymath badge). */
76
+ difficulty?: "easy" | "medium" | "hard";
77
+ }>;
78
+ }
79
+ /** Served-questions floor for the rank badges (victor, podium) and lifetime best-rank — below this a rank isn't a claim. */
80
+ export declare const RANK_BADGE_MIN_QUESTIONS = 6;
81
+ /**
82
+ * Raw share (0–1) of answers committed before the clock's halfway mark — quick
83
+ * answers read as decisive (implicit confidence from timing). Null when not
84
+ * measurable. This is the value the badge gates on (the rounded percent below
85
+ * is display-only, and rounding up could award the badge under the threshold).
86
+ */
87
+ export declare function decisiveShare(input: {
88
+ timerDurationMs: number;
89
+ results: Array<{
90
+ timeToAnswerMs: number;
91
+ }>;
92
+ }): number | null;
93
+ /** Rounded percentage form of {@link decisiveShare}, for display. */
94
+ export declare function decisivenessPercent(input: {
95
+ timerDurationMs: number;
96
+ results: Array<{
97
+ timeToAnswerMs: number;
98
+ }>;
99
+ }): number | null;
100
+ /** Badges earned by a completed run (solo or multiplayer), in display order. */
101
+ export declare function computeBadges(input: BadgeInput): BadgeAward[];
102
+ /** Four ascending rarity tiers. Index in RARITY_ORDER is the tier level. */
103
+ export type Rarity = "common" | "rare" | "legendary" | "exotic";
104
+ export declare const RARITY_ORDER: Rarity[];
105
+ export declare const RARITY_LABELS: Record<Rarity, string>;
106
+ /**
107
+ * Canonical tier colours, shared by every surface that renders the rarity
108
+ * scale (badge chips, legends) so the key always matches the badges it
109
+ * explains.
110
+ */
111
+ export declare const RARITY_CHIP_CLASSES: Record<Rarity, string>;
112
+ /** The rarity tier a badge reaches when earned under the given run conditions. */
113
+ export declare function computeBadgeRarity(id: BadgeId, run: BadgeRunParams): Rarity;
114
+ /** Parse a stored badge-id JSON array; malformed/missing/unknown ids read as none. */
115
+ export declare function parseBadgeIds(json: string | null | undefined): BadgeId[];
116
+ export interface BadgeTallyEntry {
117
+ count: number;
118
+ /** Highest rarity tier the player has reached for this badge. */
119
+ bestRarity: Rarity;
120
+ }
121
+ /** Per-badge counts + best rarity across a player's runs (any mode). */
122
+ export type BadgeTally = Partial<Record<BadgeId, BadgeTallyEntry>>;
123
+ /** Fold one earned badge into a tally (count + best rarity). Mutates `tally`. */
124
+ export declare function addToBadgeTally(tally: BadgeTally, id: BadgeId, rarity: Rarity): void;
125
+ /** Merge tallies from different sources (e.g. solo + multiplayer) into one. */
126
+ export declare function mergeBadgeTallies(...tallies: BadgeTally[]): BadgeTally;