File size: 32,011 Bytes
f91a684
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
// ─── RYP Quest Data ─────────────────────────────────────────────────────────
// Defines all quest tracks, their stages, and reward metadata.
// Item IDs map directly to existing data files (codingQuestions, systemDesignData, etc.)

export type ItemType = 'coding' | 'system-design' | 'cs-fundamentals' | 'aptitude';
export type NodeType = 'stage' | 'milestone' | 'mystery';

export interface QuestNode {
  id: string;
  title: string;
  description: string;
  type: NodeType;
  itemType: ItemType;
  itemIds: string[];       // IDs from source data files
  coinReward: number;
  /** Canvas position as percentage [0-100] of container width/height */
  x: number;
  y: number;
  /** Optional section/chapter label β€” rendered as a divider when it changes */
  section?: string;
  /** Optional treasure hunt thematic description for the section */
  sectionDesc?: string;
}

export interface Quest {
  id: string;
  title: string;
  tagline: string;
  description: string;
  icon: string;
  /** Tailwind gradient class for cards */
  gradient: string;
  /** Primary hex color for neon effects */
  colorPrimary: string;
  /** RGBA glow color */
  colorGlow: string;
  /** CSS background for the map canvas */
  mapBg: string;
  nodes: QuestNode[];
  totalCoins: number;
  badge: string;
  badgeIcon: string;
  isWeekly?: boolean;
}

// ─── Helper to get current ISO week key ─────────────────────────────────────
export function getWeekKey(date = new Date()): string {
  const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
  const dayNum = d.getUTCDay() || 7;
  d.setUTCDate(d.getUTCDate() + 4 - dayNum);
  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
  const weekNo = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
  return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;
}

export function getNextMondayMidnight(): Date {
  const now = new Date();
  const day = now.getDay(); // 0=Sun, 1=Mon...
  const daysUntilMonday = day === 0 ? 1 : 8 - day;
  const next = new Date(now);
  next.setDate(now.getDate() + daysUntilMonday);
  next.setHours(0, 0, 0, 0);
  return next;
}

// ─── Zigzag x-position helper ────────────────────────────────────────────────
const ZIG = [55, 72, 55, 30, 55, 72, 55, 30];
function zigX(i: number) { return ZIG[i % ZIG.length]; }

