This commit is contained in:
2024-10-13 16:55:06 -04:00
parent 915f5673bc
commit 5db870244f

View File

@@ -60,7 +60,7 @@ struct Trader {
password: String, // hash(name..salt..password)
id: usize,
balances: HashMap<usize,FiNum>, // Maps Currency to Amount
order_finder: HashMap<usize,(usize,usize)>,
order_finder: HashMap<usize,(usize,usize)>, // Maps OrderIDs to asset pairs (Order trees)
}
#[derive(Clone)]
@@ -120,7 +120,7 @@ struct RoyaltyTree {
tree: Vec<Royalty>,
next_entry: usize,
spare_change: FiNum, // Waiting to be distributed
order_finder: HashMap<usize,usize>,
order_finder: HashMap<usize,usize>, // Maps OrderID to location (index) in the tree
}
struct Royalty {
@@ -356,7 +356,8 @@ struct Market {
orders: HashMap<(usize,usize),OrderQueue>,
royalties: HashMap<usize,RoyaltyTree>, // Active orders that are accepting asset X. They receive royalties when someone makes an order to sell X
royalty_rate: HashMap<usize,FiNum>,
order_finder: HashMap<usize,(usize,usize)>, // To find an order, look in Orders.get(usize,usize) at position usize
order_finder: HashMap<usize,(usize,usize)>, // 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<usize> {
let x=self.rng.gen_range(0..self.order_count);
let mut bottom=0;
for (pair,bucket) in &self.orders {
if x<bottom+bucket.v.len() { return Some(bucket.v[x-bottom].order_id) }
bottom+=bucket.v.len();
}
None
}
fn register_trader(&mut self, name:&str) -> 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<String>=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>,
order_finder: HashMap<usize,usize>, // Maps IDs to locations in v
order_finder: HashMap<usize,usize>, // 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<Order> {
if self.v.len()==0 { None }
self.remove(0)
}
fn remove(&mut self, pos: usize) -> Option<Order> {
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<File>) {
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