Something went wrong. Try again.
Toolkit for tile-based quality reconstruction of astronomical image stacks
dwarf stacking two-seestar
Something went wrong. Try again.
8.4 kB · 163 lines
C++
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164#include "services/scan_summary.hpp"
/// @brief Implements latest scan job./// @details This implementation summarizes scanner jobs for dashboard status endpoints; it keeps JSON shapes, filesystem/// access, process handling, and error reporting localized to this backend component.std::optional<Job> latest_scan_job(const InMemoryJobStore& store) { auto jobs = store.list(200); for (auto& j : jobs) { if (j.type == "scan") return j; } return std::nullopt;}
nlohmann::json summarize_scan_job(const std::optional<Job>& job, const std::string& fallback_input_path) { if (!job.has_value()) { return { {"has_scan", false}, {"job_id", nullptr}, {"job_state", "pending"}, {"input_path", fallback_input_path}, {"input_dirs", nlohmann::json::array()}, {"object_name", ""}, {"target", ""}, {"ok", false}, {"frames_detected", 0}, {"image_width", 0}, {"image_height", 0}, {"color_mode", "UNKNOWN"}, {"color_mode_candidates", nlohmann::json::array()}, {"bayer_pattern", nullptr}, {"requires_user_confirmation", false}, {"errors", nlohmann::json::array()}, {"errors_total", 0}, {"errors_truncated", false}, {"warnings", nlohmann::json::array()}, {"warnings_total", 0}, {"warnings_truncated", false}, {"frames", nlohmann::json::array()}, {"frames_total", 0}, {"frames_truncated", false}, {"per_dir_results", nlohmann::json::array()}, {"per_dir_results_total", 0}, {"per_dir_results_truncated", false}, }; }
const auto& data = job->data; nlohmann::json result = data.contains("result") && data["result"].is_object() ? data["result"] : nlohmann::json::object(); nlohmann::json errors = result.contains("errors") && result["errors"].is_array() ? result["errors"] : nlohmann::json::array(); nlohmann::json warnings = result.contains("warnings") && result["warnings"].is_array() ? result["warnings"] : nlohmann::json::array(); nlohmann::json input_dirs = result.contains("input_dirs") && result["input_dirs"].is_array() ? result["input_dirs"] : (data.contains("input_dirs") && data["input_dirs"].is_array() ? data["input_dirs"] : nlohmann::json::array()); nlohmann::json frames = result.contains("frames") && result["frames"].is_array() ? result["frames"] : nlohmann::json::array(); nlohmann::json per_dir_results = result.contains("per_dir_results") && result["per_dir_results"].is_array() ? result["per_dir_results"] : nlohmann::json::array();
std::string input_path = result.value("input_path", data.value("input_path", fallback_input_path)); std::string object_name = result.value("object_name", data.value("object_name", std::string())); bool ok = result.contains("ok") && result["ok"].is_boolean() ? result["ok"].get<bool>() : errors.empty();
return { {"has_scan", true}, {"job_id", job->job_id}, {"job_state", job_state_str(job->state)}, {"input_path", input_path}, {"input_dirs", input_dirs}, {"object_name", object_name}, {"target", result.value("target", data.value("target", object_name))}, {"ok", ok}, {"frames_detected", result.value("frames_detected", 0)}, {"image_width", result.value("image_width", 0)}, {"image_height", result.value("image_height", 0)}, {"color_mode", result.value("color_mode", "UNKNOWN")}, {"color_mode_candidates", result.contains("color_mode_candidates") && result["color_mode_candidates"].is_array() ? result["color_mode_candidates"] : nlohmann::json::array()}, {"bayer_pattern", result.contains("bayer_pattern") ? result["bayer_pattern"] : nlohmann::json(nullptr)}, {"requires_user_confirmation", result.value("requires_user_confirmation", false)}, {"errors", errors}, {"errors_total", result.value("errors_total", static_cast<int>(errors.size()))}, {"errors_truncated", result.value("errors_truncated", false)}, {"warnings", warnings}, {"warnings_total", result.value("warnings_total", static_cast<int>(warnings.size()))}, {"warnings_truncated", result.value("warnings_truncated", false)}, {"frames", frames}, {"frames_total", result.value("frames_total", result.value("frames_detected", static_cast<int>(frames.size())))}, {"frames_truncated", result.value("frames_truncated", false)}, {"per_dir_results", per_dir_results}, {"per_dir_results_total", result.value("per_dir_results_total", static_cast<int>(per_dir_results.size()))}, {"per_dir_results_truncated", result.value("per_dir_results_truncated", false)}, };}
/// @brief Implements scan quality./// @details This implementation summarizes scanner jobs for dashboard status endpoints; it keeps JSON shapes, filesystem/// access, process handling, and error reporting localized to this backend component.nlohmann::json scan_quality(const InMemoryJobStore& store) { auto job = latest_scan_job(store); auto summary = summarize_scan_job(job); if (!summary.value("has_scan", false)) { return { {"score", 0.0}, {"factors", nlohmann::json::array({{{"id", "no_scan"}, {"value", 1.0}, {"label", "No scan run yet"}}})}, {"scan", summary}, }; }
int errors = static_cast<int>(summary.contains("errors") && summary["errors"].is_array() ? summary["errors"].size() : 0); int warnings = static_cast<int>(summary.contains("warnings") && summary["warnings"].is_array() ? summary["warnings"].size() : 0); double score = std::max(0.0, 1.0 - 0.25 * errors - 0.1 * warnings); return { {"score", std::round(score * 1000.0) / 1000.0}, {"factors", nlohmann::json::array({ {{"id", "errors"}, {"value", errors}, {"label", "scan errors"}}, {{"id", "warnings"}, {"value", warnings}, {"label", "scan warnings"}}, })}, {"scan", summary}, };}
/// @brief Implements scan guardrails./// @details This implementation summarizes scanner jobs for dashboard status endpoints; it keeps JSON shapes, filesystem/// access, process handling, and error reporting localized to this backend component.nlohmann::json scan_guardrails(const InMemoryJobStore& store) { auto job = latest_scan_job(store); auto summary = summarize_scan_job(job); if (!summary.value("has_scan", false)) { return { {"status", "check"}, {"checks", nlohmann::json::array({{{"id", "scan"}, {"status", "check"}, {"label", "Scan ausstehend"}}})}, }; }
nlohmann::json errors = summary.contains("errors") && summary["errors"].is_array() ? summary["errors"] : nlohmann::json::array(); nlohmann::json warnings = summary.contains("warnings") && summary["warnings"].is_array() ? summary["warnings"] : nlohmann::json::array(); bool requires_confirm = summary.value("requires_user_confirmation", false); std::string color_mode = summary.value("color_mode", "UNKNOWN"); std::string color_mode_status = (requires_confirm || color_mode.empty() || color_mode == "UNKNOWN") ? "check" : "ok"; std::string color_mode_label = color_mode_status == "check" ? "Color mode bestaetigen" : "Color mode: " + color_mode;
nlohmann::json checks = nlohmann::json::array({ {{"id", "scan_ok"}, {"status", errors.empty() ? "ok" : "check"}, {"label", errors.empty() ? "Scan erfolgreich" : "Scan mit Fehlern"}, {"count", errors.size()}}, {{"id", "color_mode"}, {"status", color_mode_status}, {"label", color_mode_label}, {"value", color_mode}}, {{"id", "scan_warnings"}, {"status", warnings.empty() ? "ok" : "check"}, {"label", warnings.empty() ? "Keine Scan-Warnungen" : "Warnungen vorhanden"}, {"count", warnings.size()}}, }); std::string status = (!errors.empty() || !warnings.empty() || color_mode_status == "check") ? "check" : "ok"; return {{"status", status}, {"checks", checks}};}