// ─── 1. DSA Quest β€” 16 Chapters ─────────────────────────────────────────────
const dsaQuest: Quest = {
  id: 'dsa-quest',
  title: 'DSA Quest',
  tagline: 'Master the art of algorithms',
  description: 'A 16-chapter odyssey through the complete DSA roadmap β€” from Basics to Advanced Patterns. Conquer 126 topics, earn coins, and claim the DSA Master badge.',
  icon: '🧠',
  gradient: 'from-indigo-500 to-blue-600',
  colorPrimary: '#6366f1',
  colorGlow: 'rgba(99,102,241,0.4)',
  mapBg: 'radial-gradient(ellipse at 20% 30%, rgba(99,102,241,0.15) 0%, transparent 60%), radial-gradient(ellipse at 80% 70%, rgba(59,130,246,0.12) 0%, transparent 60%), #05050f',
  badge: 'DSA Master',
  badgeIcon: 'πŸ†',
  totalCoins: 2680,
  nodes: (() => {
    let idx = 0;
    let curSection = '';
    let curSectionDesc = '';
    const n: QuestNode[] = [];
    const push = (id: string, title: string, desc: string, type: NodeType, ids: string[], reward: number) => {
      n.push({ id, title, description: desc, type, itemType: 'coding', itemIds: ids, coinReward: reward, x: zigX(idx), y: 0, section: curSection, sectionDesc: curSectionDesc });
      idx++;
    };
    const chapter = (name: string, description: string) => { 
      curSection = name; 
      curSectionDesc = description;
    };
    const milestone = (id: string, title: string, desc: string, reward: number) => {
      push(id, title, desc, 'milestone', [id], reward);
    };

    // ── Ch 1: BASICS ──
    chapter('Basics', 'Learn to tell your `if`s from your `else`s before you accidentally loop yourself off the plank.');
    push('dsa-1-1', 'Time & Space Complexity', 'Analyze efficiency of algorithms', 'stage', ['dsa-1-1'], 15);
    push('dsa-1-2', 'Recursion Basics', 'Master the art of self-calling functions', 'stage', ['dsa-1-2'], 15);
    push('dsa-1-3', 'Math: GCD, LCM, Primes, Modulo', 'Number theory fundamentals', 'stage', ['dsa-1-3'], 15);
    push('dsa-1-4', 'I/O, Conditionals, Loops', 'Core programming constructs', 'stage', ['dsa-1-4'], 15);
    milestone('dsa-m1', 'βš“ Chapter I Complete', 'BASICS mastered β€” set sail!', 40);

    // ── Ch 2: ARRAYS ──
    chapter('Arrays', 'A contiguous row of treasure chests. Try not to drop an IndexOutOfBounds anchor on your toe.');
    push('dsa-2-1', 'Traversal, Insertion, Deletion', 'Array fundamentals', 'stage', ['dsa-2-1'], 15);
    push('dsa-2-2', 'Prefix Sum', 'Running totals for range queries', 'stage', ['dsa-2-2'], 15);
    push('dsa-2-3', 'Subarrays / Submatrices', 'Contiguous sub-structure problems', 'stage', ['dsa-2-3'], 15);
    push('dsa-2-4', 'Two Pointers', 'Converge from both ends', 'stage', ['two-sum', 'three-sum'], 15);
    push('dsa-2-5', 'Sliding Window', 'Fixed & variable window techniques', 'stage', ['dsa-2-5'], 15);
    push('dsa-2-6', 'Kadane\'s Algorithm', 'Maximum subarray sum', 'stage', ['max-subarray'], 15);
    push('dsa-2-7', 'Sorting-based Problems', 'Solve via sort-first approach', 'stage', ['dsa-2-7'], 15);
    milestone('dsa-m2', 'βš“ Chapter II Complete', 'ARRAYS conquered!', 40);

    // ── Ch 3: STRINGS ──
    chapter('Strings', 'Parrot-speak deciphering. Find anagrams, palindromes, and substrings hidden in pirate curses.');
    push('dsa-3-1', 'String Traversal', 'Iterate and manipulate characters', 'stage', ['dsa-3-1'], 15);
    push('dsa-3-2', 'Palindrome', 'Mirror symmetry in strings', 'stage', ['dsa-3-2'], 15);
    push('dsa-3-3', 'Anagram', 'Character frequency matching', 'stage', ['dsa-3-3'], 15);
    push('dsa-3-4', 'Pattern Matching', 'KMP, Rabin-Karp, and more', 'stage', ['dsa-3-4'], 15);
    push('dsa-3-5', 'Substrings / Subsequences', 'Contiguous vs non-contiguous', 'stage', ['longest-substring-without-repeating'], 15);
    push('dsa-3-6', 'Frequency Counting', 'HashMap-based character analysis', 'stage', ['dsa-3-6'], 15);
    push('dsa-3-7', 'String Hashing Basics', 'Rolling hash for pattern search', 'stage', ['dsa-3-7'], 15);
    milestone('dsa-m3', 'βš“ Chapter III Complete', 'STRINGS decoded!', 40);

    // ── Ch 4: LINKED LIST ──
    chapter('Linked List', 'A trail of bottles bobbing in the sea, each pointing to the next. Lose one pointer, lose the whole fleet.');
    push('dsa-4-1', 'Singly Linked List', 'One-directional node chains', 'stage', ['dsa-4-1'], 15);
    push('dsa-4-2', 'Doubly Linked List', 'Bidirectional traversal', 'stage', ['dsa-4-2'], 15);
    push('dsa-4-3', 'Fast & Slow Pointers', 'Floyd\'s tortoise and hare', 'stage', ['dsa-4-3'], 15);
    push('dsa-4-4', 'Reverse Linked List', 'In-place reversal techniques', 'stage', ['dsa-4-4'], 15);
    push('dsa-4-5', 'Merge Two Lists', 'Combine sorted chains', 'stage', ['dsa-4-5'], 15);
    push('dsa-4-6', 'Detect Cycle', 'Find loops in linked structures', 'stage', ['dsa-4-6'], 15);
    push('dsa-4-7', 'Intersection Problems', 'Where two lists meet', 'stage', ['dsa-4-7'], 15);
    milestone('dsa-m4', 'βš“ Chapter IV Complete', 'LINKED LIST mastered!', 40);

    // ── Ch 5: STACK & QUEUE ──
    chapter('Stack & Queue', 'Stuff cannons with cannonballs (LIFO) and line up your crew for grog (FIFO). Don\'t mess up the order!');
    push('dsa-5-1', 'Stack Operations', 'LIFO push, pop, peek', 'stage', ['dsa-5-1'], 15);
    push('dsa-5-2', 'Queue Operations', 'FIFO enqueue, dequeue', 'stage', ['dsa-5-2'], 15);
    push('dsa-5-3', 'Deque', 'Double-ended queue', 'stage', ['dsa-5-3'], 15);
    push('dsa-5-4', 'Monotonic Stack / Queue', 'Maintain sorted order constraints', 'stage', ['dsa-5-4'], 15);
    push('dsa-5-5', 'Next Greater / Smaller', 'Classic monotonic stack pattern', 'stage', ['dsa-5-5'], 15);
    push('dsa-5-6', 'Valid Parentheses', 'Bracket matching and nesting', 'stage', ['dsa-5-6'], 15);
    push('dsa-5-7', 'Sliding Window Maximum', 'Deque-based window optimization', 'stage', ['dsa-5-7'], 15);
    milestone('dsa-m5', 'βš“ Chapter V Complete', 'STACK & QUEUE unlocked!', 40);

    // ── Ch 6: SEARCHING & SORTING ──
    chapter('Searching & Sorting', 'Stop rummaging blindly! Learn to O(log n) search for the rum and sort the gold from the barnacles.');
    push('dsa-6-1', 'Linear Search', 'Brute-force element finding', 'stage', ['dsa-6-1'], 15);
    push('dsa-6-2', 'Binary Search', 'Divide and conquer O(log n)', 'stage', ['dsa-6-2'], 15);
    push('dsa-6-3', 'Lower / Upper Bound', 'Boundary finding in sorted data', 'stage', ['dsa-6-3'], 15);
    push('dsa-6-4', 'Search in Rotated Array', 'Modified binary search', 'stage', ['dsa-6-4'], 15);
    push('dsa-6-5', 'Merge Sort', 'Stable divide-and-conquer sort', 'stage', ['dsa-6-5'], 15);
    push('dsa-6-6', 'Quick Sort', 'Partition-based sorting', 'stage', ['dsa-6-6'], 15);
    push('dsa-6-7', 'Heap Sort', 'Priority-queue based sorting', 'stage', ['dsa-6-7'], 15);
    push('dsa-6-8', 'Counting / Radix / Bucket Sort', 'Non-comparison sorting techniques', 'stage', ['dsa-6-8'], 15);
    milestone('dsa-m6', 'βš“ Chapter VI Complete', 'SEARCHING & SORTING conquered!', 40);

    // ── Ch 7: HASHING ──
    chapter('Hashing', 'The captain\'s magical ledger. Instantly O(1) look up who stole your boots using secret hash keys.');
    push('dsa-7-1', 'HashMap / HashSet', 'O(1) lookup data structures', 'stage', ['dsa-7-1'], 15);
    push('dsa-7-2', 'Frequency Maps', 'Count occurrences efficiently', 'stage', ['dsa-7-2'], 15);
    push('dsa-7-3', 'Duplicate Detection', 'Find repeats with hashing', 'stage', ['contains-duplicate'], 15);
    push('dsa-7-4', 'Two Sum Pattern', 'Complement lookup technique', 'stage', ['two-sum'], 15);
    push('dsa-7-5', 'Grouping Problems', 'Group anagrams and similar', 'stage', ['dsa-7-5'], 15);
    push('dsa-7-6', 'Prefix-Hash Technique', 'Subarray sum equals k', 'stage', ['dsa-7-6'], 15);
    milestone('dsa-m7', 'βš“ Chapter VII Complete', 'HASHING mastered!', 40);

    // ── Ch 8: TREES ──
    chapter('Trees', 'Climb the recursive rigging! Branches split left and right, but beware of violently unbalanced heights.');
    push('dsa-8-1', 'Binary Tree Basics', 'Nodes, edges, root, leaf', 'stage', ['dsa-8-1'], 15);
    push('dsa-8-2', 'Tree Traversals', 'Preorder, Inorder, Postorder, Level Order', 'stage', ['level-order-traversal'], 15);
    push('dsa-8-3', 'Height, Depth, Diameter', 'Core tree metrics', 'stage', ['max-depth-bt'], 15);
    push('dsa-8-4', 'Left / Right View', 'Side-view projections', 'stage', ['dsa-8-4'], 15);
    push('dsa-8-5', 'Balanced Tree', 'AVL condition and checks', 'stage', ['dsa-8-5'], 15);
    push('dsa-8-6', 'Tree Construction', 'Build trees from traversals', 'stage', ['dsa-8-6'], 15);
    push('dsa-8-7', 'Lowest Common Ancestor', 'Find shared ancestor nodes', 'stage', ['dsa-8-7'], 15);
    milestone('dsa-m8', 'βš“ Chapter VIII Complete', 'TREES explored!', 40);

    // ── Ch 9: ADVANCED TREES ──
    chapter('Advanced Trees', 'Mutant sea-weed structures. Heaps, Tries, and AVL trees for when normal branches just don\'t cut it.');
    push('dsa-9-1', 'Binary Search Tree', 'Ordered tree operations', 'stage', ['dsa-9-1'], 15);
    push('dsa-9-2', 'AVL Tree Basics', 'Self-balancing rotations', 'stage', ['dsa-9-2'], 15);
    push('dsa-9-3', 'Heap / Priority Queue', 'Min-heap and max-heap', 'stage', ['dsa-9-3'], 15);
    push('dsa-9-4', 'Trie', 'Prefix tree for strings', 'stage', ['dsa-9-4'], 15);
    push('dsa-9-5', 'Segment Tree', 'Range queries & updates', 'stage', ['dsa-9-5'], 15);
    push('dsa-9-6', 'Fenwick Tree / BIT', 'Binary indexed tree', 'stage', ['dsa-9-6'], 15);
    push('dsa-9-7', 'Tree Serialization', 'Encode and decode trees', 'stage', ['dsa-9-7'], 15);
    milestone('dsa-m9', 'βš“ Chapter IX Complete', 'ADVANCED TREES mastered!', 40);

    // ── Ch 10: GRAPHS ──
    chapter('Graphs', 'Navigate the treacherous archipelago. Find the shortest path before the BFS (Breadth-First Shark) finds you.');
    push('dsa-10-1', 'Graph Representation', 'Adjacency list & matrix', 'stage', ['dsa-10-1'], 15);
    push('dsa-10-2', 'BFS / DFS', 'Breadth-first & depth-first', 'stage', ['number-of-islands'], 15);
    push('dsa-10-3', 'Connected Components', 'Find isolated subgraphs', 'stage', ['dsa-10-3'], 15);
    push('dsa-10-4', 'Cycle Detection', 'Detect loops in graphs', 'stage', ['dsa-10-4'], 15);
    push('dsa-10-5', 'Topological Sort', 'Order DAG dependencies', 'stage', ['course-schedule-i'], 15);
    push('dsa-10-6', 'Shortest Path Algorithms', 'BFS for unweighted graphs', 'stage', ['dsa-10-6'], 15);
    push('dsa-10-7', 'MST: Kruskal & Prim', 'Minimum spanning tree', 'stage', ['dsa-10-7'], 15);
    push('dsa-10-8', 'Dijkstra, Bellman-Ford, Floyd-Warshall', 'Weighted shortest paths', 'stage', ['dsa-10-8'], 15);
    push('dsa-10-9', 'Union-Find / Disjoint Set', 'Efficient connectivity queries', 'stage', ['dsa-10-9'], 15);
    milestone('dsa-m10', 'βš“ Chapter X Complete', 'GRAPHS navigated!', 40);

    // ── Ch 11: GREEDY ──
    chapter('Greedy', 'Take the biggest, shiniest loot right now! Worry about the optimal substructure of your sinking ship later.');
    push('dsa-11-1', 'Greedy Choice Principle', 'Local optimum β†’ global optimum', 'stage', ['dsa-11-1'], 15);
    push('dsa-11-2', 'Interval Scheduling', 'Maximize non-overlapping intervals', 'stage', ['dsa-11-2'], 15);
    push('dsa-11-3', 'Activity Selection', 'Classic greedy scheduling', 'stage', ['dsa-11-3'], 15);
    push('dsa-11-4', 'Fractional Knapsack', 'Greedy value-to-weight ratio', 'stage', ['dsa-11-4'], 15);
    push('dsa-11-5', 'Minimum Platforms / Meetings', 'Overlap counting', 'stage', ['dsa-11-5'], 15);
    push('dsa-11-6', 'Job Sequencing', 'Deadline-based scheduling', 'stage', ['dsa-11-6'], 15);
    push('dsa-11-7', 'Huffman-style Greedy', 'Optimal merge pattern', 'stage', ['dsa-11-7'], 15);
    milestone('dsa-m11', 'βš“ Chapter XI Complete', 'GREEDY strategies unlocked!', 40);

    // ── Ch 12: DYNAMIC PROGRAMMING ──
    chapter('Dynamic Programming', 'Write down your past mistakes in a table so you don\'t repeatedly sail into the exact same whirlpools.');
    push('dsa-12-1', 'Memoization', 'Top-down DP with caching', 'stage', ['dsa-12-1'], 15);
    push('dsa-12-2', 'Tabulation', 'Bottom-up iterative DP', 'stage', ['dsa-12-2'], 15);
    push('dsa-12-3', '1D DP', 'Single-dimension state transitions', 'stage', ['climbing-stairs'], 15);
    push('dsa-12-4', '2D DP', 'Grid and matrix DP', 'stage', ['dsa-12-4'], 15);
    push('dsa-12-5', 'Knapsack Patterns', '0/1 and unbounded knapsack', 'stage', ['coin-change-ii'], 15);
    push('dsa-12-6', 'LIS / LCS', 'Longest increasing/common subsequence', 'stage', ['longest-increasing-subsequence'], 15);
    push('dsa-12-7', 'Subsequence DP', 'Count and optimize subsequences', 'stage', ['dsa-12-7'], 15);
    push('dsa-12-8', 'Grid DP', 'Unique paths and min cost paths', 'stage', ['dsa-12-8'], 15);
    push('dsa-12-9', 'Partition DP', 'Optimal partition problems', 'stage', ['dsa-12-9'], 15);
    push('dsa-12-10', 'DP on Trees / Graphs', 'State transitions on structures', 'stage', ['dsa-12-10'], 15);
    milestone('dsa-m12', 'βš“ Chapter XII Complete', 'DYNAMIC PROGRAMMING conquered!', 40);

    // ── Ch 13: BACKTRACKING ──
    chapter('Backtracking', 'Explore every spooky cave. If you hit a dead end, furiously row backward and try the other tunnel.');
    push('dsa-13-1', 'Subsets', 'Generate all subsets', 'stage', ['dsa-13-1'], 15);
    push('dsa-13-2', 'Permutations', 'All possible arrangements', 'stage', ['dsa-13-2'], 15);
    push('dsa-13-3', 'Combinations', 'Choose k from n', 'stage', ['dsa-13-3'], 15);
    push('dsa-13-4', 'N-Queens', 'Place queens non-attacking', 'stage', ['dsa-13-4'], 15);
    push('dsa-13-5', 'Sudoku', 'Constraint satisfaction solving', 'stage', ['dsa-13-5'], 15);
    push('dsa-13-6', 'Rat in a Maze', 'Path finding with backtracking', 'stage', ['dsa-13-6'], 15);
    push('dsa-13-7', 'Word Search', 'Grid character path search', 'stage', ['dsa-13-7'], 15);
    milestone('dsa-m13', 'βš“ Chapter XIII Complete', 'BACKTRACKING mastered!', 40);

    // ── Ch 14: BIT MANIPULATION ──
    chapter('Bit Manipulation', 'Flipping magical 1s and 0s. Conjure bitwise voodoo to solve problems faster than a cannon blast.');
    push('dsa-14-1', 'AND, OR, XOR, NOT', 'Bitwise operator fundamentals', 'stage', ['sum-two-integers'], 15);
    push('dsa-14-2', 'Left / Right Shift', 'Binary shift operations', 'stage', ['dsa-14-2'], 15);
    push('dsa-14-3', 'Check/Set/Clear/Toggle Bit', 'Single bit operations', 'stage', ['dsa-14-3'], 15);
    push('dsa-14-4', 'Count Set Bits', 'Hamming weight / popcount', 'stage', ['number-of-1-bits'], 15);
    push('dsa-14-5', 'Power of Two', 'Bit trick for power detection', 'stage', ['dsa-14-5'], 15);
    push('dsa-14-6', 'XOR-based Problems', 'Single number, missing number', 'stage', ['missing-number'], 15);
    push('dsa-14-7', 'Bitmasking Basics', 'Subset representation with bits', 'stage', ['counting-bits'], 15);
    milestone('dsa-m14', 'βš“ Chapter XIV Complete', 'BIT MANIPULATION unlocked!', 40);

    // ── Ch 15: ADVANCED ──
    chapter('Advanced', 'The Bermuda Triangle of algorithms. Segment trees and sparse tables that swallow novice sailors whole.');
    push('dsa-15-1', 'Trie Advanced', 'Auto-complete and word dictionaries', 'stage', ['dsa-15-1'], 15);
    push('dsa-15-2', 'Segment Tree Advanced', 'Lazy propagation and more', 'stage', ['dsa-15-2'], 15);
    push('dsa-15-3', 'Lazy Propagation', 'Deferred updates on segment trees', 'stage', ['dsa-15-3'], 15);
    push('dsa-15-4', 'Fenwick Tree Advanced', 'Range update queries', 'stage', ['dsa-15-4'], 15);
    push('dsa-15-5', 'Sparse Table', 'O(1) range minimum queries', 'stage', ['dsa-15-5'], 15);
    push('dsa-15-6', 'Rolling Hash', 'Efficient substring matching', 'stage', ['dsa-15-6'], 15);
    push('dsa-15-7', 'Advanced DS Patterns', 'Combining structures creatively', 'stage', ['dsa-15-7'], 15);
    push('dsa-15-8', 'Advanced Graph Techniques', 'SCC, bridges, articulation points', 'stage', ['dsa-15-8'], 15);
    push('dsa-15-9', 'Divide & Conquer Optimization', 'Advanced DC techniques', 'stage', ['dsa-15-9'], 15);
    milestone('dsa-m15', 'βš“ Chapter XV Complete', 'ADVANCED techniques conquered!', 40);

    // ── Ch 16: PATTERNS ──
    chapter('Patterns', 'The ultimate pirate codex. Recognize the secret shapes of the sea to solve any interview riddle the Kraken throws at you.');
    push('dsa-16-1', 'Two Pointers Pattern', 'Recognize and apply two pointers', 'stage', ['dsa-16-1'], 15);
    push('dsa-16-2', 'Sliding Window Pattern', 'Identify sliding window problems', 'stage', ['dsa-16-2'], 15);
    push('dsa-16-3', 'Prefix Sum Pattern', 'Cumulative sum techniques', 'stage', ['dsa-16-3'], 15);
    push('dsa-16-4', 'Binary Search Pattern', 'Search space reduction', 'stage', ['dsa-16-4'], 15);
    push('dsa-16-5', 'Fast & Slow Pointer', 'Cycle and midpoint detection', 'stage', ['dsa-16-5'], 15);
    push('dsa-16-6', 'Monotonic Stack / Queue', 'Next greater / window max', 'stage', ['dsa-16-6'], 15);
    push('dsa-16-7', 'Interval Merging', 'Overlap and merge intervals', 'stage', ['dsa-16-7'], 15);
    push('dsa-16-8', 'BFS / DFS Pattern', 'Graph & tree traversal patterns', 'stage', ['clone-graph'], 15);
    push('dsa-16-9', 'Backtracking Pattern', 'Explore all possibilities', 'stage', ['dsa-16-9'], 15);
    push('dsa-16-10', 'DP Pattern', 'State, transition, base case', 'stage', ['dsa-16-10'], 15);
    push('dsa-16-11', 'Graph Pattern', 'Connected components, paths, DAGs', 'stage', ['dsa-16-11'], 15);
    milestone('dsa-m16', 'πŸ† DSA Master', 'ALL 16 CHAPTERS CONQUERED!', 100);

    return n;
  })(),
};

