hacklu24-workout-planner

HackLU 2024 Challenge 'Workout Planner'
git clone https://git.sinitax.com/sinitax/hacklu24-workout-planner
Log | Files | Refs | sfeed.txt

main.rs (4274B)


      1#![feature(get_mut_unchecked)]
      2
      3use std::collections::BTreeMap;
      4use std::io::{self, Read, Stdin, Stdout, Write};
      5use std::iter::RepeatN;
      6use std::rc::Rc;
      7
      8struct InputHelper {
      9    stdin: Stdin,
     10    stdout: Stdout,
     11    buf: Vec<u8>,
     12}
     13
     14impl InputHelper {
     15    fn with_capacity(cap: usize) -> Self {
     16        let stdin = io::stdin();
     17        let stdout = io::stdout();
     18        Self {
     19            stdin,
     20            stdout,
     21            buf: vec![0u8; cap],
     22        }
     23    }
     24
     25    fn ask(&mut self, msg: &str) -> &[u8] {
     26        self.stdout.write(msg.as_bytes()).unwrap();
     27        self.stdout.write(b"\n").unwrap();
     28        let len = self.stdin.read(&mut self.buf).unwrap();
     29        &self.buf[..len].trim_ascii()
     30    }
     31
     32    fn ask_num(&mut self, msg: &str) -> i64 {
     33        let buf = self.ask(msg);
     34        std::str::from_utf8(buf).unwrap().parse().unwrap()
     35    }
     36}
     37
     38#[derive(Debug)]
     39struct Exercise {
     40    name: Vec<u8>,
     41    description: Vec<u8>,
     42}
     43
     44#[derive(Debug, Clone)]
     45struct Workout {
     46    exercises: Vec<RepeatN<Rc<Exercise>>>,
     47}
     48
     49fn main() {
     50    let mut exercises = BTreeMap::new();
     51    let mut workouts = Vec::new();
     52
     53    let mut input = InputHelper::with_capacity(0x100);
     54
     55    println!("Welcome to your personal training helper! Here are your options:");
     56    loop {
     57        println!("1. : add a new exercise to your portfolio");
     58        println!("2. : plan a new workout");
     59        println!("3. : start a training session");
     60        println!("4. : edit an exercise");
     61        println!("5. : exit the app");
     62
     63        let line = input.ask("Choose an option: ").trim_ascii();
     64        match &*line {
     65            b"1" => {
     66                let name = input.ask("What's the name of your exercise? ").to_owned();
     67
     68                let description = input
     69                    .ask("what is the description of your exercise? ")
     70                    .to_owned();
     71
     72                let name2 = name.clone();
     73                let exercise: Exercise = Exercise { name, description };
     74                exercises.insert(name2, Rc::new(exercise));
     75                println!("Exercise added!");
     76            }
     77            b"2" => {
     78                let num_exercises = input.ask_num("How many exercises should your workout have? ");
     79                let mut workout = Workout {
     80                    exercises: Vec::new(),
     81                };
     82
     83                for _ in 0..num_exercises {
     84                    let name = input.ask("Enter the name of the exercise: ");
     85                    if let Some(exercise) = exercises.get(name) {
     86                        let num_repetitions =
     87                            input.ask_num("How many times should your exercise be repeated? ");
     88                        workout.exercises.push(std::iter::repeat_n(
     89                            Rc::clone(exercise),
     90                            num_repetitions as usize,
     91                        ));
     92                    } else {
     93                        println!("No exercise found with that name.");
     94                    }
     95                }
     96
     97                println!("Your workout has id {}", workouts.len());
     98                workouts.push(workout);
     99            }
    100            b"3" => {
    101                let id = input.ask_num("what's the id of your workout? ");
    102
    103                let workout = &workouts[id as usize];
    104
    105                for exercise in workout.exercises.iter().cloned() {
    106                    for ex in exercise {
    107                        println!("{:?} - {:?}", ex.name, ex.description); // pls  help, this looks weird :(
    108                    }
    109                }
    110            }
    111            b"4" => {
    112                let name = input.ask("Enter the name of the exercise you want to edit: ");
    113                if let Some(exercise) = exercises.get_mut(name) {
    114                    let description = input.ask("Enter the new description: ");
    115                    unsafe {
    116                        Rc::get_mut_unchecked(exercise)
    117                            .description
    118                            .copy_from_slice(description)
    119                    }
    120                    println!("Exercise updated!");
    121                } else {
    122                    println!("No exercise found with that name.");
    123                }
    124            }
    125            b"5" => break,
    126            _ => println!("That was not a valid option"),
    127        }
    128    }
    129}