Add performance ranking and heady badges

This commit is contained in:
fullsizemalt 2025-12-26 21:28:25 -08:00
parent 43e37f5c98
commit 992cb3db98
3 changed files with 97 additions and 102 deletions

View file

@ -99,6 +99,36 @@ def read_performance(slug: str, session: Session = Depends(get_session)):
# Sort by rating desc, then date desc
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
# We need to ensure nested models (show, song) are validated correctly
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['times_played'] = times_played
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

View file

@ -1,6 +1,6 @@
# 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 |
|---------|--------|
@ -45,54 +60,23 @@
| SPF DNS record fixed | ✅ Complete |
| Password reset tested | ✅ Complete |
## Previous Completions (Dec 23, 2025)
---
## Current Sprint
### In Progress
| Feature | Status |
|---------|--------|
| Privacy Settings (3 toggles) | ✅ Complete |
| Sticky Settings Sidebar | ✅ Complete |
| 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 |
| Performance Ranking | 🔄 Backend + Frontend |
| Heady Badges | 🔄 Visual polish for top-rated |
---
### Up Next
## Postal Mail Server Details
### Infrastructure
| 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
| Feature | Priority |
|---------|----------|
| Theme persistence (frontend) | Medium |
| Email notification triggers | Low |
---
@ -105,40 +89,18 @@
| Privacy: Public Profile | ✅ Done |
| Privacy: Show Attendance | ✅ 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 |
|---------|------------|--------|
| Comment Replies | Notification system | Ready to implement |
| New Show Added | Import trigger hook | Needs backend work |
| Chase Song Played | Post-import check | Needs backend work |
| Weekly Digest | Email templates + cron | Future |
---
## 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)
| Feature | Status |
|---------|--------|
| Comment Replies Pref | ✅ Backend column added |
| Chase Song Pref | ✅ Backend column added |
| Weekly Digest Pref | ✅ Backend column added |
| Email Triggers | ❌ Not implemented |
---
@ -148,36 +110,17 @@
- [x] Test email verification flow end-to-end
- [x] Test password reset flow end-to-end
- [ ] Performance ranking display
- [ ] Heady badges for top-rated versions
### Medium Priority
- [ ] Theme persistence to frontend
- [ ] Analytics provider decision
- [ ] Notification preferences backend
- [ ] Avatar unlock system
### Low Priority
- [ ] bugs.elmeg.xyz subdomain
- [ ] Data export (GDPR)
- [ ] Account deletion
---
## 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
- [ ] Email notification triggers

View file

@ -67,11 +67,22 @@ export default async function PerformanceDetailPage({ params }: { params: Promis
</Link>
<div>
{/* 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">
<Sparkles className="h-3 w-3 mr-1" />
Specific Performance
</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 && (
<Badge variant="outline">{performance.set_name}</Badge>
)}
@ -136,7 +147,13 @@ export default async function PerformanceDetailPage({ params }: { params: Promis
Rate This Version
</div>
<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>
</div>
</div>