// ─── 2. System Design Quest ──────────────────────────────────────────────────
const systemDesignQuest: Quest = {
  id: 'system-design-quest',
  title: 'System Design Quest',
  tagline: 'Architect systems at scale',
  description: 'From fundamentals to production-grade design β€” load balancers, databases, caching, and distributed system patterns.',
  icon: 'πŸ—οΈ',
  gradient: 'from-cyan-500 to-teal-600',
  colorPrimary: '#06b6d4',
  colorGlow: 'rgba(6,182,212,0.4)',
  mapBg: 'radial-gradient(ellipse at 50% 20%, rgba(6,182,212,0.12) 0%, transparent 55%), linear-gradient(180deg, #030d10 0%, #050f14 100%)',
  badge: 'Architect',
  badgeIcon: 'πŸ›οΈ',
  totalCoins: 175,
  nodes: [
    {
      id: 'sd-s1', title: 'System Basics', description: 'CAP theorem, scalability, fundamentals',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-1', 'sd-2', 'sd-3'],
      coinReward: 25, x: 50, y: 8,
    },
    {
      id: 'sd-s2', title: 'Load Balancing', description: 'Distributing traffic at scale',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-lb-1', 'sd-lb-2', 'sd-lb-3'],
      coinReward: 30, x: 25, y: 26,
    },
    {
      id: 'sd-s3', title: 'Data Stores', description: 'SQL vs NoSQL, indexing, sharding',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-ds-1', 'sd-ds-2', 'sd-ds-3'],
      coinReward: 30, x: 70, y: 44,
    },
    {
      id: 'sd-s4', title: 'Performance', description: 'Caching, latency, and throughput',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-pp-1', 'sd-pp-2', 'sd-pp-3'],
      coinReward: 30, x: 30, y: 63,
    },
    {
      id: 'sd-m1', title: 'Architect\'s Summit', description: 'The Final Design Challenge',
      type: 'milestone', itemType: 'system-design',
      itemIds: ['sd-4', 'sd-5', 'sd-6'],
      coinReward: 60, x: 55, y: 84,
    },
  ],
};

