Initial Commit
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
use axum::{extract::State, Json};
|
||||
|
||||
use super::{AppError, AppState};
|
||||
|
||||
pub async fn get_stats(
|
||||
State(state): State<AppState>,
|
||||
) -> Result<Json<serde_json::Value>, AppError> {
|
||||
// Total sessions
|
||||
let total_sessions: i64 = sqlx::query_scalar("SELECT COUNT(*) FROM imaging_log")
|
||||
.fetch_one(&state.pool)
|
||||
.await?;
|
||||
|
||||
// Total integration time
|
||||
let total_integration_min: Option<i64> =
|
||||
sqlx::query_scalar("SELECT SUM(integration_min) FROM imaging_log")
|
||||
.fetch_optional(&state.pool)
|
||||
.await?
|
||||
.flatten();
|
||||
|
||||
// Objects imaged (at least one keeper)
|
||||
let objects_with_keeper: i64 = sqlx::query_scalar(
|
||||
"SELECT COUNT(DISTINCT catalog_id) FROM imaging_log WHERE quality = 'keeper'",
|
||||
)
|
||||
.fetch_one(&state.pool)
|
||||
.await?;
|
||||
|
||||
// Filter usage
|
||||
let filter_usage = sqlx::query(
|
||||
"SELECT filter_id, COUNT(*) as count, SUM(integration_min) as total_min FROM imaging_log GROUP BY filter_id",
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let filter_stats: Vec<serde_json::Value> = filter_usage.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"filter_id": r.try_get::<String, _>("filter_id").unwrap_or_default(),
|
||||
"count": r.try_get::<i64, _>("count").unwrap_or_default(),
|
||||
"total_min": r.try_get::<Option<i64>, _>("total_min").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Integration per month (last 12 months)
|
||||
let monthly = sqlx::query(
|
||||
r#"SELECT substr(session_date, 1, 7) as month,
|
||||
COUNT(*) as sessions,
|
||||
SUM(integration_min) as total_min
|
||||
FROM imaging_log
|
||||
WHERE session_date >= date('now', '-12 months')
|
||||
GROUP BY month
|
||||
ORDER BY month"#,
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let monthly_stats: Vec<serde_json::Value> = monthly.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"month": r.try_get::<String, _>("month").unwrap_or_default(),
|
||||
"sessions": r.try_get::<i64, _>("sessions").unwrap_or_default(),
|
||||
"total_min": r.try_get::<Option<i64>, _>("total_min").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Object type breakdown
|
||||
let type_breakdown = sqlx::query(
|
||||
r#"SELECT c.obj_type, COUNT(*) as sessions, SUM(l.integration_min) as total_min
|
||||
FROM imaging_log l JOIN catalog c ON c.id = l.catalog_id
|
||||
GROUP BY c.obj_type ORDER BY total_min DESC"#,
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let type_stats: Vec<serde_json::Value> = type_breakdown.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"obj_type": r.try_get::<String, _>("obj_type").unwrap_or_default(),
|
||||
"sessions": r.try_get::<i64, _>("sessions").unwrap_or_default(),
|
||||
"total_min": r.try_get::<Option<i64>, _>("total_min").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Quality breakdown
|
||||
let quality = sqlx::query(
|
||||
"SELECT quality, COUNT(*) as count FROM imaging_log GROUP BY quality",
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let quality_stats: Vec<serde_json::Value> = quality.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"quality": r.try_get::<String, _>("quality").unwrap_or_default(),
|
||||
"count": r.try_get::<i64, _>("count").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Top targets by integration
|
||||
let top_targets = sqlx::query(
|
||||
r#"SELECT c.id, c.name, c.common_name, c.obj_type,
|
||||
COUNT(l.id) as sessions,
|
||||
SUM(l.integration_min) as total_min
|
||||
FROM imaging_log l JOIN catalog c ON c.id = l.catalog_id
|
||||
GROUP BY l.catalog_id
|
||||
ORDER BY total_min DESC
|
||||
LIMIT 20"#,
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let top_target_list: Vec<serde_json::Value> = top_targets.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"id": r.try_get::<String, _>("id").unwrap_or_default(),
|
||||
"name": r.try_get::<String, _>("name").unwrap_or_default(),
|
||||
"common_name": r.try_get::<Option<String>, _>("common_name").unwrap_or_default(),
|
||||
"obj_type": r.try_get::<String, _>("obj_type").unwrap_or_default(),
|
||||
"sessions": r.try_get::<i64, _>("sessions").unwrap_or_default(),
|
||||
"total_min": r.try_get::<Option<i64>, _>("total_min").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
// Guiding RMS over time
|
||||
let guiding = sqlx::query(
|
||||
"SELECT session_date, rms_total, rms_ra, rms_dec FROM phd2_logs ORDER BY session_date",
|
||||
)
|
||||
.fetch_all(&state.pool)
|
||||
.await?;
|
||||
|
||||
let guiding_data: Vec<serde_json::Value> = guiding.iter().map(|r| {
|
||||
use sqlx::Row;
|
||||
serde_json::json!({
|
||||
"date": r.try_get::<String, _>("session_date").unwrap_or_default(),
|
||||
"rms_total": r.try_get::<Option<f64>, _>("rms_total").unwrap_or_default(),
|
||||
"rms_ra": r.try_get::<Option<f64>, _>("rms_ra").unwrap_or_default(),
|
||||
"rms_dec": r.try_get::<Option<f64>, _>("rms_dec").unwrap_or_default(),
|
||||
})
|
||||
}).collect();
|
||||
|
||||
Ok(Json(serde_json::json!({
|
||||
"total_sessions": total_sessions,
|
||||
"total_integration_min": total_integration_min.unwrap_or(0),
|
||||
"objects_with_keeper": objects_with_keeper,
|
||||
"filter_usage": filter_stats,
|
||||
"monthly": monthly_stats,
|
||||
"by_type": type_stats,
|
||||
"quality": quality_stats,
|
||||
"top_targets": top_target_list,
|
||||
"guiding": guiding_data,
|
||||
})))
|
||||
}
|
||||
Reference in New Issue
Block a user