Skip to main content

research_agent/domain/
knowledge_gap.rs

1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
4#[serde(rename_all = "snake_case")]
5pub enum GapType {
6    MissingLiterature,
7    UnansweredQuestion,
8    MethodologyGap,
9    ConnectionGap,
10}
11
12impl GapType {
13    pub fn as_str(&self) -> &'static str {
14        match self {
15            Self::MissingLiterature => "missing_literature",
16            Self::UnansweredQuestion => "unanswered_question",
17            Self::MethodologyGap => "methodology_gap",
18            Self::ConnectionGap => "connection_gap",
19        }
20    }
21
22    pub fn from_str_lossy(s: &str) -> Self {
23        match s {
24            "unanswered_question" => Self::UnansweredQuestion,
25            "methodology_gap" => Self::MethodologyGap,
26            "connection_gap" => Self::ConnectionGap,
27            _ => Self::MissingLiterature,
28        }
29    }
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct KnowledgeGap {
34    pub id: String,
35    pub description: String,
36    pub topic_id: String,
37    pub gap_type: GapType,
38    pub priority: f32,
39    pub discovered_at: String,
40}
41
42impl KnowledgeGap {
43    pub fn new(description: String, topic_id: String, gap_type: GapType) -> Self {
44        let now = chrono::Utc::now().to_rfc3339();
45        Self {
46            id: uuid::Uuid::new_v4().to_string(),
47            description,
48            topic_id,
49            gap_type,
50            priority: 0.5,
51            discovered_at: now,
52        }
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59
60    #[test]
61    fn gap_type_roundtrip() {
62        let types = [
63            GapType::MissingLiterature,
64            GapType::UnansweredQuestion,
65            GapType::MethodologyGap,
66            GapType::ConnectionGap,
67        ];
68        for t in &types {
69            assert_eq!(GapType::from_str_lossy(t.as_str()), *t);
70        }
71    }
72
73    #[test]
74    fn gap_new() {
75        let g = KnowledgeGap::new(
76            "Missing survey papers".into(),
77            "topic-1".into(),
78            GapType::MissingLiterature,
79        );
80        assert_eq!(g.description, "Missing survey papers");
81        assert_eq!(g.topic_id, "topic-1");
82        assert!(!g.id.is_empty());
83    }
84}