-
Notifications
You must be signed in to change notification settings - Fork 15
Week 2 day 5 #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Week 2 day 5 #5
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 = "Stephen-Ngozi-Merkle-Tree" | ||
| version = "0.1.0" | ||
| edition = "2024" | ||
|
Comment on lines
+1
to
+4
|
||
|
|
||
| [dependencies] | ||
| 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, | ||
| } |
| 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
|
||||||||||||||||||||||||||||||||||||||||||||||
| 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
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any transaction type input other than "c" is treated as Debit, so typos like "C"/"credit"/"x" will silently become Debit. Validate the input (case-insensitive "c" or "d") and re-prompt or show an error instead of defaulting.
| 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 tx_type = loop { | |
| 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().to_lowercase(); | |
| match tx_input.as_str() { | |
| "c" => break TransactionType::Credit, | |
| "d" => break TransactionType::Debit, | |
| _ => { | |
| println!("Invalid input. Please enter 'c' for Credit or 'd' for Debit."); | |
| } | |
| } |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currency formatting is inconsistent: the add flow prints "$" while the view/update flows print "Naria...". Pick a single currency label/symbol and use it consistently across all outputs.
| println!("ID: {}, Name: {}, Amount: ${:.2}, Type: {:?}", | |
| println!("ID: {}, Name: {}, Amount: Naria{:.2}, Type: {:?}", |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Naria" appears to be a misspelling of the currency name "Naira". Fixing the string will make output clearer.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prompt text uses "Expence" instead of "Expense".
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the update flow, any transaction type input other than "c" becomes Debit, which can record the wrong transaction type. Add validation/re-prompt for "c" or "d" (case-insensitive).
| 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 tx_type = loop { | |
| let mut tx_input = String::new(); | |
| io::stdin().read_line(&mut tx_input).expect("Failed to read input"); | |
| let tx_input = tx_input.trim().to_lowercase(); | |
| match tx_input.as_str() { | |
| "c" => break TransactionType::Credit, | |
| "d" => break TransactionType::Debit, | |
| _ => { | |
| println!("Invalid transaction type. Please enter 'c' for Credit or 'd' for Debit:"); | |
| } | |
| } |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Status message "Expense Updated Successfu" is truncated/misspelled; correct it to a complete word to avoid confusing output.
| println!("Expense Updated Successfu"); | |
| println!("Expense Updated Successfully"); |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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 program prints nothing and returns to the menu. Add an else branch to inform the user that the ID was not found.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Naria" appears to be a misspelling of "Naira" here as well.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The prompt text is grammatically incorrect: "Enter the ID of the expense you to delete:". Update it to something like "Enter the ID of the expense you want to delete:" for clarity.
| println!("Enter the ID of the expense you to delete:"); | |
| println!("Enter the ID of the expense you want to delete:"); |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Delete confirmation message uses "Expence" instead of "Expense".
| println!(" Your Expence is Deleted "); | |
| println!(" Your Expense is Deleted "); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,84 @@ | ||||||||||||||||||||||||||||||||||||
| use std::{collections::HashMap,fs::File,io::Write}; | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
| use std::{collections::HashMap,fs::File,io::Write}; | |
| use std::{collections::HashMap, fs::File, io::Write}; |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using u8 for IDs means next_id will overflow after 255 expenses (panic in debug builds, wrap in release), which can lead to duplicate IDs and lost data. Use a larger type (e.g., u32/u64/usize) and/or handle overflow explicitly.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
values and next_id are public, which exposes internal state (and allows callers to mutate/replace entries without invariants). Prefer keeping fields private and providing methods like get(id)/iter() for read access.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a block of commented-out, unfinished code inside update. Removing dead/commented code will make the method easier to read and maintain.
| // let updated_expense = Expense { | |
| // id, | |
| // amount, | |
| // tx_type, | |
| // }; | |
| // self.values.put(id) |
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
save_to_file writes expenses in HashMap iteration order, which is non-deterministic; this can produce shuffled output across runs. Consider iterating over view_all() (sorted) before writing to make saved files stable/readable.
Copilot
AI
Feb 9, 2026
There was a problem hiding this comment.
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 I/O errors via expect(...). Since this is a public method, returning std::io::Result<()> would let the caller decide how to handle failures (retry, show message, etc.).
| pub fn save_to_file(&self, filename: &str) { | |
| let mut file = File::create(filename).expect("Could not create file"); | |
| for expense in self.values.values() { | |
| 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"); | |
| } | |
| pub fn save_to_file(&self, filename: &str) -> std::io::Result<()> { | |
| let mut file = File::create(filename)?; | |
| for expense in self.values.values() { | |
| let line = format!("ID: {}, Name: {}, Amount: {:.2}, Type: {:?}\n", | |
| expense.id, expense.name, expense.amount, expense.tx_type); | |
| file.write_all(line.as_bytes())?; | |
| } | |
| Ok(()) |
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cargo package names are typically lowercase and snake_case; using uppercase letters can trigger warnings and won’t be accepted on crates.io. Consider changing
nameto a lowercase identifier (hyphens are ok, but lowercase is preferred).