use pad::PadStr; use rand::Rng; use std::fs::File; use std::io::{BufRead, BufReader, Error}; use std::process; const FILENAME: &str = "members-list.txt"; #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] struct Member { name: String, emoji: String, membership_number: u16, } #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] struct UserInput { name: String, membership_number: u16, } fn main() -> Result<(), Error> { let file = File::open(FILENAME)?; let mut structs = read_file_to_members(file)?; println!("{} | membership number", "name".pad_to_width(10)); println!("-----------|------------------------"); structs.sort_by(|a, b| b.membership_number.cmp(&a.membership_number)); structs.reverse(); for line in structs.iter() { let name_string = line.name.pad_to_width(10); println!("{} | {}", name_string, line.membership_number); } println!("Add member: y/n"); let yes_no = get_string(); if yes_no == "n" { process::exit(0); } else if yes_no == "y" { println!("Enter the name of the new member!"); let input = get_string(); let mut new_member = fetch_input_and_add_to_members(input)?; let stripped_structs = strip_emoji_from_members(structs); for stripped_struct in stripped_structs { new_member.push(stripped_struct); } println!("{} | membership number", "name".pad_to_width(10)); println!("-----------|------------------------"); new_member.sort_by(|a, b| b.membership_number.cmp(&a.membership_number)); new_member.reverse(); for member in new_member { let name_string = member.name.pad_to_width(10); println!("{} | {}", name_string, member.membership_number); } } Ok(()) } fn read_file_to_members(file: File) -> Result<Vec<Member>, Error> { let buffered = BufReader::new(file); let mut _line_read = String::new(); let mut member_vec = Vec::new(); for line in buffered.lines() { _line_read = match line { Ok(line) => line, Err(e) => { return Err(e); } }; let string_vec: Vec<&str> = _line_read.split_whitespace().collect(); let member = Member { name: string_vec[0].to_string(), emoji: string_vec[1].to_string(), membership_number: string_vec[2].parse::<u16>().unwrap(), }; member_vec.push(member); } Ok(member_vec) } fn fetch_input_and_add_to_members(user_input: String) -> Result<Vec<UserInput>, Error> { let mut input = Vec::new(); let membership_number = rand::thread_rng().gen::<u16>(); let new_member = UserInput { name: user_input, membership_number, }; input.push(new_member); Ok(input) } fn strip_emoji_from_members(members: Vec<Member>) -> Vec<UserInput> { let mut stripped_member_vec = Vec::new(); for member in members.iter() { let stripped_member = UserInput { name: member.name.clone(), membership_number: member.membership_number, }; stripped_member_vec.push(stripped_member); } stripped_member_vec } fn get_string() -> String { let mut buffer = String::new(); let stdin = std::io::stdin(); stdin.read_line(&mut buffer).expect("BROKEN STDIN"); let input = buffer.trim(); input.parse().expect("Peng") }