diff --git a/src/endpoints/analytics/get_quest_activity.rs b/src/endpoints/analytics/get_quest_activity.rs index c04e0a5d..acc48c0a 100644 --- a/src/endpoints/analytics/get_quest_activity.rs +++ b/src/endpoints/analytics/get_quest_activity.rs @@ -1,4 +1,4 @@ -use crate::models::{QuestTaskDocument}; +use crate::models::QuestTaskDocument; use crate::{models::AppState, utils::get_error}; use axum::{ extract::{Query, State}, @@ -8,78 +8,134 @@ use axum::{ use axum_auto_routes::route; use futures::StreamExt; use mongodb::bson::doc; -use std::sync::Arc; use serde::Deserialize; +use std::sync::Arc; #[derive(Deserialize)] pub struct GetQuestsQuery { id: u32, } - -#[route(get, "/analytics/get_quest_activity", crate::endpoints::analytics::get_quest_activity)] -pub async fn handler(State(state): State>, - Query(query): Query, +#[route( + get, + "/analytics/get_quest_activity", + crate::endpoints::analytics::get_quest_activity +)] +pub async fn handler( + State(state): State>, + Query(query): Query, ) -> impl IntoResponse { let quest_id = query.id; let day_wise_distribution = vec![ doc! { - "$match": doc! { - "quest_id": quest_id - } - }, + "$match": doc! { + "quest_id": quest_id + } + }, doc! { - "$group": doc! { - "_id": null, - "ids": doc! { - "$push": "$id" + "$group": doc! { + "_id": null, + "ids": doc! { + "$push": "$id" + } } - } - }, + }, doc! { - "$lookup": doc! { - "from": "completed_tasks", - "localField": "ids", - "foreignField": "task_id", - "as": "matching_documents" - } - }, + "$lookup": doc! { + "from": "completed_tasks", + "localField": "ids", + "foreignField": "task_id", + "as": "matching_documents" + } + }, doc! { - "$unwind": "$matching_documents" - }, + "$unwind": "$matching_documents" + }, doc! { - "$replaceRoot": doc! { - "newRoot": "$matching_documents" - } - }, + "$replaceRoot": doc! { + "newRoot": doc! { + "$mergeObjects": [ + "$$ROOT", + "$matching_documents" + ] + } + } + }, + doc! { + "$group": doc! { + "_id": doc! { + "_id": "$address", + "ids": "$ids" + }, + "maxTimestamp": doc! { + "$max": "$timestamp" + }, + "tasks": doc! { + "$addToSet": "$task_id" + }, + "count": doc! { + "$sum": 1 + } + } + }, doc! { - "$addFields": doc! { - "createdDate": doc! { - "$toDate": "$timestamp" + "$addFields": doc! { + "createdDate": doc! { + "$toDate": "$maxTimestamp" + } } - } - }, + }, doc! { - "$group": doc! { - "_id": doc! { - "$dateToString": doc! { - "format": "%Y-%m-%d %d", - "date": "$createdDate" + "$match": doc! { + "$expr": doc! { + "$and": [ + doc! { + "$eq": [ + doc! { + "$size": "$tasks" + }, + doc! { + "$size": "$_id.ids" + } + ] + } + ] } - }, - "participants": doc! { - "$sum": 1 } - } - }, + }, doc! { - "$sort": doc! { - "_id": 1 - } - }, + "$group": doc! { + "_id": doc! { + "$dateToString": doc! { + "format": "%Y-%m-%d %d", + "date": "$createdDate" + } + }, + "count": doc! { + "$sum": 1 + } + } + }, + doc! { + "$sort": doc! { + "_id": 1 + } + }, + doc! { + "$project": doc! { + "_id": 0, + "date": "$_id", + "participants": "$count" + } + }, ]; - match state.db.collection::("tasks").aggregate(day_wise_distribution, None).await { + match state + .db + .collection::("tasks") + .aggregate(day_wise_distribution, None) + .await + { Ok(mut cursor) => { let mut day_wise_distribution = Vec::new(); while let Some(result) = cursor.next().await {