// ─── 3. CS Fundamentals Quest ────────────────────────────────────────────────
const csFundamentalsQuest: Quest = {
  id: 'cs-fundamentals-quest',
  title: 'CS Fundamentals Quest',
  tagline: 'Build rock-solid computer science foundations',
  description: 'Master the core CS concepts that interviewers test β€” databases, operating systems, networking, and theory.',
  icon: 'πŸ“š',
  gradient: 'from-emerald-500 to-green-600',
  colorPrimary: '#10b981',
  colorGlow: 'rgba(16,185,129,0.4)',
  mapBg: 'radial-gradient(ellipse at 30% 60%, rgba(16,185,129,0.1) 0%, transparent 55%), radial-gradient(ellipse at 70% 20%, rgba(5,150,105,0.08) 0%, transparent 45%), #030d07',
  badge: 'CS Scholar',
  badgeIcon: 'πŸŽ“',
  totalCoins: 150,
  nodes: [
    {
      id: 'cs-s1', title: 'Databases', description: 'DBMS, SQL, transactions & indexing',
      type: 'stage', itemType: 'cs-fundamentals',
      itemIds: ['database__intro-dbms__0', 'database__intro-dbms__1', 'database__data-models__0'],
      coinReward: 30, x: 50, y: 8,
    },
    {
      id: 'cs-s2', title: 'Operating Systems', description: 'Processes, memory & file systems',
      type: 'stage', itemType: 'cs-fundamentals',
      itemIds: ['os__os-intro__0', 'os__process-management__0', 'os__memory-management__0'],
      coinReward: 30, x: 28, y: 32,
    },
    {
      id: 'cs-s3', title: 'Computer Networks', description: 'TCP/IP, DNS, HTTP & protocols',
      type: 'stage', itemType: 'cs-fundamentals',
      itemIds: ['computer-network__cn-intro__0', 'computer-network__cn-intro__1', 'computer-network__cn-intro__2'],
      coinReward: 30, x: 68, y: 57,
    },
    {
      id: 'cs-m1', title: 'Scholar\'s Peak', description: 'The Ultimate CS Challenge',
      type: 'milestone', itemType: 'cs-fundamentals',
      itemIds: ['os__file-systems__0', 'database__sql__0', 'computer-network__cn-intro__3'],
      coinReward: 60, x: 45, y: 82,
    },
  ],
};

// ─── 4. Aptitude Quest ───────────────────────────────────────────────────────
const aptitudeQuest: Quest = {
  id: 'aptitude-quest',
  title: 'Aptitude Quest',
  tagline: 'Sharpen your analytical edge',
  description: 'From quantitative reasoning to data interpretation β€” master the aptitude skills needed for placement tests and interviews.',
  icon: '🎯',
  gradient: 'from-amber-500 to-orange-600',
  colorPrimary: '#f59e0b',
  colorGlow: 'rgba(245,158,11,0.4)',
  mapBg: 'radial-gradient(ellipse at 60% 25%, rgba(245,158,11,0.1) 0%, transparent 50%), radial-gradient(ellipse at 20% 75%, rgba(234,88,12,0.08) 0%, transparent 45%), #0d0800',
  badge: 'Analyst',
  badgeIcon: 'πŸ“Š',
  totalCoins: 125,
  nodes: [
    {
      id: 'apt-s1', title: 'Quantitative Basics', description: 'Percentages, profit, interest',
      type: 'stage', itemType: 'aptitude',
      itemIds: ['quant/arithmetic/percentage', 'quant/arithmetic/profit-loss', 'quant/arithmetic/interest'],
      coinReward: 20, x: 55, y: 8,
    },
    {
      id: 'apt-s2', title: 'Logical Reasoning', description: 'Patterns, deductions & puzzles',
      type: 'stage', itemType: 'aptitude',
      itemIds: ['logical/coding-decoding', 'logical/blood-relations', 'logical/series'],
      coinReward: 20, x: 30, y: 28,
    },
    {
      id: 'apt-s3', title: 'Verbal Ability', description: 'Comprehension & language skills',
      type: 'stage', itemType: 'aptitude',
      itemIds: ['verbal/reading-comprehension', 'verbal/grammar', 'verbal/vocabulary'],
      coinReward: 20, x: 65, y: 50,
    },
    {
      id: 'apt-s4', title: 'Data Interpretation', description: 'Charts, tables & graphs',
      type: 'stage', itemType: 'aptitude',
      itemIds: ['di/bar-chart', 'di/pie-chart', 'di/line-graph'],
      coinReward: 20, x: 32, y: 70,
    },
    {
      id: 'apt-m1', title: 'Analyst\'s Throne', description: 'The Grand Aptitude Challenge',
      type: 'milestone', itemType: 'aptitude',
      itemIds: ['quant/arithmetic/ratio', 'logical/syllogism', 'di/mixed-graphs'],
      coinReward: 45, x: 55, y: 88,
    },
  ],
};

// ─── 5. Interview Sprint (Weekly) ────────────────────────────────────────────
const interviewSprint: Quest = {
  id: 'interview-sprint',
  title: 'Interview Sprint',
  tagline: '7 days. 7 stages. One champion.',
  description: 'A weekly gauntlet mixing coding, system design, and CS fundamentals. Resets every Monday. Are you fast enough?',
  icon: '⚑',
  gradient: 'from-violet-500 to-rose-600',
  colorPrimary: '#8b5cf6',
  colorGlow: 'rgba(139,92,246,0.45)',
  mapBg: 'radial-gradient(ellipse at 50% 50%, rgba(139,92,246,0.15) 0%, transparent 65%), radial-gradient(ellipse at 80% 20%, rgba(244,63,94,0.1) 0%, transparent 45%), #080008',
  badge: 'Sprint Champion',
  badgeIcon: '⚑',
  totalCoins: 300,
  isWeekly: true,
  nodes: [
    {
      id: 'sprint-d1', title: 'Day 1 β€” Warm Up', description: 'Easy array & CS basics',
      type: 'stage', itemType: 'coding',
      itemIds: ['two-sum', 'contains-duplicate', 'climbing-stairs'],
      coinReward: 30, x: 50, y: 5,
    },
    {
      id: 'sprint-d2', title: 'Day 2 β€” Design Intro', description: 'System design fundamentals',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-1', 'sd-2', 'sd-3'],
      coinReward: 35, x: 28, y: 18,
    },
    {
      id: 'sprint-d3', title: 'Day 3 β€” CS Core', description: 'OS and networking',
      type: 'stage', itemType: 'cs-fundamentals',
      itemIds: ['os__os-intro__0', 'computer-network__cn-intro__0', 'database__intro-dbms__0'],
      coinReward: 35, x: 68, y: 32,
    },
    {
      id: 'sprint-m1', title: 'Midpoint', description: 'The Sprint Checkpoint',
      type: 'milestone', itemType: 'coding',
      itemIds: ['max-subarray', 'product-except-self', 'max-depth-bt'],
      coinReward: 50, x: 42, y: 48,
    },
    {
      id: 'sprint-d5', title: 'Day 5 β€” Algorithms', description: 'DP and graph patterns',
      type: 'stage', itemType: 'coding',
      itemIds: ['longest-increasing-subsequence', 'number-of-islands', 'course-schedule-i'],
      coinReward: 40, x: 65, y: 64,
    },
    {
      id: 'sprint-d6', title: 'Day 6 β€” Scale Up', description: 'Advanced system design',
      type: 'stage', itemType: 'system-design',
      itemIds: ['sd-lb-1', 'sd-ds-1', 'sd-pp-1'],
      coinReward: 40, x: 28, y: 78,
    },
    {
      id: 'sprint-m2', title: 'Sprint Finale', description: 'The Champion\'s Trial',
      type: 'milestone', itemType: 'coding',
      itemIds: ['minimum-window-substring', 'word-break', 'serialize-deserialize-bt'],
      coinReward: 70, x: 54, y: 93,
    },
  ],
};

export const ALL_QUESTS: Quest[] = [
  dsaQuest,
  systemDesignQuest,
  csFundamentalsQuest,
  aptitudeQuest,
  interviewSprint,
];

// ─── Progress helpers ─────────────────────────────────────────────────────────

const PROGRESS_PREFIX = 'ryp.quest';

export interface QuestProgress {
  completedNodeIds: string[];
  completedItemIds: string[];
  coinsEarned: number;
  badgeEarned: boolean;
  weekKey?: string;      // for weekly sprint
  startedAt: string;
  lastUpdatedAt: string;
}

export function loadQuestProgress(userId: string, questId: string): QuestProgress {
  try {
    const raw = localStorage.getItem(`${PROGRESS_PREFIX}.${userId}.${questId}`);
    if (raw) return JSON.parse(raw) as QuestProgress;
  } catch { /* ignore */ }
  return {
    completedNodeIds: [],
    completedItemIds: [],
    coinsEarned: 0,
    badgeEarned: false,
    startedAt: new Date().toISOString(),
    lastUpdatedAt: new Date().toISOString(),
  };
}

export function saveQuestProgress(userId: string, questId: string, progress: QuestProgress) {
  progress.lastUpdatedAt = new Date().toISOString();
  localStorage.setItem(`${PROGRESS_PREFIX}.${userId}.${questId}`, JSON.stringify(progress));
}

/** For weekly sprint: reset if stored weekKey differs from current */
export function getEffectiveProgress(userId: string, quest: Quest): QuestProgress {
  const progress = loadQuestProgress(userId, quest.id);
  if (quest.isWeekly) {
    const currentWeek = getWeekKey();
    if (progress.weekKey !== currentWeek) {
      // New week β†’ reset
      const fresh: QuestProgress = {
        completedNodeIds: [],
        completedItemIds: [],
        coinsEarned: 0,
        badgeEarned: false,
        weekKey: currentWeek,
        startedAt: new Date().toISOString(),
        lastUpdatedAt: new Date().toISOString(),
      };
      saveQuestProgress(userId, quest.id, fresh);
      return fresh;
    }
    if (!progress.weekKey) {
      progress.weekKey = currentWeek;
      saveQuestProgress(userId, quest.id, progress);
    }
  }
  return progress;
}

/** Returns the index of the first unlocked (not yet completed) node */
export function getActiveNodeIndex(nodes: QuestNode[], completedNodeIds: string[]): number {
  for (let i = 0; i < nodes.length; i++) {
    if (!completedNodeIds.includes(nodes[i].id)) return i;
  }
  return nodes.length; // all done
}

/** A node is accessible if all previous nodes are completed */
export function isNodeUnlocked(nodeIndex: number, completedNodeIds: string[], nodes: QuestNode[]): boolean {
  if (nodeIndex === 0) return true;
  return completedNodeIds.includes(nodes[nodeIndex - 1].id);
}