1use std::collections::HashMap;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Map;
5use serde_json::Number;
6use serde_json::Value;
7
8use crate::expression::Logs;
9
10pub type SplitMap = HashMap<String, Split>;
11
12#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
13#[serde(rename_all = "camelCase")]
14pub struct Split {
15 pub id: String,
16 pub r#type: SplitType,
17 pub dimensions: HashMap<String, Dimension>,
18}
19
20#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
21pub enum SplitType {
22 #[serde(rename = "test")]
23 Test,
24
25 #[serde(rename = "ml")]
26 ML,
27}
28
29#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
30#[serde(tag = "type", rename_all = "camelCase")]
31pub enum Dimension {
32 Discrete(DiscreteDimension),
33 Continuous(ContinuousDimension),
34}
35
36impl Dimension {
37 pub fn get_id(&self) -> &str {
38 match self {
39 Dimension::Discrete(d) => &d.id,
40 Dimension::Continuous(d) => &d.id,
41 }
42 }
43}
44
45#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
46#[serde(rename_all = "camelCase")]
47pub struct DiscreteDimension {
48 pub id: String,
49 split_id: String,
50 index: u64,
51 name: String,
52 pub arms: HashMap<String, Arm>,
53}
54
55#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
56#[serde(rename_all = "camelCase")]
57pub struct ContinuousDimension {
58 pub id: String,
59 split_id: String,
60 index: u64,
61 name: String,
62}
63
64#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
65#[serde(rename_all = "camelCase")]
66pub struct Arm {
67 pub id: String,
68 dimension_id: String,
69 pub index: u64,
70 name: String,
71 pub allocation: Number,
72}
73
74#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
75#[serde(rename_all = "camelCase")]
76pub struct CommitConfig {
77 pub split_config: HashMap<String, SplitConfig>,
78}
79
80impl CommitConfig {
81 pub fn new() -> Self {
82 Self {
83 split_config: HashMap::new(),
84 }
85 }
86}
87
88#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
89#[serde(tag = "type")]
90pub enum SplitConfig {
91 EpsilonGreedyConfig(EpsilonGreedyConfig),
92 PersonalizationSplitConfig(PersonalizationSplitConfig),
93}
94
95#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
96#[serde(rename_all = "camelCase")]
97pub struct EpsilonGreedyConfig {
98 pub epsilon: Number,
99 pub best_assignment: HashMap<String, SplitAssignmentEntry>,
100}
101
102#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
103pub struct PersonalizationSplitConfig {
104 pub epsilon: Number,
105 pub logic: HashMap<String, PersonalizationSplitLogicDimension>,
106}
107
108#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
109#[serde(rename_all = "camelCase")]
110pub struct PersonalizationSplitLogicDimension {
111 pub rules: Vec<PersonalSplitLogicDimensionRule>,
112 pub default_arm_id: String,
113}
114
115#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
116#[serde(rename_all = "camelCase")]
117pub struct PersonalSplitLogicDimensionRule {
118 pub feature_values_path: Vec<String>,
119 pub feature_value: Value,
120 pub arm_id: String,
121}
122
123#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
124#[serde(rename_all = "camelCase")]
125pub struct AssignmentCacheValue {
126 pub assignment: HashMap<String, SplitAssignmentEntry>,
127 pub event_object_type_name: Option<String>,
128 pub event_payload: Option<Map<String, Value>>,
129 pub event_payload_logs: Option<Logs>,
130}
131
132#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone, Hash)]
133#[serde(rename_all = "camelCase")]
134pub struct AssignmentCacheKey {
135 pub split_id: String,
136 pub unit_id: String,
137}
138
139pub type AssignmentCache = HashMap<AssignmentCacheKey, AssignmentCacheValue>;
140
141#[derive(Deserialize, Serialize, Eq, PartialEq, Debug, Clone)]
142#[serde(rename_all = "camelCase", tag = "type")]
143pub enum SplitAssignmentEntry {
144 #[serde(rename_all = "camelCase")]
145 Discrete {
146 arm_id: String,
147 },
148
149 Continuous {
150 value: Number,
151 },
152}