1use areev_cal::store_types::GrainTypeDiversityConfig;
8use areev_core::types::GrainType;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum OutputFormat {
14 Sml,
16 Toon,
18 Markdown,
20 PlainText,
22 Json,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq)]
28pub enum MetadataLevel {
29 None,
31 Minimal,
33 Full,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq)]
40pub enum Ordering {
41 ByRelevance,
43 Chronological,
45 ReverseChronological,
47 ByEntity,
49}
50
51#[derive(Debug, Clone, Default)]
53pub struct SectionConfig {
54 pub group_by_type: bool,
56 pub type_order: Vec<GrainType>,
60}
61
62#[derive(Debug, Clone)]
64pub struct GrainTypeOverride {
65 pub include: bool,
67 pub max_count: Option<usize>,
69}
70
71impl Default for GrainTypeOverride {
72 fn default() -> Self {
73 Self {
74 include: true,
75 max_count: None,
76 }
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct FormatPolicy {
83 pub format: OutputFormat,
84 pub metadata: MetadataLevel,
85 pub ordering: Ordering,
86 pub sections: SectionConfig,
87 pub token_budget: Option<usize>,
88 pub grain_overrides: HashMap<GrainType, GrainTypeOverride>,
89 pub query_text: Option<String>,
93 pub grain_type_diversity: Option<GrainTypeDiversityConfig>,
97 pub include_retracted: bool,
103}
104
105impl FormatPolicy {
106 pub fn new(format: OutputFormat) -> Self {
107 Self {
108 format,
109 metadata: MetadataLevel::Minimal,
110 ordering: Ordering::ByRelevance,
111 sections: SectionConfig::default(),
112 token_budget: None,
113 grain_overrides: HashMap::new(),
114 query_text: None,
115 grain_type_diversity: Some(GrainTypeDiversityConfig::default()),
116 include_retracted: false,
117 }
118 }
119
120 pub fn include_retracted(mut self, on: bool) -> Self {
121 self.include_retracted = on;
122 self
123 }
124
125 pub fn metadata(mut self, level: MetadataLevel) -> Self {
126 self.metadata = level;
127 self
128 }
129
130 pub fn ordering(mut self, ordering: Ordering) -> Self {
131 self.ordering = ordering;
132 self
133 }
134
135 pub fn token_budget(mut self, budget: usize) -> Self {
136 self.token_budget = Some(budget);
137 self
138 }
139
140 pub fn group_by_type(mut self) -> Self {
141 self.sections.group_by_type = true;
142 self
143 }
144
145 pub fn grain_override(mut self, gt: GrainType, ovr: GrainTypeOverride) -> Self {
146 self.grain_overrides.insert(gt, ovr);
147 self
148 }
149
150 pub fn query_text(mut self, text: impl Into<String>) -> Self {
152 self.query_text = Some(text.into());
153 self
154 }
155
156 pub fn grain_type_diversity(mut self, config: GrainTypeDiversityConfig) -> Self {
158 self.grain_type_diversity = Some(config);
159 self
160 }
161
162 pub fn no_grain_type_diversity(mut self) -> Self {
164 self.grain_type_diversity = None;
165 self
166 }
167}
168
169impl Default for FormatPolicy {
170 fn default() -> Self {
171 Self::new(OutputFormat::PlainText)
172 .metadata(MetadataLevel::Minimal)
173 .ordering(Ordering::ByRelevance)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_default_policy() {
183 let p = FormatPolicy::default();
184 assert_eq!(p.format, OutputFormat::PlainText);
185 assert_eq!(p.metadata, MetadataLevel::Minimal);
186 assert_eq!(p.ordering, Ordering::ByRelevance);
187 assert!(p.token_budget.is_none());
188 assert!(!p.sections.group_by_type);
189 }
190
191 #[test]
192 fn test_builder_chain() {
193 let p = FormatPolicy::new(OutputFormat::Sml)
194 .metadata(MetadataLevel::Full)
195 .ordering(Ordering::Chronological)
196 .token_budget(4096)
197 .group_by_type()
198 .grain_override(
199 GrainType::Consent,
200 GrainTypeOverride {
201 include: true,
202 max_count: Some(5),
203 },
204 );
205
206 assert_eq!(p.format, OutputFormat::Sml);
207 assert_eq!(p.metadata, MetadataLevel::Full);
208 assert_eq!(p.ordering, Ordering::Chronological);
209 assert_eq!(p.token_budget, Some(4096));
210 assert!(p.sections.group_by_type);
211 assert_eq!(
212 p.grain_overrides
213 .get(&GrainType::Consent)
214 .unwrap()
215 .max_count,
216 Some(5)
217 );
218 }
219}