use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[non_exhaustive]
pub enum Domain {
GraphAnalytics,
StatisticalML,
Compliance,
TemporalAnalysis,
RiskAnalytics,
Banking,
BehavioralAnalytics,
OrderMatching,
ProcessIntelligence,
Clearing,
TreasuryManagement,
Accounting,
PaymentProcessing,
FinancialAudit,
#[default]
Core,
}
impl Domain {
pub const ALL: &'static [Domain] = &[
Domain::GraphAnalytics,
Domain::StatisticalML,
Domain::Compliance,
Domain::TemporalAnalysis,
Domain::RiskAnalytics,
Domain::Banking,
Domain::BehavioralAnalytics,
Domain::OrderMatching,
Domain::ProcessIntelligence,
Domain::Clearing,
Domain::TreasuryManagement,
Domain::Accounting,
Domain::PaymentProcessing,
Domain::FinancialAudit,
Domain::Core,
];
pub const P1: &'static [Domain] = &[
Domain::GraphAnalytics,
Domain::StatisticalML,
Domain::Compliance,
Domain::TemporalAnalysis,
Domain::RiskAnalytics,
];
pub const P2: &'static [Domain] = &[
Domain::Banking,
Domain::BehavioralAnalytics,
Domain::OrderMatching,
Domain::ProcessIntelligence,
Domain::Clearing,
];
pub const P3: &'static [Domain] = &[
Domain::TreasuryManagement,
Domain::Accounting,
Domain::PaymentProcessing,
Domain::FinancialAudit,
];
#[must_use]
pub const fn as_str(&self) -> &'static str {
match self {
Domain::GraphAnalytics => "GraphAnalytics",
Domain::StatisticalML => "StatisticalML",
Domain::Compliance => "Compliance",
Domain::TemporalAnalysis => "TemporalAnalysis",
Domain::RiskAnalytics => "RiskAnalytics",
Domain::Banking => "Banking",
Domain::BehavioralAnalytics => "BehavioralAnalytics",
Domain::OrderMatching => "OrderMatching",
Domain::ProcessIntelligence => "ProcessIntelligence",
Domain::Clearing => "Clearing",
Domain::TreasuryManagement => "TreasuryManagement",
Domain::Accounting => "Accounting",
Domain::PaymentProcessing => "PaymentProcessing",
Domain::FinancialAudit => "FinancialAudit",
Domain::Core => "Core",
}
}
#[must_use]
pub fn parse(s: &str) -> Option<Self> {
match s {
"GraphAnalytics" => Some(Domain::GraphAnalytics),
"StatisticalML" => Some(Domain::StatisticalML),
"Compliance" => Some(Domain::Compliance),
"TemporalAnalysis" => Some(Domain::TemporalAnalysis),
"RiskAnalytics" => Some(Domain::RiskAnalytics),
"Banking" => Some(Domain::Banking),
"BehavioralAnalytics" => Some(Domain::BehavioralAnalytics),
"OrderMatching" => Some(Domain::OrderMatching),
"ProcessIntelligence" => Some(Domain::ProcessIntelligence),
"Clearing" => Some(Domain::Clearing),
"TreasuryManagement" => Some(Domain::TreasuryManagement),
"Accounting" => Some(Domain::Accounting),
"PaymentProcessing" => Some(Domain::PaymentProcessing),
"FinancialAudit" => Some(Domain::FinancialAudit),
"Core" => Some(Domain::Core),
_ => None,
}
}
#[must_use]
pub const fn is_p1(&self) -> bool {
matches!(
self,
Domain::GraphAnalytics
| Domain::StatisticalML
| Domain::Compliance
| Domain::TemporalAnalysis
| Domain::RiskAnalytics
)
}
#[must_use]
pub fn to_ring_domain(&self) -> ringkernel_core::domain::Domain {
ringkernel_core::domain::Domain::from(*self)
}
#[must_use]
pub fn from_ring_domain(ring: ringkernel_core::domain::Domain) -> Self {
Domain::from(ring)
}
}
impl fmt::Display for Domain {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl From<Domain> for ringkernel_core::domain::Domain {
fn from(d: Domain) -> Self {
use ringkernel_core::domain::Domain as RD;
match d {
Domain::GraphAnalytics => RD::GraphAnalytics,
Domain::StatisticalML => RD::StatisticalML,
Domain::Compliance => RD::Compliance,
Domain::TemporalAnalysis => RD::TimeSeries,
Domain::RiskAnalytics => RD::RiskManagement,
Domain::Banking => RD::Banking,
Domain::BehavioralAnalytics => RD::BehavioralAnalytics,
Domain::OrderMatching => RD::OrderMatching,
Domain::ProcessIntelligence => RD::ProcessIntelligence,
Domain::Clearing => RD::Clearing,
Domain::TreasuryManagement => RD::TreasuryManagement,
Domain::Accounting => RD::Accounting,
Domain::PaymentProcessing => RD::PaymentProcessing,
Domain::FinancialAudit => RD::FinancialAudit,
Domain::Core => RD::General,
}
}
}
impl From<ringkernel_core::domain::Domain> for Domain {
fn from(rd: ringkernel_core::domain::Domain) -> Self {
use ringkernel_core::domain::Domain as RD;
match rd {
RD::General => Domain::Core,
RD::GraphAnalytics => Domain::GraphAnalytics,
RD::StatisticalML => Domain::StatisticalML,
RD::Compliance => Domain::Compliance,
RD::RiskManagement => Domain::RiskAnalytics,
RD::OrderMatching => Domain::OrderMatching,
RD::Accounting => Domain::Accounting,
RD::TimeSeries => Domain::TemporalAnalysis,
RD::Banking => Domain::Banking,
RD::BehavioralAnalytics => Domain::BehavioralAnalytics,
RD::ProcessIntelligence => Domain::ProcessIntelligence,
RD::Clearing => Domain::Clearing,
RD::TreasuryManagement => Domain::TreasuryManagement,
RD::PaymentProcessing => Domain::PaymentProcessing,
RD::FinancialAudit => Domain::FinancialAudit,
RD::NetworkAnalysis => Domain::GraphAnalytics,
RD::FraudDetection => Domain::Banking,
RD::Settlement => Domain::Clearing,
RD::MarketData => Domain::Core,
RD::Simulation => Domain::Core,
RD::Custom => Domain::Core,
_ => Domain::Core,
}
}
}
pub mod features {
pub const GRAPH_PAGERANK: &str = "GraphAnalytics.PageRank";
pub const GRAPH_BETWEENNESS: &str = "GraphAnalytics.BetweennessCentrality";
pub const GRAPH_CLOSENESS: &str = "GraphAnalytics.ClosenessCentrality";
pub const GRAPH_DEGREE: &str = "GraphAnalytics.DegreeCentrality";
pub const GRAPH_EIGENVECTOR: &str = "GraphAnalytics.EigenvectorCentrality";
pub const GRAPH_KATZ: &str = "GraphAnalytics.KatzCentrality";
pub const GRAPH_COMMUNITY: &str = "GraphAnalytics.CommunityDetection";
pub const GRAPH_MOTIF: &str = "GraphAnalytics.MotifDetection";
pub const GRAPH_SIMILARITY: &str = "GraphAnalytics.Similarity";
pub const ML_KMEANS: &str = "StatisticalML.KMeans";
pub const ML_DBSCAN: &str = "StatisticalML.DBSCAN";
pub const ML_ISOLATION_FOREST: &str = "StatisticalML.IsolationForest";
pub const ML_LOF: &str = "StatisticalML.LocalOutlierFactor";
pub const ML_ENSEMBLE: &str = "StatisticalML.Ensemble";
pub const ML_REGRESSION: &str = "StatisticalML.Regression";
pub const COMPLIANCE_AML: &str = "Compliance.AML";
pub const COMPLIANCE_SANCTIONS: &str = "Compliance.SanctionsScreening";
pub const COMPLIANCE_KYC: &str = "Compliance.KYC";
pub const COMPLIANCE_MONITORING: &str = "Compliance.TransactionMonitoring";
pub const RISK_CREDIT: &str = "RiskAnalytics.CreditRisk";
pub const RISK_MARKET: &str = "RiskAnalytics.MarketRisk";
pub const RISK_VAR: &str = "RiskAnalytics.VaR";
pub const RISK_PORTFOLIO: &str = "RiskAnalytics.PortfolioRisk";
pub const RISK_STRESS: &str = "RiskAnalytics.StressTesting";
pub const TEMPORAL_ARIMA: &str = "TemporalAnalysis.ARIMA";
pub const TEMPORAL_PROPHET: &str = "TemporalAnalysis.Prophet";
pub const TEMPORAL_CHANGEPOINT: &str = "TemporalAnalysis.ChangePoint";
pub const TEMPORAL_SEASONAL: &str = "TemporalAnalysis.Seasonal";
pub const TEMPORAL_VOLATILITY: &str = "TemporalAnalysis.Volatility";
pub const BANKING_FRAUD: &str = "Banking.FraudDetection";
pub const ORDERBOOK_MATCHING: &str = "OrderMatching.OrderMatching";
pub const PROCINT_MINING: &str = "ProcessIntelligence.ProcessMining";
pub const PROCINT_CONFORMANCE: &str = "ProcessIntelligence.ConformanceChecking";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_domain_all_count() {
assert_eq!(Domain::ALL.len(), 15);
}
#[test]
fn test_domain_priority_coverage() {
let p1_count = Domain::P1.len();
let p2_count = Domain::P2.len();
let p3_count = Domain::P3.len();
assert_eq!(p1_count + p2_count + p3_count + 1, Domain::ALL.len());
}
#[test]
fn test_domain_from_str() {
assert_eq!(
Domain::parse("GraphAnalytics"),
Some(Domain::GraphAnalytics)
);
assert_eq!(Domain::parse("Unknown"), None);
}
#[test]
fn test_domain_display() {
assert_eq!(Domain::GraphAnalytics.to_string(), "GraphAnalytics");
assert_eq!(Domain::RiskAnalytics.to_string(), "RiskAnalytics");
}
#[test]
fn test_domain_default() {
assert_eq!(Domain::default(), Domain::Core);
}
#[test]
fn test_to_ring_domain_renamed_variants() {
use ringkernel_core::domain::Domain as RD;
assert_eq!(Domain::TemporalAnalysis.to_ring_domain(), RD::TimeSeries);
assert_eq!(Domain::RiskAnalytics.to_ring_domain(), RD::RiskManagement);
assert_eq!(Domain::Core.to_ring_domain(), RD::General);
}
#[test]
fn test_to_ring_domain_identity_variants() {
use ringkernel_core::domain::Domain as RD;
assert_eq!(Domain::GraphAnalytics.to_ring_domain(), RD::GraphAnalytics);
assert_eq!(Domain::StatisticalML.to_ring_domain(), RD::StatisticalML);
assert_eq!(Domain::Compliance.to_ring_domain(), RD::Compliance);
assert_eq!(Domain::Banking.to_ring_domain(), RD::Banking);
assert_eq!(
Domain::BehavioralAnalytics.to_ring_domain(),
RD::BehavioralAnalytics
);
assert_eq!(Domain::OrderMatching.to_ring_domain(), RD::OrderMatching);
assert_eq!(
Domain::ProcessIntelligence.to_ring_domain(),
RD::ProcessIntelligence
);
assert_eq!(Domain::Clearing.to_ring_domain(), RD::Clearing);
assert_eq!(
Domain::TreasuryManagement.to_ring_domain(),
RD::TreasuryManagement
);
assert_eq!(Domain::Accounting.to_ring_domain(), RD::Accounting);
assert_eq!(
Domain::PaymentProcessing.to_ring_domain(),
RD::PaymentProcessing
);
assert_eq!(Domain::FinancialAudit.to_ring_domain(), RD::FinancialAudit);
}
#[test]
fn test_from_ring_domain_renamed_variants() {
use ringkernel_core::domain::Domain as RD;
assert_eq!(
Domain::from_ring_domain(RD::TimeSeries),
Domain::TemporalAnalysis
);
assert_eq!(
Domain::from_ring_domain(RD::RiskManagement),
Domain::RiskAnalytics
);
assert_eq!(Domain::from_ring_domain(RD::General), Domain::Core);
}
#[test]
fn test_from_ring_domain_closest_match() {
use ringkernel_core::domain::Domain as RD;
assert_eq!(
Domain::from_ring_domain(RD::NetworkAnalysis),
Domain::GraphAnalytics
);
assert_eq!(
Domain::from_ring_domain(RD::FraudDetection),
Domain::Banking
);
assert_eq!(Domain::from_ring_domain(RD::Settlement), Domain::Clearing);
assert_eq!(Domain::from_ring_domain(RD::MarketData), Domain::Core);
assert_eq!(Domain::from_ring_domain(RD::Simulation), Domain::Core);
assert_eq!(Domain::from_ring_domain(RD::Custom), Domain::Core);
}
#[test]
fn test_ring_domain_roundtrip() {
for &domain in Domain::ALL {
let ring = domain.to_ring_domain();
let back = Domain::from_ring_domain(ring);
assert_eq!(
back, domain,
"roundtrip failed for {:?} -> {:?} -> {:?}",
domain, ring, back
);
}
}
}