an http based roguelike rpg about jelqing
Blame: src/game/roll.rs
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 1 | use super::{ |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 2 | Grip, Lube, Outcome, Run, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 3 | balance::{ |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 4 | ARRIVAL_BONUS, BAND_BONUS, CLEAN_HIT, DANGER_EQ, EQ_BAND, GREED_HOT, GREED_WARM, HOT_EQ, |
e028a4184d00 | atagen | 2026-10-14 10:49 UTC | 5 | NEAR_MISS, QUEUED_ETA, UNDERHAND_STRETCH, UNDERHAND_WET, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 6 | }, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 7 | body::Pending, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 8 | measure::round3, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 9 | techniques::{Profile, Training}, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 10 | }; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 11 | use crate::{headers::SERVER_TIMING, problem::Problem}; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 12 | use axum::http::{StatusCode, header}; |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 13 | use serde_json::{Value, json}; |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 14 | |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 15 | fn gains(detail: &str, length: f64, girth: f64, foreskin: Option<f64>) -> Value { |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 16 | let mut body = json!({ "detail": detail, "length": round3(length), "girth": round3(girth) }); |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 17 | if let Some(foreskin) = foreskin { |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 18 | body["foreskin"] = json!(round3(foreskin)); |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 19 | } |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 20 | body |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 21 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 22 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 23 | impl Run { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 24 | pub(super) fn roll( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 25 | &mut self, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 26 | training: Training, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 27 | intensity: i32, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 28 | lube: Option<Lube>, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 29 | ) -> Result<Outcome, Problem> { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 30 | let profile = training.profile(); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 31 | let natural: i32 = self.oracle.span_int( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 32 | self.decision( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 33 | "natural", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 34 | "What does the twenty-sided die show for this technique?", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 35 | ), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 36 | 1, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 37 | 20, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 38 | ); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 39 | let modifier = self.modifier(training, lube); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 40 | let dc = profile.dc + intensity / 3; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 41 | let total = natural + modifier; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 42 | let timing = format!("roll;desc=\"d20{modifier:+} vs {dc}\";dur={natural}"); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 43 | let timed = |p: Problem| p.header(SERVER_TIMING, &timing); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 44 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 45 | let (length, girth) = self.scaled_gains(&profile, intensity); |
e028a4184d00 | atagen | 2026-10-14 10:49 UTC | 46 | let rupture_line = self.rupture_line(); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 47 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 48 | if natural == 1 { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 49 | return Err(timed(self.critical_failure(training, &profile))); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 50 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 51 | self.here.warm_arrival = false; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 52 | if natural == 2 && self.hotter_than(DANGER_EQ) { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 53 | return Err(timed(self.rupture())); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 54 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 55 | if self.hotter_than(rupture_line) && total < dc { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 56 | return Err(timed(self.rupture())); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 57 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 58 | if natural == 20 { |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 59 | let foreskin = self.gain(length * 2.0, girth * 2.0, profile.foreskin_growth); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 60 | return Ok(Outcome::json( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 61 | StatusCode::PERMANENT_REDIRECT, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 62 | gains( |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 63 | "Your length has moved permanently.", |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 64 | length * 2.0, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 65 | girth * 2.0, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 66 | foreskin, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 67 | ), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 68 | ) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 69 | .header(header::LOCATION, self.path("/length")) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 70 | .header(SERVER_TIMING, timing)); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 71 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 72 | if total < dc - NEAR_MISS { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 73 | return Err(timed(not_extended())); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 74 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 75 | if total < dc { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 76 | return Ok(Outcome::empty(StatusCode::NO_CONTENT).header(SERVER_TIMING, timing)); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 77 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 78 | Ok(self |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 79 | .land(&profile, length, girth, total >= dc + CLEAN_HIT) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 80 | .header(SERVER_TIMING, timing)) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 81 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 82 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 83 | fn modifier(&self, training: Training, lube: Option<Lube>) -> i32 { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 84 | let band = if EQ_BAND.contains(&self.body.eq) { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 85 | BAND_BONUS |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 86 | } else { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 87 | 0 |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 88 | }; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 89 | let grip = match (self.body.grip, training) { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 90 | (Grip::Underhand, Training::Stretch) => UNDERHAND_STRETCH, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 91 | (Grip::Underhand, Training::Wet) => UNDERHAND_WET, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 92 | _ => 0, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 93 | }; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 94 | let arrival = if self.here.warm_arrival { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 95 | ARRIVAL_BONUS |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 96 | } else { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 97 | 0 |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 98 | }; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 99 | lube.map_or(0, Lube::modifier) + band + grip + arrival |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 100 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 101 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 102 | fn land(&mut self, profile: &Profile, length: f64, girth: f64, clean: bool) -> Outcome { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 103 | if self.body.eq < *EQ_BAND.start() { |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 104 | let foreskin = self.gain(length / 2.0, girth / 2.0, profile.foreskin_growth); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 105 | Outcome::json( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 106 | StatusCode::PARTIAL_CONTENT, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 107 | gains( |
e028a4184d00 | atagen | 2026-10-14 10:49 UTC | 108 | "Partial gains were applied. EQ was short of Ideal.", |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 109 | length / 2.0, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 110 | girth / 2.0, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 111 | foreskin, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 112 | ), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 113 | ) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 114 | } else if clean { |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 115 | let foreskin = self.gain(length, girth, profile.foreskin_growth); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 116 | Outcome::json( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 117 | StatusCode::OK, |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 118 | gains("Gains were applied.", length, girth, foreskin), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 119 | ) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 120 | } else { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 121 | let eta = self.oracle.span_int( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 122 | self.decision("eta", "In how many turns will the queued gains arrive?"), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 123 | *QUEUED_ETA.start(), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 124 | *QUEUED_ETA.end(), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 125 | ); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 126 | self.body.pending.push(Pending { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 127 | due: self.turn + eta.unsigned_abs(), |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 128 | length, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 129 | girth, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 130 | foreskin: profile.foreskin_growth, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 131 | }); |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 132 | let mut body = json!({ |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 133 | "detail": "Gains have been queued. They may arrive.", |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 134 | "eta_turns": eta, |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 135 | }); |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 136 | let torn = std::mem::take(&mut self.body.torn); |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 137 | if torn > 0.0 { |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 138 | body["foreskin"] = json!(-round3(torn)); |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 139 | } |
6033b0db186c | atagen | 2026-10-13 12:44 UTC | 140 | Outcome::json(StatusCode::ACCEPTED, body) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 141 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 142 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 143 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 144 | pub(super) fn scaled_gains(&self, profile: &Profile, intensity: i32) -> (f64, f64) { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 145 | let scale = f64::from(intensity); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 146 | let (mut length, mut girth) = (profile.length * scale, profile.girth * scale); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 147 | let greed = if self.body.eq > HOT_EQ { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 148 | GREED_HOT |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 149 | } else if self.body.eq > DANGER_EQ { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 150 | GREED_WARM |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 151 | } else { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 152 | 1.0 |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 153 | }; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 154 | length *= greed; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 155 | girth *= greed; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 156 | if self.here.teapot { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 157 | length *= 0.5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 158 | girth *= 1.5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 159 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 160 | if self.items.kit.ring { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 161 | girth *= 2.0; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 162 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 163 | if self.body.conditions.friction_burn { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 164 | length *= 0.5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 165 | girth *= 0.5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 166 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 167 | (length, girth) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 168 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 169 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 170 | pub(super) fn critical_failure(&mut self, training: Training, profile: &Profile) -> Problem { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 171 | let uses_foreskin = profile.foreskin.is_some_and(|(min, _)| min > 0.0); |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 172 | if uses_foreskin && let Some(lost) = self.body.foreskin.take() { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 173 | self.standing.shame += 25; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 174 | return Problem::new( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 175 | StatusCode::GONE, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 176 | "foreskin-lost", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 177 | "The technique has removed the foreskin. It will not be returning.", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 178 | ) |
97c05b741d8f | atagen | 2026-10-13 11:27 UTC | 179 | .with("foreskin", -round3(lost)) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 180 | .header(header::CONTENT_LOCATION, self.path("/foreskin")); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 181 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 182 | if self.hotter_than(DANGER_EQ) { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 183 | return self.rupture(); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 184 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 185 | if training == Training::Stretch && !self.here.teapot { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 186 | self.here.teapot = true; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 187 | self.items.kit.teapot_spout = true; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 188 | self.standing.shame += 5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 189 | return Problem::new( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 190 | StatusCode::IM_A_TEAPOT, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 191 | "teapot", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 192 | "The subject is now short and stout. Length gains are halved for the rest of the floor.", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 193 | ); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 194 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 195 | if training == Training::Uli && !self.body.conditions.peyronie { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 196 | self.body.conditions.peyronie = true; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 197 | self.standing.shame += 5; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 198 | return Problem::new( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 199 | StatusCode::MISDIRECTED_REQUEST, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 200 | "curvature", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 201 | "A curvature has developed. Techniques will land slightly to the left until a professional is consulted.", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 202 | ); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 203 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 204 | not_extended() |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 205 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 206 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 207 | pub(super) fn gossip(&mut self, outcome: Outcome) -> Outcome { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 208 | let reportable = matches!(outcome.status().as_u16(), 200 | 202 | 206 | 308); |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 209 | if !self.here.brother_told || !reportable { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 210 | return outcome; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 211 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 212 | self.here.brother_told = false; |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 213 | outcome.retold( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 214 | StatusCode::ALREADY_REPORTED, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 215 | "Your brother has already told Mum.", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 216 | ) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 217 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 218 | } |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 219 | |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 220 | pub(super) fn not_extended() -> Problem { |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 221 | Problem::new( |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 222 | StatusCode::NOT_EXTENDED, |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 223 | "not-extended", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 224 | "The requested extension was not applied. The server has recorded the attempt.", |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 225 | ) |
8b8e83329a1d | atagen | 2026-10-12 12:01 UTC | 226 | } |