libtbr/src/recipe_functions/common.rs
2025-09-10 14:03:36 +07:00

231 lines
7 KiB
Rust

use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator};
use serde_json::Value;
use crate::models::{self, recipe::Recipe01};
use std::collections::HashMap;
use std::{fs::File, io::Read};
pub trait EnumAsValue<T> {
fn name(&self) -> String;
fn value(&self) -> T;
fn get(val: T) -> Self;
}
// Change path here!
fn extract_tb_config(content: String) -> HashMap<String, String> {
let mut result = HashMap::new();
let lines = content.lines();
for line in lines {
let parts: Vec<&str> = line.split('=').collect();
if parts.len() == 2 {
result.insert(parts[0].trim().to_string(), parts[1].trim().to_string());
}
}
result
}
/// Get config from `.tbcfg` file in current directory
pub fn get_config() -> HashMap<String, String> {
// need `.tbcfg`
let cfg_result = std::fs::read_to_string("./.tbcfg");
match cfg_result {
Ok(cfg) => extract_tb_config(cfg),
Err(e) => panic!("Failed to read .tbcfg: {}", e),
}
}
pub fn create_recipe_model_from_file(path: String) -> models::recipe::Recipe {
println!("create_recipe_model_from_file: {}", path);
let mut file = File::open(path).unwrap();
println!("check file: {}", file.metadata().unwrap().is_file());
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
models::recipe::Recipe::init(data)
}
pub fn create_recipe_path(country_path: &str, version: usize) -> String {
let mut path = String::from(get_config().get("RECIPE_DIR").unwrap());
path.push_str(country_path);
path.push_str("/coffeethai02_");
// version
path.push_str(&version.to_string());
if country_path != "tha" {
path.push('_');
path.push_str(country_path);
}
path.push_str(".json");
path
}
pub fn get_all_files_in_directory(directory_path: &str) -> Vec<String> {
let mut files = Vec::new();
let dir = std::fs::read_dir(directory_path).unwrap();
for entry in dir {
let entry = entry.unwrap();
let path = entry.path();
if path.is_file() {
let npath = path.as_os_str().to_str().unwrap().to_string();
println!("pushed {}", npath);
files.push(npath);
}
}
files
}
pub fn filter_files_by_pattern(files: Vec<String>, pattern: &str) -> Vec<String> {
files
.into_iter()
.filter(|file| file.contains(pattern))
.collect()
}
pub fn get_pd_prefix(country: &str) -> String {
match country {
"mys" => "12".to_string(),
"sgp" => "52".to_string(),
"aus" => "51".to_string(),
"tha" => "12".to_string(),
"hkg" => "54".to_string(),
"dubai" => "53".to_string(),
"uae" => "53".to_string(),
_ => "12".to_string(),
}
}
pub fn get_mat_prefix(country: &str) -> String {
match country {
"sgp" => "52".to_string(),
"aus" => "51".to_string(),
"hkg" => "54".to_string(),
"dubai" => "53".to_string(),
"uae" => "53".to_string(),
_ => "".to_string(),
}
}
pub fn check_allowed_change_mat_prefix(mat_id: Value) -> bool {
let mat_id_i = mat_id.as_i64().unwrap();
let exception_list = [
2101, 1031, 1, 9100, 8101, 8102, 8111, 8112, 8113, 8114, 8115, 8116, 8117, 8118, 8119,
8120, 8001, 8002, 8888, 8889, 200000, 201001, 201002, 100004, 0,
];
!exception_list.contains(&mat_id_i)
}
pub fn change_prefix_by_country(
country: &str,
mut recipes: Vec<Option<Recipe01>>,
) -> Vec<Recipe01> {
let mut result = Vec::new();
// get prefix first
let prefix = get_pd_prefix(country);
let mat_prefix = get_mat_prefix(country);
// run
let updated = recipes
.par_iter_mut()
.update(|x| {
if let Some(x) = x {
// change productCode
let mut new_product_code = x.productCode.clone();
new_product_code =
format!("{}-{}", prefix, new_product_code.split_once('-').unwrap().1);
x.productCode = new_product_code;
// run through recipes
let mut new_recipes_format = Vec::new();
for ele in x.clone().recipes {
let mut eled = ele.clone();
if check_allowed_change_mat_prefix(eled.clone().materialPathId) {
let new_f = format!("{}{}", mat_prefix, eled.clone().materialPathId);
eled.materialPathId = Value::Number(new_f.parse::<i64>().unwrap().into());
}
new_recipes_format.push(eled);
}
x.recipes = new_recipes_format;
if let Some(s) = x.clone().SubMenu {
//
let cls = s.clone();
for mut sl in cls.clone() {
let mut new_sl_pd = sl.productCode.clone();
new_sl_pd = format!("{}-{}", prefix, new_sl_pd.split_once('-').unwrap().1);
sl.productCode = new_sl_pd;
let mut new_recipes_sub = Vec::new();
for ele in sl.recipes {
let mut eled = ele.clone();
if check_allowed_change_mat_prefix(eled.clone().materialPathId) {
let new_f =
format!("{}{}", mat_prefix, eled.clone().materialPathId);
eled.materialPathId =
Value::Number(new_f.parse::<i64>().unwrap().into());
}
new_recipes_sub.push(eled);
}
sl.recipes = new_recipes_sub;
}
x.SubMenu = Some(cls.clone());
}
}
})
.filter(|x| x.is_some())
.map(|x| x.clone().unwrap())
.collect_vec_list();
// check by update
for x in updated.iter() {
result.extend_from_slice(x);
}
result
}
pub fn valid_country_name() -> Vec<&'static str> {
vec!["mys", "sgp", "aus", "tha", "hkg", "dubai", "uae"]
}
pub fn grep_latest_versions(dir_path: &str) -> Result<HashMap<String, usize>, std::io::Error> {
let mut vs = HashMap::new();
// open dir
let entries = std::fs::read_dir(dir_path)?
.map(|res| res.map(|e| e.path()))
.collect::<Result<Vec<_>, std::io::Error>>()?;
for e in entries {
let path = e.clone().to_str().unwrap().to_string();
let mut cl_path = path.clone();
let path_split = path.split("/").collect::<Vec<&str>>();
let dir_name = path_split[path_split.len() - 1];
if valid_country_name().contains(&dir_name) {
cl_path.push_str("/version");
// read filename
let mut file = File::open(cl_path)?;
let mut data = String::new();
file.read_to_string(&mut data).unwrap();
vs.insert(dir_name.to_string(), data.parse::<usize>().unwrap());
}
// expect dir with country
}
Ok(vs)
}