|
| 1 | +use comfy_table::Table; |
| 2 | + |
| 3 | +struct Asset { |
| 4 | + ticker: String, |
| 5 | + buy_price_cents: u32, |
| 6 | + current_price_cents: u32, |
| 7 | + // if sell price is None, it isn't sold |
| 8 | + sell_price_cents: Option<u32>, |
| 9 | +} |
| 10 | + |
| 11 | +fn is_asset_sold(asset: &Asset) -> bool { |
| 12 | + match asset.sell_price_cents { |
| 13 | + Some(_x) => true, |
| 14 | + None => false, |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +fn is_asset_held(asset: &Asset) -> bool { |
| 19 | + !is_asset_sold(asset) |
| 20 | +} |
| 21 | + |
| 22 | +fn percent_increase(old: u32, new: u32) -> f32 { |
| 23 | + // ensure floating point math |
| 24 | + (new as f32 - old as f32) / old as f32 * 100_f32 |
| 25 | +} |
| 26 | + |
| 27 | +fn format_money(cents: u32) -> String { |
| 28 | + format!("${:.2}", cents as f32 / 100.0) |
| 29 | +} |
| 30 | + |
| 31 | +fn print_assets(assets: &[Asset]) { |
| 32 | + let mut table = Table::new(); |
| 33 | + table.set_header(vec![ |
| 34 | + "Ticker", |
| 35 | + "Buy Price", |
| 36 | + "Current Price", |
| 37 | + "Percent Change", |
| 38 | + "Sell Price", |
| 39 | + ]); |
| 40 | + |
| 41 | + for asset in assets { |
| 42 | + table.add_row(vec![ |
| 43 | + // ticker |
| 44 | + asset.ticker.clone(), |
| 45 | + // buy price (formatted as money) |
| 46 | + format_money(asset.buy_price_cents), |
| 47 | + // current price (formatted as money) if held, else the current price is irrelevant |
| 48 | + if is_asset_held(asset) { |
| 49 | + format_money(asset.current_price_cents) |
| 50 | + } else { |
| 51 | + "N/A (sold)".to_string() |
| 52 | + }, |
| 53 | + // percent change - calculate on current price if held, calculate on sell price if sold |
| 54 | + format!( |
| 55 | + "{:.2}%", |
| 56 | + percent_increase( |
| 57 | + asset.buy_price_cents, |
| 58 | + if is_asset_held(asset) { |
| 59 | + asset.current_price_cents |
| 60 | + } else { |
| 61 | + asset.sell_price_cents.unwrap() |
| 62 | + } |
| 63 | + ) |
| 64 | + ), |
| 65 | + // sell price - show N/A if not sold |
| 66 | + if is_asset_sold(asset) { |
| 67 | + format_money(asset.sell_price_cents.unwrap()) |
| 68 | + } else { |
| 69 | + "N/A (currently held)".to_string() |
| 70 | + }, |
| 71 | + ]); |
| 72 | + } |
| 73 | + |
| 74 | + println!("Assets"); |
| 75 | + println!("{table}"); |
| 76 | +} |
| 77 | + |
| 78 | +fn main() { |
| 79 | + let assets: [Asset; 2] = [ |
| 80 | + Asset { |
| 81 | + ticker: "MSFT".to_string(), |
| 82 | + buy_price_cents: 1000, |
| 83 | + current_price_cents: (25000), |
| 84 | + sell_price_cents: None, |
| 85 | + }, |
| 86 | + Asset { |
| 87 | + ticker: "APPL".to_string(), |
| 88 | + buy_price_cents: 30000, |
| 89 | + current_price_cents: (10000000), |
| 90 | + sell_price_cents: Some(40000), |
| 91 | + }, |
| 92 | + ]; |
| 93 | + |
| 94 | + print_assets(&assets); |
| 95 | + println!(); |
| 96 | +} |
0 commit comments