pub fn new(callback: impl Fn(HashMap<String,u32>) + std::marker::Send + 'static) -> Game {
        let state = Arc::new(Mutex::new(GameState {
                money: 0,
                slaves: LinkedList::new(),
                graveyard: Vec::new()
            }));
        let state_clone = Arc::clone(&state);
        Game { // the runtime attribute keeps the slaves working
            state, runtime: thread::spawn(move || {
                loop { // I would replace this with a time limit, but the docker container has a timeout anyway
                    let mut state = state_clone.lock().unwrap();

                    // run through slaves to figure out how much money to add
                    let mut cur = state.slaves.cursor_front_mut();
                    let mut add = 0;
                    let mut graveyard = vec![]; // i'd like to use state.graveyard directly, but borrow checker can't disambiguate between mutable references on different attributes of a struct and yada yada you don't really need to know this part to solve the challenge
                    while let Some(mut slave) = cur.current() {
                        if slave.expiry == 0 { // if one of them dies
                            if let Some(s) = cur.remove_current() {
                                graveyard.push(s);
                            }
                        } else {
                            slave.expiry -= 1;
                            add += slave.income;
                            cur.move_next();
                        }
                    }
                    state.money += add;
                    state.graveyard.append(&mut graveyard);

                    callback(state.summary()); // to dynamically update the UI
                    drop(state); // drop the lock for other usage
                    sleep_seconds!(1);
                }
            }),
            market: vec![ // hardcoded list of slaves; I'm kinda lazy
                Slave::new("Murky".to_string(), 0, 5),
                Slave::new("Cute Filly".to_string(), 2, 10),
                Slave::new("Troubleshoes".to_string(), 5, 50),
                Slave::new("Diana Pie".to_string(), 7, 40),
                Slave::new("Prissy Unicorn".to_string(), 2, 70),
            ]
        }
    }
/// Creating a new game spawns a thread to tick forward game-time. Each tick runs callback().
Creating a new game spawns a thread to tick forward game-time. Each tick runs callback().
Creating a new game spawns a thread to tick forward game - time . Each tick runs callback () .
pub fn new(callback: impl Fn(HashMap<String,u32>) + std::marker::Send + 'static) -> Game {
        let state = Arc::new(Mutex::new(GameState {
                money: 0,
                slaves: LinkedList::new(),
                graveyard: Vec::new()
            }));
        let state_clone = Arc::clone(&state);
        Game { // the runtime attribute keeps the slaves working
            state, runtime: thread::spawn(move || {
                loop { // I would replace this with a time limit, but the docker container has a timeout anyway
                    let mut state = state_clone.lock().unwrap();
                    // run through slaves to figure out how much money to add
                    let mut cur = state.slaves.cursor_front_mut();
                    let mut add = 0;
                    let mut graveyard = vec![]; // i'd like to use state.graveyard directly, but borrow checker can't disambiguate between mutable references on different attributes of a struct and yada yada you don't really need to know this part to solve the challenge
                    while let Some(mut slave) = cur.current() {
                        if slave.expiry == 0 { // if one of them dies
                            if let Some(s) = cur.remove_current() {
                                graveyard.push(s);
                            }
                        } else {
                            slave.expiry -= 1;
                            add += slave.income;
                            cur.move_next();
                        }
                    }
                    state.money += add;
                    state.graveyard.append(&mut graveyard);
                    callback(state.summary()); // to dynamically update the UI
                    drop(state); // drop the lock for other usage
                    sleep_seconds!(1);
                }
            }),
            market: vec![ // hardcoded list of slaves; I'm kinda lazy
                Slave::new("Murky".to_string(), 0, 5),
                Slave::new("Cute Filly".to_string(), 2, 10),
                Slave::new("Troubleshoes".to_string(), 5, 50),
                Slave::new("Diana Pie".to_string(), 7, 40),
                Slave::new("Prissy Unicorn".to_string(), 2, 70),
            ]
        }
    }
pub fn new ( callback : impl Fn ( HashMap < String , u32 > ) + std :: marker :: Send + ' static ) -> Game { let state = Arc :: new ( Mutex :: new ( GameState { money : 0 , slaves : LinkedList :: new ( ) , graveyard : Vec :: new ( ) } ) ) ; let state_clone = Arc :: clone ( & state ) ; Game { // the runtime attribute keeps the slaves working state , runtime : thread :: spawn ( move | | { loop { // I would replace this with a time limit, but the docker container has a timeout anyway let mut state = state_clone . lock ( ) . unwrap ( ) ; // run through slaves to figure out how much money to add let mut cur = state . slaves . cursor_front_mut ( ) ; let mut add = 0 ; let mut graveyard = vec ! [ ] ; // i'd like to use state.graveyard directly, but borrow checker can't disambiguate between mutable references on different attributes of a struct and yada yada you don't really need to know this part to solve the challenge while let Some ( mut slave ) = cur . current ( ) { if slave . expiry == 0 { // if one of them dies if let Some ( s ) = cur . remove_current ( ) { graveyard . push ( s ) ; } } else { slave . expiry -= 1 ; add += slave . income ; cur . move_next ( ) ; } } state . money += add ; state . graveyard . append ( & mut graveyard ) ; callback ( state . summary ( ) ) ; // to dynamically update the UI drop ( state ) ; // drop the lock for other usage sleep_seconds ! ( 1 ) ; } } ) , market : vec ! [ // hardcoded list of slaves; I'm kinda lazy Slave new ( " " to_string ( ) 0 5 ) Slave new ( " " to_string ( ) 2 10 ) Slave new ( " " to_string ( ) 5 50 ) Slave new ( " " to_string ( ) 7 40 ) Slave new ( " " to_string ( ) 2 70 ) ] } }
Creating a new game spawns a thread to tick forward game-time.
Creating a new game spawns a thread to tick forward game - time .
callback
impl Fn(HashMap<String,u32>) + std::marker::Send + 'static
callback
impl Fn(HashMap<String,u32>) + std::marker::Send + 'static