Files
jap_learn/src/data_provider/history.rs
T

93 lines
2.8 KiB
Rust
Raw Normal View History

2026-08-24 01:22:00 +03:00
use crate::fs::*;
2026-08-18 12:47:06 +03:00
use crate::lang::{Id, WordOpenMode};
2026-07-29 12:57:46 +03:00
use chrono::{DateTime, Utc};
use std::fs::{File, OpenOptions};
use std::io::Write;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
2026-08-24 01:22:00 +03:00
use crate::notification::NotificationData;
use crate::notification::NotificationData::PermissionDenied;
2026-07-29 12:57:46 +03:00
2026-08-24 01:22:00 +03:00
pub fn get_history_of_set(id: Id) -> Result<Vec<HistoryItem>, NotificationData> {
let app_dir = history_dir()?;
2026-07-29 12:57:46 +03:00
let head = app_dir.clone().join(format!("set_{}_history.csv", id));
let mut lines = Vec::new();
append_lines_if_exists(head, &mut lines);
2026-08-01 23:40:56 +03:00
lines.reverse();
2026-08-24 01:22:00 +03:00
Ok(parse_history_items(lines))
2026-07-29 12:57:46 +03:00
}
fn append_lines_if_exists(path: PathBuf, lines: &mut Vec<String>) {
if path.exists() {
let reader = BufReader::new(File::open(path).unwrap());
for line in reader.lines() {
lines.push(line.unwrap());
}
}
}
fn parse_history_items(strings: Vec<String>) -> Vec<HistoryItem> {
let mut items = Vec::with_capacity(strings.len());
for string in strings {
if let [time, word, mode, before, after] = string.split(';').collect::<Vec<&str>>()[..] {
2026-08-19 23:37:59 +03:00
let id = word.parse::<Id>();
2026-08-19 23:51:41 +03:00
if id.is_err() {
2026-08-19 23:37:59 +03:00
continue;
}
let id = id.unwrap();
if !id.is_valid() {
continue;
}
2026-07-29 12:57:46 +03:00
items.push(HistoryItem {
2026-08-20 17:48:03 +03:00
timestamp: DateTime::from_timestamp(time.parse().unwrap_or_default(), 0).unwrap_or_default(),
2026-08-19 23:37:59 +03:00
word_id: id,
mode: match mode.parse::<u8>().unwrap_or_default() {
2026-07-29 12:57:46 +03:00
2 => WordOpenMode::Hard,
3 => WordOpenMode::Ok,
4 => WordOpenMode::Easy,
_ => WordOpenMode::None,
},
2026-08-19 23:37:59 +03:00
before: before.parse().unwrap_or_default(),
after: after.parse().unwrap_or_default(),
2026-07-29 12:57:46 +03:00
});
}
}
items
}
2026-08-24 01:22:00 +03:00
pub fn push_note(set_id: Id, item: HistoryItem) -> Result<(), NotificationData> {
let app_dir = history_dir()?;
2026-07-29 12:57:46 +03:00
let path = app_dir.clone().join(format!("set_{}_history.csv", set_id));
2026-08-01 19:43:07 +03:00
let mut file = OpenOptions::new()
.create(true)
.append(true)
.open(path)
2026-08-24 01:22:00 +03:00
.map_err(|_| PermissionDenied)?;
2026-08-01 19:43:07 +03:00
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
);
2026-08-24 01:22:00 +03:00
writeln!(&mut file, "{}", line_str).map_err(|_| PermissionDenied)?;
Ok(())
2026-08-04 16:53:09 +03:00
}
2026-07-29 12:57:46 +03:00
#[derive(Clone)]
pub struct HistoryItem {
pub timestamp: DateTime<Utc>,
2026-08-18 12:47:06 +03:00
pub word_id: Id,
2026-07-29 12:57:46 +03:00
pub mode: WordOpenMode,
pub before: u8,
pub after: u8,
}