Handle case where there is no time
This commit is contained in:
203
examples/atp.rs
Normal file
203
examples/atp.rs
Normal file
@@ -0,0 +1,203 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use time::Date;
|
||||
|
||||
use trueskill_tt::{History, BETA, MU, P_DRAW};
|
||||
|
||||
fn main() {
|
||||
let mut csv = csv::Reader::open("examples/atp.csv").unwrap();
|
||||
|
||||
let mut composition = Vec::new();
|
||||
let mut results = Vec::new();
|
||||
let mut times = Vec::new();
|
||||
|
||||
let time_format = time::format_description::parse("[year]-[month]-[day]").unwrap();
|
||||
|
||||
for row in csv.records() {
|
||||
if &row["double"] == "t" {
|
||||
composition.push(vec![
|
||||
vec![row["w1_id"].to_string(), row["w2_id"].to_string()],
|
||||
vec![row["l1_id"].to_string(), row["l2_id"].to_string()],
|
||||
]);
|
||||
} else {
|
||||
composition.push(vec![
|
||||
vec![row["w1_id"].to_string()],
|
||||
vec![row["l1_id"].to_string()],
|
||||
]);
|
||||
}
|
||||
|
||||
results.push(vec![1, 0]);
|
||||
|
||||
let time = Date::parse(&row["time_start"], &time_format)
|
||||
.unwrap()
|
||||
.midnight()
|
||||
.assume_utc()
|
||||
.unix_timestamp();
|
||||
|
||||
times.push(time as u64);
|
||||
}
|
||||
|
||||
let mut h = History::new(
|
||||
composition,
|
||||
results,
|
||||
times,
|
||||
HashMap::new(),
|
||||
MU,
|
||||
1.6,
|
||||
BETA,
|
||||
0.036,
|
||||
P_DRAW,
|
||||
);
|
||||
h.convergence();
|
||||
|
||||
/*
|
||||
composition,
|
||||
results,
|
||||
times,
|
||||
priors,
|
||||
MU,
|
||||
BETA,
|
||||
SIGMA,
|
||||
GAMMA,
|
||||
P_DRAW,
|
||||
|
||||
*/
|
||||
/*
|
||||
let mut priors = HashMap::new();
|
||||
|
||||
for k in ["aj", "bj", "cj"] {
|
||||
let player = Player::new(
|
||||
Gaussian::new(25.0, 25.0 / 3.0),
|
||||
25.0 / 6.0,
|
||||
0.15 * 25.0 / 3.0,
|
||||
N_INF,
|
||||
);
|
||||
|
||||
priors.insert(k.to_string(), player);
|
||||
}
|
||||
|
||||
let mut h1 = History::new(
|
||||
composition,
|
||||
results,
|
||||
times,
|
||||
priors,
|
||||
MU,
|
||||
BETA,
|
||||
SIGMA,
|
||||
GAMMA,
|
||||
P_DRAW,
|
||||
);
|
||||
*/
|
||||
|
||||
/*
|
||||
let columns = data
|
||||
.lines()
|
||||
.skip(1)
|
||||
.map(|line| {
|
||||
let columns = line.split(',').collect::<Vec<_>>();
|
||||
|
||||
Column {
|
||||
w1_id: columns[3],
|
||||
w2_id: columns[3],
|
||||
l1_id: columns[3],
|
||||
l2_id: columns[3],
|
||||
double: columns[3],
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
*/
|
||||
|
||||
// match_id,double,round_number,w1_id,w1_name,w2_id,w2_name,l1_id,l1_name,l2_id,l2_name,time_start,time_end,ground,tour_id,tour_name
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
|
||||
/*
|
||||
import pandas as pd
|
||||
#sudo pip3 install trueskillthroughtime
|
||||
from trueskillthroughtime import *
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
# Data
|
||||
df = pd.read_csv('input/history.csv', low_memory=False)
|
||||
|
||||
columns = zip(df.w1_id, df.w2_id, df.l1_id, df.l2_id, df.double)
|
||||
composition = [[[w1,w2],[l1,l2]] if d == 't' else [[w1],[l1]] for w1, w2, l1, l2, d in columns ]
|
||||
times = [ datetime.strptime(t, "%Y-%m-%d").timestamp()/(60*60*24) for t in df.time_start]
|
||||
|
||||
#start = time.time()
|
||||
h = History(composition = composition, times = times, sigma = 1.6, gamma = 0.036)
|
||||
h.convergence(epsilon=0.01, iterations=10)
|
||||
#end = time.time()
|
||||
#print(end-start)
|
||||
*/
|
||||
}
|
||||
|
||||
mod csv {
|
||||
use std::fs::File;
|
||||
use std::io::{self, BufRead, BufReader, Lines};
|
||||
use std::ops;
|
||||
use std::path::Path;
|
||||
|
||||
pub struct Reader {
|
||||
header_map: Vec<String>,
|
||||
lines: Lines<BufReader<File>>,
|
||||
}
|
||||
|
||||
impl Reader {
|
||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
|
||||
let mut lines = File::open(path).map(BufReader::new)?.lines();
|
||||
|
||||
let header_map = if let Some(header) = lines.next() {
|
||||
let header = header?;
|
||||
|
||||
header.split(',').map(Into::into).collect::<Vec<_>>()
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
Ok(Self { header_map, lines })
|
||||
}
|
||||
|
||||
pub fn records(&mut self) -> Records<'_> {
|
||||
Records {
|
||||
header_map: &self.header_map,
|
||||
lines: &mut self.lines,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Records<'a> {
|
||||
header_map: &'a Vec<String>,
|
||||
lines: &'a mut Lines<BufReader<File>>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Records<'a> {
|
||||
type Item = Record<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let line = self.lines.next()?;
|
||||
|
||||
Some(Record {
|
||||
header_map: self.header_map,
|
||||
columns: line.unwrap().split(',').map(Into::into).collect::<Vec<_>>(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Record<'a> {
|
||||
header_map: &'a Vec<String>,
|
||||
columns: Vec<String>,
|
||||
}
|
||||
|
||||
impl<'a> ops::Index<&str> for Record<'a> {
|
||||
type Output = str;
|
||||
|
||||
fn index(&self, index: &str) -> &Self::Output {
|
||||
&self.columns[self
|
||||
.header_map
|
||||
.iter()
|
||||
.position(|header| header == index)
|
||||
.unwrap()]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user