atagen

jelq

public

an http based roguelike rpg about jelqing

Star0
Watch0
a11497af08aaaa6aaa48616cc29eec2b48d31d45
1
ssh://brewery@pls.lobotomise.me:33/atagen/jelq.git
src/game/dispatch.rsRust166 lines5.5 KB
1
use super::{
2
    Floor, Lube, Outcome, Run, Story, Technique,
3
    techniques::{Training, Utility},
4
};
5
use crate::problem::Problem;
6
use axum::http::{StatusCode, header};
7
use serde_json::json;
8
use std::{fmt::Write as _, ops::ControlFlow};
9
10
impl Run {
11
    pub fn jelq(
12
        &mut self,
13
        techniques: &[Technique],
14
        intensity: i32,
15
        lube: Option<Lube>,
16
    ) -> Result<Outcome, Problem> {
17
        if techniques != [Technique::Utility(Utility::Energy)] {
18
            self.check_exhausted()?;
19
        }
20
        if self.online.story == Story::Pending {
21
            return Ok(self.branch_offer());
22
        }
23
        if self.floor == Floor::Forum {
24
            return Ok(Outcome::json(
25
                StatusCode::SEE_OTHER,
26
                json!({ "detail": "Refer to the forum." }),
27
            )
28
            .header(header::LOCATION, self.path("/thread")));
29
        }
30
        if self.items.kit.cage {
31
            return Err(Problem::new(
32
                StatusCode::LOCKED,
33
                "caged",
34
                "The cage is locked. The key is not in the box.",
35
            ));
36
        }
37
        match *techniques {
38
            [Technique::Utility(utility)] => self.utility(utility, lube),
39
            [Technique::Training(training)] => self.single(training, intensity, lube),
40
            [Technique::Training(a), Technique::Training(b)] => self.combo(a, b, intensity, lube),
41
            [_, _] => Err(Problem::new(
42
                StatusCode::BAD_REQUEST,
43
                "combo-invalid",
44
                "Only training techniques can be combined.",
45
            )),
46
            _ => Err(Problem::new(
47
                StatusCode::BAD_REQUEST,
48
                "too-many-techniques",
49
                "Two techniques at most. The server has limits even if you do not.",
50
            )),
51
        }
52
    }
53
54
    pub(super) fn utility(
55
        &mut self,
56
        utility: Utility,
57
        lube: Option<Lube>,
58
    ) -> Result<Outcome, Problem> {
59
        match utility {
60
            Utility::Warmup => return self.warm_up(),
61
            Utility::Ice => return self.ice(),
62
            Utility::Supplement => return self.supplement(),
63
            Utility::Meditate => return self.meditate(),
64
            Utility::Energy => return self.energy(),
65
            Utility::Edge | Utility::Pump => {}
66
        }
67
        self.ready(Technique::Utility(utility), lube)?;
68
        self.check_storage()?;
69
        self.floor_enemy()?;
70
        match utility {
71
            Utility::Edge => self.edge(),
72
            _ => self.pump(),
73
        }
74
    }
75
76
    pub(super) fn single(
77
        &mut self,
78
        training: Training,
79
        intensity: i32,
80
        lube: Option<Lube>,
81
    ) -> Result<Outcome, Problem> {
82
        self.ready(Technique::Training(training), lube)?;
83
        self.check_storage()?;
84
        self.lube_available(lube)?;
85
        self.floor_enemy()?;
86
        self.take_lube(lube)?;
87
        self.chafe(lube, intensity);
88
        self.commit(intensity, lube, 1);
89
        if let ControlFlow::Break(interrupted) = self.mishaps(training, intensity)? {
90
            return Ok(interrupted);
91
        }
92
        if let ControlFlow::Break(interrupted) = self.hazards(intensity)? {
93
            return Ok(interrupted);
94
        }
95
        let outcome = self.roll(training, intensity, lube)?;
96
        Ok(self.gossip(outcome))
97
    }
98
99
    pub(super) fn combo(
100
        &mut self,
101
        a: Training,
102
        b: Training,
103
        intensity: i32,
104
        lube: Option<Lube>,
105
    ) -> Result<Outcome, Problem> {
106
        if a == b {
107
            return Err(Problem::new(
108
                StatusCode::BAD_REQUEST,
109
                "combo-invalid",
110
                "A technique cannot be combined with itself. The server has checked.",
111
            ));
112
        }
113
        self.ready(Technique::Training(a), lube)?;
114
        self.ready(Technique::Training(b), lube)?;
115
        self.check_storage()?;
116
        self.lube_available(lube)?;
117
        self.floor_enemy()?;
118
        self.take_lube(lube)?;
119
        self.chafe(lube, intensity);
120
        self.chafe(lube, intensity);
121
        self.commit(intensity, lube, 2);
122
        for training in [a, b] {
123
            if let ControlFlow::Break(interrupted) = self.mishaps(training, intensity)? {
124
                return Ok(interrupted);
125
            }
126
        }
127
        if let ControlFlow::Break(interrupted) = self.hazards(intensity)? {
128
            return Ok(interrupted);
129
        }
130
131
        let mut statuses = Vec::new();
132
        for training in [a, b] {
133
            let result = self.roll(training, intensity, lube);
134
            if self.ended.is_some() {
135
                return result;
136
            }
137
            let status = match result {
138
                Ok(outcome) => self.gossip(outcome).status(),
139
                Err(problem) => problem.status(),
140
            };
141
            statuses.push((training, status));
142
        }
143
144
        let mut xml = String::from(
145
            "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<D:multistatus xmlns:D=\"DAV:\">\n",
146
        );
147
        for (training, status) in statuses {
148
            let _ = write!(
149
                xml,
150
                "  <D:response>\n    <D:href>{}?technique={}</D:href>\n    <D:status>HTTP/1.1 {} {}</D:status>\n  </D:response>\n",
151
                self.path(""),
152
                training.name(),
153
                status.as_u16(),
154
                crate::problem::reason(status),
155
            );
156
        }
157
        xml.push_str(
158
            "  <D:responsedescription>Each technique has been reported separately.</D:responsedescription>\n</D:multistatus>\n",
159
        );
160
        Ok(Outcome::raw(
161
            StatusCode::MULTI_STATUS,
162
            "application/xml; charset=utf-8",
163
            xml,
164
        ))
165
    }
166
}