Merge pull request 'feat(sidecar): protocol 14 — the Economics forwards (PLAN_REDESIGNS §11.2)' (#25) from feat/protocol-14-economics into edge
Reviewed-on: #25
This commit is contained in:
@@ -183,6 +183,11 @@ use tracing_subscriber::EnvFilter;
|
||||
/// earned a kit" messages (D333), with `noticesTold` in its report; both pass through untouched
|
||||
/// like the rest of that body. The first-class optional plugins (§11) join this protocol too.
|
||||
///
|
||||
/// Economics (§20.3, the module's PLAN_REDESIGNS.md §11.2) adds three forwards:
|
||||
/// `POST /economics/pay` (coins from an event step, kept once paid), `POST /economics/balances`
|
||||
/// and `POST /economics/adjust` (staff). The plugin remembers a payment's key; this process keeps
|
||||
/// nothing. The tally's `balance` and the `economics.wiped` event ride the feed like any frame.
|
||||
///
|
||||
/// `docs/rust-link/PROTOCOL.md` is the specification — §8 the read path, §9 identity, §10 the
|
||||
/// mirror, §11 configuration, §12 clans, §13 the raid frame, §14 the leases, §15 the world verbs,
|
||||
/// §16 the rewards, §17 the map, §18 the optional mods, §19 the walk's fixes, §20 the step editor;
|
||||
|
||||
@@ -134,6 +134,11 @@ pub async fn serve(addr: &str, state: AppState) -> anyhow::Result<()> {
|
||||
// used a kit up or are on its cooldown, for the warning beside a kit weekend. The plugin
|
||||
// reads Kits and answers counts; the list of players is the website's and is not kept.
|
||||
.route("/kits/uses", post(kits_uses))
|
||||
// Protocol 14, Economics (§20.3): thin forwards. The plugin remembers a payment's key so a
|
||||
// retry never pays twice; nothing about a payment or a balance is kept here.
|
||||
.route("/economics/pay", post(economics_pay))
|
||||
.route("/economics/balances", post(economics_balances))
|
||||
.route("/economics/adjust", post(economics_adjust))
|
||||
.route("/chat", post(chat))
|
||||
// Protocol 11 (§30): the map. The picture passes through in slices and is never kept
|
||||
// here, and positions are asked for while somebody is looking and never filed (D111). The
|
||||
@@ -590,6 +595,24 @@ async fn kits_uses(State(st): State<AppState>, Json(body): Json<Value>) -> Respo
|
||||
forward_object(&st, body, "kits.uses", "a kit-use question").await
|
||||
}
|
||||
|
||||
/// Coins to a list of players from an event step (protocol 14). The body is `{key, amount,
|
||||
/// steamIds, message?, delivery?}`; the answer is `economics.paid` with each player's balance
|
||||
/// before and after, or `economics.error` with a reason.
|
||||
async fn economics_pay(State(st): State<AppState>, Json(body): Json<Value>) -> Response {
|
||||
forward_object(&st, body, "economics.pay", "a payment").await
|
||||
}
|
||||
|
||||
/// The balances of a list of players, with the server's starting balance (protocol 14).
|
||||
async fn economics_balances(State(st): State<AppState>, Json(body): Json<Value>) -> Response {
|
||||
forward_object(&st, body, "economics.balances", "a balance question").await
|
||||
}
|
||||
|
||||
/// Staff deposit, withdraw or set one player's balance (protocol 14). The body is `{key, steamId,
|
||||
/// op, amount}`; the answer is `economics.adjusted` with the balance before and after.
|
||||
async fn economics_adjust(State(st): State<AppState>, Json(body): Json<Value>) -> Response {
|
||||
forward_object(&st, body, "economics.adjust", "a balance adjustment").await
|
||||
}
|
||||
|
||||
/// Say one line in the server's chat. A repeated key is answered `ok` by the plugin and not said
|
||||
/// again, so a retried step never repeats itself.
|
||||
async fn chat(State(st): State<AppState>, Json(body): Json<Value>) -> Response {
|
||||
@@ -1195,6 +1218,36 @@ mod tests {
|
||||
assert_eq!(stamped["notices"][0]["delivery"], "popup");
|
||||
}
|
||||
|
||||
/// Protocol 14, Economics: each body keeps its fields and is stamped with its own command, so
|
||||
/// a payment cannot be sent as an adjustment by naming one in its body.
|
||||
#[test]
|
||||
fn protocol_14_economics_bodies_pass_through() {
|
||||
let body = json!({ "cmd": "economics.adjust", "key": "7:4", "amount": 500.0, "steamIds": ["76561190000000001"], "message": "You earned {amount} coins", "delivery": "popup" });
|
||||
let stamped = stamp(body, "economics.pay", "r-31").expect("an object is stamped");
|
||||
|
||||
assert_eq!(stamped["cmd"], "economics.pay");
|
||||
assert_eq!(stamped["reqId"], "r-31");
|
||||
assert_eq!(stamped["key"], "7:4");
|
||||
assert_eq!(stamped["amount"], 500.0);
|
||||
assert_eq!(stamped["message"], "You earned {amount} coins");
|
||||
|
||||
let stamped = stamp(
|
||||
json!({ "steamIds": ["76561190000000001"] }),
|
||||
"economics.balances",
|
||||
"r-32",
|
||||
)
|
||||
.expect("an object is stamped");
|
||||
assert_eq!(stamped["cmd"], "economics.balances");
|
||||
assert_eq!(stamped["steamIds"][0], "76561190000000001");
|
||||
|
||||
let body = json!({ "key": "adj-1", "steamId": "76561190000000001", "op": "withdraw", "amount": 340.5 });
|
||||
let stamped = stamp(body, "economics.adjust", "r-33").expect("an object is stamped");
|
||||
assert_eq!(stamped["cmd"], "economics.adjust");
|
||||
assert_eq!(stamped["op"], "withdraw");
|
||||
assert_eq!(stamped["amount"], 340.5);
|
||||
assert!(stamp(json!([1]), "economics.pay", "r-34").is_none());
|
||||
}
|
||||
|
||||
/// Protocol 12: a title set is forwarded whole. The markup inside each `text` is the module's
|
||||
/// and the plugin's business, so it must arrive byte for byte as the website composed it.
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user