Implement RNR rating adjustment
This commit is contained in:
parent
1b603bf727
commit
2e3bd017f3
5 changed files with 240 additions and 75 deletions
89
src/sync.rs
89
src/sync.rs
|
|
@ -8,31 +8,31 @@ use sqlite::*;
|
|||
|
||||
// Score calculation
|
||||
|
||||
/// Calculate the collective expected score for each team.
|
||||
fn expected_scores(ratings: &Teams<&mut f64>) -> Vec<f64> {
|
||||
let qs: Vec<f64> = ratings
|
||||
.into_iter()
|
||||
.map(|es| 10_f64.powf(es.iter().map(|x| **x).sum::<f64>() / es.len() as f64 / 400.0))
|
||||
.collect();
|
||||
let sumq: f64 = qs.iter().sum();
|
||||
qs.into_iter().map(|q| q / sumq).collect()
|
||||
}
|
||||
// /// Calculate the collective expected score for each team.
|
||||
// fn expected_scores(ratings: &Teams<&mut f64>) -> Vec<f64> {
|
||||
// let qs: Vec<f64> = ratings
|
||||
// .into_iter()
|
||||
// .map(|es| 10_f64.powf(es.iter().map(|x| **x).sum::<f64>() / es.len() as f64 / 400.0))
|
||||
// .collect();
|
||||
// let sumq: f64 = qs.iter().sum();
|
||||
// qs.into_iter().map(|q| q / sumq).collect()
|
||||
// }
|
||||
|
||||
/// Adjust the ratings of each player based on who won.
|
||||
fn adjust_ratings(ratings: Teams<&mut f64>, winner: usize) {
|
||||
let exp_scores = expected_scores(&ratings);
|
||||
// /// Adjust the ratings of each player based on who won.
|
||||
// fn adjust_ratings(ratings: Teams<&mut f64>, winner: usize) {
|
||||
// let exp_scores = expected_scores(&ratings);
|
||||
|
||||
ratings
|
||||
.into_iter()
|
||||
.zip(exp_scores.into_iter())
|
||||
.enumerate()
|
||||
.for_each(|(i, (es, exp_sc))| {
|
||||
let len = es.len() as f64;
|
||||
let score = f64::from(winner == i);
|
||||
es.into_iter()
|
||||
.for_each(|e| *e += 40.0 * (score - exp_sc) / len);
|
||||
})
|
||||
}
|
||||
// ratings
|
||||
// .into_iter()
|
||||
// .zip(exp_scores.into_iter())
|
||||
// .enumerate()
|
||||
// .for_each(|(i, (es, exp_sc))| {
|
||||
// let len = es.len() as f64;
|
||||
// let score = f64::from(winner == i);
|
||||
// es.into_iter()
|
||||
// .for_each(|e| *e += 40.0 * (score - exp_sc) / len);
|
||||
// })
|
||||
// }
|
||||
|
||||
// Extract set data
|
||||
|
||||
|
|
@ -135,14 +135,41 @@ fn update_from_set(connection: &Connection, dataset: &str, results: SetData) ->
|
|||
let players_data = results.teams;
|
||||
add_players(connection, dataset, &players_data)?;
|
||||
|
||||
let mut elos = get_ratings(connection, dataset, &players_data)?;
|
||||
adjust_ratings(
|
||||
elos.iter_mut()
|
||||
.map(|v| v.iter_mut().map(|x| &mut x.1).collect())
|
||||
.collect(),
|
||||
results.winner,
|
||||
);
|
||||
update_ratings(connection, dataset, elos)
|
||||
// Singles matches are currently not supported
|
||||
if players_data.len() != 2 || players_data[0].len() != 1 || players_data[1].len() != 1 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut it = players_data.into_iter();
|
||||
let player1 = it.next().unwrap()[0].id;
|
||||
let player2 = it.next().unwrap()[0].id;
|
||||
|
||||
let advantage = get_advantage(connection, dataset, player1, player2)
|
||||
.or_else(|_| hypothetical_advantage(connection, dataset, player1, player2))?;
|
||||
let adjust = 40.0 * (1.0 - 1.0 / (1.0 + 10_f64.powf(advantage / 400.0)));
|
||||
|
||||
if results.winner == 0 {
|
||||
adjust_advantages(connection, dataset, player1, 0.5 * adjust)?;
|
||||
adjust_advantages(connection, dataset, player2, -0.5 * adjust)?;
|
||||
adjust_advantage(
|
||||
connection,
|
||||
dataset,
|
||||
player1,
|
||||
player2,
|
||||
-2.0 * (1.0 - 0.5) * adjust,
|
||||
)?;
|
||||
} else {
|
||||
adjust_advantages(connection, dataset, player1, -0.5 * adjust)?;
|
||||
adjust_advantages(connection, dataset, player2, 0.5 * adjust)?;
|
||||
adjust_advantage(
|
||||
connection,
|
||||
dataset,
|
||||
player1,
|
||||
player2,
|
||||
2.0 * (1.0 - 0.5) * adjust,
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn sync_dataset(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue