use super::{EntrantId, PlayerId, QueryUnwrap, Timestamp, VideogameId}; use cynic::GraphQlResponse; use schema::schema; // Variables #[derive(cynic::QueryVariables, Debug)] pub struct TournamentSetsVars<'a> { // HACK: This should really be an optional variable, but there seems to be a // server-side bug that completely breaks everything when this isn't passed. // We can use a dummy value of 1 when we don't want to filter by time. pub last_query: Timestamp, pub game_id: VideogameId, pub country: Option<&'a str>, pub state: Option<&'a str>, } // Query #[derive(cynic::QueryFragment, Debug)] #[cynic(graphql_type = "Query", variables = "TournamentSetsVars")] pub struct TournamentSets { #[arguments(query: { page: 1, perPage: 1, sortBy: "endAt desc", filter: { past: true, afterDate: $last_query, videogameIds: [$game_id], countryCode: $country, addrState: $state }})] tournaments: Option, } #[derive(cynic::QueryFragment, Debug)] #[cynic(variables = "TournamentSetsVars")] struct TournamentConnection { #[cynic(flatten)] nodes: Vec, } #[derive(cynic::QueryFragment, Debug)] #[cynic(variables = "TournamentSetsVars")] struct Tournament { name: Option, #[arguments(limit: 99999, filter: { videogameId: [$game_id] })] #[cynic(flatten)] events: Vec, } #[derive(cynic::QueryFragment, Debug)] struct Event { #[arguments(page: 1, perPage: 999)] sets: Option, } #[derive(cynic::QueryFragment, Debug)] struct SetConnection { #[cynic(flatten)] nodes: Vec, } #[derive(cynic::QueryFragment, Debug)] struct Set { #[arguments(includeByes: true)] #[cynic(flatten)] slots: Vec, winner_id: Option, } #[derive(cynic::QueryFragment, Debug)] struct SetSlot { entrant: Option, } #[derive(cynic::QueryFragment, Debug)] struct Entrant { id: Option, #[cynic(flatten)] participants: Vec, } #[derive(cynic::QueryFragment, Debug)] struct Participant { player: Option, } #[derive(cynic::QueryFragment, Debug)] struct Player { id: Option, } // Unwrap pub struct TournamentResponse { pub name: String, pub sets: Vec, } pub struct SetResponse { pub teams: Vec>, pub winner: usize, } impl<'a> QueryUnwrap> for TournamentSets { type VarsUnwrapped = TournamentSetsVars<'a>; type Unwrapped = Vec; fn wrap_vars(vars: TournamentSetsVars) -> TournamentSetsVars { vars } // This might be the most spaghetti code I've ever written fn unwrap_response( response: GraphQlResponse, ) -> Option> { Some( response .data? .tournaments? .nodes .into_iter() .filter_map(|tour| { let sets = tour .events .into_iter() .filter_map(|event| { Some( event .sets? .nodes .into_iter() .filter_map(|set| { let winner_id = set.winner_id?; let winner = set.slots.iter().position(|slot| { slot.entrant .as_ref() .and_then(|x| x.id) .map(|id| id.0 == winner_id as u64) .unwrap_or(false) })?; let teams = set .slots .into_iter() .map(|slot| { slot.entrant? .participants .into_iter() .map(|p| p.player?.id) .try_collect() }) .try_collect()?; Some(SetResponse { teams, winner }) }) .collect::>(), ) }) .flatten() .collect(); Some(TournamentResponse { name: tour.name?, sets, }) }) .collect(), ) } }