diff --git a/src/main.rs b/src/main.rs index f79b7e4..497b3d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -60,7 +60,7 @@ struct Trader { password: String, // hash(name..salt..password) id: usize, balances: HashMap, // Maps Currency to Amount - order_finder: HashMap, + order_finder: HashMap, // Maps OrderIDs to asset pairs (Order trees) } #[derive(Clone)] @@ -120,7 +120,7 @@ struct RoyaltyTree { tree: Vec, next_entry: usize, spare_change: FiNum, // Waiting to be distributed - order_finder: HashMap, + order_finder: HashMap, // Maps OrderID to location (index) in the tree } struct Royalty { @@ -356,7 +356,8 @@ struct Market { orders: HashMap<(usize,usize),OrderQueue>, royalties: HashMap, // Active orders that are accepting asset X. They receive royalties when someone makes an order to sell X royalty_rate: HashMap, - order_finder: HashMap, // To find an order, look in Orders.get(usize,usize) at position usize + order_finder: HashMap, // Maps Order ID to an asset pair (in other systems, a "market.") From there you can look in self.orders.get((usize,usize)) which is an OrderQueue, and OrderQueues have a mapping from ID to position in the OrderQueue + order_count: usize, next_order_id: usize, rng: StdRng, } @@ -372,7 +373,8 @@ impl Market { orders: HashMap::new(), royalties: HashMap::new(), royalty_rate: HashMap::new(), - order_finder: HashMap::new(), + order_finder: HashMap::new(), + order_count: 0, next_order_id: 1, rng: StdRng::seed_from_u64(1u64), }; @@ -393,6 +395,15 @@ impl Market { println!(" {}: Orders {} Traders {} Total {} Should Be {}",self.number_to_name(*cur),acc_orders,acc_traders,acc,*amt); } } + fn random_order_id(&mut self) -> Option { + let x=self.rng.gen_range(0..self.order_count); + let mut bottom=0; + for (pair,bucket) in &self.orders { + if x usize { // Add error checking for inserting a trader twice let rval=self.traders.len(); self.trader_name2num.insert(String::from(name),self.traders.len()); @@ -503,11 +514,27 @@ impl Market { self.traders[bids1.peek().owner].add_balance(asset_type0,asset0_paying); log.push(format!(" {} got {} {}, {} got {} {}",self.traders[bids0.peek().owner].name,asset1_paying,asset1.name, self.traders[bids1.peek().owner].name,asset0_paying,asset0.name)); - if bids0.peek().sell_remain==FiNum::zero() { println!("Nope0!!!"); bids0.pop(); } // Stopped work here. Must fixup all the data structures for these pops. - if bids1.peek().sell_remain==FiNum::zero() { println!("Nope1!!!"); bids1.pop(); } + if bids0.peek().sell_remain==FiNum::zero() { println!("Nope0!!!"); bids0.pop(); self.order_count-=1; } // Stopped work here. Must fixup all the data structures for these pops. + if bids1.peek().sell_remain==FiNum::zero() { println!("Nope1!!!"); bids1.pop(); self.order_count-=1; } } Result::ExecutedBatch(log) } + fn retract_order(&mut self, order_id:usize) -> Result { + let pair=self.order_finder.get(&order_id).unwrap(); + let queue=self.orders.get_mut(pair).unwrap(); + let queue_index=*queue.order_finder.get(&order_id).unwrap(); + let order=&queue.v[queue_index]; + println!("Order owner is {}",order.owner); + // Remove from royalties + let rt=self.royalties.get_mut(&pair.0).unwrap(); + rt.remove_order_id(order_id); + // Remove from order_finder + self.order_finder.remove(&order_id); + // Remove from orders + queue.remove(queue_index); + self.order_count-=1; + Result::RetractedOrder(order_id) + } fn make_order(&mut self, owner:usize, sell_type:usize, buy_type:usize, sell_qty_initial:FiNum, buy_qty_initial:FiNum, execute_if_possible:bool) -> Result { let mut log:Vec=Vec::new(); let initial_balance=self.traders[owner].get_balance(sell_type); @@ -562,6 +589,7 @@ impl Market { self.order_finder.remove(&top_order.order_id); self.traders[top_order.owner].order_finder.remove(&top_order.order_id); self.orders.get_mut(&ap).unwrap().pop(); // This removes id (which is stored as part of the Order) from self.order's finder + self.order_count-=1; } else { top_order.sell_remain-=qty; } @@ -590,6 +618,7 @@ impl Market { // Insert the new order in the priority queue (OrderQueue) let neworder=Order { owner:owner, sell_qty:sell_qty_remain, sell_remain:sell_qty_remain, buy_qty:buy_qty, royalty_remain:royalty1_qty, commission_remain:commission1_qty, order_id:id }; bids.insert(neworder); + self.order_count+=1; self.order_finder.insert(id,(sell_type,buy_type)); self.traders[owner].sub_balance(sell_type,sell_qty_remain); self.traders[0].add_balance(sell_type,commission0_qty); @@ -626,7 +655,7 @@ impl PartialEq for Order { struct OrderQueue { v: Vec, - order_finder: HashMap, // Maps IDs to locations in v + order_finder: HashMap, // Maps OrderIDs to locations in v } impl OrderQueue { @@ -678,13 +707,16 @@ impl OrderQueue { self.bubble_up(self.v.len()-1); } fn pop(&mut self) -> Option { - if self.v.len()==0 { None } + self.remove(0) + } + fn remove(&mut self, pos: usize) -> Option { + if self.v.len()<=pos { None } else { let end=self.v.len()-1; - self.v.swap(0,end); + self.v.swap(pos,end); self.order_finder.remove(&self.v[end].order_id); let rval=self.v.pop(); - self.trickle_down(0); + self.trickle_down(pos); rval } } @@ -704,11 +736,15 @@ impl Market { 1 => Command::AddFunds { user_id: self.rng.gen_range(1..self.traders.len()), asset_id: self.rng.gen_range(0..self.assets.len()), amt: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), }, - 2 => Command::Order { user_id: self.rng.gen_range(1..self.traders.len()), + 2 => Command::AddFunds { user_id: self.rng.gen_range(1..self.traders.len()), + asset_id: self.rng.gen_range(0..self.assets.len()), + amt: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), }, + 3 => Command::Order { user_id: self.rng.gen_range(1..self.traders.len()), sell_type: self.rng.gen_range(0..self.assets.len()), sell_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), buy_type: self.rng.gen_range(0..self.assets.len()), buy_qty: FiNum::new(self.rng.gen_range(1<<32..20<<32+1)), }, +// 4 => Command::RetractOrder { {*} _ => Command::Error("This can never happen".to_string()), } } @@ -964,7 +1000,7 @@ impl Market { self.make_order(*user_id,*sell_type,*buy_type,*sell_qty,*buy_qty,false) } Command::RetractOrder { order_id } => { - Result::Error(format!("Retract Order {} not yet implemented.",order_id)) + self.retract_order(*order_id) } Command::ExecuteBatch { asset_type0, strike0, asset_type1, strike1 } => { self.execute_batch(*asset_type0, *strike0, *asset_type1, *strike1) @@ -1037,6 +1073,7 @@ fn tokens_to_command(m: &Market, logged_in: usize, tokens: Vec<&str>,line: &str) if !m.order_finder.contains_key(&order_id) { return Command::Error(format!("Order not found: {}",p_order_id)) } let trader=&m.traders[logged_in]; let order_type=trader.order_finder.get(&order_id); + println!("Order_type {:?}",order_type); let order_queue=m.orders.get(order_type.expect("Retrieving Order Queue")); Command::RetractOrder { order_id: order_id } } @@ -1089,6 +1126,7 @@ fn interactive(m: &mut Market, mut out: Option) { let tokens: Vec<&str> = input.split_whitespace().collect(); let cmd:Command=match tokens.as_slice() { ["dump"] => { m.dump(); Command::None }, + ["randomorder"] => { println!("Random OrderID: {:?}",m.random_order_id()); Command::None } ["login", username] => { if let Some(t)=m.trader_name2num.get_mut(*username) { trader=*t; println!("Logged in as {}",m.traders[trader].name) } else { println!("Trader {} not found.",username) } Command::None