month_tasks.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. use std::{
  2. fs, io,
  3. path::{Path, PathBuf},
  4. };
  5. use chrono::{TimeZone, Utc};
  6. use log::debug;
  7. use serde::{Deserialize, Serialize};
  8. use darkfi::util::Timestamp;
  9. use crate::{
  10. error::{TaudError, TaudResult},
  11. task_info::TaskInfo,
  12. util::{load, save},
  13. };
  14. #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
  15. pub struct MonthTasks {
  16. created_at: Timestamp,
  17. task_tks: Vec<String>,
  18. }
  19. impl MonthTasks {
  20. pub fn new(task_tks: &[String]) -> Self {
  21. Self { created_at: Timestamp::current_time(), task_tks: task_tks.to_owned() }
  22. }
  23. pub fn add(&mut self, ref_id: &str) {
  24. debug!(target: "tau", "MonthTasks::add()");
  25. if !self.task_tks.contains(&ref_id.into()) {
  26. self.task_tks.push(ref_id.into());
  27. }
  28. }
  29. pub fn objects(&self, dataset_path: &Path) -> TaudResult<Vec<TaskInfo>> {
  30. debug!(target: "tau", "MonthTasks::objects()");
  31. let mut tks: Vec<TaskInfo> = vec![];
  32. for ref_id in self.task_tks.iter() {
  33. tks.push(TaskInfo::load(ref_id, dataset_path)?);
  34. }
  35. Ok(tks)
  36. }
  37. pub fn remove(&mut self, ref_id: &str) {
  38. debug!(target: "tau", "MonthTasks::remove()");
  39. if let Some(index) = self.task_tks.iter().position(|t| *t == ref_id) {
  40. self.task_tks.remove(index);
  41. }
  42. }
  43. pub fn set_date(&mut self, date: &Timestamp) {
  44. debug!(target: "tau", "MonthTasks::set_date()");
  45. self.created_at = *date;
  46. }
  47. fn get_path(date: &Timestamp, dataset_path: &Path) -> PathBuf {
  48. debug!(target: "tau", "MonthTasks::get_path()");
  49. dataset_path.join("month").join(Utc.timestamp(date.0, 0).format("%m%y").to_string())
  50. }
  51. pub fn save(&self, dataset_path: &Path) -> TaudResult<()> {
  52. debug!(target: "tau", "MonthTasks::save()");
  53. save::<Self>(&Self::get_path(&self.created_at, dataset_path), self)
  54. .map_err(TaudError::Darkfi)
  55. }
  56. fn get_all(dataset_path: &Path) -> io::Result<Vec<PathBuf>> {
  57. debug!(target: "tau", "MonthTasks::get_all()");
  58. let mut entries = fs::read_dir(dataset_path.join("month"))?
  59. .map(|res| res.map(|e| e.path()))
  60. .collect::<Result<Vec<_>, io::Error>>()?;
  61. entries.sort();
  62. Ok(entries)
  63. }
  64. fn create(date: &Timestamp, dataset_path: &Path) -> TaudResult<Self> {
  65. debug!(target: "tau", "MonthTasks::create()");
  66. let mut mt = Self::new(&[]);
  67. mt.set_date(date);
  68. mt.save(dataset_path)?;
  69. Ok(mt)
  70. }
  71. pub fn load_or_create(date: Option<&Timestamp>, dataset_path: &Path) -> TaudResult<Self> {
  72. debug!(target: "tau", "MonthTasks::load_or_create()");
  73. // if a date is given we load that date's month tasks
  74. // if not, we load tasks from all months
  75. match date {
  76. Some(date) => match load::<Self>(&Self::get_path(date, dataset_path)) {
  77. Ok(mt) => Ok(mt),
  78. Err(_) => Self::create(date, dataset_path),
  79. },
  80. None => {
  81. let path_all = match Self::get_all(dataset_path) {
  82. Ok(t) => t,
  83. Err(_) => vec![],
  84. };
  85. let mut loaded_mt = Self::new(&[]);
  86. for path in path_all {
  87. let mt = load::<Self>(&path)?;
  88. loaded_mt.created_at = mt.created_at;
  89. for tks in mt.task_tks {
  90. if !loaded_mt.task_tks.contains(&tks) {
  91. loaded_mt.task_tks.push(tks)
  92. }
  93. }
  94. }
  95. Ok(loaded_mt)
  96. }
  97. }
  98. }
  99. pub fn load_current_open_tasks(dataset_path: &Path) -> TaudResult<Vec<TaskInfo>> {
  100. let mt = Self::load_or_create(None, dataset_path)?;
  101. Ok(mt.objects(dataset_path)?.into_iter().filter(|t| t.get_state() != "stop").collect())
  102. }
  103. }
  104. #[cfg(test)]
  105. mod tests {
  106. use std::{
  107. fs::{create_dir_all, remove_dir_all},
  108. path::PathBuf,
  109. };
  110. use super::*;
  111. use darkfi::Result;
  112. const TEST_DATA_PATH: &str = "/tmp/test_tau_data";
  113. fn get_path() -> Result<PathBuf> {
  114. remove_dir_all(TEST_DATA_PATH).ok();
  115. let path = PathBuf::from(TEST_DATA_PATH);
  116. // mkdir dataset_path if not exists
  117. create_dir_all(path.join("month"))?;
  118. create_dir_all(path.join("task"))?;
  119. Ok(path)
  120. }
  121. #[test]
  122. fn load_and_save_tasks() -> TaudResult<()> {
  123. let dataset_path = get_path()?;
  124. // load and save TaskInfo
  125. ///////////////////////
  126. let mut task =
  127. TaskInfo::new("test_title", "test_desc", "NICKNAME", None, 0.0, &dataset_path)?;
  128. task.save(&dataset_path)?;
  129. let t_load = TaskInfo::load(&task.ref_id, &dataset_path)?;
  130. assert_eq!(task, t_load);
  131. task.set_title("test_title_2");
  132. task.save(&dataset_path)?;
  133. let t_load = TaskInfo::load(&task.ref_id, &dataset_path)?;
  134. assert_eq!(task, t_load);
  135. // load and save MonthTasks
  136. ///////////////////////
  137. let task_tks = vec![];
  138. let mut mt = MonthTasks::new(&task_tks);
  139. mt.save(&dataset_path)?;
  140. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  141. assert_eq!(mt, mt_load);
  142. mt.add(&task.ref_id);
  143. mt.save(&dataset_path)?;
  144. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  145. assert_eq!(mt, mt_load);
  146. // activate task
  147. ///////////////////////
  148. let task =
  149. TaskInfo::new("test_title_3", "test_desc", "NICKNAME", None, 0.0, &dataset_path)?;
  150. task.save(&dataset_path)?;
  151. let mt_load = MonthTasks::load_or_create(Some(&Timestamp::current_time()), &dataset_path)?;
  152. assert!(mt_load.task_tks.contains(&task.ref_id));
  153. remove_dir_all(TEST_DATA_PATH).ok();
  154. Ok(())
  155. }
  156. }