atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
e76ab808e7ad49d0b6fccd17728da137daacdb8c
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git

Blame: src/game/clinic.rs

782069860236atagen2026-10-10 12:44 UTC1
use axum::http::{StatusCode, header};
782069860236atagen2026-10-10 12:44 UTC2
use serde_json::json;
782069860236atagen2026-10-10 12:44 UTC3
782069860236atagen2026-10-10 12:44 UTC4
use super::{Floor, Outcome, Run, etag_matches, parse_credentials, round2};
782069860236atagen2026-10-10 12:44 UTC5
use crate::{headers::X_DIAGNOSIS, problem::Problem};
782069860236atagen2026-10-10 12:44 UTC6
782069860236atagen2026-10-10 12:44 UTC7
const INTAKE: [&str; 3] = [
782069860236atagen2026-10-10 12:44 UTC8
    "The clinic does not accept excuses.",
782069860236atagen2026-10-10 12:44 UTC9
    "The clinic accepts one token. You have not been carrying it.",
782069860236atagen2026-10-10 12:44 UTC10
    "Be honest.",
782069860236atagen2026-10-10 12:44 UTC11
];
782069860236atagen2026-10-10 12:44 UTC12
782069860236atagen2026-10-10 12:44 UTC13
impl Run {
782069860236atagen2026-10-10 12:44 UTC14
    pub fn diagnose(
782069860236atagen2026-10-10 12:44 UTC15
        &mut self,
782069860236atagen2026-10-10 12:44 UTC16
        authorization: Option<&str>,
782069860236atagen2026-10-10 12:44 UTC17
        if_none_match: Option<&str>,
782069860236atagen2026-10-10 12:44 UTC18
    ) -> Result<Outcome, Problem> {
782069860236atagen2026-10-10 12:44 UTC19
        if self.floor != Floor::Clinic {
782069860236atagen2026-10-10 12:44 UTC20
            let floors = Floor::Clinic.number() - self.floor.number();
782069860236atagen2026-10-10 12:44 UTC21
            return Err(Problem::new(
782069860236atagen2026-10-10 12:44 UTC22
                StatusCode::TOO_EARLY,
782069860236atagen2026-10-10 12:44 UTC23
                "no-appointment",
782069860236atagen2026-10-10 12:44 UTC24
                format!("The clinic's next available appointment is {floors} floors away."),
782069860236atagen2026-10-10 12:44 UTC25
            ));
782069860236atagen2026-10-10 12:44 UTC26
        }
782069860236atagen2026-10-10 12:44 UTC27
        let intake = Problem::new(
782069860236atagen2026-10-10 12:44 UTC28
            StatusCode::UNAUTHORIZED,
782069860236atagen2026-10-10 12:44 UTC29
            "intake",
9683736a2c5eatagen2026-10-10 13:15 UTC30
            "The clinic requires authorisation.",
782069860236atagen2026-10-10 12:44 UTC31
        );
782069860236atagen2026-10-10 12:44 UTC32
        let Some(authorization) = authorization else {
782069860236atagen2026-10-10 12:44 UTC33
            return Err(intake.header(header::WWW_AUTHENTICATE, "Bearer realm=\"clinic\""));
782069860236atagen2026-10-10 12:44 UTC34
        };
782069860236atagen2026-10-10 12:44 UTC35
        let truthful = parse_credentials(authorization, "bearer")
782069860236atagen2026-10-10 12:44 UTC36
            .is_some_and(|token| token.eq_ignore_ascii_case("honesty"));
782069860236atagen2026-10-10 12:44 UTC37
        if !truthful {
782069860236atagen2026-10-10 12:44 UTC38
            let hint = INTAKE[self.clinic.intake_attempts.min(INTAKE.len() - 1)];
782069860236atagen2026-10-10 12:44 UTC39
            self.clinic.intake_attempts += 1;
782069860236atagen2026-10-10 12:44 UTC40
            return Err(intake.header(
782069860236atagen2026-10-10 12:44 UTC41
                header::WWW_AUTHENTICATE,
782069860236atagen2026-10-10 12:44 UTC42
                format!(
782069860236atagen2026-10-10 12:44 UTC43
                    "Bearer realm=\"clinic\", error=\"invalid_token\", error_description=\"{hint}\""
782069860236atagen2026-10-10 12:44 UTC44
                ),
782069860236atagen2026-10-10 12:44 UTC45
            ));
782069860236atagen2026-10-10 12:44 UTC46
        }
782069860236atagen2026-10-10 12:44 UTC47
782069860236atagen2026-10-10 12:44 UTC48
        self.conditions.peyronie = false;
782069860236atagen2026-10-10 12:44 UTC49
        self.conditions.priapism_turns = 0;
782069860236atagen2026-10-10 12:44 UTC50
        let etag = self.origin_etag();
782069860236atagen2026-10-10 12:44 UTC51
        if if_none_match.is_some_and(|inm| etag_matches(inm, &etag)) {
782069860236atagen2026-10-10 12:44 UTC52
            self.clinic.cured = true;
782069860236atagen2026-10-10 12:44 UTC53
            return Ok(Outcome::empty(StatusCode::NOT_MODIFIED)
782069860236atagen2026-10-10 12:44 UTC54
                .header(header::ETAG, etag)
782069860236atagen2026-10-10 12:44 UTC55
                .header(X_DIAGNOSIS, "normal"));
782069860236atagen2026-10-10 12:44 UTC56
        }
782069860236atagen2026-10-10 12:44 UTC57
        if !self.clinic.measured {
782069860236atagen2026-10-10 12:44 UTC58
            self.clinic.measured = true;
782069860236atagen2026-10-10 12:44 UTC59
            if !self.items.ruler {
782069860236atagen2026-10-10 12:44 UTC60
                self.shame += 15;
782069860236atagen2026-10-10 12:44 UTC61
            }
782069860236atagen2026-10-10 12:44 UTC62
        }
782069860236atagen2026-10-10 12:44 UTC63
        Ok(Outcome::json(
782069860236atagen2026-10-10 12:44 UTC64
            StatusCode::OK,
782069860236atagen2026-10-10 12:44 UTC65
            json!({
782069860236atagen2026-10-10 12:44 UTC66
                "diagnosis": "within normal range",
782069860236atagen2026-10-10 12:44 UTC67
                "measured_length": round2(self.length),
782069860236atagen2026-10-10 12:44 UTC68
                "prescription": "Please stop.",
782069860236atagen2026-10-10 12:44 UTC69
            }),
782069860236atagen2026-10-10 12:44 UTC70
        )
782069860236atagen2026-10-10 12:44 UTC71
        .header(header::ETAG, etag))
782069860236atagen2026-10-10 12:44 UTC72
    }
782069860236atagen2026-10-10 12:44 UTC73
}