Add performance ranking and heady badges
This commit is contained in:
parent
43e37f5c98
commit
992cb3db98
3 changed files with 97 additions and 102 deletions
|
|
@ -99,6 +99,36 @@ def read_performance(slug: str, session: Session = Depends(get_session)):
|
||||||
# Sort by rating desc, then date desc
|
# Sort by rating desc, then date desc
|
||||||
other_performances.sort(key=lambda x: (x.avg_rating or 0, x.show_date), reverse=True)
|
other_performances.sort(key=lambda x: (x.avg_rating or 0, x.show_date), reverse=True)
|
||||||
|
|
||||||
|
# --- Calculate Ranking for Current Performance ---
|
||||||
|
current_perf_stats = rating_map.get(performance_id, {"avg": 0.0, "count": 0})
|
||||||
|
current_avg = current_perf_stats["avg"] or 0.0
|
||||||
|
current_rating_count = current_perf_stats["count"]
|
||||||
|
|
||||||
|
# Build list of all performances with their ratings for ranking
|
||||||
|
all_rated_perfs = []
|
||||||
|
for p, s, v in all_perfs_data:
|
||||||
|
stats = rating_map.get(p.id, {"avg": 0.0, "count": 0})
|
||||||
|
all_rated_perfs.append({"id": p.id, "avg": stats["avg"] or 0.0, "count": stats["count"]})
|
||||||
|
|
||||||
|
# Sort by avg rating desc
|
||||||
|
all_rated_perfs.sort(key=lambda x: x["avg"], reverse=True)
|
||||||
|
|
||||||
|
# Find rank (1-indexed)
|
||||||
|
rank = None
|
||||||
|
for i, item in enumerate(all_rated_perfs):
|
||||||
|
if item["id"] == performance_id:
|
||||||
|
rank = i + 1
|
||||||
|
break
|
||||||
|
|
||||||
|
total_versions = len(all_perfs_data)
|
||||||
|
|
||||||
|
# Heady = top 20% with at least 1 rating and avg >= 8.0
|
||||||
|
is_heady = False
|
||||||
|
if current_rating_count > 0 and current_avg >= 8.0:
|
||||||
|
if rank and total_versions > 0:
|
||||||
|
percentile = rank / total_versions
|
||||||
|
is_heady = percentile <= 0.2 # Top 20%
|
||||||
|
|
||||||
# Construct response manually to include extra fields
|
# Construct response manually to include extra fields
|
||||||
# We need to ensure nested models (show, song) are validated correctly
|
# We need to ensure nested models (show, song) are validated correctly
|
||||||
perf_dict = performance.model_dump()
|
perf_dict = performance.model_dump()
|
||||||
|
|
@ -112,6 +142,11 @@ def read_performance(slug: str, session: Session = Depends(get_session)):
|
||||||
perf_dict['gap'] = gap
|
perf_dict['gap'] = gap
|
||||||
perf_dict['times_played'] = times_played
|
perf_dict['times_played'] = times_played
|
||||||
perf_dict['other_performances'] = other_performances
|
perf_dict['other_performances'] = other_performances
|
||||||
|
perf_dict['rank'] = rank
|
||||||
|
perf_dict['total_versions'] = total_versions
|
||||||
|
perf_dict['avg_rating'] = current_avg
|
||||||
|
perf_dict['rating_count'] = current_rating_count
|
||||||
|
perf_dict['is_heady'] = is_heady
|
||||||
|
|
||||||
return perf_dict
|
return perf_dict
|
||||||
|
|
||||||
|
|
|
||||||
143
docs/ROADMAP.md
143
docs/ROADMAP.md
|
|
@ -1,6 +1,6 @@
|
||||||
# Elmeg Platform Roadmap
|
# Elmeg Platform Roadmap
|
||||||
|
|
||||||
**Last Updated:** 2025-12-26
|
**Last Updated:** 2025-12-27
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -34,7 +34,22 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Recent Completions (Dec 26, 2025)
|
## Recent Completions (Dec 27, 2025)
|
||||||
|
|
||||||
|
| Feature | Status |
|
||||||
|
|---------|--------|
|
||||||
|
| Auth Persistence Fix | ✅ Fixed - added missing DB columns for preferences |
|
||||||
|
| Review Display | ✅ Shows avatar, username, localized date, granular score |
|
||||||
|
| Rating System | ✅ Shows user's existing rating, added `/ratings/me` endpoint |
|
||||||
|
| Activity Feed | ✅ Living links to entities, accurate type language |
|
||||||
|
| Username Consistency | ✅ Fixed - feed now uses Profile username |
|
||||||
|
| Notification Prefs Backend | ✅ Added DB columns (theme, email_on_reply, etc) |
|
||||||
|
| Avatar Unlock System | ✅ XP tiers implemented in settings |
|
||||||
|
| Duplicate Performances | ✅ Fixed - deleted 220 duplicates |
|
||||||
|
| Score Precision | ✅ Fixed - database column changed to FLOAT |
|
||||||
|
| UI Polish | ✅ Removed emojis, music icon, updated site description |
|
||||||
|
|
||||||
|
## Previous Completions (Dec 26, 2025)
|
||||||
|
|
||||||
| Feature | Status |
|
| Feature | Status |
|
||||||
|---------|--------|
|
|---------|--------|
|
||||||
|
|
@ -45,54 +60,23 @@
|
||||||
| SPF DNS record fixed | ✅ Complete |
|
| SPF DNS record fixed | ✅ Complete |
|
||||||
| Password reset tested | ✅ Complete |
|
| Password reset tested | ✅ Complete |
|
||||||
|
|
||||||
## Previous Completions (Dec 23, 2025)
|
---
|
||||||
|
|
||||||
|
## Current Sprint
|
||||||
|
|
||||||
|
### In Progress
|
||||||
|
|
||||||
| Feature | Status |
|
| Feature | Status |
|
||||||
|---------|--------|
|
|---------|--------|
|
||||||
| Privacy Settings (3 toggles) | ✅ Complete |
|
| Performance Ranking | 🔄 Backend + Frontend |
|
||||||
| Sticky Settings Sidebar | ✅ Complete |
|
| Heady Badges | 🔄 Visual polish for top-rated |
|
||||||
| Bug Tracker MVP | ✅ Deployed |
|
|
||||||
| Auth Console Error Fix | ✅ Fixed |
|
|
||||||
| Videos Page Link Fix | ✅ Fixed |
|
|
||||||
| Hide Test Users | ✅ Implemented |
|
|
||||||
| Bandcamp/Nugs Links | ✅ Complete |
|
|
||||||
| Enhanced Footer | ✅ Deployed |
|
|
||||||
| **Postal Mail Server** | ✅ Built & Deployed |
|
|
||||||
| **Email DNS Records** | ✅ SPF/DKIM/DMARC/RP |
|
|
||||||
| **SMTP Integration** | ✅ Backend configured |
|
|
||||||
|
|
||||||
---
|
### Up Next
|
||||||
|
|
||||||
## Postal Mail Server Details
|
| Feature | Priority |
|
||||||
|
|---------|----------|
|
||||||
### Infrastructure
|
| Theme persistence (frontend) | Medium |
|
||||||
|
| Email notification triggers | Low |
|
||||||
| Component | Details |
|
|
||||||
|-----------|---------|
|
|
||||||
| Location | tangible-aacorn (Hetzner ARM64) |
|
|
||||||
| Build | Custom ARM64 from source |
|
|
||||||
| Database | MariaDB 11 |
|
|
||||||
| Queue | RabbitMQ 3.13 |
|
|
||||||
| Routing | Traefik with Let's Encrypt |
|
|
||||||
|
|
||||||
### DNS Records (Cloudflare)
|
|
||||||
|
|
||||||
| Type | Name | Value |
|
|
||||||
|------|------|-------|
|
|
||||||
| A | postal | 159.69.219.254 (DNS only) |
|
|
||||||
| A | smtp | 159.69.219.254 (DNS only) |
|
|
||||||
| MX | @ | smtp.elmeg.xyz (Priority 10) |
|
|
||||||
| TXT | @ | v=spf1 mx a ip4:159.69.219.254 ~all |
|
|
||||||
| TXT | postal-VkYvkc._domainkey | v=DKIM1; t=s; h=sha256; p=... |
|
|
||||||
| TXT | _dmarc | v=DMARC1; p=none; rua=mailto:admin@elmeg.xyz |
|
|
||||||
| CNAME | psrp | smtp.elmeg.xyz |
|
|
||||||
|
|
||||||
### Admin Access
|
|
||||||
|
|
||||||
- **URL:** <https://postal.elmeg.xyz>
|
|
||||||
- **Login:** <admin@elmeg.xyz>
|
|
||||||
- **Organization:** Elmeg
|
|
||||||
- **Mail Server:** main
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -105,40 +89,18 @@
|
||||||
| Privacy: Public Profile | ✅ Done |
|
| Privacy: Public Profile | ✅ Done |
|
||||||
| Privacy: Show Attendance | ✅ Done |
|
| Privacy: Show Attendance | ✅ Done |
|
||||||
| Privacy: Leaderboards | ✅ Done |
|
| Privacy: Leaderboards | ✅ Done |
|
||||||
| Theme Persistence | ✅ Works client-side |
|
| Theme Persistence | ✅ Backend ready |
|
||||||
|
| Notification Toggles | ✅ UI + Backend ready |
|
||||||
|
| Avatar XP Unlock System | ✅ Complete |
|
||||||
|
|
||||||
### Phase 2: Notifications (Deferred)
|
### Phase 2: Notifications (Backend Ready)
|
||||||
|
|
||||||
| Feature | Dependency | Status |
|
| Feature | Status |
|
||||||
|---------|------------|--------|
|
|---------|--------|
|
||||||
| Comment Replies | Notification system | Ready to implement |
|
| Comment Replies Pref | ✅ Backend column added |
|
||||||
| New Show Added | Import trigger hook | Needs backend work |
|
| Chase Song Pref | ✅ Backend column added |
|
||||||
| Chase Song Played | Post-import check | Needs backend work |
|
| Weekly Digest Pref | ✅ Backend column added |
|
||||||
| Weekly Digest | Email templates + cron | Future |
|
| Email Triggers | ❌ Not implemented |
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## External Links System
|
|
||||||
|
|
||||||
### ✅ Phase 1: Database + Admin - COMPLETE
|
|
||||||
|
|
||||||
### ✅ Phase 2: Frontend Display - COMPLETE
|
|
||||||
|
|
||||||
### Phase 3: Import Tools (Future)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Bug Tracker
|
|
||||||
|
|
||||||
**Status: ✅ DEPLOYED at `/bugs`**
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Avatar System Roadmap
|
|
||||||
|
|
||||||
### ✅ Phase 1: Jewel Tones (Complete)
|
|
||||||
|
|
||||||
### Phase 2-4: (Future)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -148,36 +110,17 @@
|
||||||
|
|
||||||
- [x] Test email verification flow end-to-end
|
- [x] Test email verification flow end-to-end
|
||||||
- [x] Test password reset flow end-to-end
|
- [x] Test password reset flow end-to-end
|
||||||
|
- [ ] Performance ranking display
|
||||||
|
- [ ] Heady badges for top-rated versions
|
||||||
|
|
||||||
### Medium Priority
|
### Medium Priority
|
||||||
|
|
||||||
|
- [ ] Theme persistence to frontend
|
||||||
- [ ] Analytics provider decision
|
- [ ] Analytics provider decision
|
||||||
- [ ] Notification preferences backend
|
|
||||||
- [ ] Avatar unlock system
|
|
||||||
|
|
||||||
### Low Priority
|
### Low Priority
|
||||||
|
|
||||||
- [ ] bugs.elmeg.xyz subdomain
|
- [ ] bugs.elmeg.xyz subdomain
|
||||||
- [ ] Data export (GDPR)
|
- [ ] Data export (GDPR)
|
||||||
- [ ] Account deletion
|
- [ ] Account deletion
|
||||||
|
- [ ] Email notification triggers
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation Priority
|
|
||||||
|
|
||||||
### Immediate (Testing)
|
|
||||||
|
|
||||||
1. [x] Register test account to trigger verification email
|
|
||||||
2. [x] Registration UX shows "Check Your Email" message
|
|
||||||
3. [x] Test password reset flow
|
|
||||||
4. [x] Monitor email deliverability in Postal dashboard
|
|
||||||
|
|
||||||
### This Week
|
|
||||||
|
|
||||||
- [ ] Answer analytics question
|
|
||||||
- [ ] Theme persistence to user preferences
|
|
||||||
|
|
||||||
### Next Sprint
|
|
||||||
|
|
||||||
- [ ] Notification preferences backend
|
|
||||||
- [ ] Avatar unlock system
|
|
||||||
|
|
|
||||||
|
|
@ -67,11 +67,22 @@ export default async function PerformanceDetailPage({ params }: { params: Promis
|
||||||
</Link>
|
</Link>
|
||||||
<div>
|
<div>
|
||||||
{/* Context Badge */}
|
{/* Context Badge */}
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2 flex-wrap">
|
||||||
<Badge variant="secondary" className="bg-primary/10 text-primary border-primary/20">
|
<Badge variant="secondary" className="bg-primary/10 text-primary border-primary/20">
|
||||||
<Sparkles className="h-3 w-3 mr-1" />
|
<Sparkles className="h-3 w-3 mr-1" />
|
||||||
Specific Performance
|
Specific Performance
|
||||||
</Badge>
|
</Badge>
|
||||||
|
{performance.is_heady && (
|
||||||
|
<Badge className="bg-yellow-500/10 text-yellow-600 border-yellow-500/20 border">
|
||||||
|
<Sparkles className="h-3 w-3 mr-1" />
|
||||||
|
Heady Version
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
|
{performance.rank && performance.total_versions && (
|
||||||
|
<Badge variant="outline" className="font-mono">
|
||||||
|
#{performance.rank} of {performance.total_versions}
|
||||||
|
</Badge>
|
||||||
|
)}
|
||||||
{performance.set_name && (
|
{performance.set_name && (
|
||||||
<Badge variant="outline">{performance.set_name}</Badge>
|
<Badge variant="outline">{performance.set_name}</Badge>
|
||||||
)}
|
)}
|
||||||
|
|
@ -136,7 +147,13 @@ export default async function PerformanceDetailPage({ params }: { params: Promis
|
||||||
Rate This Version
|
Rate This Version
|
||||||
</div>
|
</div>
|
||||||
<SocialWrapper type="ratings">
|
<SocialWrapper type="ratings">
|
||||||
<EntityRating entityType="performance" entityId={performance.id} />
|
<EntityRating
|
||||||
|
entityType="performance"
|
||||||
|
entityId={performance.id}
|
||||||
|
rank={performance.rank}
|
||||||
|
ratingCount={performance.rating_count}
|
||||||
|
isHeady={performance.is_heady}
|
||||||
|
/>
|
||||||
</SocialWrapper>
|
</SocialWrapper>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue