diff --git a/21_Calendar/rust/Cargo.toml b/21_Calendar/rust/Cargo.toml new file mode 100644 index 00000000..1ec69633 --- /dev/null +++ b/21_Calendar/rust/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/21_Calendar/rust/README.md b/21_Calendar/rust/README.md new file mode 100644 index 00000000..e616424e --- /dev/null +++ b/21_Calendar/rust/README.md @@ -0,0 +1,3 @@ +Original source downloaded [from Vintage Basic](http://www.vintage-basic.net/games.html) + +Conversion to [Rust](https://www.rust-lang.org/) by [Uğur Küpeli](https://github.com/ugurkupeli) \ No newline at end of file diff --git a/21_Calendar/rust/src/main.rs b/21_Calendar/rust/src/main.rs new file mode 100644 index 00000000..a279f95d --- /dev/null +++ b/21_Calendar/rust/src/main.rs @@ -0,0 +1,152 @@ +use std::io::stdin; + +const WIDTH: usize = 64; +const DAYS_WIDTH: usize = WIDTH / 8; +const MONTH_WIDTH: usize = WIDTH - (DAYS_WIDTH * 2); +const DAY_NUMS_WIDTH: usize = WIDTH / 7; + +const DAYS: [&str; 7] = [ + "SUNDAY", + "MONDAY", + "TUESDAY", + "WEDNESDAY", + "THURSDAY", + "FRIDAY", + "SATURDAY", +]; + +fn main() { + println!("\n\t\t CALENDAR"); + println!("CREATIVE COMPUTING MORRISTOWN, NEW JERSEY\n"); + + let (starting_day, leap_year) = prompt(); + let (months, total_days) = get_months_and_days(leap_year); + + let mut days_passed = 0; + let mut current_day_index = DAYS.iter().position(|d| *d == starting_day).unwrap(); + + for (month, days) in months { + print_header(month, days_passed, total_days - days_passed); + print_days(&mut current_day_index, days); + days_passed += days as u16; + println!("\n"); + } +} + +fn prompt() -> (String, bool) { + let mut day = String::new(); + + loop { + println!("\nFirst day of the year?"); + if let Ok(_) = stdin().read_line(&mut day) { + day = day.trim().to_uppercase(); + if DAYS.contains(&day.as_str()) { + break; + } else { + day.clear(); + } + } + } + + let mut leap = false; + + loop { + println!("Is this a leap year?"); + let mut input = String::new(); + if let Ok(_) = stdin().read_line(&mut input) { + match input.to_uppercase().trim() { + "Y" | "YES" => { + leap = true; + break; + } + "N" | "NO" => break, + _ => (), + } + } + } + + println!(); + (day, leap) +} + +fn get_months_and_days(leap_year: bool) -> (Vec<(String, u8)>, u16) { + let months = [ + "JANUARY", + "FEBUARY", + "MARCH", + "APRIL", + "MAY", + "JUNE", + "JULY", + "AUGUST", + "SEPTEMBER", + "OCTOBER", + "NOVEMBER", + "DECEMBER", + ]; + + let mut months_with_days = Vec::new(); + let mut total_days: u16 = 0; + + for (i, month) in months.iter().enumerate() { + let days = if i == 1 { + if leap_year { + 29u8 + } else { + 28 + } + } else if if i < 7 { (i % 2) == 0 } else { (i % 2) != 0 } { + 31 + } else { + 30 + }; + + total_days += days as u16; + months_with_days.push((month.to_string(), days)); + } + + (months_with_days, total_days) +} + +fn print_between(s: String, w: usize, star: bool) { + let s = format!(" {s} "); + if star { + print!("{:*^w$}", s); + return; + } + print!("{:^w$}", s); +} + +fn print_header(month: String, days_passed: u16, days_left: u16) { + print_between(days_passed.to_string(), DAYS_WIDTH, true); + print_between(month.to_string(), MONTH_WIDTH, true); + print_between(days_left.to_string(), DAYS_WIDTH, true); + println!(); + + for d in DAYS { + let d = d.chars().nth(0).unwrap(); + print_between(d.to_string(), DAY_NUMS_WIDTH, false); + } + println!(); + + println!("{:*>WIDTH$}", ""); +} + +fn print_days(current_day_index: &mut usize, days: u8) { + let mut current_date = 1u8; + + print!("{:>w$}", " ", w = DAY_NUMS_WIDTH * *current_day_index); + + for _ in 1..=days { + print_between(current_date.to_string(), DAY_NUMS_WIDTH, false); + + if ((*current_day_index + 1) % 7) == 0 { + *current_day_index = 0; + println!(); + } else { + *current_day_index += 1; + } + + current_date += 1; + } +}