@quizpot/quizcore 0.0.2 → 0.0.3

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 (110) hide show
  1. package/dist/index.cjs +582 -0
  2. package/dist/index.d.cts +472 -0
  3. package/dist/index.d.cts.map +1 -0
  4. package/dist/index.d.mts +472 -0
  5. package/dist/index.d.mts.map +1 -0
  6. package/dist/index.mjs +522 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +4 -4
  9. package/dist/events/client/host/kick-player.d.ts +0 -8
  10. package/dist/events/client/host/kick-player.d.ts.map +0 -1
  11. package/dist/events/client/host/kick-player.js +0 -4
  12. package/dist/events/client/host/next-step.d.ts +0 -5
  13. package/dist/events/client/host/next-step.d.ts.map +0 -1
  14. package/dist/events/client/host/next-step.js +0 -3
  15. package/dist/events/client/host/start-lobby.d.ts +0 -6
  16. package/dist/events/client/host/start-lobby.d.ts.map +0 -1
  17. package/dist/events/client/host/start-lobby.js +0 -4
  18. package/dist/events/client/player/submit-answer.d.ts +0 -9
  19. package/dist/events/client/player/submit-answer.d.ts.map +0 -1
  20. package/dist/events/client/player/submit-answer.js +0 -4
  21. package/dist/events/server/lobby-deleted.d.ts +0 -8
  22. package/dist/events/server/lobby-deleted.d.ts.map +0 -1
  23. package/dist/events/server/lobby-deleted.js +0 -4
  24. package/dist/events/server/lobby-joined.d.ts +0 -14
  25. package/dist/events/server/lobby-joined.d.ts.map +0 -1
  26. package/dist/events/server/lobby-joined.js +0 -18
  27. package/dist/events/server/lobby-status-update.d.ts +0 -32
  28. package/dist/events/server/lobby-status-update.d.ts.map +0 -1
  29. package/dist/events/server/lobby-status-update.js +0 -4
  30. package/dist/events/server/player-answer-result.d.ts +0 -11
  31. package/dist/events/server/player-answer-result.d.ts.map +0 -1
  32. package/dist/events/server/player-answer-result.js +0 -4
  33. package/dist/events/server/player-joined.d.ts +0 -9
  34. package/dist/events/server/player-joined.d.ts.map +0 -1
  35. package/dist/events/server/player-joined.js +0 -4
  36. package/dist/events/server/player-kicked.d.ts +0 -6
  37. package/dist/events/server/player-kicked.d.ts.map +0 -1
  38. package/dist/events/server/player-kicked.js +0 -4
  39. package/dist/events/server/player-left.d.ts +0 -9
  40. package/dist/events/server/player-left.d.ts.map +0 -1
  41. package/dist/events/server/player-left.js +0 -4
  42. package/dist/events/server/player-update.d.ts +0 -9
  43. package/dist/events/server/player-update.d.ts.map +0 -1
  44. package/dist/events/server/player-update.js +0 -4
  45. package/dist/events/server/update-lobby-answers.d.ts +0 -8
  46. package/dist/events/server/update-lobby-answers.d.ts.map +0 -1
  47. package/dist/events/server/update-lobby-answers.js +0 -4
  48. package/dist/index.d.ts +0 -26
  49. package/dist/index.d.ts.map +0 -1
  50. package/dist/index.js +0 -25
  51. package/dist/managers/lobby-manager.d.ts +0 -12
  52. package/dist/managers/lobby-manager.d.ts.map +0 -1
  53. package/dist/managers/lobby-manager.js +0 -112
  54. package/dist/types/events.d.ts +0 -16
  55. package/dist/types/events.d.ts.map +0 -1
  56. package/dist/types/events.js +0 -1
  57. package/dist/types/lobby.d.ts +0 -42
  58. package/dist/types/lobby.d.ts.map +0 -1
  59. package/dist/types/lobby.js +0 -10
  60. package/dist/types/question.d.ts +0 -106
  61. package/dist/types/question.d.ts.map +0 -1
  62. package/dist/types/question.js +0 -22
  63. package/dist/types/questions/multiple-choice.d.ts +0 -51
  64. package/dist/types/questions/multiple-choice.d.ts.map +0 -1
  65. package/dist/types/questions/multiple-choice.js +0 -21
  66. package/dist/types/questions/short-answer.d.ts +0 -34
  67. package/dist/types/questions/short-answer.d.ts.map +0 -1
  68. package/dist/types/questions/short-answer.js +0 -11
  69. package/dist/types/questions/true-false.d.ts +0 -36
  70. package/dist/types/questions/true-false.d.ts.map +0 -1
  71. package/dist/types/questions/true-false.js +0 -12
  72. package/dist/types/quizfile.d.ts +0 -79
  73. package/dist/types/quizfile.d.ts.map +0 -1
  74. package/dist/types/quizfile.js +0 -23
  75. package/dist/types/quizstep.d.ts +0 -73
  76. package/dist/types/quizstep.d.ts.map +0 -1
  77. package/dist/types/quizstep.js +0 -7
  78. package/dist/types/quiztheme.d.ts +0 -7
  79. package/dist/types/quiztheme.d.ts.map +0 -1
  80. package/dist/types/quiztheme.js +0 -5
  81. package/dist/types/slide.d.ts +0 -18
  82. package/dist/types/slide.d.ts.map +0 -1
  83. package/dist/types/slide.js +0 -9
  84. package/dist/types/slides/comparison.d.ts +0 -9
  85. package/dist/types/slides/comparison.d.ts.map +0 -1
  86. package/dist/types/slides/comparison.js +0 -7
  87. package/dist/types/slides/titleImageTextSlide.d.ts +0 -9
  88. package/dist/types/slides/titleImageTextSlide.d.ts.map +0 -1
  89. package/dist/types/slides/titleImageTextSlide.js +0 -7
  90. package/dist/types/slides/titleSlide.d.ts +0 -8
  91. package/dist/types/slides/titleSlide.d.ts.map +0 -1
  92. package/dist/types/slides/titleSlide.js +0 -6
  93. package/dist/util/guards.d.ts +0 -18
  94. package/dist/util/guards.d.ts.map +0 -1
  95. package/dist/util/guards.js +0 -15
  96. package/dist/util/names/additives.json +0 -23
  97. package/dist/util/names/animals.json +0 -23
  98. package/dist/util/names/colors.json +0 -14
  99. package/dist/util/names/names.d.ts +0 -4
  100. package/dist/util/names/names.d.ts.map +0 -1
  101. package/dist/util/names/names.js +0 -31
  102. package/dist/util/sanitizer.d.ts +0 -3
  103. package/dist/util/sanitizer.d.ts.map +0 -1
  104. package/dist/util/sanitizer.js +0 -18
  105. package/dist/util/score.d.ts +0 -11
  106. package/dist/util/score.d.ts.map +0 -1
  107. package/dist/util/score.js +0 -33
  108. package/dist/util/validator.d.ts +0 -14
  109. package/dist/util/validator.d.ts.map +0 -1
  110. package/dist/util/validator.js +0 -27
package/dist/index.mjs ADDED
@@ -0,0 +1,522 @@
1
+ import z from "zod";
2
+ //#region src/events/client/host/kick-player.ts
3
+ const createKickPlayerEvent = (playerId) => ({
4
+ type: "KICK_PLAYER",
5
+ payload: { playerId }
6
+ });
7
+ //#endregion
8
+ //#region src/events/client/host/next-step.ts
9
+ const createNextStepEvent = () => ({ type: "NEXT_STEP" });
10
+ //#endregion
11
+ //#region src/events/client/host/start-lobby.ts
12
+ const createStartLobbyEvent = () => ({
13
+ type: "START_LOBBY",
14
+ payload: {}
15
+ });
16
+ //#endregion
17
+ //#region src/events/client/player/submit-answer.ts
18
+ const createSubmitAnswerEvent = (submission) => ({
19
+ type: "SUBMIT_ANSWER",
20
+ payload: { submission }
21
+ });
22
+ //#endregion
23
+ //#region src/events/server/lobby-deleted.ts
24
+ const createLobbyDeletedEvent = (reason) => ({
25
+ type: "LOBBY_DELETED",
26
+ payload: { reason }
27
+ });
28
+ //#endregion
29
+ //#region src/events/server/lobby-joined.ts
30
+ const createLobbyJoinedEvent = (lobby, me, isHost) => ({
31
+ type: "LOBBY_JOINED",
32
+ payload: {
33
+ lobby: {
34
+ code: lobby.code,
35
+ quizInfo: lobby.quizInfo,
36
+ status: lobby.status,
37
+ timeoutStartedAt: lobby.timeoutStartedAt,
38
+ duration: lobby.duration,
39
+ currentStep: lobby.currentStep,
40
+ settings: lobby.settings
41
+ },
42
+ me,
43
+ players: isHost ? lobby.players : void 0,
44
+ currentAnswers: isHost ? lobby.currentAnswers : void 0,
45
+ answers: isHost ? lobby.answers : void 0
46
+ }
47
+ });
48
+ //#endregion
49
+ //#region src/events/server/lobby-status-update.ts
50
+ const createLobbyStatusUpdateEvent = (payload) => ({
51
+ type: "LOBBY_STATUS_UPDATE",
52
+ payload
53
+ });
54
+ //#endregion
55
+ //#region src/events/server/player-answer-result.ts
56
+ const createPlayerAnswerResultEvent = (isCorrect, pointsAwarded, score, streak) => ({
57
+ type: "PLAYER_ANSWER_RESULT",
58
+ payload: {
59
+ isCorrect,
60
+ pointsAwarded,
61
+ score,
62
+ streak
63
+ }
64
+ });
65
+ //#endregion
66
+ //#region src/events/server/player-joined.ts
67
+ const createPlayerJoinedEvent = (player) => ({
68
+ type: "PLAYER_JOINED",
69
+ payload: { player }
70
+ });
71
+ //#endregion
72
+ //#region src/events/server/player-kicked.ts
73
+ const createPlayerKickedEvent = () => ({
74
+ type: "PLAYER_KICKED",
75
+ payload: {}
76
+ });
77
+ //#endregion
78
+ //#region src/events/server/player-left.ts
79
+ const createPlayerLeftEvent = (player) => ({
80
+ type: "PLAYER_LEFT",
81
+ payload: { player }
82
+ });
83
+ //#endregion
84
+ //#region src/events/server/player-update.ts
85
+ const createPlayerUpdateEvent = (player) => ({
86
+ type: "PLAYER_UPDATE",
87
+ payload: { player }
88
+ });
89
+ //#endregion
90
+ //#region src/events/server/update-lobby-answers.ts
91
+ const createUpdateLobbyAnswersEvent = (count) => ({
92
+ type: "UPDATE_LOBBY_ANSWERS",
93
+ payload: { count }
94
+ });
95
+ //#endregion
96
+ //#region src/types/lobby.ts
97
+ let LobbyStatus = /* @__PURE__ */ function(LobbyStatus) {
98
+ LobbyStatus["waiting"] = "waiting";
99
+ LobbyStatus["slide"] = "slide";
100
+ LobbyStatus["question"] = "question";
101
+ LobbyStatus["answer"] = "answer";
102
+ LobbyStatus["answers"] = "answers";
103
+ LobbyStatus["score"] = "score";
104
+ LobbyStatus["end"] = "end";
105
+ return LobbyStatus;
106
+ }({});
107
+ //#endregion
108
+ //#region src/util/guards.ts
109
+ const isQuestion = (step) => {
110
+ return step.type === "question";
111
+ };
112
+ const isSlide = (step) => {
113
+ return step.type === "slide";
114
+ };
115
+ const isMultipleChoice = (data) => {
116
+ return data.type === "multiple-choice";
117
+ };
118
+ const isTrueFalse = (data) => {
119
+ return data.type === "true-false";
120
+ };
121
+ const isShortAnswer = (data) => {
122
+ return data.type === "short-answer";
123
+ };
124
+ //#endregion
125
+ //#region src/util/score.ts
126
+ const BASE_SCORE = 500;
127
+ const TIME_BONUS_MAX = 500;
128
+ const calculateScore = (player, question, answer, quiz) => {
129
+ if (!answer.isCorrect) return {
130
+ newScore: player.score,
131
+ pointsAwarded: 0
132
+ };
133
+ const pointMultiplier = {
134
+ noPoints: 0,
135
+ normalPoints: 1,
136
+ doublePoints: 2
137
+ }[question.points] ?? 1;
138
+ if (pointMultiplier === 0) return {
139
+ newScore: player.score,
140
+ pointsAwarded: 0
141
+ };
142
+ let timeBonus = 0;
143
+ if (question.timeLimit > 0) {
144
+ const timeLimitMs = question.timeLimit * 1e3;
145
+ timeBonus = TIME_BONUS_MAX * (1 - Math.max(0, Math.min(answer.timeTaken, timeLimitMs)) / timeLimitMs);
146
+ }
147
+ let questionScore = (BASE_SCORE + timeBonus) * pointMultiplier;
148
+ if (player.streak >= 2) {
149
+ const totalQuestions = quiz.steps.filter((s) => s.type === "question").length;
150
+ const dynamicCap = Math.min(1.2 + Math.max(0, totalQuestions - 5) * .02, 1.5);
151
+ const streakMultiplier = Math.min(1 + (player.streak - 1) * .05, dynamicCap);
152
+ questionScore *= streakMultiplier;
153
+ }
154
+ const finalPoints = Math.trunc(questionScore);
155
+ return {
156
+ newScore: player.score + finalPoints,
157
+ pointsAwarded: finalPoints
158
+ };
159
+ };
160
+ //#endregion
161
+ //#region src/util/validator.ts
162
+ const isCorrect = (question, submission) => {
163
+ if (isMultipleChoice(question) && submission.type === "multiple-choice") {
164
+ if (question.matchAll) {
165
+ const correctIndices = question.choices.map((c, i) => c.correct ? i : -1).filter((i) => i !== -1);
166
+ return submission.choices.length === correctIndices.length && submission.choices.every((index) => correctIndices.includes(index));
167
+ }
168
+ if (submission.choices.length === 0) return false;
169
+ return submission.choices.every((index) => {
170
+ const choice = question.choices[index];
171
+ return choice ? choice.correct : false;
172
+ });
173
+ }
174
+ if (isTrueFalse(question) && submission.type === "true-false") return question.answer === submission.answer;
175
+ if (isShortAnswer(question) && submission.type === "short-answer") {
176
+ const playerAns = submission.answer.trim().toLowerCase();
177
+ return question.answers.some((ans) => ans.trim().toLowerCase() === playerAns);
178
+ }
179
+ return false;
180
+ };
181
+ //#endregion
182
+ //#region src/managers/lobby-manager.ts
183
+ const createLobby = (code, hostId, quiz) => ({
184
+ code,
185
+ host: hostId,
186
+ quiz,
187
+ quizInfo: {
188
+ title: quiz.title,
189
+ stepCount: quiz.steps.length,
190
+ theme: quiz.theme
191
+ },
192
+ players: [],
193
+ status: LobbyStatus.waiting,
194
+ currentStep: 0,
195
+ timeoutStartedAt: null,
196
+ duration: null,
197
+ currentAnswers: [],
198
+ answers: [],
199
+ settings: {
200
+ customNames: true,
201
+ displayOnDevice: true
202
+ }
203
+ });
204
+ const advanceLobby = (lobby) => {
205
+ const isLastStep = lobby.currentStep >= lobby.quiz.steps.length - 1;
206
+ switch (lobby.status) {
207
+ case LobbyStatus.waiting: return prepareStep(lobby, 0);
208
+ case LobbyStatus.slide:
209
+ case LobbyStatus.score: return isLastStep ? {
210
+ ...lobby,
211
+ status: LobbyStatus.end
212
+ } : prepareStep(lobby, lobby.currentStep + 1);
213
+ case LobbyStatus.question: {
214
+ const step = lobby.quiz.steps[lobby.currentStep];
215
+ if (step.type !== "question") return lobby;
216
+ return {
217
+ ...lobby,
218
+ status: LobbyStatus.answer,
219
+ timeoutStartedAt: Date.now(),
220
+ duration: step.data.timeLimit * 1e3,
221
+ currentAnswers: []
222
+ };
223
+ }
224
+ case LobbyStatus.answer: return {
225
+ ...lobby,
226
+ status: LobbyStatus.answers
227
+ };
228
+ case LobbyStatus.answers: return {
229
+ ...lobby,
230
+ status: LobbyStatus.score
231
+ };
232
+ default: return lobby;
233
+ }
234
+ };
235
+ const prepareStep = (lobby, index) => {
236
+ const step = lobby.quiz.steps[index];
237
+ if (!step) return lobby;
238
+ if (step.type === "slide") return {
239
+ ...lobby,
240
+ status: LobbyStatus.slide,
241
+ currentStep: index
242
+ };
243
+ return {
244
+ ...lobby,
245
+ status: LobbyStatus.question,
246
+ currentStep: index,
247
+ timeoutStartedAt: null,
248
+ duration: null,
249
+ currentAnswers: []
250
+ };
251
+ };
252
+ const handleSubmission = (lobby, playerId, submission) => {
253
+ if (lobby.status !== LobbyStatus.answer) return null;
254
+ const step = lobby.quiz.steps[lobby.currentStep];
255
+ if (!isQuestion(step)) return null;
256
+ const player = lobby.players.find((p) => p.id === playerId);
257
+ if (!player) return null;
258
+ if (lobby.currentAnswers.some((a) => a.playerId === playerId)) return null;
259
+ const correct = isCorrect(step.data, submission);
260
+ const answerObj = {
261
+ playerId,
262
+ submission,
263
+ timeTaken: Date.now() - (lobby.timeoutStartedAt ?? 0),
264
+ isCorrect: correct,
265
+ pointsAwarded: 0
266
+ };
267
+ const { newScore, pointsAwarded } = calculateScore(player, step.data, answerObj, lobby.quiz);
268
+ answerObj.pointsAwarded = pointsAwarded;
269
+ return {
270
+ nextLobby: {
271
+ ...lobby,
272
+ players: lobby.players.map((p) => p.id === playerId ? {
273
+ ...p,
274
+ score: newScore,
275
+ streak: correct ? p.streak + 1 : 0
276
+ } : p),
277
+ currentAnswers: [...lobby.currentAnswers, answerObj]
278
+ },
279
+ result: {
280
+ type: "PLAYER_ANSWER_RESULT",
281
+ payload: {
282
+ isCorrect: correct,
283
+ pointsAwarded,
284
+ score: newScore,
285
+ streak: correct ? player.streak + 1 : 0
286
+ }
287
+ }
288
+ };
289
+ };
290
+ //#endregion
291
+ //#region src/types/questions/true-false.ts
292
+ const TrueFalseQuestionSchema = BaseQuestionSchema.extend({
293
+ type: z.literal("true-false"),
294
+ answer: z.boolean(),
295
+ labels: z.array(z.string()).min(2).max(2)
296
+ });
297
+ const SafeTrueFalseQuestionSchema = TrueFalseQuestionSchema.omit({ answer: true });
298
+ const TrueFalseQuestionAnswerSchema = z.object({
299
+ type: z.literal("true-false"),
300
+ answer: z.boolean()
301
+ });
302
+ //#endregion
303
+ //#region src/types/questions/short-answer.ts
304
+ const ShortAnswerQuestionSchema = BaseQuestionSchema.extend({
305
+ type: z.literal("short-answer"),
306
+ answers: z.array(z.string()).min(1)
307
+ });
308
+ const SafeShortAnswerQuestionSchema = ShortAnswerQuestionSchema.omit({ answers: true });
309
+ const ShortAnswerQuestionAnswerSchema = z.object({
310
+ type: z.literal("short-answer"),
311
+ answer: z.string()
312
+ });
313
+ //#endregion
314
+ //#region src/types/question.ts
315
+ const QuestionSchema = z.discriminatedUnion("type", [
316
+ MultipleChoiceQuestionSchema,
317
+ TrueFalseQuestionSchema,
318
+ ShortAnswerQuestionSchema
319
+ ]);
320
+ z.discriminatedUnion("type", [
321
+ SafeMultipleChoiceQuestionSchema,
322
+ SafeTrueFalseQuestionSchema,
323
+ SafeShortAnswerQuestionSchema
324
+ ]);
325
+ const QuestionPointsSchema = z.enum([
326
+ "normalPoints",
327
+ "doublePoints",
328
+ "noPoints"
329
+ ]);
330
+ const BaseQuestionSchema = z.object({
331
+ question: z.string().min(1),
332
+ imageHash: z.hash("sha256", { error: "Invalid image hash" }).optional(),
333
+ displayTime: z.number().min(1).max(60),
334
+ timeLimit: z.number().min(1).max(180),
335
+ points: QuestionPointsSchema
336
+ });
337
+ //#endregion
338
+ //#region src/types/questions/multiple-choice.ts
339
+ const ChoiceSchema = z.object({
340
+ text: z.string(),
341
+ correct: z.boolean()
342
+ });
343
+ const SafeChoiceSchema = ChoiceSchema.omit({ correct: true });
344
+ const MultipleChoiceQuestionSchema = BaseQuestionSchema.extend({
345
+ type: z.literal("multiple-choice"),
346
+ choices: z.array(ChoiceSchema).min(2),
347
+ matchAll: z.boolean()
348
+ });
349
+ const SafeMultipleChoiceQuestionSchema = MultipleChoiceQuestionSchema.omit({ choices: true }).extend({ choices: z.array(SafeChoiceSchema).min(2) });
350
+ const MultipleChoiceQuestionAnswerSchema = z.object({
351
+ type: z.literal("multiple-choice"),
352
+ choices: z.array(z.number()).min(1)
353
+ });
354
+ //#endregion
355
+ //#region src/types/quiztheme.ts
356
+ const QuizThemeSchema = z.object({
357
+ color: z.string().regex(/^#[0-9a-fA-F]{6}$/, { message: "Invalid color format. Must be a 7-character hex code (e.g., #RRGGBB)." }),
358
+ background: z.hash("sha256", { error: "Invalid background hash" }).optional()
359
+ });
360
+ //#endregion
361
+ //#region src/types/slides/titleSlide.ts
362
+ const TitleSlideLayoutSchema = z.object({
363
+ slideType: z.literal("title"),
364
+ title: z.string(),
365
+ subtitle: z.string().optional()
366
+ });
367
+ //#endregion
368
+ //#region src/types/slides/titleImageTextSlide.ts
369
+ const TitleImageTextSlideLayoutSchema = z.object({
370
+ slideType: z.literal("titleImageText"),
371
+ title: z.string(),
372
+ imageHash: z.hash("sha256", { error: "Invalid image hash" }).optional(),
373
+ text: z.string()
374
+ });
375
+ //#endregion
376
+ //#region src/types/slides/comparison.ts
377
+ const ComparisonSlideLayoutSchema = z.object({
378
+ slideType: z.literal("comparison"),
379
+ title: z.string(),
380
+ left: z.string(),
381
+ right: z.string()
382
+ });
383
+ //#endregion
384
+ //#region src/types/slide.ts
385
+ const SlideSchema = z.discriminatedUnion("slideType", [
386
+ TitleSlideLayoutSchema,
387
+ TitleImageTextSlideLayoutSchema,
388
+ ComparisonSlideLayoutSchema
389
+ ]);
390
+ //#endregion
391
+ //#region src/types/quizstep.ts
392
+ const QuizStepSchema = z.discriminatedUnion("type", [z.object({
393
+ type: z.literal("question"),
394
+ data: QuestionSchema
395
+ }), z.object({
396
+ type: z.literal("slide"),
397
+ data: SlideSchema
398
+ })]);
399
+ //#endregion
400
+ //#region src/types/quizfile.ts
401
+ const QuizFileSchema = z.object({
402
+ id: z.uuid(),
403
+ version: z.literal(2),
404
+ title: z.string().min(1, "Title must be atleast 1 character long").max(64, "Title can't be longer than 64 characters"),
405
+ description: z.string().max(255, "Description can't be longer than 256 characters").optional(),
406
+ theme: QuizThemeSchema,
407
+ language: z.string().length(2, "Language must be a 2-letter ISO 639-1 code"),
408
+ steps: z.array(QuizStepSchema).min(1, "Quiz must have at least 1 step"),
409
+ images: z.record(z.hash("sha256", { error: "Invalid image hash" }), z.string().refine((val) => {
410
+ return val.startsWith("http") || val.startsWith("data:image/");
411
+ }, "Image must be a valid URL or Base64 data string")),
412
+ updatedAt: z.iso.datetime(),
413
+ createdAt: z.iso.datetime()
414
+ });
415
+ //#endregion
416
+ //#region src/util/names/animals.json
417
+ var animals_default = [
418
+ "Dog",
419
+ "Cat",
420
+ "Rabbit",
421
+ "Lion",
422
+ "Tiger",
423
+ "Bear",
424
+ "Wolf",
425
+ "Fox",
426
+ "Panda",
427
+ "Elephant",
428
+ "Gorilla",
429
+ "Giraffe",
430
+ "Hippo",
431
+ "Rhino",
432
+ "Zebra",
433
+ "Crocodile",
434
+ "Alligator",
435
+ "Octopus",
436
+ "Butterfly",
437
+ "Bee",
438
+ "Ant"
439
+ ];
440
+ //#endregion
441
+ //#region src/util/names/additives.json
442
+ var additives_default = [
443
+ "Funny",
444
+ "Happy",
445
+ "Sad",
446
+ "Angry",
447
+ "Scary",
448
+ "Serious",
449
+ "Cautious",
450
+ "Joyful",
451
+ "Broken",
452
+ "Smart",
453
+ "Shy",
454
+ "Silly",
455
+ "Lazy",
456
+ "Cheerful",
457
+ "Calm",
458
+ "Sleepy",
459
+ "Tired",
460
+ "Lonely",
461
+ "Crazy",
462
+ "Mad",
463
+ "Gentle"
464
+ ];
465
+ //#endregion
466
+ //#region src/util/names/colors.json
467
+ var colors_default = [
468
+ "Red",
469
+ "Blue",
470
+ "Green",
471
+ "Yellow",
472
+ "Purple",
473
+ "Orange",
474
+ "Pink",
475
+ "Brown",
476
+ "Black",
477
+ "White",
478
+ "Gray",
479
+ "Cyan"
480
+ ];
481
+ //#endregion
482
+ //#region src/util/names/names.ts
483
+ const generateName = () => {
484
+ const animal = animals_default[Math.floor(Math.random() * animals_default.length)];
485
+ const additive = additives_default[Math.floor(Math.random() * additives_default.length)];
486
+ return `${colors_default[Math.floor(Math.random() * colors_default.length)]}${additive}${animal}`;
487
+ };
488
+ const generateUniqueName = (players) => {
489
+ const maxPossible = animals_default.length * additives_default.length * colors_default.length;
490
+ if (players.length >= maxPossible) throw new Error("No unique names available");
491
+ const existingNames = new Set(players.map((p) => p.name));
492
+ for (let i = 0; i < 100; i++) {
493
+ const candidate = generateName();
494
+ if (!existingNames.has(candidate)) return candidate;
495
+ }
496
+ for (const c of colors_default) for (const ad of additives_default) for (const an of animals_default) {
497
+ const candidate = `${c}${ad}${an}`;
498
+ if (!existingNames.has(candidate)) return candidate;
499
+ }
500
+ throw new Error("No unique names available");
501
+ };
502
+ //#endregion
503
+ //#region src/util/sanitizer.ts
504
+ const sanitizeQuestion = (question) => {
505
+ if (isMultipleChoice(question)) return {
506
+ ...question,
507
+ choices: question.choices.map(({ text }) => ({ text }))
508
+ };
509
+ if (isTrueFalse(question)) {
510
+ const { answer, ...sanitized } = question;
511
+ return sanitized;
512
+ }
513
+ if (isShortAnswer(question)) {
514
+ const { answers, ...sanitized } = question;
515
+ return sanitized;
516
+ }
517
+ throw new Error("Invalid question type");
518
+ };
519
+ //#endregion
520
+ export { ChoiceSchema, LobbyStatus, MultipleChoiceQuestionAnswerSchema, MultipleChoiceQuestionSchema, QuizFileSchema, SafeChoiceSchema, SafeMultipleChoiceQuestionSchema, SafeShortAnswerQuestionSchema, SafeTrueFalseQuestionSchema, ShortAnswerQuestionAnswerSchema, ShortAnswerQuestionSchema, TrueFalseQuestionAnswerSchema, TrueFalseQuestionSchema, advanceLobby, calculateScore, createKickPlayerEvent, createLobby, createLobbyDeletedEvent, createLobbyJoinedEvent, createLobbyStatusUpdateEvent, createNextStepEvent, createPlayerAnswerResultEvent, createPlayerJoinedEvent, createPlayerKickedEvent, createPlayerLeftEvent, createPlayerUpdateEvent, createStartLobbyEvent, createSubmitAnswerEvent, createUpdateLobbyAnswersEvent, generateName, generateUniqueName, handleSubmission, isCorrect, isMultipleChoice, isQuestion, isShortAnswer, isSlide, isTrueFalse, sanitizeQuestion };
521
+
522
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":["animals","additives","colors"],"sources":["../src/events/client/host/kick-player.ts","../src/events/client/host/next-step.ts","../src/events/client/host/start-lobby.ts","../src/events/client/player/submit-answer.ts","../src/events/server/lobby-deleted.ts","../src/events/server/lobby-joined.ts","../src/events/server/lobby-status-update.ts","../src/events/server/player-answer-result.ts","../src/events/server/player-joined.ts","../src/events/server/player-kicked.ts","../src/events/server/player-left.ts","../src/events/server/player-update.ts","../src/events/server/update-lobby-answers.ts","../src/types/lobby.ts","../src/util/guards.ts","../src/util/score.ts","../src/util/validator.ts","../src/managers/lobby-manager.ts","../src/types/questions/true-false.ts","../src/types/questions/short-answer.ts","../src/types/question.ts","../src/types/questions/multiple-choice.ts","../src/types/quiztheme.ts","../src/types/slides/titleSlide.ts","../src/types/slides/titleImageTextSlide.ts","../src/types/slides/comparison.ts","../src/types/slide.ts","../src/types/quizstep.ts","../src/types/quizfile.ts","../src/util/names/animals.json","../src/util/names/additives.json","../src/util/names/colors.json","../src/util/names/names.ts","../src/util/sanitizer.ts"],"sourcesContent":["export type KickPlayer = {\n type: \"KICK_PLAYER\";\n payload: { playerId: string };\n};\n\nexport const createKickPlayerEvent = (playerId: string): KickPlayer => ({\n type: \"KICK_PLAYER\",\n payload: { playerId }\n});","export type NextStep = {\n type: \"NEXT_STEP\";\n};\n\nexport const createNextStepEvent = (): NextStep => ({\n type: \"NEXT_STEP\",\n});","export type StartLobby = {\n type: \"START_LOBBY\";\n payload: {};\n};\n\nexport const createStartLobbyEvent = (): StartLobby => ({\n type: \"START_LOBBY\",\n payload: {}\n});","import { SubmittedAnswer } from \"../../../util/validator\";\n\nexport type SubmitAnswer = {\n type: \"SUBMIT_ANSWER\";\n payload: { submission: SubmittedAnswer };\n};\n\nexport const createSubmitAnswerEvent = (submission: SubmittedAnswer): SubmitAnswer => ({\n type: \"SUBMIT_ANSWER\",\n payload: { submission }\n});","export type LobbyDeleted = {\n type: \"LOBBY_DELETED\";\n payload: { reason: string };\n};\n\nexport const createLobbyDeletedEvent = (reason: string): LobbyDeleted => ({\n type: \"LOBBY_DELETED\",\n payload: { reason }\n});","import { Lobby, Player } from \"../../types/lobby\";\nimport { Answer } from \"../../util/validator\";\n\nexport type LobbyJoined = {\n type: \"LOBBY_JOINED\";\n payload: { \n lobby: Omit<Lobby, \"host\" | \"quiz\" | \"players\" | \"currentAnswers\" | \"answers\">;\n me?: Player;\n players?: Player[];\n currentAnswers?: Answer[];\n answers?: Answer[];\n };\n};\n\nexport const createLobbyJoinedEvent = (\n lobby: Lobby, \n me: Player, \n isHost: boolean\n): LobbyJoined => ({\n type: \"LOBBY_JOINED\",\n payload: {\n lobby: {\n code: lobby.code,\n quizInfo: lobby.quizInfo,\n status: lobby.status,\n timeoutStartedAt: lobby.timeoutStartedAt,\n duration: lobby.duration,\n currentStep: lobby.currentStep,\n settings: lobby.settings,\n },\n me,\n players: isHost ? lobby.players : undefined,\n currentAnswers: isHost ? lobby.currentAnswers : undefined,\n answers: isHost ? lobby.answers : undefined,\n }\n});","import { LobbyStatus, Player } from \"../../types/lobby\";\nimport { SafeQuestion } from \"../../types/question\";\nimport { Slide } from \"../../types/slide\";\nimport { Answer } from \"../../util/validator\";\n\nexport type LobbyStatusUpdate = {\n type: \"LOBBY_STATUS_UPDATE\";\n payload: \n | { status: LobbyStatus.waiting }\n | { status: LobbyStatus.slide; slide: Slide }\n | { status: LobbyStatus.question; question: SafeQuestion; timeoutStartedAt: number; duration: number }\n | { status: LobbyStatus.answer; timeoutStartedAt: number; duration: number }\n | { status: LobbyStatus.answers; answers: Answer[] }\n | { status: LobbyStatus.score; leaderboard: Player[] }\n | { status: LobbyStatus.end };\n};\n\nexport const createLobbyStatusUpdateEvent = (\n payload: LobbyStatusUpdate[\"payload\"]\n): LobbyStatusUpdate => ({\n type: \"LOBBY_STATUS_UPDATE\",\n payload,\n});","export type PlayerAnswerResult = {\n type: \"PLAYER_ANSWER_RESULT\";\n payload: {\n isCorrect: boolean;\n pointsAwarded: number;\n score: number;\n streak: number;\n };\n};\n\nexport const createPlayerAnswerResultEvent = (\n isCorrect: boolean, \n pointsAwarded: number, \n score: number, \n streak: number\n): PlayerAnswerResult => ({\n type: \"PLAYER_ANSWER_RESULT\",\n payload: { isCorrect, pointsAwarded, score, streak }\n});","import { Player } from \"../../types/lobby\";\n\nexport type PlayerJoined = {\n type: \"PLAYER_JOINED\";\n payload: { player: Player };\n};\n\nexport const createPlayerJoinedEvent = (player: Player): PlayerJoined => ({\n type: \"PLAYER_JOINED\",\n payload: { player }\n});","export type PlayerKicked = {\n type: \"PLAYER_KICKED\";\n payload: {};\n};\n\nexport const createPlayerKickedEvent = (): PlayerKicked => ({\n type: \"PLAYER_KICKED\",\n payload: {}\n});","import { Player } from \"../../types/lobby\";\n\nexport type PlayerLeft = {\n type: \"PLAYER_LEFT\";\n payload: { player: Player };\n};\n\nexport const createPlayerLeftEvent = (player: Player): PlayerLeft => ({\n type: \"PLAYER_LEFT\",\n payload: { player }\n});","import { Player } from \"../../types/lobby\";\n\nexport type PlayerUpdate = {\n type: \"PLAYER_UPDATE\";\n payload: { player: Player };\n};\n\nexport const createPlayerUpdateEvent = (player: Player): PlayerUpdate => ({\n type: \"PLAYER_UPDATE\",\n payload: { player }\n});","export type UpdateLobbyAnswers = {\n type: \"UPDATE_LOBBY_ANSWERS\";\n payload: { count: number };\n};\n\nexport const createUpdateLobbyAnswersEvent = (count: number): UpdateLobbyAnswers => ({\n type: \"UPDATE_LOBBY_ANSWERS\",\n payload: { count }\n});","import { Answer } from \"../util/validator\";\nimport { QuizFile } from \"./quizfile\";\nimport { QuizTheme } from \"./quiztheme\";\n\nexport type Lobby = {\n code: string;\n host: string; // Id of the WebSocket connection\n quiz: QuizFile;\n quizInfo: {\n title: string;\n stepCount: number;\n theme: QuizTheme;\n };\n players: Player[];\n status: LobbyStatus;\n timeoutStartedAt: number | null;\n duration: number | null;\n currentStep: number;\n currentAnswers: Answer[];\n answers: Answer[];\n settings: LobbySettings;\n}\n\nexport type LobbySettings = {\n customNames: boolean;\n displayOnDevice: boolean;\n}\n\nexport enum LobbyStatus {\n waiting = 'waiting',\n slide = 'slide',\n question = 'question',\n answer = 'answer',\n answers = 'answers',\n score = 'score',\n end = 'end',\n}\n\nexport type Player = {\n id: string;\n name: string;\n score: number;\n streak: number;\n isConnected: boolean;\n}","import { Question } from \"../types/question\";\nimport { MultipleChoiceQuestion } from \"../types/questions/multiple-choice\";\nimport { ShortAnswerQuestion } from \"../types/questions/short-answer\";\nimport { TrueFalseQuestion } from \"../types/questions/true-false\";\nimport { QuizStep } from \"../types/quizstep\";\nimport { Slide } from \"../types/slide\";\n\nexport const isQuestion = (step: QuizStep): step is { type: \"question\"; data: Question } => {\n return step.type === \"question\";\n};\n\nexport const isSlide = (step: QuizStep): step is { type: \"slide\"; data: Slide } => {\n return step.type === \"slide\";\n};\n\nexport const isMultipleChoice = (data: Question): data is MultipleChoiceQuestion => {\n return data.type === \"multiple-choice\";\n};\n\nexport const isTrueFalse = (data: Question): data is TrueFalseQuestion => {\n return data.type === \"true-false\";\n};\n\nexport const isShortAnswer = (data: Question): data is ShortAnswerQuestion => {\n return data.type === \"short-answer\";\n};","import { Answer } from \"./validator\";\nimport { QuizFile } from \"../types/quizfile\";\nimport { Question } from \"../types/question\";\n\nconst BASE_SCORE = 500;\nconst TIME_BONUS_MAX = 500;\n\nexport const calculateScore = (\n player: { score: number; streak: number },\n question: Question,\n answer: Answer,\n quiz: QuizFile\n): { newScore: number; pointsAwarded: number } => {\n if (!answer.isCorrect) return { newScore: player.score, pointsAwarded: 0 };\n\n const multipliers: Record<string, number> = {\n noPoints: 0,\n normalPoints: 1,\n doublePoints: 2,\n };\n const pointMultiplier = multipliers[question.points] ?? 1;\n if (pointMultiplier === 0) return { newScore: player.score, pointsAwarded: 0 };\n\n let timeBonus = 0;\n if (question.timeLimit > 0) {\n const timeLimitMs = question.timeLimit * 1000;\n const timeTaken = Math.max(0, Math.min(answer.timeTaken, timeLimitMs));\n const timeRemainingRatio = 1 - (timeTaken / timeLimitMs);\n timeBonus = TIME_BONUS_MAX * timeRemainingRatio;\n }\n\n let questionScore = (BASE_SCORE + timeBonus) * pointMultiplier;\n\n if (player.streak >= 2) {\n const totalQuestions = quiz.steps.filter(s => s.type === \"question\").length;\n \n const dynamicCap = Math.min(1.2 + Math.max(0, totalQuestions - 5) * 0.02, 1.5);\n const streakMultiplier = Math.min(1 + (player.streak - 1) * 0.05, dynamicCap);\n \n questionScore *= streakMultiplier;\n }\n\n const finalPoints = Math.trunc(questionScore);\n return {\n newScore: player.score + finalPoints,\n pointsAwarded: finalPoints\n };\n};","import { isMultipleChoice, isShortAnswer, isTrueFalse } from \"../util/guards\";\nimport { ShortAnswerQuestionAnswer } from \"../types/questions/short-answer\";\nimport { TrueFalseQuestionAnswer } from \"../types/questions/true-false\";\nimport { MultipleChoiceQuestionAnswer } from \"../types/questions/multiple-choice\";\nimport { Question } from \"../types/question\";\n\nexport type SubmittedAnswer = \n | MultipleChoiceQuestionAnswer\n | TrueFalseQuestionAnswer \n | ShortAnswerQuestionAnswer;\n\nexport interface Answer {\n playerId: string;\n submission: SubmittedAnswer;\n timeTaken: number;\n isCorrect: boolean;\n pointsAwarded: number;\n};\n\nexport const isCorrect = (question: Question, submission: SubmittedAnswer): boolean => {\n if (isMultipleChoice(question) && submission.type === \"multiple-choice\") {\n if (question.matchAll) {\n const correctIndices = question.choices\n .map((c, i) => (c.correct ? i : -1))\n .filter((i) => i !== -1);\n\n return (\n submission.choices.length === correctIndices.length &&\n submission.choices.every((index) => correctIndices.includes(index))\n );\n }\n\n if (submission.choices.length === 0) return false;\n\n return submission.choices.every(index => {\n const choice = question.choices[index];\n return choice ? choice.correct : false;\n });\n }\n\n if (isTrueFalse(question) && submission.type === \"true-false\") {\n return question.answer === submission.answer;\n }\n\n if (isShortAnswer(question) && submission.type === \"short-answer\") {\n const playerAns = submission.answer.trim().toLowerCase();\n return question.answers.some(ans => ans.trim().toLowerCase() === playerAns);\n }\n\n return false;\n};","import { PlayerAnswerResult } from \"../events/server/player-answer-result\";\nimport { Lobby, LobbyStatus } from \"../types/lobby\";\nimport { QuizFile } from \"../types/quizfile\";\nimport { isQuestion } from \"../util/guards\";\nimport { calculateScore } from \"../util/score\";\nimport { Answer, isCorrect, SubmittedAnswer } from \"../util/validator\";\n\nexport const createLobby = (\n code: string, \n hostId: string, \n quiz: QuizFile\n): Lobby => ({\n code,\n host: hostId,\n quiz,\n quizInfo: {\n title: quiz.title,\n stepCount: quiz.steps.length,\n theme: quiz.theme\n },\n players: [],\n status: LobbyStatus.waiting,\n currentStep: 0,\n timeoutStartedAt: null,\n duration: null,\n currentAnswers: [],\n answers: [],\n settings: { customNames: true, displayOnDevice: true }\n});\n\nexport const advanceLobby = (lobby: Lobby): Lobby => {\n const isLastStep = lobby.currentStep >= lobby.quiz.steps.length - 1;\n\n switch (lobby.status) {\n case LobbyStatus.waiting:\n return prepareStep(lobby, 0);\n\n case LobbyStatus.slide:\n case LobbyStatus.score:\n return isLastStep \n ? { ...lobby, status: LobbyStatus.end } \n : prepareStep(lobby, lobby.currentStep + 1);\n\n case LobbyStatus.question: {\n const step = lobby.quiz.steps[lobby.currentStep];\n if (step.type !== 'question') return lobby;\n\n return { \n ...lobby, \n status: LobbyStatus.answer, \n timeoutStartedAt: Date.now(), \n duration: step.data.timeLimit * 1000,\n currentAnswers: [] \n };\n }\n\n case LobbyStatus.answer:\n return { ...lobby, status: LobbyStatus.answers };\n\n case LobbyStatus.answers:\n return { ...lobby, status: LobbyStatus.score };\n\n default:\n return lobby;\n }\n};\n\n// Prepares the lobby for the next step\nconst prepareStep = (lobby: Lobby, index: number): Lobby => {\n const step = lobby.quiz.steps[index];\n \n if (!step) return lobby;\n\n if (step.type === \"slide\") {\n return { \n ...lobby, \n status: LobbyStatus.slide, \n currentStep: index \n };\n }\n\n return { \n ...lobby, \n status: LobbyStatus.question, \n currentStep: index,\n timeoutStartedAt: null,\n duration: null,\n currentAnswers: []\n };\n};\n\nexport type SubmissionResult = {\n nextLobby: Lobby;\n result: PlayerAnswerResult;\n};\n\nexport const handleSubmission = (\n lobby: Lobby, \n playerId: string, \n submission: SubmittedAnswer\n): SubmissionResult | null => {\n if (lobby.status !== LobbyStatus.answer) return null;\n\n const step = lobby.quiz.steps[lobby.currentStep];\n if (!isQuestion(step)) return null;\n\n const player = lobby.players.find(p => p.id === playerId);\n if (!player) return null;\n\n if (lobby.currentAnswers.some(a => a.playerId === playerId)) return null;\n\n const correct = isCorrect(step.data, submission);\n const timeTaken = Date.now() - (lobby.timeoutStartedAt ?? 0);\n\n const answerObj: Answer = {\n playerId,\n submission,\n timeTaken,\n isCorrect: correct,\n pointsAwarded: 0\n };\n\n const { newScore, pointsAwarded } = calculateScore(player, step.data, answerObj, lobby.quiz);\n answerObj.pointsAwarded = pointsAwarded;\n\n const nextLobby: Lobby = {\n ...lobby,\n players: lobby.players.map(p => p.id === playerId ? {\n ...p,\n score: newScore,\n streak: correct ? p.streak + 1 : 0\n } : p),\n currentAnswers: [...lobby.currentAnswers, answerObj]\n };\n\n return {\n nextLobby,\n result: {\n type: \"PLAYER_ANSWER_RESULT\",\n payload: { isCorrect: correct, pointsAwarded, score: newScore, streak: correct ? player.streak + 1 : 0 }\n }\n };\n};","import z from \"zod\";\nimport { BaseQuestionSchema } from \"../question\";\n\nexport const TrueFalseQuestionSchema = BaseQuestionSchema.extend({\n type: z.literal(\"true-false\"),\n answer: z.boolean(),\n labels: z.array(z.string()).min(2).max(2),\n});\n\nexport type TrueFalseQuestion = z.infer<typeof TrueFalseQuestionSchema>;\n\nexport const SafeTrueFalseQuestionSchema = TrueFalseQuestionSchema.omit({ answer: true });\n\nexport type SafeTrueFalseQuestion = z.infer<typeof SafeTrueFalseQuestionSchema>;\n\nexport const TrueFalseQuestionAnswerSchema = z.object({\n type: z.literal(\"true-false\"),\n answer: z.boolean(),\n});\n\nexport type TrueFalseQuestionAnswer = z.infer<typeof TrueFalseQuestionAnswerSchema>;\n","import z from \"zod\";\nimport { BaseQuestionSchema } from \"../question\";\n\nexport const ShortAnswerQuestionSchema = BaseQuestionSchema.extend({\n type: z.literal(\"short-answer\"),\n answers: z.array(z.string()).min(1),\n});\n\nexport type ShortAnswerQuestion = z.infer<typeof ShortAnswerQuestionSchema>;\n\nexport const SafeShortAnswerQuestionSchema = ShortAnswerQuestionSchema.omit({ answers: true });\n\nexport type SafeShortAnswerQuestion = z.infer<typeof SafeShortAnswerQuestionSchema>;\n\nexport const ShortAnswerQuestionAnswerSchema = z.object({\n type: z.literal(\"short-answer\"),\n answer: z.string(),\n});\n\nexport type ShortAnswerQuestionAnswer = z.infer<typeof ShortAnswerQuestionAnswerSchema>;\n","import z from \"zod\";\nimport { MultipleChoiceQuestion, MultipleChoiceQuestionSchema, SafeMultipleChoiceQuestion, SafeMultipleChoiceQuestionSchema } from \"./questions/multiple-choice\";\nimport { SafeTrueFalseQuestion, SafeTrueFalseQuestionSchema, TrueFalseQuestion, TrueFalseQuestionSchema } from \"./questions/true-false\";\nimport { SafeShortAnswerQuestion, SafeShortAnswerQuestionSchema, ShortAnswerQuestion, ShortAnswerQuestionSchema } from \"./questions/short-answer\";\n\nexport type Question = MultipleChoiceQuestion | TrueFalseQuestion | ShortAnswerQuestion;\n\nexport const QuestionSchema = z.discriminatedUnion(\"type\", [\n MultipleChoiceQuestionSchema,\n TrueFalseQuestionSchema,\n ShortAnswerQuestionSchema,\n]);\n\nexport type SafeQuestion =\n | SafeMultipleChoiceQuestion\n | SafeTrueFalseQuestion\n | SafeShortAnswerQuestion;\n\nexport const SafeQuestionSchema = z.discriminatedUnion(\"type\", [\n SafeMultipleChoiceQuestionSchema,\n SafeTrueFalseQuestionSchema,\n SafeShortAnswerQuestionSchema,\n]);\n\nexport type QuestionPoints = z.infer<typeof QuestionPointsSchema>;\n\nexport const QuestionPointsSchema = z.enum([\"normalPoints\", \"doublePoints\", \"noPoints\"]);\n\nexport type BaseQuestion = z.infer<typeof BaseQuestionSchema>;\n\nexport const BaseQuestionSchema = z.object({\n question: z.string().min(1),\n imageHash: z.hash(\"sha256\", { error: \"Invalid image hash\" }).optional(),\n displayTime: z.number().min(1).max(60),\n timeLimit: z.number().min(1).max(180),\n points: QuestionPointsSchema,\n});","import z from \"zod\";\nimport { BaseQuestionSchema } from \"../question\";\n\nexport const ChoiceSchema = z.object({\n text: z.string(),\n correct: z.boolean(),\n});\n\nexport type Choice = z.infer<typeof ChoiceSchema>;\n\nexport const SafeChoiceSchema = ChoiceSchema.omit({ correct: true });\n\nexport type SafeChoice = z.infer<typeof SafeChoiceSchema>;\n\nexport const MultipleChoiceQuestionSchema = BaseQuestionSchema.extend({\n type: z.literal(\"multiple-choice\"),\n choices: z.array(ChoiceSchema).min(2),\n matchAll: z.boolean(),\n});\n\nexport type MultipleChoiceQuestion = z.infer<typeof MultipleChoiceQuestionSchema>;\n\nexport const SafeMultipleChoiceQuestionSchema = MultipleChoiceQuestionSchema.omit({ \n choices: true \n}).extend({\n choices: z.array(SafeChoiceSchema).min(2),\n});\n\nexport type SafeMultipleChoiceQuestion = z.infer<typeof SafeMultipleChoiceQuestionSchema>;\n\nexport const MultipleChoiceQuestionAnswerSchema = z.object({\n type: z.literal(\"multiple-choice\"),\n choices: z.array(z.number()).min(1),\n});\n\nexport type MultipleChoiceQuestionAnswer = z.infer<typeof MultipleChoiceQuestionAnswerSchema>;","import z from \"zod\";\n\nexport type QuizTheme = z.infer<typeof QuizThemeSchema>;\n\nexport const QuizThemeSchema = z.object({\n color: z.string().regex(\n /^#[0-9a-fA-F]{6}$/,\n { message: 'Invalid color format. Must be a 7-character hex code (e.g., #RRGGBB).' }\n ),\n background: z.hash(\"sha256\", { error: \"Invalid background hash\" }).optional(),\n});","import z from \"zod\";\n\nexport const TitleSlideLayoutSchema = z.object({\n slideType: z.literal(\"title\"),\n title: z.string(),\n subtitle: z.string().optional(),\n});\n\nexport type TitleSlideLayout = z.infer<typeof TitleSlideLayoutSchema>;","import z from \"zod\";\n\nexport const TitleImageTextSlideLayoutSchema = z.object({\n slideType: z.literal(\"titleImageText\"),\n title: z.string(),\n imageHash: z.hash(\"sha256\", { error: \"Invalid image hash\" }).optional(),\n text: z.string(),\n});\n\nexport type TitleImageTextSlideLayout = z.infer<typeof TitleImageTextSlideLayoutSchema>;\n","import z from \"zod\";\n\nexport const ComparisonSlideLayoutSchema = z.object({\n slideType: z.literal(\"comparison\"),\n title: z.string(),\n left: z.string(),\n right: z.string(),\n});\n\nexport type ComparisonSlideLayout = z.infer<typeof ComparisonSlideLayoutSchema>;\n","import z from \"zod\";\nimport { TitleSlideLayoutSchema } from \"./slides/titleSlide\";\nimport { TitleImageTextSlideLayoutSchema } from \"./slides/titleImageTextSlide\";\nimport { ComparisonSlideLayoutSchema } from \"./slides/comparison\";\n\nexport type Slide = z.infer<typeof SlideSchema>;\n\nexport const SlideSchema = z.discriminatedUnion(\"slideType\", [\n TitleSlideLayoutSchema,\n TitleImageTextSlideLayoutSchema,\n ComparisonSlideLayoutSchema\n]);\n","import z from \"zod\";\nimport { Question, QuestionSchema } from \"./question\";\nimport { Slide, SlideSchema } from \"./slide\";\n\nexport type QuizStep =\n | {\n type: \"question\";\n data: Question;\n }\n | {\n type: \"slide\";\n data: Slide;\n };\n\nexport const QuizStepSchema = z.discriminatedUnion(\"type\", [\n z.object({ type: z.literal(\"question\"), data: QuestionSchema }),\n z.object({ type: z.literal(\"slide\"), data: SlideSchema }),\n]);","import z from \"zod\";\nimport { QuizThemeSchema } from \"./quiztheme\";\nimport { QuizStepSchema } from \"./quizstep\";\n\nexport type QuizFile = z.infer<typeof QuizFileSchema>;\n\nexport const QuizFileSchema = z.object({\n id: z.uuid(),\n version: z.literal(2),\n\n title: z.string()\n .min(1, \"Title must be atleast 1 character long\")\n .max(64, \"Title can't be longer than 64 characters\"),\n description: z.string()\n .max(255, \"Description can't be longer than 256 characters\")\n .optional(),\n theme: QuizThemeSchema,\n language: z.string()\n .length(2, \"Language must be a 2-letter ISO 639-1 code\"),\n\n steps: z.array(QuizStepSchema)\n .min(1, \"Quiz must have at least 1 step\"),\n\n images: z.record(\n z.hash(\"sha256\", { error: \"Invalid image hash\" }),\n z.string().refine((val) => {\n return val.startsWith(\"http\") || val.startsWith(\"data:image/\");\n }, \"Image must be a valid URL or Base64 data string\")\n ),\n\n updatedAt: z.iso.datetime(),\n createdAt: z.iso.datetime(),\n});","","","","import animals from \"./animals.json\";\nimport additives from \"./additives.json\";\nimport colors from \"./colors.json\";\nimport { Player } from \"../../types/lobby\";\n\nexport const generateName = (): string => {\n const animal = animals[Math.floor(Math.random() * animals.length)];\n const additive = additives[Math.floor(Math.random() * additives.length)];\n const color = colors[Math.floor(Math.random() * colors.length)];\n\n return `${color}${additive}${animal}`;\n};\n\nexport const generateUniqueName = (players: Player[]): string => {\n const maxPossible = animals.length * additives.length * colors.length;\n\n if (players.length >= maxPossible) {\n throw new Error(\"No unique names available\");\n }\n\n const existingNames = new Set(players.map((p) => p.name));\n \n for (let i = 0; i < 100; i++) {\n const candidate = generateName();\n if (!existingNames.has(candidate)) return candidate;\n }\n\n for (const c of colors) {\n for (const ad of additives) {\n for (const an of animals) {\n const candidate = `${c}${ad}${an}`;\n if (!existingNames.has(candidate)) return candidate;\n }\n }\n }\n\n throw new Error(\"No unique names available\"); // Fallback\n};","import { Question, SafeQuestion } from \"../types/question\";\nimport { isMultipleChoice, isShortAnswer, isTrueFalse } from \"./guards\";\n\nexport const sanitizeQuestion = (question: Question): SafeQuestion => {\n if (isMultipleChoice(question)) {\n return {\n ...question,\n choices: question.choices.map(({ text }) => ({ text })),\n };\n }\n\n if (isTrueFalse(question)) {\n const { answer, ...sanitized } = question;\n return sanitized;\n }\n\n if (isShortAnswer(question)) {\n const { answers, ...sanitized } = question;\n return sanitized;\n }\n\n throw new Error(\"Invalid question type\");\n};"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quizpot/quizcore",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Core library for Quizpot",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -8,9 +8,8 @@
8
8
  "dist"
9
9
  ],
10
10
  "scripts": {
11
- "watch": "tsc --watch",
12
- "build": "tsc",
13
- "prepare": "npm run build"
11
+ "build": "tsdown src/index.ts --format esm,cjs --dts --clean",
12
+ "watch": "tsdown src/index.ts --format esm,cjs --dts --watch"
14
13
  },
15
14
  "exports": {
16
15
  ".": {
@@ -20,6 +19,7 @@
20
19
  }
21
20
  },
22
21
  "devDependencies": {
22
+ "tsdown": "^0.21.7",
23
23
  "typescript": "^5.9.3"
24
24
  },
25
25
  "dependencies": {
@@ -1,8 +0,0 @@
1
- export type KickPlayer = {
2
- type: "KICK_PLAYER";
3
- payload: {
4
- playerId: string;
5
- };
6
- };
7
- export declare const createKickPlayerEvent: (playerId: string) => KickPlayer;
8
- //# sourceMappingURL=kick-player.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"kick-player.d.ts","sourceRoot":"","sources":["../../../../src/events/client/host/kick-player.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,KAAG,UAGvD,CAAC"}
@@ -1,4 +0,0 @@
1
- export const createKickPlayerEvent = (playerId) => ({
2
- type: "KICK_PLAYER",
3
- payload: { playerId }
4
- });
@@ -1,5 +0,0 @@
1
- export type NextStep = {
2
- type: "NEXT_STEP";
3
- };
4
- export declare const createNextStepEvent: () => NextStep;
5
- //# sourceMappingURL=next-step.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"next-step.d.ts","sourceRoot":"","sources":["../../../../src/events/client/host/next-step.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,WAAW,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,mBAAmB,QAAO,QAErC,CAAC"}
@@ -1,3 +0,0 @@
1
- export const createNextStepEvent = () => ({
2
- type: "NEXT_STEP",
3
- });
@@ -1,6 +0,0 @@
1
- export type StartLobby = {
2
- type: "START_LOBBY";
3
- payload: {};
4
- };
5
- export declare const createStartLobbyEvent: () => StartLobby;
6
- //# sourceMappingURL=start-lobby.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"start-lobby.d.ts","sourceRoot":"","sources":["../../../../src/events/client/host/start-lobby.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,EAAE,CAAC;CACb,CAAC;AAEF,eAAO,MAAM,qBAAqB,QAAO,UAGvC,CAAC"}