use crate::{ factions::{NC, NSO, TR, VS}, utils::Filters, }; use async_graphql::{Context, Object}; use sqlx::{Pool, Postgres, Row}; /// A filterable list of currently active players. pub struct Population { filters: Filters, } impl Population { pub fn new(filters: Option) -> Self { Self { filters: filters.unwrap_or_default(), } } } impl Population { async fn by_faction<'ctx>(&self, ctx: &Context<'ctx>, faction: i32) -> i64 { let pool = ctx.data::>().unwrap(); let sql = format!( "SELECT count(*) FROM players WHERE last_updated > now() - interval '15 minutes' AND faction_id = $1 {};", self.filters.sql(), ); println!("{}", sql); let query: i64 = sqlx::query(sql.as_str()) .bind(faction) .fetch_one(pool) .await .unwrap() .get(0); query } } #[Object] impl Population { async fn total<'ctx>(&self, ctx: &Context<'ctx>) -> i64 { let pool = ctx.data::>().unwrap(); let sql = format!( "SELECT count(*) FROM players WHERE last_updated > now() - interval '15 minutes' {};", self.filters.sql(), ); println!("{}", sql); let query: i64 = sqlx::query(sql.as_str()) .fetch_one(pool) .await .unwrap() .get(0); query } async fn nc<'ctx>(&self, ctx: &Context<'ctx>) -> i64 { self.by_faction(ctx, NC).await } async fn vs<'ctx>(&self, ctx: &Context<'ctx>) -> i64 { self.by_faction(ctx, VS).await } async fn tr<'ctx>(&self, ctx: &Context<'ctx>) -> i64 { self.by_faction(ctx, TR).await } async fn ns<'ctx>(&self, ctx: &Context<'ctx>) -> i64 { self.by_faction(ctx, NSO).await } } #[derive(Default)] pub struct PopulationQuery; #[Object] impl PopulationQuery { /// A filterable list of currently active players. /// This is a core query that others will use to filter by, /// i.e. `emerald { population { total } }` is equivalent to `population(filter: { world: { name: "emerald" } }) { total }` pub async fn population(&self, filter: Option) -> Population { Population::new(filter) } }