summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authorLeonard Kugis <leonard@kug.is>2022-10-10 02:09:57 +0200
committerLeonard Kugis <leonard@kug.is>2022-10-10 02:09:57 +0200
commit9a00eb67fd03d0d852f12b7546df3ef4e0c2e498 (patch)
tree05d2e553e51d3017efaef85a87b8ec4a63ded2da /src/main.rs
Initial commit, base functionalityHEADmaster
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs173
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: &gtk::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