diff options
author | Leonard Kugis <leonard@kug.is> | 2022-10-10 02:09:57 +0200 |
---|---|---|
committer | Leonard Kugis <leonard@kug.is> | 2022-10-10 02:09:57 +0200 |
commit | 9a00eb67fd03d0d852f12b7546df3ef4e0c2e498 (patch) | |
tree | 05d2e553e51d3017efaef85a87b8ec4a63ded2da /src/main.rs |
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..b92c136 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,173 @@ +use gtk::prelude::*; +use clap::Parser; +use csv; +use rand::Rng; +use text_io; + +const APP_ID: &str = "com.encrox.rraffle"; + +#[derive(Parser, Debug)] +struct Cli { + /// CSV file with names and number of lots + #[arg(short, long)] + file: Option<std::path::PathBuf>, + + /// Show GUI + #[arg(short, long)] + gui: bool, + + /// Shuffle animation + #[arg(short, long)] + animation: Option<std::path::PathBuf>, + + /// Number of draws + #[arg(short, long, default_value_t = 5)] + draws: u32, + + /// Number of wins per entry + #[arg(short, long, default_value_t = 2)] + wins: u32, + + /// Interactive when in CLI mode + #[arg(short, long)] + interactive: bool, +} + +#[derive(Debug)] +struct Entry { + name: String, + lots: u32, + wins: u32, + odds: f64 +} + +fn load_csv(entries : &mut Vec<Entry>, file: std::path::PathBuf) { + let reader = csv::Reader::from_path(file); + for record in reader.unwrap().records() { + //dbg!(record.unwrap().get(0).unwrap()); + let rec = record.unwrap(); + entries.push(Entry { + name: rec.get(0).unwrap().to_string(), + lots: rec.get(1).unwrap().parse::<u32>().unwrap(), + wins: 2, + odds: 0.0 + }); + } +} + +fn max_wins(entries : &mut Vec<Entry>, wins : u32) { + for entry in entries { + entry.wins = wins; + } +} + +fn calc_odds(entries : &mut Vec<Entry>) { + let mut sum : u32 = 0; + for entry in &mut *entries { + sum += if entry.wins > 0 { entry.lots } else { 0 }; + } + for entry in entries { + entry.odds = if entry.wins > 0 { entry.lots as f64 / sum as f64 } else { 0.0 }; + } +} + +fn get_winner(entries : &mut Vec<Entry>) -> &Entry { + let mut rng = rand::thread_rng(); + let rn = rng.gen::<f64>(); + let mut sum : f64 = 0.0; + for entry in entries { + if rn >= sum && rn < sum + entry.odds { + entry.lots -= 1; + entry.wins -= 1; + return entry; + } + sum += entry.odds; + } + unreachable!(); +} + +fn main() { + let args = Cli::parse(); + //dbg!(args); + + if args.gui { + // Create a new application + let app = gtk::Application::builder().application_id(APP_ID).build(); + + // Connect to "activate" signal of `app` + app.connect_activate(build_ui); + + // Run the application + app.run_with_args(&[""]); + } else { + if !args.file.is_none() { + let mut entries = Vec::<Entry>::new(); + load_csv(&mut entries, args.file.unwrap()); + max_wins(&mut entries, args.wins); + let mut round = 1; + 'outer: loop { + calc_odds(&mut entries); + println!("Draw round: {}", round); + println!("Entries: {:?}", &entries); + if args.interactive { + print!("Option (s = start, a = abort) [s/a]: "); + loop { + let option : char = text_io::read!(); + match option { + 'a' => break 'outer, + 's' => break, + _ => println!("Unknown option: {}", option), + } + } + } + let winner = get_winner(&mut entries); + println!("Winner is: {}", winner.name); + if args.interactive { + print!("Option (n = next, a = abort) [n/a]: "); + loop { + let option : char = text_io::read!(); + match option { + 'a' => break 'outer, + 'n' => break, + _ => println!("Unknown option: {}", option), + } + } + } + if round == args.draws && !args.interactive { + println!("Number of draws reached."); + break; + } + round += 1; + } + } + } +} + +fn build_ui(app: >k::Application) { + let glade_src = include_str!("main.glade"); + let builder = gtk::Builder::from_string(glade_src); + + let window: gtk::ApplicationWindow = builder.object("window").expect("Couldn't get window"); + let tv : gtk::TreeView = builder.object("tv").expect("Couldn't get tree view"); + let btn_draw_single : gtk::Button = builder.object("btn_draw_single").expect("Couldn't get button btn_draw_single"); + let btn_draw_multiple : gtk::Button = builder.object("btn_draw_multiple").expect("Couldn't get button btn_draw_multiple"); + let file_choose_csv : gtk::FileChooserButton = builder.object("file_choose_csv").expect("Couldn't get button file_choose_csv"); + let btn_load : gtk::Button = builder.object("btn_load").expect("Couldn't get button btn_load"); + let lbl_round : gtk::Label = builder.object("lbl_round").expect("Couldn't get lbl_round"); + let btn_reset : gtk::Button = builder.object("btn_reset").expect("Couldn't get btn_reset"); + let sp_num_draws : gtk::SpinButton = builder.object("sp_num_draws").expect("Couldn't get sp_num_draws"); + let ts : gtk::TreeStore = builder.object("ts").expect("Couldn't get tree store"); + + window.set_application(Some(app)); + + btn_load.connect_clicked(glib::clone!(@weak file_choose_csv, @weak ts => move |button| { + //let data = load_csv(file_choose_csv.filename().unwrap()); + //for entry in data { + let iter = ts.insert(None, -1); + ts.set(&iter, &[(0, &glib::Value::from("Eva")), (1, &0.to_value())]); + //} + })); + + // Present window + window.show_all(); +}
\ No newline at end of file |