1pub fn generate_project_id(title: &str) -> String {
23 let words: Vec<&str> = title.split_whitespace().filter(|w| !w.is_empty()).collect();
24
25 let id = if words.len() >= 3 {
26 words.iter().take(3).filter_map(|w| w.chars().next()).collect::<String>()
28 } else if words.len() == 2 {
29 let mut chars: Vec<char> =
31 words.iter().filter_map(|w| w.chars().next()).collect();
32 let longer = if words[0].len() >= words[1].len() { words[0] } else { words[1] };
34 if let Some(c) = longer.chars().nth(1) {
35 chars.push(c);
36 }
37 chars.into_iter().collect()
38 } else if words.len() == 1 {
39 words[0].chars().take(3).collect()
41 } else {
42 "XXX".to_string()
44 };
45
46 id.to_uppercase()
47}
48
49pub fn generate_task_id(project_id: &str, counter: u32) -> String {
62 format!("{}-{:03}", project_id, counter)
63}
64
65pub fn parse_task_id(task_id: &str) -> Option<(String, u32)> {
78 let parts: Vec<&str> = task_id.splitn(2, '-').collect();
79 if parts.len() != 2 {
80 return None;
81 }
82
83 let project_id = parts[0].to_string();
84 let counter = parts[1].parse::<u32>().ok()?;
85
86 Some((project_id, counter))
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_project_id_multiple_words() {
95 assert_eq!(generate_project_id("My Cool Project"), "MCP");
96 assert_eq!(generate_project_id("Knowledge Base System"), "KBS");
97 }
98
99 #[test]
100 fn test_project_id_two_words() {
101 assert_eq!(generate_project_id("Home Automation"), "HAU");
103 assert_eq!(generate_project_id("AI Research"), "ARE");
104 }
105
106 #[test]
107 fn test_project_id_single_word() {
108 assert_eq!(generate_project_id("Inventory"), "INV");
109 assert_eq!(generate_project_id("AI"), "AI");
110 assert_eq!(generate_project_id("X"), "X");
111 }
112
113 #[test]
114 fn test_project_id_empty() {
115 assert_eq!(generate_project_id(""), "XXX");
116 assert_eq!(generate_project_id(" "), "XXX");
117 }
118
119 #[test]
120 fn test_project_id_lowercase() {
121 assert_eq!(generate_project_id("my cool project"), "MCP");
122 }
123
124 #[test]
125 fn test_task_id_generation() {
126 assert_eq!(generate_task_id("MCP", 1), "MCP-001");
127 assert_eq!(generate_task_id("MCP", 42), "MCP-042");
128 assert_eq!(generate_task_id("MCP", 999), "MCP-999");
129 }
130
131 #[test]
132 fn test_parse_task_id() {
133 assert_eq!(parse_task_id("MCP-001"), Some(("MCP".to_string(), 1)));
134 assert_eq!(parse_task_id("INV-042"), Some(("INV".to_string(), 42)));
135 assert_eq!(parse_task_id("invalid"), None);
136 assert_eq!(parse_task_id("MCP-abc"), None);
137 }
138}