use chrono::{DateTime, NaiveDate, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ParsedQuery {
pub original: String,
pub entities: Vec<Entity>,
pub events: Vec<Event>,
pub modifiers: Vec<String>,
pub temporal: TemporalInfo,
pub is_attribute_query: bool,
pub attribute: Option<AttributeQuery>,
pub compounds: Vec<String>,
pub ic_weights: HashMap<String, f32>,
pub confidence: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entity {
pub text: String,
pub stem: String,
pub entity_type: EntityType,
pub ic_weight: f32,
pub negated: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum EntityType {
Person,
Place,
Thing,
Event,
Time,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Event {
pub text: String,
pub stem: String,
pub ic_weight: f32,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct TemporalInfo {
pub has_temporal_intent: bool,
pub intent: TemporalIntent,
pub relative_refs: Vec<RelativeTimeRef>,
pub resolved_dates: Vec<NaiveDate>,
pub absolute_dates: Vec<NaiveDate>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum TemporalIntent {
WhenQuestion,
SpecificTime,
Ordering,
Duration,
#[default]
None,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelativeTimeRef {
pub text: String,
pub resolved: Option<NaiveDate>,
pub direction: TimeDirection,
pub unit: TimeUnit,
pub offset: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TimeDirection {
Past,
Future,
Current,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum TimeUnit {
Day,
Week,
Month,
Year,
Unknown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AttributeQuery {
pub entity: String,
pub attribute: String,
pub synonyms: Vec<String>,
}
pub trait QueryParser: Send + Sync {
fn parse(&self, query: &str, context_date: Option<DateTime<Utc>>) -> ParsedQuery;
fn name(&self) -> &'static str;
fn is_available(&self) -> bool {
true
}
}
impl ParsedQuery {
pub fn empty(original: &str) -> Self {
Self {
original: original.to_string(),
entities: Vec::new(),
events: Vec::new(),
modifiers: Vec::new(),
temporal: TemporalInfo::default(),
is_attribute_query: false,
attribute: None,
compounds: Vec::new(),
ic_weights: HashMap::new(),
confidence: 0.0,
}
}
pub fn entity_texts(&self) -> Vec<&str> {
self.entities.iter().map(|e| e.text.as_str()).collect()
}
pub fn event_stems(&self) -> Vec<&str> {
self.events.iter().map(|e| e.stem.as_str()).collect()
}
pub fn is_temporal_query(&self) -> bool {
self.temporal.has_temporal_intent
}
}