Fix remaining dual-rating issues in email templates
- Email chart: single unified ELO chart instead of separate singles/doubles - Email leaderboard: single unified leaderboard - Removed duplicate top_doubles query (was identical to top_singles anyway)
This commit is contained in:
parent
4fbb803a66
commit
534d293be4
@ -719,3 +719,4 @@ thread 'main' (234988) panicked at src/main.rs:52:10:
|
||||
called `Result::unwrap()` on an `Err` value: Os { code: 48, kind: AddrInUse, message: "Address already in use" }
|
||||
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
|
||||
Migration error: error returned from database: (code: 1) no such column: rating
|
||||
Migration error: error returned from database: (code: 1) no such column: rating
|
||||
|
||||
@ -1068,3 +1068,16 @@ Starting Pickleball ELO Tracker Server on port 3000...
|
||||
➕ Add Player: http://localhost:3000/players/new
|
||||
🎾 Record Match: http://localhost:3000/matches/new
|
||||
|
||||
🏓 Pickleball ELO Tracker v3.0
|
||||
==============================
|
||||
|
||||
Starting Pickleball ELO Tracker Server on port 3000...
|
||||
|
||||
✅ Server running at http://localhost:3000
|
||||
📊 Leaderboard: http://localhost:3000/leaderboard
|
||||
📜 Match History: http://localhost:3000/matches
|
||||
👥 Players: http://localhost:3000/players
|
||||
⚖️ Team Balancer: http://localhost:3000/balance
|
||||
➕ Add Player: http://localhost:3000/players/new
|
||||
🎾 Record Match: http://localhost:3000/matches/new
|
||||
|
||||
|
||||
BIN
pickleball-elo
BIN
pickleball-elo
Binary file not shown.
72
src/main.rs
72
src/main.rs
@ -2766,14 +2766,14 @@ async fn send_daily_summary(
|
||||
format!("https://quickchart.io/chart?c={}&w=500&h=250&bkg=white", encoded)
|
||||
}
|
||||
|
||||
// Get singles/doubles history for email charts
|
||||
let singles_email_history: Vec<(i64, String, String, f64)> = sqlx::query_as(
|
||||
// Get unified ELO history for email chart (all match types)
|
||||
let elo_email_history: Vec<(i64, String, String, f64)> = sqlx::query_as(
|
||||
r#"SELECT m.id, strftime('%H:%M', datetime(m.timestamp, '-5 hours')) as time_str,
|
||||
p.name, mp.rating_after
|
||||
FROM matches m
|
||||
JOIN match_participants mp ON m.id = mp.match_id
|
||||
JOIN players p ON mp.player_id = p.id
|
||||
WHERE date(m.timestamp) = ? AND m.match_type = 'singles'
|
||||
WHERE date(m.timestamp) = ?
|
||||
ORDER BY m.timestamp, p.name"#
|
||||
)
|
||||
.bind(&target_date)
|
||||
@ -2781,32 +2781,16 @@ async fn send_daily_summary(
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let doubles_email_history: Vec<(i64, String, String, f64)> = sqlx::query_as(
|
||||
r#"SELECT m.id, strftime('%H:%M', datetime(m.timestamp, '-5 hours')) as time_str,
|
||||
p.name, mp.rating_after
|
||||
FROM matches m
|
||||
JOIN match_participants mp ON m.id = mp.match_id
|
||||
JOIN players p ON mp.player_id = p.id
|
||||
WHERE date(m.timestamp) = ? AND m.match_type = 'doubles'
|
||||
ORDER BY m.timestamp, p.name"#
|
||||
)
|
||||
.bind(&target_date)
|
||||
.fetch_all(&state.pool)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
let elo_chart_url = build_email_chart(&elo_email_history, &colors_email, "Unified ELO Rating");
|
||||
|
||||
let singles_chart_url = build_email_chart(&singles_email_history, &colors_email, "Singles Rating");
|
||||
let doubles_chart_url = build_email_chart(&doubles_email_history, &colors_email, "Doubles Rating");
|
||||
let charts_email_html = if !elo_chart_url.is_empty() {
|
||||
format!(r#"<img src="{}" alt="ELO Rating Chart" style="width:100%;max-width:500px;margin-bottom:15px;">"#, elo_chart_url)
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let charts_email_html = format!(
|
||||
r#"{}{}
|
||||
"#,
|
||||
if !singles_chart_url.is_empty() { format!(r#"<img src="{}" alt="Singles Rating Chart" style="width:100%;max-width:500px;margin-bottom:15px;">"#, singles_chart_url) } else { String::new() },
|
||||
if !doubles_chart_url.is_empty() { format!(r#"<img src="{}" alt="Doubles Rating Chart" style="width:100%;max-width:500px;">"#, doubles_chart_url) } else { String::new() }
|
||||
);
|
||||
|
||||
// Get leaderboard data
|
||||
let top_singles: Vec<(String, f64)> = sqlx::query_as(
|
||||
// Get unified leaderboard data
|
||||
let top_players: Vec<(String, f64)> = sqlx::query_as(
|
||||
r#"SELECT DISTINCT p.name, p.singles_rating
|
||||
FROM players p
|
||||
JOIN match_participants mp ON p.id = mp.player_id
|
||||
@ -2816,24 +2800,7 @@ async fn send_daily_summary(
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let top_doubles: Vec<(String, f64)> = sqlx::query_as(
|
||||
r#"SELECT DISTINCT p.name, p.singles_rating
|
||||
FROM players p
|
||||
JOIN match_participants mp ON p.id = mp.player_id
|
||||
ORDER BY p.singles_rating DESC LIMIT 5"#
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await
|
||||
.unwrap_or_default();
|
||||
|
||||
let singles_html: String = top_singles.iter().enumerate()
|
||||
.map(|(i, (name, rating))| {
|
||||
let medal = match i { 0 => "🥇", 1 => "🥈", 2 => "🥉", _ => "" };
|
||||
format!("<tr><td>{} {}. {}</td><td style='text-align:right;'>{:.0}</td></tr>", medal, i+1, name, rating)
|
||||
})
|
||||
.collect();
|
||||
|
||||
let doubles_html: String = top_doubles.iter().enumerate()
|
||||
let leaderboard_html: String = top_players.iter().enumerate()
|
||||
.map(|(i, (name, rating))| {
|
||||
let medal = match i { 0 => "🥇", 1 => "🥈", 2 => "🥉", _ => "" };
|
||||
format!("<tr><td>{} {}. {}</td><td style='text-align:right;'>{:.0}</td></tr>", medal, i+1, name, rating)
|
||||
@ -2942,17 +2909,8 @@ async fn send_daily_summary(
|
||||
{}
|
||||
</table>
|
||||
|
||||
<h2 style="color: #003594; border-bottom: 2px solid #FFB81C; padding-bottom: 10px; margin-top: 30px;">📊 Leaderboard</h2>
|
||||
<div style="display: flex; gap: 20px;">
|
||||
<div style="flex: 1;">
|
||||
<h3 style="color: #003594; font-size: 14px;">Singles</h3>
|
||||
<table style="width: 100%;">{}</table>
|
||||
</div>
|
||||
<div style="flex: 1;">
|
||||
<h3 style="color: #003594; font-size: 14px;">Doubles</h3>
|
||||
<table style="width: 100%;">{}</table>
|
||||
</div>
|
||||
</div>
|
||||
<h2 style="color: #003594; border-bottom: 2px solid #FFB81C; padding-bottom: 10px; margin-top: 30px;">📊 Leaderboard (Unified ELO)</h2>
|
||||
<table style="width: 100%; max-width: 300px;">{}</table>
|
||||
|
||||
<h2 style="color: #003594; border-bottom: 2px solid #FFB81C; padding-bottom: 10px; margin-top: 30px;">🤝 Partner Synergy</h2>
|
||||
<p style="color: #666; font-size: 12px; margin-bottom: 10px;">Win rate when partnered together (all-time doubles)</p>
|
||||
@ -2964,7 +2922,7 @@ async fn send_daily_summary(
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
"#, target_date, matches_email_html, charts_email_html, players_email_html, singles_html, doubles_html, heatmap_email);
|
||||
"#, target_date, matches_email_html, charts_email_html, players_email_html, leaderboard_html, heatmap_email);
|
||||
|
||||
// Send emails
|
||||
use lettre::{Message, SmtpTransport, Transport};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user