Skip to content

Commit aaac9e2

Browse files
committed
add daily challenges
1 parent 4f2b850 commit aaac9e2

10 files changed

Lines changed: 1137 additions & 737 deletions
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Challenge History Page
2+
3+
Extracted from `weekly-challenges.md`. Depends on `weekly-challenge-progress` and `daily-challenge-core`.
4+
5+
## Goal
6+
View past completed and failed challenges (both weekly and daily) in a combined history view.
7+
8+
## Route
9+
`/challenges/history`
10+
11+
## Layout
12+
- Filter tabs: All | Weekly | Daily
13+
- Grouped by week
14+
- Each entry shows: type icon, description, status (✅/✗), completion date or failure note, target achieved
15+
16+
## Tauri Command
17+
```rust
18+
fn get_challenge_history(
19+
challenge_type: Option<String>, // "weekly", "daily", or None
20+
limit: i32
21+
) -> Result<Vec<ChallengeHistoryItem>, String>
22+
```
23+
24+
## Acceptance Criteria
25+
- [ ] Lists past challenges from `challenge_history` table
26+
- [ ] Filter tabs work (weekly/daily/all)
27+
- [ ] Grouped by week with clear date headings
28+
- [ ] Empty state handled gracefully
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# Weekly Challenges – Generation & Reroll
2+
3+
Extracted from `weekly-challenges.md`. Depends on `daily-challenge-core` (shares `challenge_history` table).
4+
5+
## Goal
6+
Generate 3 diverse weekly challenge options each Sunday. Allow 2 rerolls before acceptance.
7+
8+
## Database
9+
```sql
10+
CREATE TABLE challenge_options (
11+
id INTEGER PRIMARY KEY AUTOINCREMENT,
12+
week_start_date TEXT NOT NULL,
13+
challenge_type TEXT NOT NULL,
14+
challenge_description TEXT NOT NULL,
15+
challenge_target INTEGER NOT NULL,
16+
challenge_target_games INTEGER,
17+
hero_id INTEGER,
18+
metric TEXT,
19+
option_index INTEGER NOT NULL, -- 1, 2, 3
20+
reroll_generation INTEGER DEFAULT 0,
21+
created_at INTEGER NOT NULL
22+
);
23+
24+
CREATE TABLE weekly_challenges (
25+
id INTEGER PRIMARY KEY AUTOINCREMENT,
26+
week_start_date TEXT NOT NULL,
27+
challenge_type TEXT NOT NULL,
28+
challenge_description TEXT NOT NULL,
29+
challenge_target INTEGER NOT NULL,
30+
challenge_target_games INTEGER,
31+
hero_id INTEGER,
32+
metric TEXT,
33+
status TEXT NOT NULL DEFAULT 'active', -- active, completed, failed, skipped
34+
accepted_at INTEGER,
35+
completed_at INTEGER,
36+
reroll_count INTEGER DEFAULT 0,
37+
UNIQUE(week_start_date)
38+
);
39+
```
40+
41+
## Generation Logic
42+
- 3 options, diverse types: max 1 hero-specific, max 1 performance, mix variety
43+
- Hero selection from last 30 games, prefer heroes with 10+ games
44+
- Difficulty: mix of easy/medium/hard across the 3 options
45+
- Reroll: delete old options, regenerate, increment reroll_count; max 2
46+
47+
## Tauri Commands
48+
```rust
49+
fn get_weekly_challenge_options() -> Result<Vec<ChallengeOption>, String>
50+
fn reroll_weekly_challenges() -> Result<Vec<ChallengeOption>, String>
51+
fn skip_weekly_challenge() -> Result<(), String>
52+
```
53+
54+
## Acceptance Criteria
55+
- [ ] 3 diverse options generated each Sunday
56+
- [ ] Reroll generates fresh set, decrements limit
57+
- [ ] Reroll disabled after 2 uses
58+
- [ ] Options persist until new week or accepted
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Weekly Challenges – Acceptance & Progress Tracking
2+
3+
Extracted from `weekly-challenges.md`. Depends on `weekly-challenge-generation`.
4+
5+
## Goal
6+
Accept a challenge, track progress against matches played during the week, auto-complete or auto-fail.
7+
8+
## Requirements
9+
- On accept: set `accepted_at` timestamp; only matches after this time and before week end count
10+
- Progress evaluated per challenge type (wins, avg stat, hero-specific, etc.)
11+
- Auto-complete when target reached; auto-fail on Sunday rollover
12+
- Archive completed/failed challenges to `challenge_history`
13+
14+
## Tauri Commands
15+
```rust
16+
fn accept_weekly_challenge(challenge_id: i64) -> Result<WeeklyChallenge, String>
17+
fn get_active_weekly_challenge() -> Result<Option<WeeklyChallenge>, String>
18+
fn get_weekly_challenge_progress() -> Result<Option<ChallengeProgress>, String>
19+
```
20+
21+
## ChallengeProgress struct
22+
```rust
23+
pub struct ChallengeProgress {
24+
pub challenge: WeeklyChallenge,
25+
pub current_value: i32,
26+
pub target: i32,
27+
pub games_counted: i32,
28+
pub days_remaining: i32,
29+
pub completed: bool,
30+
}
31+
```
32+
33+
## Acceptance Criteria
34+
- [ ] Accepting locks in challenge, disables reroll
35+
- [ ] Progress counts only post-acceptance, within the week
36+
- [ ] Auto-completes when target met
37+
- [ ] Sunday rollover archives incomplete as failed
38+
- [ ] `days_remaining` calculated correctly
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Weekly Challenges – UI (Selection Page & Dashboard Widget)
2+
3+
Extracted from `weekly-challenges.md`. Depends on `weekly-challenge-progress`.
4+
5+
## Goal
6+
Build the `/challenges` page for viewing/selecting weekly options, and a dashboard widget showing active progress.
7+
8+
## Routes
9+
- `/challenges` — main challenge page (selection or active progress view)
10+
11+
## Selection View (no challenge accepted yet)
12+
- Show 3 option cards with description, type tag, difficulty badge
13+
- Accept button on each card
14+
- Reroll button with remaining count ("2 rerolls remaining")
15+
- Skip This Week button
16+
17+
## Active Progress View (challenge accepted)
18+
- Challenge description + progress bar (current/target)
19+
- Days remaining in week
20+
- List of recent relevant matches with pass/fail indicator
21+
22+
## Dashboard Widget
23+
- Card showing active weekly challenge with mini progress bar
24+
- Link to `/challenges` for details
25+
- Shows "Choose this week's challenge" if none accepted yet
26+
27+
## Acceptance Criteria
28+
- [ ] Can view 3 options and accept one
29+
- [ ] Reroll works and shows updated count
30+
- [ ] Active challenge shows real-time progress
31+
- [ ] Dashboard widget visible alongside daily widget
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Daily Challenges – Core Backend
2+
3+
Extracted from `weekly-challenges.md`.
4+
5+
## Goal
6+
Implement the database schema, generation logic, and Tauri commands for daily challenges.
7+
8+
## Requirements
9+
10+
### Database
11+
New tables:
12+
- `daily_challenges` – one row per day, auto-generated at first access
13+
- `challenge_history` – archived completed/failed challenges (shared with future weekly challenges)
14+
15+
```sql
16+
CREATE TABLE daily_challenges (
17+
id INTEGER PRIMARY KEY AUTOINCREMENT,
18+
challenge_date TEXT NOT NULL, -- "YYYY-MM-DD"
19+
challenge_type TEXT NOT NULL, -- "quick_win", "performance", "efficiency", "participation"
20+
challenge_description TEXT NOT NULL,
21+
challenge_target INTEGER NOT NULL,
22+
challenge_target_games INTEGER DEFAULT 1,
23+
hero_id INTEGER, -- NULL for non-hero challenges
24+
metric TEXT, -- "wins", "kills", "gpm", "last_hits", "deaths", "hero_damage"
25+
status TEXT NOT NULL DEFAULT 'active', -- active, completed, failed
26+
created_at INTEGER NOT NULL,
27+
completed_at INTEGER,
28+
UNIQUE(challenge_date)
29+
);
30+
31+
CREATE TABLE challenge_history (
32+
id INTEGER PRIMARY KEY AUTOINCREMENT,
33+
challenge_type TEXT NOT NULL, -- 'daily' (or 'weekly' later)
34+
period_start_date TEXT NOT NULL,
35+
challenge_description TEXT NOT NULL,
36+
status TEXT NOT NULL, -- completed, failed
37+
completed_at INTEGER,
38+
target_achieved INTEGER
39+
);
40+
```
41+
42+
### Challenge Types & Templates
43+
Use a fixed template list with hero/stat filled from player history:
44+
45+
**Quick Win (easy):**
46+
- "Win 1 game today"
47+
- "Win 1 game with [Hero]" (hero from last 10 games)
48+
49+
**Performance (medium):**
50+
- "Get [N]+ kills in one game" (N = avg kills + 2, min 10)
51+
- "Achieve [N]+ GPM in one game" (N = avg GPM + 30, min 400)
52+
- "Finish with positive KDA in one game"
53+
- "Deal [N]+ hero damage in one game" (N calibrated to avg, min 15000)
54+
55+
**Efficiency (medium):**
56+
- "Get [N]+ CS at 10 minutes" (N = avg CS@10 + 5, min 50) – requires parsed matches
57+
- "Die [N] times or less in one game" (N = avg deaths - 1, max 3)
58+
59+
**Participation (easy):**
60+
- "Play 2 games today"
61+
- "Play a game with [Hero]" (hero not played in last 7 days)
62+
63+
### Generation Logic
64+
- 60% Easy (quick_win / participation), 30% Medium (performance), 10% Hard
65+
- Check last 7 daily challenges to avoid repeating same type consecutively
66+
- For hero-specific challenges, pick from matches in last 10 games
67+
- Auto-generate when first accessed for the day; cache in DB
68+
69+
### Daily Streak
70+
- Count consecutive days where `status = 'completed'` going back from yesterday
71+
- Return 0 if yesterday was not completed
72+
73+
### Archive Logic
74+
- On each call to `get_current_daily_challenge`, check if any `active` challenges exist for past dates and mark them `failed`, archive to `challenge_history`
75+
76+
### Tauri Commands
77+
```rust
78+
fn get_daily_challenge() -> Result<Option<DailyChallenge>, String>
79+
fn get_daily_challenge_progress() -> Result<Option<DailyChallengeProgress>, String>
80+
fn get_daily_streak() -> Result<i32, String>
81+
```
82+
83+
### DailyChallengeProgress struct
84+
```rust
85+
pub struct DailyChallengeProgress {
86+
pub challenge: DailyChallenge,
87+
pub current_value: i32, // e.g. wins so far today
88+
pub target: i32,
89+
pub completed: bool,
90+
pub games_counted: i32, // number of matches evaluated
91+
}
92+
```
93+
94+
## Acceptance Criteria
95+
- [ ] Tables created in `init_db`
96+
- [ ] Daily challenge auto-generated on first access each day
97+
- [ ] Old active challenges auto-archived as failed
98+
- [ ] Progress evaluated against today's matches (after midnight)
99+
- [ ] Challenge auto-marked completed when target met
100+
- [ ] Streak correctly calculated from history
101+
- [ ] All 3 Tauri commands working
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Daily Challenges – Dashboard Widget
2+
3+
Depends on: `daily-challenge-core`
4+
5+
## Goal
6+
Show today's daily challenge progress on the dashboard with streak tracking.
7+
8+
## Requirements
9+
10+
### Widget States
11+
- **Active**: Show description, progress bar, time until midnight ("resets in Xh Ym")
12+
- **Completed**: Show "✅ Daily Complete!" with time completed and current streak
13+
- **No matches yet**: Show at 0% progress with motivational copy
14+
- **Loading/no challenge**: Skeleton/spinner
15+
16+
### Layout (fits within existing dashboard card grid)
17+
```
18+
⚡ Today's Challenge
19+
Get 10+ kills in one game
20+
[████░░░░░░] 0/1
21+
Resets in 8h 23m
22+
🔥 3 day streak
23+
```
24+
25+
### Behaviour
26+
- Load on dashboard mount alongside existing goal calendar
27+
- Refresh after `refresh_matches` is called (re-invoke `get_daily_challenge_progress`)
28+
- Does NOT need its own refresh button — piggybacks on existing match refresh
29+
30+
### Navigation
31+
- No dedicated challenges page needed yet — widget is self-contained
32+
33+
## Acceptance Criteria
34+
- [ ] Widget visible on dashboard
35+
- [ ] Shows correct progress after fetching matches
36+
- [ ] Countdown to midnight updates each minute (use `setInterval`)
37+
- [ ] Streak displayed when > 0
38+
- [ ] Completed state visually distinct from active state

0 commit comments

Comments
 (0)