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" }
|
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
|
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
|
||||||
|
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
|
➕ Add Player: http://localhost:3000/players/new
|
||||||
🎾 Record Match: http://localhost:3000/matches/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)
|
format!("https://quickchart.io/chart?c={}&w=500&h=250&bkg=white", encoded)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get singles/doubles history for email charts
|
// Get unified ELO history for email chart (all match types)
|
||||||
let singles_email_history: Vec<(i64, String, String, f64)> = sqlx::query_as(
|
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,
|
r#"SELECT m.id, strftime('%H:%M', datetime(m.timestamp, '-5 hours')) as time_str,
|
||||||
p.name, mp.rating_after
|
p.name, mp.rating_after
|
||||||
FROM matches m
|
FROM matches m
|
||||||
JOIN match_participants mp ON m.id = mp.match_id
|
JOIN match_participants mp ON m.id = mp.match_id
|
||||||
JOIN players p ON mp.player_id = p.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"#
|
ORDER BY m.timestamp, p.name"#
|
||||||
)
|
)
|
||||||
.bind(&target_date)
|
.bind(&target_date)
|
||||||
@ -2781,32 +2781,16 @@ async fn send_daily_summary(
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let doubles_email_history: Vec<(i64, String, String, f64)> = sqlx::query_as(
|
let elo_chart_url = build_email_chart(&elo_email_history, &colors_email, "Unified ELO Rating");
|
||||||
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 singles_chart_url = build_email_chart(&singles_email_history, &colors_email, "Singles Rating");
|
let charts_email_html = if !elo_chart_url.is_empty() {
|
||||||
let doubles_chart_url = build_email_chart(&doubles_email_history, &colors_email, "Doubles Rating");
|
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!(
|
// Get unified leaderboard data
|
||||||
r#"{}{}
|
let top_players: Vec<(String, f64)> = sqlx::query_as(
|
||||||
"#,
|
|
||||||
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(
|
|
||||||
r#"SELECT DISTINCT p.name, p.singles_rating
|
r#"SELECT DISTINCT p.name, p.singles_rating
|
||||||
FROM players p
|
FROM players p
|
||||||
JOIN match_participants mp ON p.id = mp.player_id
|
JOIN match_participants mp ON p.id = mp.player_id
|
||||||
@ -2816,24 +2800,7 @@ async fn send_daily_summary(
|
|||||||
.await
|
.await
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let top_doubles: Vec<(String, f64)> = sqlx::query_as(
|
let leaderboard_html: String = top_players.iter().enumerate()
|
||||||
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()
|
|
||||||
.map(|(i, (name, rating))| {
|
.map(|(i, (name, rating))| {
|
||||||
let medal = match i { 0 => "🥇", 1 => "🥈", 2 => "🥉", _ => "" };
|
let medal = match i { 0 => "🥇", 1 => "🥈", 2 => "🥉", _ => "" };
|
||||||
format!("<tr><td>{} {}. {}</td><td style='text-align:right;'>{:.0}</td></tr>", medal, i+1, name, rating)
|
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>
|
</table>
|
||||||
|
|
||||||
<h2 style="color: #003594; border-bottom: 2px solid #FFB81C; padding-bottom: 10px; margin-top: 30px;">📊 Leaderboard</h2>
|
<h2 style="color: #003594; border-bottom: 2px solid #FFB81C; padding-bottom: 10px; margin-top: 30px;">📊 Leaderboard (Unified ELO)</h2>
|
||||||
<div style="display: flex; gap: 20px;">
|
<table style="width: 100%; max-width: 300px;">{}</table>
|
||||||
<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;">🤝 Partner Synergy</h2>
|
<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>
|
<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>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</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
|
// Send emails
|
||||||
use lettre::{Message, SmtpTransport, Transport};
|
use lettre::{Message, SmtpTransport, Transport};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user