use crate::{Intent, Moment};
use serde::Serialize;
use std::collections::BTreeMap;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, serde::Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Gender {
#[serde(alias = "Male", alias = "男")]
Male,
#[serde(alias = "Female", alias = "女")]
Female,
}
#[derive(Debug, Clone, Serialize, serde::Deserialize)]
pub struct Query {
pub year: i32,
pub month: u32,
pub day: u32,
pub hour: u32,
pub minute: u32,
pub tz: f64,
pub gender: Option<Gender>,
pub latitude: Option<f64>,
pub longitude: Option<f64>,
pub seed: Option<u64>,
pub name: Option<String>,
#[serde(default)]
pub schools: BTreeMap<String, String>,
}
impl Query {
#[must_use]
pub fn at(year: i32, month: u32, day: u32, hour: u32, minute: u32, tz: f64) -> Self {
Self {
year,
month,
day,
hour,
minute,
tz,
gender: None,
latitude: None,
longitude: None,
seed: None,
name: None,
schools: BTreeMap::new(),
}
}
#[must_use]
pub fn school_of<'a>(&'a self, engine_id: &str, default_id: &'a str) -> &'a str {
self.schools.get(engine_id).map_or(default_id, |s| s.as_str())
}
}
#[must_use]
pub fn effective_seed(m: &Moment, q: &Query) -> u64 {
q.seed.unwrap_or_else(|| m.jd_ut.to_bits())
}
#[derive(Debug, Clone, Serialize, serde::Deserialize)]
pub struct AskTime {
pub year: i32,
pub month: u32,
pub day: u32,
pub hour: u32,
pub minute: u32,
pub tz: f64,
}
#[derive(Debug, Clone, Serialize, serde::Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum QueryKind {
Natal(Query),
Fortune {
natal: Query,
t_target: AskTime,
},
Event {
t_ask: AskTime,
seed: u64,
q_text: Option<String>,
},
Election {
window_start: AskTime,
window_end: AskTime,
category: String,
},
Synastry {
a: Query,
b: Query,
},
Mundane {
p_polity: Query,
},
Locative {
t_ask: AskTime,
seed: u64,
category: String,
},
Onomancy {
name: String,
surname_strokes: Option<u32>,
given_strokes: Option<u32>,
},
}
impl QueryKind {
#[must_use]
pub fn intent(&self) -> Intent {
match self {
Self::Natal(_) => Intent::Natal,
Self::Fortune { .. } => Intent::Fortune,
Self::Event { .. } => Intent::Event,
Self::Election { .. } => Intent::Election,
Self::Synastry { .. } => Intent::Synastry,
Self::Mundane { .. } => Intent::Mundane,
Self::Locative { .. } => Intent::Locative,
Self::Onomancy { .. } => Intent::Onomancy,
}
}
#[must_use]
pub fn id(&self) -> &'static str {
self.intent().id()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Subject {
Person,
Company,
Product,
Event,
}
impl Subject {
#[must_use]
pub fn from_str_opt(s: &str) -> Option<Self> {
match s {
"person" | "Person" | "人" => Some(Self::Person),
"company" | "Company" | "公司" => Some(Self::Company),
"product" | "Product" | "object" | "Object" | "物" | "产品" => Some(Self::Product),
"event" | "Event" | "事" => Some(Self::Event),
_ => None,
}
}
#[must_use]
pub fn cn(self) -> &'static str {
match self {
Self::Person => "人",
Self::Company => "公司/组织",
Self::Product => "物/产品",
Self::Event => "事/事件",
}
}
}