1use serde::{Deserialize, Serialize};
10use std::fmt;
11
12#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
19#[non_exhaustive]
20pub enum Domain {
21 GraphAnalytics,
23
24 StatisticalML,
26
27 Compliance,
29
30 TemporalAnalysis,
32
33 RiskAnalytics,
35
36 Banking,
38
39 BehavioralAnalytics,
41
42 OrderMatching,
44
45 ProcessIntelligence,
47
48 Clearing,
50
51 TreasuryManagement,
53
54 Accounting,
56
57 PaymentProcessing,
59
60 FinancialAudit,
62
63 #[default]
65 Core,
66}
67
68impl Domain {
69 pub const ALL: &'static [Domain] = &[
71 Domain::GraphAnalytics,
72 Domain::StatisticalML,
73 Domain::Compliance,
74 Domain::TemporalAnalysis,
75 Domain::RiskAnalytics,
76 Domain::Banking,
77 Domain::BehavioralAnalytics,
78 Domain::OrderMatching,
79 Domain::ProcessIntelligence,
80 Domain::Clearing,
81 Domain::TreasuryManagement,
82 Domain::Accounting,
83 Domain::PaymentProcessing,
84 Domain::FinancialAudit,
85 Domain::Core,
86 ];
87
88 pub const P1: &'static [Domain] = &[
90 Domain::GraphAnalytics,
91 Domain::StatisticalML,
92 Domain::Compliance,
93 Domain::TemporalAnalysis,
94 Domain::RiskAnalytics,
95 ];
96
97 pub const P2: &'static [Domain] = &[
99 Domain::Banking,
100 Domain::BehavioralAnalytics,
101 Domain::OrderMatching,
102 Domain::ProcessIntelligence,
103 Domain::Clearing,
104 ];
105
106 pub const P3: &'static [Domain] = &[
108 Domain::TreasuryManagement,
109 Domain::Accounting,
110 Domain::PaymentProcessing,
111 Domain::FinancialAudit,
112 ];
113
114 #[must_use]
116 pub const fn as_str(&self) -> &'static str {
117 match self {
118 Domain::GraphAnalytics => "GraphAnalytics",
119 Domain::StatisticalML => "StatisticalML",
120 Domain::Compliance => "Compliance",
121 Domain::TemporalAnalysis => "TemporalAnalysis",
122 Domain::RiskAnalytics => "RiskAnalytics",
123 Domain::Banking => "Banking",
124 Domain::BehavioralAnalytics => "BehavioralAnalytics",
125 Domain::OrderMatching => "OrderMatching",
126 Domain::ProcessIntelligence => "ProcessIntelligence",
127 Domain::Clearing => "Clearing",
128 Domain::TreasuryManagement => "TreasuryManagement",
129 Domain::Accounting => "Accounting",
130 Domain::PaymentProcessing => "PaymentProcessing",
131 Domain::FinancialAudit => "FinancialAudit",
132 Domain::Core => "Core",
133 }
134 }
135
136 #[must_use]
138 pub fn parse(s: &str) -> Option<Self> {
139 match s {
140 "GraphAnalytics" => Some(Domain::GraphAnalytics),
141 "StatisticalML" => Some(Domain::StatisticalML),
142 "Compliance" => Some(Domain::Compliance),
143 "TemporalAnalysis" => Some(Domain::TemporalAnalysis),
144 "RiskAnalytics" => Some(Domain::RiskAnalytics),
145 "Banking" => Some(Domain::Banking),
146 "BehavioralAnalytics" => Some(Domain::BehavioralAnalytics),
147 "OrderMatching" => Some(Domain::OrderMatching),
148 "ProcessIntelligence" => Some(Domain::ProcessIntelligence),
149 "Clearing" => Some(Domain::Clearing),
150 "TreasuryManagement" => Some(Domain::TreasuryManagement),
151 "Accounting" => Some(Domain::Accounting),
152 "PaymentProcessing" => Some(Domain::PaymentProcessing),
153 "FinancialAudit" => Some(Domain::FinancialAudit),
154 "Core" => Some(Domain::Core),
155 _ => None,
156 }
157 }
158
159 #[must_use]
161 pub const fn is_p1(&self) -> bool {
162 matches!(
163 self,
164 Domain::GraphAnalytics
165 | Domain::StatisticalML
166 | Domain::Compliance
167 | Domain::TemporalAnalysis
168 | Domain::RiskAnalytics
169 )
170 }
171
172 #[must_use]
180 pub fn to_ring_domain(&self) -> ringkernel_core::domain::Domain {
181 ringkernel_core::domain::Domain::from(*self)
182 }
183
184 #[must_use]
194 pub fn from_ring_domain(ring: ringkernel_core::domain::Domain) -> Self {
195 Domain::from(ring)
196 }
197}
198
199impl fmt::Display for Domain {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 write!(f, "{}", self.as_str())
202 }
203}
204
205impl From<Domain> for ringkernel_core::domain::Domain {
210 fn from(d: Domain) -> Self {
211 use ringkernel_core::domain::Domain as RD;
212 match d {
213 Domain::GraphAnalytics => RD::GraphAnalytics,
214 Domain::StatisticalML => RD::StatisticalML,
215 Domain::Compliance => RD::Compliance,
216 Domain::TemporalAnalysis => RD::TimeSeries,
217 Domain::RiskAnalytics => RD::RiskManagement,
218 Domain::Banking => RD::Banking,
219 Domain::BehavioralAnalytics => RD::BehavioralAnalytics,
220 Domain::OrderMatching => RD::OrderMatching,
221 Domain::ProcessIntelligence => RD::ProcessIntelligence,
222 Domain::Clearing => RD::Clearing,
223 Domain::TreasuryManagement => RD::TreasuryManagement,
224 Domain::Accounting => RD::Accounting,
225 Domain::PaymentProcessing => RD::PaymentProcessing,
226 Domain::FinancialAudit => RD::FinancialAudit,
227 Domain::Core => RD::General,
228 }
229 }
230}
231
232impl From<ringkernel_core::domain::Domain> for Domain {
233 fn from(rd: ringkernel_core::domain::Domain) -> Self {
234 use ringkernel_core::domain::Domain as RD;
235 match rd {
236 RD::General => Domain::Core,
237 RD::GraphAnalytics => Domain::GraphAnalytics,
238 RD::StatisticalML => Domain::StatisticalML,
239 RD::Compliance => Domain::Compliance,
240 RD::RiskManagement => Domain::RiskAnalytics,
241 RD::OrderMatching => Domain::OrderMatching,
242 RD::Accounting => Domain::Accounting,
243 RD::TimeSeries => Domain::TemporalAnalysis,
244 RD::Banking => Domain::Banking,
245 RD::BehavioralAnalytics => Domain::BehavioralAnalytics,
246 RD::ProcessIntelligence => Domain::ProcessIntelligence,
247 RD::Clearing => Domain::Clearing,
248 RD::TreasuryManagement => Domain::TreasuryManagement,
249 RD::PaymentProcessing => Domain::PaymentProcessing,
250 RD::FinancialAudit => Domain::FinancialAudit,
251 RD::NetworkAnalysis => Domain::GraphAnalytics,
254 RD::FraudDetection => Domain::Banking,
255 RD::Settlement => Domain::Clearing,
256 RD::MarketData => Domain::Core,
257 RD::Simulation => Domain::Core,
258 RD::Custom => Domain::Core,
259 _ => Domain::Core,
261 }
262 }
263}
264
265pub mod features {
269 pub const GRAPH_PAGERANK: &str = "GraphAnalytics.PageRank";
272 pub const GRAPH_BETWEENNESS: &str = "GraphAnalytics.BetweennessCentrality";
274 pub const GRAPH_CLOSENESS: &str = "GraphAnalytics.ClosenessCentrality";
276 pub const GRAPH_DEGREE: &str = "GraphAnalytics.DegreeCentrality";
278 pub const GRAPH_EIGENVECTOR: &str = "GraphAnalytics.EigenvectorCentrality";
280 pub const GRAPH_KATZ: &str = "GraphAnalytics.KatzCentrality";
282 pub const GRAPH_COMMUNITY: &str = "GraphAnalytics.CommunityDetection";
284 pub const GRAPH_MOTIF: &str = "GraphAnalytics.MotifDetection";
286 pub const GRAPH_SIMILARITY: &str = "GraphAnalytics.Similarity";
288
289 pub const ML_KMEANS: &str = "StatisticalML.KMeans";
292 pub const ML_DBSCAN: &str = "StatisticalML.DBSCAN";
294 pub const ML_ISOLATION_FOREST: &str = "StatisticalML.IsolationForest";
296 pub const ML_LOF: &str = "StatisticalML.LocalOutlierFactor";
298 pub const ML_ENSEMBLE: &str = "StatisticalML.Ensemble";
300 pub const ML_REGRESSION: &str = "StatisticalML.Regression";
302
303 pub const COMPLIANCE_AML: &str = "Compliance.AML";
306 pub const COMPLIANCE_SANCTIONS: &str = "Compliance.SanctionsScreening";
308 pub const COMPLIANCE_KYC: &str = "Compliance.KYC";
310 pub const COMPLIANCE_MONITORING: &str = "Compliance.TransactionMonitoring";
312
313 pub const RISK_CREDIT: &str = "RiskAnalytics.CreditRisk";
316 pub const RISK_MARKET: &str = "RiskAnalytics.MarketRisk";
318 pub const RISK_VAR: &str = "RiskAnalytics.VaR";
320 pub const RISK_PORTFOLIO: &str = "RiskAnalytics.PortfolioRisk";
322 pub const RISK_STRESS: &str = "RiskAnalytics.StressTesting";
324
325 pub const TEMPORAL_ARIMA: &str = "TemporalAnalysis.ARIMA";
328 pub const TEMPORAL_PROPHET: &str = "TemporalAnalysis.Prophet";
330 pub const TEMPORAL_CHANGEPOINT: &str = "TemporalAnalysis.ChangePoint";
332 pub const TEMPORAL_SEASONAL: &str = "TemporalAnalysis.Seasonal";
334 pub const TEMPORAL_VOLATILITY: &str = "TemporalAnalysis.Volatility";
336
337 pub const BANKING_FRAUD: &str = "Banking.FraudDetection";
340
341 pub const ORDERBOOK_MATCHING: &str = "OrderMatching.OrderMatching";
344
345 pub const PROCINT_MINING: &str = "ProcessIntelligence.ProcessMining";
348 pub const PROCINT_CONFORMANCE: &str = "ProcessIntelligence.ConformanceChecking";
350}
351
352#[cfg(test)]
353mod tests {
354 use super::*;
355
356 #[test]
357 fn test_domain_all_count() {
358 assert_eq!(Domain::ALL.len(), 15);
359 }
360
361 #[test]
362 fn test_domain_priority_coverage() {
363 let p1_count = Domain::P1.len();
364 let p2_count = Domain::P2.len();
365 let p3_count = Domain::P3.len();
366 assert_eq!(p1_count + p2_count + p3_count + 1, Domain::ALL.len());
368 }
369
370 #[test]
371 fn test_domain_from_str() {
372 assert_eq!(
373 Domain::parse("GraphAnalytics"),
374 Some(Domain::GraphAnalytics)
375 );
376 assert_eq!(Domain::parse("Unknown"), None);
377 }
378
379 #[test]
380 fn test_domain_display() {
381 assert_eq!(Domain::GraphAnalytics.to_string(), "GraphAnalytics");
382 assert_eq!(Domain::RiskAnalytics.to_string(), "RiskAnalytics");
383 }
384
385 #[test]
386 fn test_domain_default() {
387 assert_eq!(Domain::default(), Domain::Core);
388 }
389
390 #[test]
391 fn test_to_ring_domain_renamed_variants() {
392 use ringkernel_core::domain::Domain as RD;
393
394 assert_eq!(Domain::TemporalAnalysis.to_ring_domain(), RD::TimeSeries);
395 assert_eq!(Domain::RiskAnalytics.to_ring_domain(), RD::RiskManagement);
396 assert_eq!(Domain::Core.to_ring_domain(), RD::General);
397 }
398
399 #[test]
400 fn test_to_ring_domain_identity_variants() {
401 use ringkernel_core::domain::Domain as RD;
402
403 assert_eq!(Domain::GraphAnalytics.to_ring_domain(), RD::GraphAnalytics);
404 assert_eq!(Domain::StatisticalML.to_ring_domain(), RD::StatisticalML);
405 assert_eq!(Domain::Compliance.to_ring_domain(), RD::Compliance);
406 assert_eq!(Domain::Banking.to_ring_domain(), RD::Banking);
407 assert_eq!(
408 Domain::BehavioralAnalytics.to_ring_domain(),
409 RD::BehavioralAnalytics
410 );
411 assert_eq!(Domain::OrderMatching.to_ring_domain(), RD::OrderMatching);
412 assert_eq!(
413 Domain::ProcessIntelligence.to_ring_domain(),
414 RD::ProcessIntelligence
415 );
416 assert_eq!(Domain::Clearing.to_ring_domain(), RD::Clearing);
417 assert_eq!(
418 Domain::TreasuryManagement.to_ring_domain(),
419 RD::TreasuryManagement
420 );
421 assert_eq!(Domain::Accounting.to_ring_domain(), RD::Accounting);
422 assert_eq!(
423 Domain::PaymentProcessing.to_ring_domain(),
424 RD::PaymentProcessing
425 );
426 assert_eq!(Domain::FinancialAudit.to_ring_domain(), RD::FinancialAudit);
427 }
428
429 #[test]
430 fn test_from_ring_domain_renamed_variants() {
431 use ringkernel_core::domain::Domain as RD;
432
433 assert_eq!(
434 Domain::from_ring_domain(RD::TimeSeries),
435 Domain::TemporalAnalysis
436 );
437 assert_eq!(
438 Domain::from_ring_domain(RD::RiskManagement),
439 Domain::RiskAnalytics
440 );
441 assert_eq!(Domain::from_ring_domain(RD::General), Domain::Core);
442 }
443
444 #[test]
445 fn test_from_ring_domain_closest_match() {
446 use ringkernel_core::domain::Domain as RD;
447
448 assert_eq!(
449 Domain::from_ring_domain(RD::NetworkAnalysis),
450 Domain::GraphAnalytics
451 );
452 assert_eq!(
453 Domain::from_ring_domain(RD::FraudDetection),
454 Domain::Banking
455 );
456 assert_eq!(Domain::from_ring_domain(RD::Settlement), Domain::Clearing);
457 assert_eq!(Domain::from_ring_domain(RD::MarketData), Domain::Core);
458 assert_eq!(Domain::from_ring_domain(RD::Simulation), Domain::Core);
459 assert_eq!(Domain::from_ring_domain(RD::Custom), Domain::Core);
460 }
461
462 #[test]
463 fn test_ring_domain_roundtrip() {
464 for &domain in Domain::ALL {
467 let ring = domain.to_ring_domain();
468 let back = Domain::from_ring_domain(ring);
469 assert_eq!(
470 back, domain,
471 "roundtrip failed for {:?} -> {:?} -> {:?}",
472 domain, ring, back
473 );
474 }
475 }
476}