Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
7 changes: 7 additions & 0 deletions submissions/week-2/day-3/Stephen-Ngozi-User-Input/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions submissions/week-2/day-3/Stephen-Ngozi-User-Input/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "Stephen-Ngozi-User-Input"
version = "0.1.0"
edition = "2024"

[dependencies]
50 changes: 50 additions & 0 deletions submissions/week-2/day-3/Stephen-Ngozi-User-Input/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

use std::io;
enum PowerStatus {
Off,
Sleep,
Reboot,
Comment on lines +1 to +6
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description says this is a Week 3 Day 3 submission, but this PR also adds Week 2 Day 3 / Day 5 projects. Per the repo submission guidance, week/day submissions should be kept scoped to the relevant folder; consider moving Week 2 additions into separate PR(s).

Copilot uses AI. Check for mistakes.
Shutdown,
Hibernate,
}

fn format_power_status(input: &str) -> Option<PowerStatus> {
match input.to_lowercase().as_str() {
"off" => Some(PowerStatus::Off),
"sleep" => Some(PowerStatus::Sleep),
"reboot" => Some(PowerStatus::Reboot),
"shutdown" => Some(PowerStatus::Shutdown),
"hibernate" => Some(PowerStatus::Hibernate),
_ => None,
}
}


fn handle_power_status(status: PowerStatus) {
match status {
PowerStatus::Off => println!("Turning off the computer"),
PowerStatus::Sleep => println!("Putting the computer to sleep"),
PowerStatus::Reboot => println!("Rebooting the computer"),
PowerStatus::Shutdown => println!("Shutting down the computer"),
PowerStatus::Hibernate => println!("Hibernating the computer"),
}
}



