use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone)]
pub struct QueryResult {
pub query_type: QueryType,
pub matches: Option<Vec<PatternMatch>>,
pub statistics: Option<StatisticalAnalysis>,
pub alert: Option<AlertResult>,
pub summary: Option<SummaryMetrics>,
pub data: Option<QueryData>,
pub metadata: QueryMetadata,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum QueryType {
Find,
Scan,
Analyze,
Simulate,
Alert,
Value,
With,
Backtest,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatisticalAnalysis {
pub total_occurrences: usize,
pub success_rate: f64,
pub outcome_distribution: HashMap<String, f64>,
pub time_stats: TimeStatistics,
pub magnitude_stats: MagnitudeStatistics,
pub custom_metrics: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeStatistics {
pub avg_time_to_outcome: f64,
pub hourly_distribution: Vec<HourlyStats>,
pub daily_distribution: Vec<DailyStats>,
pub seasonality: Option<SeasonalityMetrics>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HourlyStats {
pub hour: u8,
pub occurrences: usize,
pub success_rate: f64,
pub avg_magnitude: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DailyStats {
pub day: String,
pub occurrences: usize,
pub success_rate: f64,
pub avg_magnitude: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SeasonalityMetrics {
pub monthly_pattern: Vec<f64>,
pub quarterly_pattern: Vec<f64>,
pub yearly_trend: Vec<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MagnitudeStatistics {
pub average: f64,
pub median: f64,
pub std_dev: f64,
pub min: f64,
pub max: f64,
pub percentiles: HashMap<String, f64>, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AlertResult {
pub id: String,
pub active: bool,
pub message: String,
pub level: String,
pub timestamp: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SummaryMetrics {
pub pattern_frequency: f64, pub pattern_reliability: f64,
pub confidence_score: f64,
pub average_outcome: f64,
pub expectancy: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryData {
pub time_series: Vec<TimeSeriesPoint>,
pub distributions: HashMap<String, Vec<f64>>,
pub correlations: HashMap<String, Vec<Vec<f64>>>,
pub tables: HashMap<String, DataTable>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeSeriesPoint {
pub timestamp: DateTime<Utc>,
pub values: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataTable {
pub columns: Vec<String>,
pub rows: Vec<Vec<serde_json::Value>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryMetadata {
pub execution_time_ms: u64,
pub data_points_analyzed: usize,
pub timeframe: String,
pub id: String,
pub date_range: (DateTime<Utc>, DateTime<Utc>),
pub query_hash: String, pub warnings: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PatternMatch {
pub pattern_name: String,
pub index: usize,
pub timestamp: DateTime<Utc>,
pub confidence: f64,
pub id: String,
pub metadata: serde_json::Value,
}
impl QueryResult {
pub fn new(query_type: QueryType, id: String, timeframe: String) -> Self {
Self {
query_type,
matches: None,
statistics: None,
alert: None,
summary: None,
data: None,
metadata: QueryMetadata {
execution_time_ms: 0,
data_points_analyzed: 0,
timeframe,
id,
date_range: (Utc::now(), Utc::now()),
query_hash: String::new(),
warnings: Vec::new(),
},
}
}
pub fn with_statistics(mut self, stats: StatisticalAnalysis) -> Self {
self.statistics = Some(stats);
self
}
pub fn with_alert(mut self, alert: AlertResult) -> Self {
self.alert = Some(alert);
self
}
pub fn calculate_summary(&mut self) {
let mut summary = SummaryMetrics {
pattern_frequency: 0.0,
pattern_reliability: 0.0,
confidence_score: 0.0,
average_outcome: 0.0,
expectancy: 0.0,
};
if let Some(ref stats) = self.statistics {
summary.pattern_frequency = if self.metadata.data_points_analyzed > 0 {
stats.total_occurrences as f64 / self.metadata.data_points_analyzed as f64
} else {
0.0
};
summary.pattern_reliability = stats.success_rate;
summary.average_outcome = stats.magnitude_stats.average;
summary.expectancy = stats.success_rate * stats.magnitude_stats.average;
}
summary.confidence_score = calculate_confidence_score(&summary, &self.statistics);
self.summary = Some(summary);
}
pub fn format_summary(&self) -> String {
if let Some(ref summary) = self.summary {
format!(
"Frequency: {:.4}, Reliability: {:.2}%, Confidence: {:.1}/100",
summary.pattern_frequency,
summary.pattern_reliability * 100.0,
summary.confidence_score
)
} else {
"No summary available".to_string()
}
}
}
fn calculate_confidence_score(
_summary: &SummaryMetrics,
stats: &Option<StatisticalAnalysis>,
) -> f64 {
let mut score: f64 = 50.0;
if let Some(stats) = stats {
if stats.total_occurrences > 100 {
score += 10.0; }
if stats.success_rate > 0.6 {
score += 10.0;
}
}
score.clamp(0.0, 100.0)
}