use bevy::prelude::*;
use issun_core::mechanics::exchange::ExchangeInput;
use issun_core::mechanics::Mechanic;
use super::types::{
BevyExchangeEventEmitter, ExchangeConfigResource, ExchangeEventWrapper, MarketLiquidity,
TradeCompleted, TradeRequested, Trader,
};
pub fn trade_system<M>(
config: Res<ExchangeConfigResource>,
mut traders: Query<(&mut Trader, Option<&MarketLiquidity>)>,
mut trade_requests: MessageReader<TradeRequested>,
mut event_writer: MessageWriter<ExchangeEventWrapper>,
mut trade_completed_writer: MessageWriter<TradeCompleted>,
) where
M: Mechanic<
Config = issun_core::mechanics::exchange::ExchangeConfig,
State = issun_core::mechanics::exchange::ExchangeState,
Input = ExchangeInput,
Event = issun_core::mechanics::exchange::ExchangeEvent,
>,
{
for request in trade_requests.read() {
let Ok((mut trader, market_liquidity)) = traders.get_mut(request.trader) else {
warn!(
"Trade request for non-existent trader: {:?}",
request.trader
);
continue;
};
let input = ExchangeInput {
offered_value: request.offered_value,
requested_value: request.requested_value,
market_liquidity: market_liquidity.map(|ml| ml.value).unwrap_or(0.5),
urgency: request.urgency,
};
let mut emitter = BevyExchangeEventEmitter::new(request.trader, &mut event_writer);
M::step(&config.config, &mut trader.state, input, &mut emitter);
let success = trader.state.total_trades > 0;
trade_completed_writer.write(TradeCompleted {
trader: request.trader,
fair_value: request.offered_value.min(request.requested_value),
fee: 0.0, success,
});
}
}
pub fn log_exchange_events(mut events: MessageReader<ExchangeEventWrapper>) {
for wrapper in events.read() {
match &wrapper.event {
issun_core::mechanics::exchange::ExchangeEvent::TradeProposed {
offered,
requested,
} => {
debug!(
"Trade proposed by {:?}: offered={}, requested={}",
wrapper.entity, offered, requested
);
}
issun_core::mechanics::exchange::ExchangeEvent::TradeAccepted { fair_value, fee } => {
info!(
"Trade accepted for {:?}: fair_value={}, fee={}",
wrapper.entity, fair_value, fee
);
}
issun_core::mechanics::exchange::ExchangeEvent::TradeRejected { reason } => {
warn!(
"Trade rejected for {:?}: reason={:?}",
wrapper.entity, reason
);
}
issun_core::mechanics::exchange::ExchangeEvent::ReputationChanged {
delta,
new_value,
} => {
debug!(
"Reputation changed for {:?}: delta={}, new={}",
wrapper.entity, delta, new_value
);
}
}
}
}