Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 33 additions & 21 deletions design-patterns/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@
//! | Client | Part of a code that uses the above mechanism |
//!

use std::{thread::sleep, time::Duration};

// Example below uses Command pattern to fire a weapon in a shooting game in
// which firing command directly fires any weapon without knowing the detail
// about each element's fire procedure.
use console::Term;

const MAX_AMMO: usize = 30;
// Define Command
trait Command {
fn execute(&self) -> u8;
Expand All @@ -54,12 +57,14 @@ struct Sniper {

impl WeaponTrait for AssultRifle {
fn fire(&mut self) -> u8 {
// sleep(Duration::from_millis((100 - self.fire_rate as u64) * 10));
self.fire_rate
}
}

impl WeaponTrait for Sniper {
fn fire(&mut self) -> u8 {
// sleep(Duration::from_millis((100 - self.fire_rate as u64) * 10));
(self.fire_rate as f32 * self.efficiency as f32 * 0.01) as u8
}
}
Expand Down Expand Up @@ -88,9 +93,9 @@ impl Command for FireSniperCommand {
}

fn main() {
let assult_rifle = AssultRifle { fire_rate: 20 };
let assult_rifle = AssultRifle { fire_rate: 90 };
let sniper = Sniper {
fire_rate: 10,
fire_rate: 30,
efficiency: 90,
};

Expand All @@ -105,57 +110,64 @@ fn main() {
];

let mut selected = 0;
let mut ammo = 50;

let mut ammo = MAX_AMMO;
let stdout = Term::stdout();

loop {
stdout.clear_screen().unwrap();
let ammo_emoji = if selected == 0 { "🔫" } else { "🚀" };
println!(
r#"
===============================================================================
[ 1 ]: Rifle [ 2 ]: Sniper [ F ]: Fire [ R ]: Reload [ Q ]: Quit
===============================================================================
[ {} ]: {}

[{:03}] {}
-------------------------------------------------------------------------------
{}

"#,
if selected == 0 {
"︻デ═一"
} else {
"╾━╤デ╦︻"
},
ammo,
if ammo > 0 {
"☢ ".repeat(ammo)
(ammo_emoji).repeat(ammo)
} else {
"!! NO AMMO !!".to_string()
}
},
if selected == 0 {
"[Rifle] ︻デ═一💥"
} else {
"[Sniper] 💥╾━╤デ╦︻"
},
);
if let Ok(character) = stdout.read_char() {
match character {
'1' => {
if selected != 0 {
selected = 0;
ammo = 50;
ammo = MAX_AMMO;
}
}
'2' => {
if selected != 1 {
selected = 1;
ammo = 50;
ammo = MAX_AMMO;
}
}
'f' => {
if ammo > 0 {
let command = commands.get(selected).clone().unwrap();
let bullets_fired = command.execute();
let a = (bullets_fired as f32 / 5f32).max(0.0) as usize;
if a < ammo {
ammo -= a;
} else {
ammo = 0;
let fire_rate = command.execute();
if ammo > 0 {
ammo -= 1;
}
// it pauses the execution depending the firerate. 100 means no pause
// We are currently dealing with the rust std library without async, so the firing will not
// block the key press buffer, so if you repeatedly press f, it takes time to complete firing.
sleep(Duration::from_millis((100 - fire_rate as u64) * 10));
}
}
'r' => {
ammo = 50;
ammo = MAX_AMMO;
}
_ => {
break;
Expand Down
86 changes: 45 additions & 41 deletions design-patterns/src/observer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
//! The code snippet below uses observer pattern to notify users
//! once it receives readings in the weather data.
//!*/
use common::input; // common library for this repository
use console::Term;
use rand;
use std::collections::HashMap;

Expand Down Expand Up @@ -84,57 +84,61 @@ fn main() {
let rain_listener: Subscriber = |value| {
println!("RAIN:\t\t{value}mm");
};

let wind_listener: Subscriber = |value| {
println!("WIND:\t\t{value}m/s2");
};
println!("Observer Pattern");
let mut sensor = Sensor::default();

let stdout = Term::stdout();
sensor.readings().subscribe(SensorType::Rain, rain_listener);
sensor.readings().subscribe(SensorType::Wind, wind_listener);
loop {
println!(
r#"
-------------------------------------------
[r/R]: Read
[sr/SR]: Subscribe to the Rain data
[sw/SW]: Subscribe to the Wind data
[ur/UR]: Unsubscribe to the Rain data
[uw/UW]: Unsubscribe to the Wind data
[e/E]: Exit
-------------------------------------------
"#
------------------------------------------------------------------
[r]: Subscribe to the Rain data
[w]: Subscribe to the Wind data
[f]: Unsubscribe to the Rain data
[s]: Unsubscribe to the Wind data
[e]: Exit

press [space] to read the subscribed data
-----------------------------------------------------------------
"#,
);
// ! input() is a common library function, not included in std
match input("Enter option: ").as_str().trim() {
"R" | "r" => {
// display readings of subscribed sensors
sensor.get_new_reading(SensorType::Rain);
sensor.get_new_reading(SensorType::Wind);
}
"SR" | "sr" => {
// Subscribe to rain sensor readings
sensor.readings().subscribe(SensorType::Rain, rain_listener);
}
"SW" | "sw" => {
// Subscribe to wind sensor readings
sensor.readings().subscribe(SensorType::Wind, wind_listener);
}
"UR" | "ur" => {
// Unsubscribe to rain sensor readings
sensor
.readings()
.unsubscribe(SensorType::Rain, rain_listener);
}
"UW" | "uw" => {
// Unsubscribe to wind sensor readings
sensor
.readings()
.unsubscribe(SensorType::Wind, wind_listener);
}
_ => {
break;
}
};
if let Ok(character) = stdout.read_char() {
match character {
'r' => {
// Subscribe to rain sensor readings
sensor.readings().subscribe(SensorType::Rain, rain_listener);
}
'w' => {
// Subscribe to wind sensor readings
sensor.readings().subscribe(SensorType::Wind, wind_listener);
}
'f' => {
// Unsubscribe to rain sensor readings
sensor
.readings()
.unsubscribe(SensorType::Rain, rain_listener);
}
's' => {
// Unsubscribe to wind sensor readings
sensor
.readings()
.unsubscribe(SensorType::Wind, wind_listener);
}
'e' => {
break;
}
_ => {
// do nothing
}
};
sensor.get_new_reading(SensorType::Rain);
sensor.get_new_reading(SensorType::Wind);
}
}
}