use crate::core::srs::WordOpenMode; use crate::data::Id; use crate::data::entities::HistoryItem; use crate::fs::*; use crate::notification::NotificationData::PermissionDenied; use crate::notification::{MaybeError, NotificationData}; use chrono::DateTime; use std::fs::{File, OpenOptions}; use std::io::Write; use std::io::{BufRead, BufReader}; use std::path::PathBuf; pub fn get_history_of_set(id: Id) -> Result, NotificationData> { let app_dir = history_dir()?; let head = app_dir.clone().join(format!("set_{}_history.csv", id)); let mut lines = Vec::new(); append_lines_if_exists(head, &mut lines)?; lines.reverse(); Ok(parse_history_items(lines)) } fn append_lines_if_exists(path: PathBuf, lines: &mut Vec) -> MaybeError { if path.exists() { let reader = BufReader::new(File::open(path).map_err(|_| PermissionDenied)?); reader .lines() .map_while(Result::ok) .for_each(|i| lines.push(i)); } Ok(()) } fn parse_history_items(strings: Vec) -> Vec { let mut items = Vec::with_capacity(strings.len()); for string in strings { if let [time, word, mode, before, after] = string.split(';').collect::>()[..] { let id = word.parse::(); if id.is_err() { continue; } let id = id.unwrap_or_default(); if !id.is_valid() { continue; } items.push(HistoryItem { timestamp: DateTime::from_timestamp(time.parse().unwrap_or_default(), 0) .unwrap_or_default(), word_id: id, mode: match mode.parse::().unwrap_or_default() { 2 => WordOpenMode::Hard, 3 => WordOpenMode::Ok, 4 => WordOpenMode::Easy, _ => WordOpenMode::None, }, before: before.parse().unwrap_or_default(), after: after.parse().unwrap_or_default(), }); } } items } pub fn push_note(set_id: Id, item: HistoryItem) -> MaybeError { let app_dir = history_dir()?; let path = app_dir.clone().join(format!("set_{}_history.csv", set_id)); let mut file = OpenOptions::new() .create(true) .append(true) .open(path) .map_err(|_| PermissionDenied)?; let line_str = format!( "{};{};{};{};{}", item.timestamp.timestamp(), item.word_id, match item.mode { WordOpenMode::Easy => 4, WordOpenMode::Ok => 3, WordOpenMode::Hard => 2, WordOpenMode::None => 1, }, item.before, item.after ); writeln!(&mut file, "{}", line_str).map_err(|_| PermissionDenied)?; Ok(()) }