fn main() {
println!("Enter power option (off, sleep, reboot, shutdown, hibernate):");

let mut input = String::new();
io::stdin()
.read_line(&mut input)
.expect("Failed to read input");

let input = input.trim();

match format_power_status(input) {
Some(status) => handle_power_status(status),
None => println!("Error: Invalid power option"),
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target
7 changes: 7 additions & 0 deletions submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "Stephen-Ngozi-Merkle-Tree"
version = "0.1.0"
edition = "2024"

[dependencies]
17 changes: 17 additions & 0 deletions submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/expense.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@


#[derive(Debug, Clone)]
pub enum TransactionType {
Credit,
Debit,
}



#[derive(Debug, Clone)]
pub struct Expense {
pub id: u8,
pub name: String,
pub amount: f64,
pub tx_type: TransactionType,
}
141 changes: 141 additions & 0 deletions submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
mod expense;
mod tracker;

use std::io;
use expense::TransactionType;
use tracker::ExpenseTracker;




fn print_menu() {
println!("\n=== Expense Tracker ===");
println!("1 - Add Expense");
println!("2 - View Expenses");
println!("3 - Update Expense");
println!("4 - Delete Expense");
println!("q - Quit");
}
fn main() {
// println!("Hello, world!");

let mut tracker = ExpenseTracker::new();

loop {
print_menu();

let mut input = String::new();
io::stdin().read_line(&mut input).expect("Failed");
let input = input.trim();


if input == "q" {
println!("Are you sure you want to quit? (y/n)");
let mut confirm = String::new();
io::stdin().read_line(&mut confirm).expect("Failed ");
let confirm = confirm.trim();

if confirm == "y" {
tracker.save_to_file("stephen_expences.txt");
println!("Data saved to stephen_expences.txt");
Comment on lines +39 to +40
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The filename/message uses "expences" (typo). Consider renaming to "stephen_expenses.txt" and updating the saved output file accordingly so naming matches "expenses" throughout.

Suggested change
tracker.save_to_file("stephen_expences.txt");
println!("Data saved to stephen_expences.txt");
tracker.save_to_file("stephen_expenses.txt");
println!("Data saved to stephen_expenses.txt");

Copilot uses AI. Check for mistakes.
println!("Bye bye go home!");
break;
}
}else if input == "1" {
println!("Enter expense name:");
let mut name = String::new();
io::stdin().read_line(&mut name).expect("Failed to read input");
let name = name.trim().to_string();

println!("Enter amount:");
let mut amount_input = String::new();
io::stdin().read_line(&mut amount_input).expect("Failed to read input");
let amount: f64 = amount_input.trim().parse().expect("Please enter a valid number");

println!("Is this Credit or Debit? (c/d):");
let mut tx_input = String::new();
io::stdin().read_line(&mut tx_input).expect("Failed to read input");
let tx_input = tx_input.trim();

let tx_type = if tx_input == "c" {
TransactionType::Credit
} else {
TransactionType::Debit
};

let new_expense = tracker.add(name, amount, tx_type);
println!(" Expense added successfully!");
println!("ID: {}, Name: {}, Amount: ${:.2}, Type: {:?}",
new_expense.id, new_expense.name, new_expense.amount, new_expense.tx_type);
}else if input == "2" {
let expenses = tracker.view_all();

if expenses.is_empty() {
println!("No Expenses in the Tracker");
} else {
println!("All Expenses");
for expense in expenses {
println!("ID: {} | Name: {} | Amount: Naria{:.2} | Type: {:?}",
expense.id, expense.name, expense.amount, expense.tx_type);
Comment on lines +78 to +79
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in output label: "Naria" is likely meant to be "Naira".

Copilot uses AI. Check for mistakes.
}
}
} else if input == "3" {
println!("Enter the ID of the Expence");
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in prompt: "Expence" should be "Expense".

Copilot uses AI. Check for mistakes.

let mut new_id_input = String::new();

io::stdin().read_line(&mut new_id_input).expect("Failed to read input");
let id: u8 = new_id_input.trim().parse().expect("Please enter a valid ID");



println!("Enter new amount:");
let mut amount_input = String::new();
io::stdin().read_line(&mut amount_input).expect("Failed to read input");
let amount: f64 = amount_input.trim().parse().expect("Please enter a valid number");

println!("Is this Credit or Debit? (c/d):");
let mut tx_input = String::new();
io::stdin().read_line(&mut tx_input).expect("Failed to read input");
let tx_input = tx_input.trim();

let tx_type = if tx_input == "c" {
TransactionType::Credit
} else {
TransactionType::Debit
};

if tracker.update(id, amount, tx_type){
println!("Expense Updated Successfu");
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in status message: "Successfu" should be "Successful" (or "Successfully").

Suggested change
println!("Expense Updated Successfu");
println!("Expense Updated Successfully");

Copilot uses AI. Check for mistakes.

if let Some(expense) = tracker.values.get(&id) {
println!("ID: {}, Name: {}, Amount: Naria{:.2}, Type: {:?}",
Comment on lines +108 to +112
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If tracker.update(...) returns false (ID not found), the user gets no feedback and the program silently continues. Add an else branch to print a not-found message (similar to delete).

Copilot uses AI. Check for mistakes.
expense.id, expense.name, expense.amount, expense.tx_type);
}else {
println!("Expense with ID {} not found!", id);

}
}
}else if input == "4" {
println!("Enter the ID of the expense you to delete:");

let mut id_input = String::new();

io::stdin().read_line(&mut id_input).expect("Failed to read input");
let id: u8 = id_input.trim().parse().expect("Please enter a valid ID");

if tracker.delete(id){
println!(" Your Expence is Deleted ");
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo in status message: "Expence" should be "Expense".

Suggested change
println!(" Your Expence is Deleted ");
println!(" Your Expense is Deleted ");

Copilot uses AI. Check for mistakes.
}else {
println!("Expense with ID {} not found!", id);
}
}else {
println!("Invalid choice. Please try again.");
}




}

}
84 changes: 84 additions & 0 deletions submissions/week-2/day-5/Stephen-Ngozi-Merkle-Tree/src/tracker.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use std::{collections::HashMap,fs::File,io::Write};
use crate::expense::{Expense, TransactionType};


// Expense tracker
// Add the expenses
// Remove
// Update
// View

// Hashmaps
// structs
// enums
// Hashmaps




pub struct ExpenseTracker {
pub values: HashMap<u8, Expense>,
pub next_id: u8,
}

impl ExpenseTracker {
pub fn new() -> Self {
Self {
values: HashMap::new(),
next_id: 1,
}
}

pub fn add(&mut self, name: String, amount: f64, tx_type: TransactionType) -> Expense {
let current_id = self.next_id;
let new_expense = Expense {
id: current_id,
name,
amount,
tx_type,
};
self.values.insert(current_id, new_expense.clone());
self.next_id += 1;
new_expense
}

pub fn view_all(&self) -> Vec<&Expense> {
let mut expenses: Vec<&Expense> = self.values.values().collect();

expenses.sort_by(|a, b|{a.id.cmp(&b.id)});
expenses

}

pub fn update(&mut self, id: u8, amount: f64, tx_type: TransactionType) -> bool {
match self.values.get_mut(&id) {
Some(exp) => {
exp.amount = amount;
exp.tx_type = tx_type;
true
}
None => false,
}
// let updated_expense = Expense {
// id,
// amount,
// tx_type,
// };
// self.values.put(id)
}

pub fn delete(&mut self, id: u8) -> bool {
self.values.remove(&id).is_some()
}


pub fn save_to_file(&self, filename: &str) {
let mut file = File::create(filename).expect("Could not create file");
Comment on lines +75 to +76
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save_to_file panics on file creation/write errors via expect. For a CLI, it’s better to return a Result (or bubble up an io::Result) so the caller can report the error without crashing.

Copilot uses AI. Check for mistakes.

for expense in self.values.values() {
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HashMap::values() iteration order is nondeterministic, so save_to_file can write expenses in a random order (the committed stephen_expences.txt already shows IDs out of order). Consider iterating in a stable order (e.g., collect/sort by id, or reuse view_all()).

Suggested change
for expense in self.values.values() {
for expense in self.view_all().iter() {

Copilot uses AI. Check for mistakes.
let line = format!("ID: {}, Name: {}, Amount: {:.2}, Type: {:?}\n",
expense.id, expense.name, expense.amount, expense.tx_type);
file.write_all(line.as_bytes()).expect("Could not write to file");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ID: 2, Name: Beans, Amount: 5000.00, Type: Credit
ID: 1, Name: Rice, Amount: 20000.00, Type: Credit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/target

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "stephenngozi-build-cli-project"
version = "0.1.0"
edition = "2024"

[dependencies]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
searching for to
In File poem.txt
Are you nobody, too?
How dreary to be somebody!
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
I'm nobody! Who are you?
Are you nobody, too?
Then there's a pair of us - don't tell!
They'd banish us, you know.

How dreary to be somebody!
How public, like a frog
To tell your name the livelong day
To an admiring bog!
Loading
Loading