This commit is contained in:
2024-08-07 18:20:42 -04:00
parent 402addb3d4
commit ab89734237

View File

@@ -46,12 +46,9 @@ use std::io::{self, BufRead, Write};
use std::env;
//use std::collections::HashMap;
use std::cmp::Ordering;
use std::rc::Rc;
use std::cell::RefCell;
use rand::prelude::*;
use rand::rngs::StdRng;
use hashbrown::HashMap;
use std::collections::HashSet;
mod finum;
use finum::FiNum;
@@ -61,7 +58,7 @@ struct Trader {
password: String, // hash(name..salt..password)
id: usize,
balances: HashMap<usize,FiNum>, // Maps Currency to Amount
orders: HashSet<usize>,
order_finder: HashMap<usize,(usize,usize)>,
}
#[derive(Clone)]
@@ -92,7 +89,7 @@ impl Trader {
password: String::from(""),
id: id,
balances: HashMap::new(),
orders: HashSet::new(),
order_finder: HashMap::new(),
}
}
fn add_balance(&mut self, cur:usize, delta:FiNum) {
@@ -114,30 +111,32 @@ struct Order {
royalty_remain: FiNum, // Based on royalty1
commission_remain: FiNum, // Based on commission1
owner: usize,
id: usize,
order_id: usize,
}
struct RoyaltyTree {
tree: Vec<Royalty>,
next_entry: usize,
spare_change: FiNum, // Waiting to be distributed
order_finder: HashMap<usize,usize>,
}
struct Royalty {
weight: FiNum, // Here and below
lazy: FiNum, // To be distributed to here and to below based on weights
acc: FiNum, // Accumulated here
order_id: usize,
}
impl Royalty {
fn new() -> Self {
Royalty { weight:FiNum::zero(), lazy:FiNum::zero(), acc:FiNum::zero() }
Royalty { weight:FiNum::zero(), lazy:FiNum::zero(), acc:FiNum::zero(), order_id:0, }
}
}
impl RoyaltyTree {
fn new() -> Self {
RoyaltyTree { tree:Vec::new(), next_entry:0, spare_change:FiNum::zero() }
RoyaltyTree { tree:Vec::new(), next_entry:0, spare_change:FiNum::zero(), order_finder:HashMap::new() }
}
fn acc_total(&self) -> FiNum {
let mut rval=FiNum::zero();
@@ -206,6 +205,12 @@ impl RoyaltyTree {
if self.weight_here_below(ff).is_zero() { self.spare_change+=amount } else { self.tree[ff].lazy+=amount };
}
}
fn remove_order_id(&mut self, id: usize) {
self.order_finder.remove(&id);
}
fn set_location(&mut self, id: usize, index: usize) {
self.order_finder.insert(id,index);
}
fn add_weight(&mut self, index: usize, weight: FiNum) {
if self.tree.len()>0 {
let mut ff0=self.forefather();
@@ -250,24 +255,12 @@ impl Dumpable for usize {
}
impl Dumpable for Rc<RefCell<Order>> {
fn dump(&self) {
}
}
impl Dumpable for Order {
fn dump(&self) {
println!("Giving {}/{} to get {}",self.sell_remain,self.sell_qty,self.buy_qty);
}
}
struct OrderFinder {
asset0: usize,
asset1: usize,
pq_loc: usize,
rt_loc: usize,
}
struct Market {
asset_name2num: HashMap<String,usize>,
@@ -278,7 +271,7 @@ 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,usize)>, // To find an order, look in Orders.get(usize,usize) at position usize
order_finder: HashMap<usize,(usize,usize)>, // To find an order, look in Orders.get(usize,usize) at position usize
next_order_id: usize,
}
@@ -369,8 +362,8 @@ impl Market {
off.sell_remain, // off.buy_qty*off.sell_remain/off.sell_qty,
(off.buy_qty/off.sell_qty).fmt_recip(),
self.traders[off.owner as usize].name,
off.id,
self.royalties.get_mut(&ap.1).unwrap().get_royalty(off.rt_loc));
off.order_id,
"GetRoyalties Code absent");
}
}
println!("Royalties accumulated but not captured:");
@@ -475,43 +468,53 @@ impl Market {
top_order.royalty_remain-=rq2;
top_order.commission_remain-=cq2;
self.traders[0].add_balance(buy_type,cq2);
self.royalties.entry(buy_type).or_insert(RoyaltyTree::new()).add_royalty(rq2);
if elt.sell_remain==0.into() { // deal with pennies stored in royalty_remain and commission_remain
self.traders[0].add_balance(buy_type,top_order.commission_remain);
self.royalties.entry(buy_type).or_insert(RoyaltyTree::new()).add_royalty(top_order.royalty_remain);
self.orders.get_mut(&ap).unwrap().pop();
self.royalties.get_mut(&sell_type).unwrap().remove_order_id(top_order.order_id);
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
} else {
top_order.sell_remain-=qty;
}
} else { break; }
}
let mut id=0;
if buy_qty>0.into() {
let ap=(sell_type,buy_type);
if let None=self.orders.get_mut(&ap) { self.orders.insert(ap,OrderQueue::new()); }
let bids=self.orders.get_mut(&ap).unwrap();
let sell_qty_remain=sell_qty*buy_qty/buy_qty_initial;
if sell_qty_remain>0.into() {
self.royalties.entry(sell_type).or_insert(RoyaltyTree::new()).add_royalty(royalty0_qty);
let rt=self.royalties.entry(buy_type).or_insert(RoyaltyTree::new());
let rt_loc=rt.next_entry;
rt.add_weight(rt_loc,buy_qty); // Weight should really be the quantity you would be able to immediately transact rather than how much you wish for.
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, id:self.next_order_id };
new_order_id=self.next_order_id;
if sell_qty_remain>0.into() { // This block can not fail
// Allocate the id for this new order
id=self.next_order_id;
self.next_order_id+=1;
// Pay royalties to existing orders on the sell size
self.royalties.entry(sell_type).or_insert(RoyaltyTree::new()).add_royalty(royalty0_qty);
// Create a new entry in the RoyaltyTree to accumulate for this Order
let rt=self.royalties.entry(buy_type).or_insert(RoyaltyTree::new());
rt.add_weight(rt.next_entry,buy_qty); // Weight should really be the quantity you would be able to immediately transact rather than how much you wish for.
rt.set_location(id,rt.next_entry);
rt.next_entry+=1;
let pq_loc=bids.insert(neworder);
// 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_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);
self.traders[owner].orders.insert(new_order_id);
self.order_finder.insert(new_order_id,OrderFinder { asset0:sell_type, asset1:buy_type, pq_loc: pq_loc, rt_loc: rt_loc });
self.traders[owner].order_finder.insert(id,(sell_type,buy_type));
log.push(format!("Moved {} {} ({}) to market",sell_qty_remain,self.number_to_name(sell_type),self.traders[owner].name));
} else { new_order_id=0; }
} else { new_order_id=0; }
}
}
self.traders[0].add_balance(sell_type,commission_acc);
self.traders[owner].sub_balance(sell_type,royalty_acc+commission_acc);
log.push(format!("Paid {} {} in royalties and {} {} ({}) in commissions",royalty_acc ,self.number_to_name(sell_type),
commission_acc,self.number_to_name(sell_type),self.traders[owner].name));
Result::PlacedOrder(new_order_id,log)
Result::PlacedOrder(id,log)
}
}
@@ -536,12 +539,14 @@ impl PartialEq for Order {
struct OrderQueue {
v: Vec<Order>,
order_finder: HashMap<usize,usize>, // Maps IDs to locations in v
}
impl OrderQueue {
fn new()->Self {
OrderQueue {
v: Vec::new()
v: Vec::new(),
order_finder:HashMap::new(),
}
}
fn peek(&mut self) -> &mut Order {
@@ -550,18 +555,19 @@ impl OrderQueue {
fn empty(&self) -> bool {
self.v.len()==0
}
fn bubble_up(&mut self, pos: usize) -> usize {
fn bubble_up(&mut self, pos: usize) {
if pos>0 {
let parent=(pos-1)/2;
if self.v[parent]<self.v[pos] {
self.v[parent].pq_loc=pos;
self.v[pos].pq_loc=parent;
self.v.swap(parent,pos);
self.bubble_up(parent)
self.swap(parent,pos);
self.bubble_up(parent);
}
else { pos }
}
else { pos }
}
fn swap(&mut self, pos0: usize, pos1: usize) {
self.order_finder.insert(self.v[pos0].order_id,pos1);
self.order_finder.insert(self.v[pos1].order_id,pos0);
self.v.swap(pos0,pos1);
}
fn trickle_down(&mut self, pos: usize) {
let mut pivot=pos;
@@ -573,23 +579,23 @@ impl OrderQueue {
if self.v[pivot]<self.v[child1] { pivot=child1; }
}
if pivot!=pos {
self.v[pivot].pq_loc=pos;
self.v[pos].pq_loc=pivot;
self.v.swap(pivot,pos);
self.swap(pivot,pos);
self.trickle_down(pivot);
}
}
}
fn insert(&mut self, mut item: Order) -> usize {
item.pq_loc=self.v.len();
fn insert(&mut self, item: Order) {
let id=item.order_id;
self.v.push(item);
self.bubble_up(self.v.len()-1)
self.order_finder.insert(id,self.v.len()-1);
self.bubble_up(self.v.len()-1);
}
fn pop(&mut self) -> Option<Order> {
if self.v.len()==0 { None }
else {
let end=self.v.len()-1;
self.v.swap(0,end);
self.order_finder.remove(&self.v[end].order_id);
let rval=self.v.pop();
self.trickle_down(0);
rval