radar-g/src/pipeline/dispatcher.rs
2024-03-07 18:08:16 +08:00

236 lines
7.4 KiB
Rust

use super::element::TargetType;
use super::offscreen_renderer::{CanvasWrapper, OffscreenRenderer};
use crate::{
components::app::{Buffer, FILE_PATH_ROOT},
CONFIG,
};
use chrono::{prelude::*, Duration};
use once_cell::sync::Lazy;
use regex::Regex;
use std::{cell::Ref, collections::HashMap, path::PathBuf};
use tracing::*;
static REREMAP: Lazy<HashMap<&str, &str>> = Lazy::new(|| {
let mut map = HashMap::new();
map.insert("%Y", r"\d{4}");
map.insert("%m", r"\d{2}");
map.insert("%d", r"\d{2}");
map.insert("%H", r"\d{2}");
map.insert("%M", r"\d{2}");
map.insert("%S", r"\d{2}");
map.insert("{prefix}", r"(.+?)");
map
});
#[derive(Debug)]
pub struct Dispatcher {
datetime: DateTime<Utc>,
fore_len: usize,
back_len: usize,
step: Duration,
}
impl Dispatcher {
pub fn new(fore_len: usize, back_len: usize, step: Duration) -> Self {
Self {
datetime: Utc::now(),
fore_len,
back_len,
step,
}
}
pub fn set_current_time(&mut self, datetime: DateTime<Utc>) {
self.datetime = datetime;
}
pub fn set_step(&mut self, step: Duration) {
self.step = step;
}
pub fn set_fore_len(&mut self, fore_len: usize) {
self.fore_len = fore_len;
}
pub fn set_back_len(&mut self, back_len: usize) {
self.back_len = back_len;
}
pub fn get_single_path(
&self,
name: &str,
current_time: DateTime<Utc>,
check_existed: bool,
) -> Option<String> {
let datetime_format: regex::Regex =
Regex::new(r"(?:%[YHMSmd](?:[-/:_]?%[YHMSmd])*)").unwrap();
let config = CONFIG.lock().unwrap();
let path_format = config
.plugins
.get("etws_loader")
.unwrap()
.path_formats
.as_ref();
if path_format.is_none() {
return None;
}
let c = path_format.unwrap().get(name).map(|s| {
let path = s.clone();
let need_formated = datetime_format.captures_iter(&path).collect::<Vec<_>>();
let mut result_path = path.clone();
for need_format in need_formated.iter() {
let fmt = need_format.get(0).unwrap().as_str();
let t = current_time.format(fmt).to_string();
result_path = result_path.replace(fmt, &t);
}
result_path
});
if let Some(c) = c {
if check_existed {
if std::path::Path::new(&c).exists() {
Some(c)
} else {
None
}
} else {
Some(c)
}
} else {
None
}
}
pub fn get_path(
&self,
name: &str,
current_time: DateTime<Utc>,
check_existed: bool,
mut max_retry_time: usize,
) -> Option<Vec<(String, DateTime<Utc>)>> {
let datetime_format: regex::Regex = Regex::new(r"%[YHMSmd](?:[-/:_]?%[YHMSmd])*").unwrap();
let config = CONFIG.lock().unwrap();
let path_format = config
.plugins
.get("etws_loader")
.unwrap()
.path_formats
.as_ref();
if path_format.is_none() {
return None;
}
path_format.unwrap().get(name).map(|s| {
let path = s.clone();
let file_path = { FILE_PATH_ROOT.lock().unwrap().clone() };
let path = if path.starts_with("./") {
let file_root = file_root(&file_path, path.replace("./", ""));
file_root.map(|root| {
let splited = path.split_at(2);
root.join(PathBuf::from(splited.1))
})
} else {
Some(PathBuf::from(path))
};
let mut result_paths = Vec::new();
if let Some(path_uninit) = path {
let mut path_str = path_uninit.to_string_lossy().to_string();
let prefixs = get_prefix(&file_path, &path_str);
for (idx, prefix) in prefixs.iter().enumerate() {
if let Some(s) = prefix.as_ref() {
path_str = path_str.replacen("{prefix}", &s, 1);
}
}
let need_formated = datetime_format.captures_iter(&path_str).collect::<Vec<_>>();
let mut fore = self.fore_len;
let mut back = 1;
while fore > 0 {
let mut result_path = path_str.clone();
let t = current_time - self.step * fore as i32;
for need_format in need_formated.iter() {
let fmt = need_format.get(0).unwrap().as_str();
let t = t.format(fmt).to_string();
result_path = result_path.replace(fmt, &t);
}
if check_existed {
// if max_retry_time == 0 {
// break;
// }
if !std::path::Path::new(&result_path).exists() {
} else {
result_paths.push((result_path.clone(), t));
}
} else {
result_paths.push((result_path.clone(), t));
}
fore = fore - 1;
}
while back < self.back_len + 1 {
let mut result_path = path_str.clone();
let t = current_time + self.step * back as i32;
for need_format in need_formated.iter() {
let fmt = need_format.get(0).unwrap().as_str();
let t = t.format(fmt).to_string();
result_path = result_path.replace(fmt, &t);
}
if check_existed {
// if max_retry_time == 0 {
// break;
// }
if !std::path::Path::new(&result_path).exists() {
} else {
result_paths.push((result_path.clone(), t));
}
} else {
result_paths.push((result_path.clone(), t));
}
back = back + 1;
}
}
result_paths
})
}
}
fn file_root(path: &PathBuf, pat: String) -> Option<PathBuf> {
let new_pat = rereplace(&pat);
let path_str = path.to_string_lossy();
let re = Regex::new(&new_pat).unwrap();
let splited = re.split(&path_str);
let splited = splited.collect::<Vec<_>>();
if splited.len() == 2 {
let root = splited.first().unwrap();
Some(PathBuf::from(root))
} else {
None
}
}
fn rereplace(pat: &str) -> String {
let mut result = pat.to_string();
for (k, v) in REREMAP.iter() {
result = result.replace(k, v);
}
result
}
fn get_prefix(path: &PathBuf, pat: &str) -> Vec<Option<String>> {
let replaced = rereplace(pat);
let path_str = path.to_string_lossy();
let re = Regex::new(&replaced).unwrap();
let prefixs = re.captures(&path_str).unwrap();
let mut prefixs = prefixs.iter().collect::<Vec<_>>();
prefixs.remove(0);
prefixs
.into_iter()
.map(|x| x.map(|v| v.as_str().to_string()))
.collect()
}