This commit is contained in:
Daan Vanoverloop 2022-09-16 14:22:40 +02:00
parent c1a61d28a4
commit 0b9318b5c4
Signed by: Danacus
GPG Key ID: F2272B50E129FC5C
10 changed files with 63 additions and 33 deletions

View File

@ -21,7 +21,7 @@ pub async fn apply_outcome(outcome: &EventOutcome, db: &Connection<Db>) -> Resul
for (player, reward) in outcome.points.iter() {
db.users()
.update_one(
doc! { "id": player.to_string() },
doc! { "name": player.to_string() },
doc! { "$inc": { "score": reward } },
None,
)

View File

@ -1,4 +1,10 @@
use rocket::{http::Status, response, response::Responder, Request};
use std::borrow::Borrow;
use rocket::{
http::Status,
response::{self, status, Responder},
Request,
};
use rocket_db_pools::mongodb;
use rocket_okapi::response::OpenApiResponderInner;
use schemars::JsonSchema;
@ -30,7 +36,7 @@ impl ToString for Ordering {
#[derive(Error, Debug)]
pub enum PartyError {
#[error("internal error {source:?}")]
#[error("{source}")]
CoreError {
#[from]
source: CoreError,
@ -68,13 +74,16 @@ impl OpenApiResponderInner for PartyError {
impl<'r, 'o: 'r> Responder<'r, 'o> for PartyError {
fn respond_to(self, req: &'r Request<'_>) -> response::Result<'o> {
println!("{:#?}", &self);
println!("{}", self.to_string());
let message = self.to_string();
match self {
Self::CoreError { source } => match source {
CoreError::UserNotFound(_) | CoreError::EventNotFound(_) => Status::NotFound,
_ => Status::InternalServerError,
CoreError::UserNotFound(_) | CoreError::EventNotFound(_) => {
(Status::NotFound, "not found".to_string())
}
_ => (Status::BadRequest, message),
},
_ => Status::InternalServerError,
_ => (Status::InternalServerError, "unknown error".to_string()),
}
.respond_to(req)
}

View File

@ -471,11 +471,18 @@ where
T: FromStr + ToString + Default + Clone + PartialEq,
{
fn edit(cx: Scope<'a>, props: EditProps<'a, WithContext<Ctx, T>>) -> View<G> {
let ctx = use_context::<Ctx>(cx);
let value = create_signal(cx, props.state.get_untracked().to_string());
let ctx = use_context::<Ctx>(cx);
create_effect(cx, move || {
if value.get_untracked().is_empty() {
if let Some(first) = ctx.options(cx).get().get(0) {
value.set(first.to_string());
}
}
});
create_effect(cx, || {
create_effect(cx, move || {
props
.state
.set((*value.get()).parse::<T>().unwrap_or(T::default()).into())

View File

@ -150,7 +150,7 @@ macro_rules! events {
impl EventSpec {
pub fn create_event(self) -> Result<Event, PartyError> {
if self.name.is_empty() {
return Err(PartyError::Unknown("invalid name".into()))
return Err(PartyError::Other("invalid name".into()))
}
let event_type = match self.event_type {
@ -176,7 +176,7 @@ macro_rules! events {
$((EventType::$name(s), EventUpdate::$name(u)) => {
s.apply_update(u)
})*
_ => Err(PartyError::Unknown("invalid update".into())),
_ => Err(PartyError::Other("invalid update: update type does not match event type".into())),
}
}
@ -524,19 +524,19 @@ pub mod free_for_all_game {
match update {
FreeForAllGameUpdate::SetRanking(r) => {
if !r.is_valid(&self.spec.participants) {
return Err(PartyError::Unknown("invalid ranking, all participants mentioned in ranking must be participating".into()));
return Err(PartyError::Other("invalid ranking, all participants mentioned in ranking must be participating".into()));
}
self.ranking = Some(r)
}
FreeForAllGameUpdate::ScoreDelta(d) => match &mut self.ranking {
Some(Ranking::Ranking(_)) | None => {
return Err(PartyError::Unknown("cannot apply score delta".into()))
Some(Ranking::Ranking(_)) => {
return Err(PartyError::Other("cannot apply score delta".into()))
}
None => self.ranking = Some(Ranking::Scores(d)),
Some(Ranking::Scores(s)) => {
for (participant, delta) in d.iter() {
if let Some(value) = s.get(participant) {
s.insert(participant.clone(), value + delta);
}
let value = s.get(participant).unwrap_or(&0);
s.insert(participant.clone(), value + delta);
}
}
},
@ -553,7 +553,7 @@ pub mod free_for_all_game {
.unwrap_or(true)
{
self.spec.participants.insert(name);
return Err(PartyError::Unknown("cannot remove participant, all participants mentioned in ranking must be participating".into()));
return Err(PartyError::Other("cannot remove participant, all participants mentioned in ranking must be participating".into()));
}
}
FreeForAllGameUpdate::SetParticipants(participants) => {
@ -563,7 +563,7 @@ pub mod free_for_all_game {
.map(|r| r.is_valid(&participants))
.unwrap_or(true)
{
return Err(PartyError::Unknown("invalid list of participants, all participants mentioned in ranking must be participating".into()));
return Err(PartyError::Other("invalid list of participants, all participants mentioned in ranking must be participating".into()));
}
self.spec.participants = participants;
}

View File

@ -18,8 +18,8 @@ pub enum PartyError {
UserNotFound(String),
#[error("event `{0}` does not exist")]
EventNotFound(String),
#[error("unknown error: {0}")]
Unknown(String),
#[error("{0}")]
Other(String),
#[error("invalid parameter: {0}")]
InvalidParameter(String),
}

View File

@ -634,8 +634,6 @@ pub fn web_edit(tokens: TokenStream) -> TokenStream {
}
};
println!("{}", &res.to_string());
TokenStream::from(res)
}
@ -703,7 +701,5 @@ pub fn web_view(tokens: TokenStream) -> TokenStream {
}
};
println!("{}", &res.to_string());
TokenStream::from(res)
}

6
web/dist/index.html vendored
View File

@ -6,7 +6,7 @@
<link href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" rel="stylesheet">
<title>LAN Party</title>
<link rel="preload" href="/index-495632ef4eca1348_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/index-495632ef4eca1348.js"></head>
<link rel="preload" href="/index-1e8437b6157bd12b_bg.wasm" as="fetch" type="application/wasm" crossorigin="">
<link rel="modulepreload" href="/index-1e8437b6157bd12b.js"></head>
<body>
<script type="module">import init from '/index-495632ef4eca1348.js';init('/index-495632ef4eca1348_bg.wasm');</script></body></html>
<script type="module">import init from '/index-1e8437b6157bd12b.js';init('/index-1e8437b6157bd12b_bg.wasm');</script></body></html>

View File

@ -41,6 +41,7 @@ pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
let event_outcome = create_signal(cx, EventOutcome::default());
let events = use_context::<Events>(cx);
let users = use_context::<Users>(cx);
let dispatch = move |msg: Msg| {
spawn_local_scoped(cx, async move {
@ -84,10 +85,8 @@ pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
.and_then(|inner| inner.ok_or(anyhow!("missing body")));
if let Ok(outcome) = res {
debug!("{:#?}", outcome);
event_outcome.set(outcome);
} else {
debug!("oh no");
messenger.add_result(
res,
Option::<String>::None,
@ -95,7 +94,22 @@ pub fn EventsPage<'a, G: Html>(cx: Scope<'a>) -> View<G> {
)
}
}
_ => {}
Msg::Stop(event_name) => {
let res = api_request::<(), EventOutcome>(
Method::POST,
&format!("/event/{}/stop", event_name),
None,
)
.await;
messenger.add_result(
res,
Some("Event finished, scores were applied"),
Some("Unable to finish event"),
);
let _ = users.load();
}
}
});
};

View File

@ -100,7 +100,7 @@ pub trait EventsExt {
impl EventsExt for Events {
async fn load(&self) -> Result<()> {
self.0.set(
api_request::<_, Vec<Event>>(Method::GET, "/event", Option::<()>::None)
api_request::<_, Vec<Event>>(Method::GET, "/event?concluded=false", Option::<()>::None)
.await
.and_then(|inner| inner.ok_or(anyhow!("missing body")))?,
);

View File

@ -40,7 +40,11 @@ pub async fn api_request<B: Serialize, R: for<'a> Deserialize<'a>>(
Ok(None)
}
} else {
Err(anyhow!("Request failed"))
if let Ok(text) = res.text().await {
Err(anyhow!("Request failed: {}", text.to_string()))
} else {
Err(anyhow!("Request failed"))
}
}
}