add recipe product code also search sub menu, add recipe sharding.
This commit is contained in:
parent
2761cf1676
commit
08bb0899a3
3 changed files with 279 additions and 39 deletions
|
|
@ -106,16 +106,38 @@ impl Recipe {
|
||||||
///
|
///
|
||||||
/// an `Option` type, specifically `Option<&Recipe01>`.
|
/// an `Option` type, specifically `Option<&Recipe01>`.
|
||||||
pub fn search_pd(&self, product_code: String) -> Option<&Recipe01> {
|
pub fn search_pd(&self, product_code: String) -> Option<&Recipe01> {
|
||||||
self.Recipe01
|
self.Recipe01.iter().find(|&r| {
|
||||||
.iter()
|
if r.SubMenu.is_none() {
|
||||||
.find(|&r| r.productCode == product_code)
|
r.productCode == product_code
|
||||||
|
} else {
|
||||||
|
r.SubMenu
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x| x.productCode == product_code)
|
||||||
|
.count()
|
||||||
|
> 0
|
||||||
|
|| r.productCode == product_code
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Similar to `search_pd` but ignoring exacted matching.
|
/// Similar to `search_pd` but ignoring exacted matching.
|
||||||
pub fn search_pd_by_no_country_code(&self, product_code: String) -> Option<&Recipe01> {
|
pub fn search_pd_by_no_country_code(&self, product_code: String) -> Option<&Recipe01> {
|
||||||
self.Recipe01
|
self.Recipe01.iter().find(|&r| {
|
||||||
.iter()
|
if r.SubMenu.is_none() {
|
||||||
.find(|&r| r.productCode.contains(&product_code))
|
r.productCode.contains(&product_code)
|
||||||
|
} else {
|
||||||
|
r.SubMenu
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x| x.productCode.contains(&product_code))
|
||||||
|
.count()
|
||||||
|
> 0
|
||||||
|
|| r.productCode.contains(&product_code)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mulitple product code searching with parallel and no exact matching.
|
/// Mulitple product code searching with parallel and no exact matching.
|
||||||
|
|
@ -126,7 +148,20 @@ impl Recipe {
|
||||||
.map(|pd| {
|
.map(|pd| {
|
||||||
self.Recipe01
|
self.Recipe01
|
||||||
.par_iter()
|
.par_iter()
|
||||||
.find_any(|x| x.productCode.contains(pd))
|
.find_any(|x| {
|
||||||
|
if x.SubMenu.is_none() {
|
||||||
|
x.productCode.contains(pd)
|
||||||
|
} else {
|
||||||
|
x.SubMenu
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x2| x2.productCode.contains(pd))
|
||||||
|
.count()
|
||||||
|
> 0
|
||||||
|
|| x.productCode.contains(pd)
|
||||||
|
}
|
||||||
|
})
|
||||||
.cloned()
|
.cloned()
|
||||||
})
|
})
|
||||||
.collect_into_vec(&mut found);
|
.collect_into_vec(&mut found);
|
||||||
|
|
@ -138,7 +173,20 @@ impl Recipe {
|
||||||
pub fn get_pd_index(&self, product_code: String) -> usize {
|
pub fn get_pd_index(&self, product_code: String) -> usize {
|
||||||
self.Recipe01
|
self.Recipe01
|
||||||
.iter()
|
.iter()
|
||||||
.position(|r| r.productCode == product_code)
|
.position(|r| {
|
||||||
|
if r.SubMenu.is_none() {
|
||||||
|
r.productCode == product_code
|
||||||
|
} else {
|
||||||
|
r.SubMenu
|
||||||
|
.clone()
|
||||||
|
.unwrap()
|
||||||
|
.iter()
|
||||||
|
.filter(|x2| x2.productCode == product_code)
|
||||||
|
.count()
|
||||||
|
> 0
|
||||||
|
|| r.productCode == product_code
|
||||||
|
}
|
||||||
|
})
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1508,6 +1556,10 @@ impl RecipeList {
|
||||||
|
|
||||||
diff_list
|
diff_list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_map(&self) -> serde_json::Value {
|
||||||
|
serde_json::to_value(self).unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The above code defines a Rust struct called MaterialSetting with various fields representing
|
/// The above code defines a Rust struct called MaterialSetting with various fields representing
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
|
use rayon::iter::{IntoParallelIterator, IntoParallelRefIterator, ParallelIterator};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::models::recipe::*;
|
use crate::models::recipe::*;
|
||||||
use crate::recipe_functions::common::*;
|
use crate::recipe_functions::common::{self, *};
|
||||||
|
|
||||||
/// Version 2 of `models::Recipe`, WIP
|
/// Version 2 of `models::Recipe`, WIP
|
||||||
///
|
///
|
||||||
|
|
@ -16,39 +19,39 @@ pub struct VersionRecipe {
|
||||||
|
|
||||||
impl VersionRecipe {
|
impl VersionRecipe {
|
||||||
// import - read all file with given format from directory and mixing them together as 1 recipe
|
// import - read all file with given format from directory and mixing them together as 1 recipe
|
||||||
pub fn create_versioning_by_country(country: &str) -> Self {
|
// pub fn create_versioning_by_country(country: &str) -> Self {
|
||||||
let mut path = String::from(get_config().get("RECIPE_DIR").unwrap());
|
// let mut path = String::from(get_config().get("RECIPE_DIR").unwrap());
|
||||||
path.push_str(country);
|
// path.push_str(country);
|
||||||
path.push('/');
|
// path.push('/');
|
||||||
|
|
||||||
// read dir
|
// // read dir
|
||||||
let files = read_all_files_in_directory(&path.clone());
|
// let files = read_all_files_in_directory(&path.clone());
|
||||||
let expected_file_format = "coffeethai02";
|
// let expected_file_format = "coffeethai02";
|
||||||
let filtered = filter_files_by_pattern(files, expected_file_format);
|
// let filtered = filter_files_by_pattern(files, expected_file_format);
|
||||||
|
|
||||||
// create recipes vector
|
// // create recipes vector
|
||||||
let mut recipes = Vec::new();
|
// let mut recipes = Vec::new();
|
||||||
let mut known_versions = Vec::new();
|
// let mut known_versions = Vec::new();
|
||||||
for file in filtered {
|
// for file in filtered {
|
||||||
// try create model
|
// // try create model
|
||||||
let mut source_path = path.clone();
|
// let mut source_path = path.clone();
|
||||||
source_path.push_str(&file);
|
// source_path.push_str(&file);
|
||||||
let current_recipe_path = create_recipe_model_from_file(source_path);
|
// let current_recipe_path = create_recipe_model_from_file(source_path);
|
||||||
known_versions.push(current_recipe_path.clone().MachineSetting.configNumber);
|
// known_versions.push(current_recipe_path.clone().MachineSetting.configNumber);
|
||||||
recipes.push(current_recipe_path.clone());
|
// recipes.push(current_recipe_path.clone());
|
||||||
}
|
// }
|
||||||
|
|
||||||
// find current
|
// // find current
|
||||||
//
|
// //
|
||||||
let versions = grep_latest_versions(&path.clone()).unwrap();
|
// let versions = grep_latest_versions(&path.clone()).unwrap();
|
||||||
let expected_version = versions.get(country).unwrap_or(&0);
|
// let expected_version = versions.get(country).unwrap_or(&0);
|
||||||
|
|
||||||
VersionRecipe {
|
// VersionRecipe {
|
||||||
currentVersion: serde_json::json!(format!("{}", expected_version)),
|
// currentVersion: serde_json::json!(format!("{}", expected_version)),
|
||||||
knownVersions: known_versions,
|
// knownVersions: known_versions,
|
||||||
recipesByCategory: break_down_recipe_into_category(recipes),
|
// recipesByCategory: break_down_recipe_into_category(recipes),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
// export
|
// export
|
||||||
// export_full
|
// export_full
|
||||||
// export_full_with_history
|
// export_full_with_history
|
||||||
|
|
@ -91,3 +94,188 @@ pub struct MenuToppingListWithHistory {
|
||||||
pub menuToppingList: MenuToppingList,
|
pub menuToppingList: MenuToppingList,
|
||||||
pub history: Vec<HashMap<String, Value>>,
|
pub history: Vec<HashMap<String, Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
pub struct RecipeListChange {
|
||||||
|
pub new_value: Value,
|
||||||
|
pub raw_old: Vec<crate::models::recipe::RecipeList>,
|
||||||
|
pub raw_new: Vec<crate::models::recipe::RecipeList>,
|
||||||
|
/// for sub menu
|
||||||
|
pub sub_changes: HashMap<String, Value>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RecipeListChange {
|
||||||
|
pub fn get_changes(&mut self) {
|
||||||
|
let old_length = self.raw_old.len();
|
||||||
|
let new_length = self.raw_new.len();
|
||||||
|
|
||||||
|
let is_match_length = old_length == new_length;
|
||||||
|
let length_for_checking = if is_match_length {
|
||||||
|
old_length
|
||||||
|
} else {
|
||||||
|
if old_length < new_length {
|
||||||
|
new_length
|
||||||
|
} else {
|
||||||
|
old_length
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut checked = Vec::with_capacity(length_for_checking);
|
||||||
|
|
||||||
|
for ci in 0..length_for_checking {
|
||||||
|
let current_repl = (self.raw_old.get(ci), self.raw_new.get(ci));
|
||||||
|
if current_repl.0.is_some() && current_repl.1.is_some() {
|
||||||
|
let old_repl = current_repl.0.unwrap();
|
||||||
|
let new_repl = current_repl.1.unwrap();
|
||||||
|
|
||||||
|
let diff = old_repl.compare(new_repl);
|
||||||
|
*checked.get_mut(ci).unwrap() = diff;
|
||||||
|
} else if current_repl.0.is_none() && current_repl.1.is_some() {
|
||||||
|
// new value
|
||||||
|
*checked.get_mut(ci).unwrap() = current_repl
|
||||||
|
.1
|
||||||
|
.unwrap()
|
||||||
|
.to_map()
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.keys()
|
||||||
|
.map(|k| k.to_string())
|
||||||
|
.collect();
|
||||||
|
} else if current_repl.0.is_some() && current_repl.1.is_none() {
|
||||||
|
// new value does not exist
|
||||||
|
*checked.get_mut(ci).unwrap() = current_repl
|
||||||
|
.0
|
||||||
|
.unwrap()
|
||||||
|
.to_map()
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.keys()
|
||||||
|
.map(|k| format!("old.{}", k).to_string())
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.new_value = serde_json::to_value(checked).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// break down recipe(s) in the folder into mapping,
|
||||||
|
/// tracking diff between fields. (This does not compare other fields than Recipe01)
|
||||||
|
pub fn build_recipe_shardings(source: PathBuf) -> HashMap<String, Value> {
|
||||||
|
let files = common::get_all_files_in_directory(source.as_path().to_str().unwrap());
|
||||||
|
|
||||||
|
let mut recipes: Vec<Recipe> = files
|
||||||
|
.par_iter()
|
||||||
|
.map(|file| common::create_recipe_model_from_file(file.to_string()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// ascending order a.compare(b)
|
||||||
|
recipes.sort_by(|a, b| {
|
||||||
|
let version_a = a.MachineSetting.get_config_number().as_i64().unwrap();
|
||||||
|
let version_b = b.MachineSetting.get_config_number().as_i64().unwrap();
|
||||||
|
|
||||||
|
version_a.cmp(&version_b)
|
||||||
|
});
|
||||||
|
|
||||||
|
// Structure
|
||||||
|
// { productCode: { version: [ Option<RecipeChange> ] } }
|
||||||
|
let mut shards = HashMap::new();
|
||||||
|
|
||||||
|
let base_version: i64 = recipes
|
||||||
|
.get(0)
|
||||||
|
.unwrap()
|
||||||
|
.MachineSetting
|
||||||
|
.get_config_number()
|
||||||
|
.as_i64()
|
||||||
|
.unwrap();
|
||||||
|
let base_recipe = recipes.get(0).unwrap();
|
||||||
|
|
||||||
|
shards = base_recipe
|
||||||
|
.Recipe01
|
||||||
|
.par_iter()
|
||||||
|
.map(|rp1| {
|
||||||
|
let mut sub_changes = HashMap::new();
|
||||||
|
|
||||||
|
if rp1.clone().SubMenu.is_some() {
|
||||||
|
let subs = rp1.clone().SubMenu.unwrap().clone();
|
||||||
|
|
||||||
|
sub_changes = subs
|
||||||
|
.par_iter()
|
||||||
|
.map(|sub1| {
|
||||||
|
let change_sub = RecipeListChange {
|
||||||
|
new_value: Value::Null,
|
||||||
|
raw_new: sub1.recipes.clone(),
|
||||||
|
raw_old: sub1.recipes.clone(),
|
||||||
|
sub_changes: HashMap::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut change_sub_map = HashMap::new();
|
||||||
|
change_sub_map.insert(base_version, change_sub.clone());
|
||||||
|
recipes.iter().for_each(|rc| {
|
||||||
|
// clone change
|
||||||
|
let mut change_sub_clone = change_sub.clone();
|
||||||
|
|
||||||
|
match rc.search_pd_by_no_country_code(sub1.clone().productCode) {
|
||||||
|
Some(spd) => {
|
||||||
|
change_sub_clone.raw_new = spd.clone().recipes;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
};
|
||||||
|
change_sub_clone.get_changes();
|
||||||
|
change_sub_map.insert(
|
||||||
|
rc.MachineSetting
|
||||||
|
.get_config_number()
|
||||||
|
.as_i64()
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
change_sub_clone.clone(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
sub1.clone().productCode,
|
||||||
|
serde_json::to_value(change_sub_map).unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|
||||||
|
let change = RecipeListChange {
|
||||||
|
new_value: Value::Null,
|
||||||
|
raw_old: rp1.recipes.clone(),
|
||||||
|
raw_new: rp1.recipes.clone(),
|
||||||
|
sub_changes,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut change_map = HashMap::new();
|
||||||
|
change_map.insert(base_version, change.clone());
|
||||||
|
recipes.iter().for_each(|rc| {
|
||||||
|
// clone change
|
||||||
|
let mut change_clone = change.clone();
|
||||||
|
|
||||||
|
match rc.search_pd_by_no_country_code(rp1.clone().productCode) {
|
||||||
|
Some(pdr) => {
|
||||||
|
change_clone.raw_new = pdr.clone().recipes;
|
||||||
|
}
|
||||||
|
None => {}
|
||||||
|
}
|
||||||
|
change_clone.get_changes();
|
||||||
|
change_map.insert(
|
||||||
|
rc.MachineSetting
|
||||||
|
.get_config_number()
|
||||||
|
.as_i64()
|
||||||
|
.unwrap()
|
||||||
|
.clone(),
|
||||||
|
change_clone,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
(
|
||||||
|
rp1.clone().productCode,
|
||||||
|
serde_json::to_value(change_map).unwrap(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
shards
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ pub fn create_recipe_path(country_path: &str, version: usize) -> String {
|
||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_all_files_in_directory(directory_path: &str) -> Vec<String> {
|
pub fn get_all_files_in_directory(directory_path: &str) -> Vec<String> {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
let dir = std::fs::read_dir(directory_path).unwrap();
|
let dir = std::fs::read_dir(directory_path).unwrap();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue