feat: Daily streak score - incentivise consistent attendance with Mon-Sat streak logic - #111
Open
23f3001369 wants to merge 1 commit into
Open
feat: Daily streak score - incentivise consistent attendance with Mon-Sat streak logic#11123f3001369 wants to merge 1 commit into
23f3001369 wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR introduces a daily streak scoring system that rewards students for consistent session attendance. The feature tracks consecutive qualifying days (Mon-Sat), awards escalating bonus SP at milestones, and provides a hearts-based safety net so a single missed day doesn't destroy weeks of progress.
Sundays are explicitly excluded — they neither count as streak days nor break streaks — making the system naturally aligned with the Mon-Sat session schedule.
Motivation
Spurti currently awards attendance and poll SP per-session, but there is no incentive for day-over-day consistency. A student who attends 5 out of 6 days gets almost the same total as one who attends all 6. The streak feature changes this by compounding rewards for unbroken chains of attendance, which:
How It Works
Qualification (per day)
A student qualifies for a streak day if, on at least one session that calendar date:
attendancePercentage >= 85%(fromattendancerecords)poll participation >= 85%(frompollrecords)If no attendance records exist (dev / pre-pipeline), the system falls back to
sptransactions:appliedDelta >= 10(which implies >= 90%) satisfies the 85% threshold.Sunday logic
nextWeekday()advances from Friday to Monday, so a Friday-Saturday-Monday chain is consecutive.isConsecutiveGap(lastQualifyingDate, candidateDate)which internally callsnextWeekday()instead of naiveaddDays(..., 1).Eligibility cutoff
Only students whose
internshipStartDate >= 2026-07-16are eligible. Students who started before this date receive no streak processing. This is enforced both at the service level and in the cron script.SP rewards
Milestone formula:
3 + (streakDay / 10) * 2Hearts (streak savers)
lastQualifyingDateis updated to the heart-saved date, resetting the gap counter so consecutive hearts work correctly.What Changed
New files
server/models/Streak.jsstreakscollectionserver/services/streakService.jsserver/cron/streakDaily.jsserver/services/__tests__/streakService.test.jsModified files
server/server.jsserver/config.jsserver/models/SPTransaction.jsclient/src/main.jsxclient/src/styles.cssCONTEXT.mdpackage.jsonAPI Endpoints
GET/api/streakPOST/api/streak/claimGET/api/admin/streaksPOST/api/admin/streak/process-allTesting
server/services/__tests__/streakService.test.jsnpx vitest run— 37/37 passingnpm run build(client Vite build) — passesPost-Merge Deployment
1. Pull and build on production
2. Restart the Express server
# Restart however the server is managed (pm2, systemd, etc.) pm2 restart spurtiNo manual DB migration needed — the
streakscollection is auto-created by MongoDB/Mongoose on first write.3. One-time backfill (historical streak data)
Preview first (dry run):
Then run for real:
This processes every active student with
internshipStartDate >= 2026-07-16from their start date through yesterday. Students who started before the cutoff date are automatically skipped.4. Set up daily cron job
Add to crontab (
crontab -e) to run after the main SP pipeline each day:5. Verify
/spurtias a student — streak card + "Streak" tab should appearGET /api/admin/streaks— should return scored studentsPOST /api/admin/streak/process-allwith{ "date": "2026-07-17" }tail -f /home/sakshi/spurti/logs/streak.logNo other action needed
.envchanges required — the cron script uses existingMONGO_URIstreakscollectionclient/distand served as static files