v0.1 init
This commit is contained in:
commit
8068810af6
18 changed files with 3859 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
402
Cargo.lock
generated
Normal file
402
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766"
|
||||
dependencies = [
|
||||
"shlex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libtbr"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"log",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shlex"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.101"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46ec44dc15085cea82cf9c78f85a9114c463a369786585ad2882d1ff0b0acf40"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a7ab927b2637c19b3dbe0965e75d8f2d30bdd697a1516191cad2ec4df8fb28a"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
[package]
|
||||
name = "libtbr"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4.41"
|
||||
log = "0.4.27"
|
||||
rayon = "1.10.0"
|
||||
serde = { version = "1.0.219", features = ["derive", "serde_derive"] }
|
||||
serde_json = "1.0.140"
|
||||
BIN
src/.DS_Store
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
Binary file not shown.
3
src/lib.rs
Normal file
3
src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pub mod models;
|
||||
pub mod previews;
|
||||
pub mod recipe_functions;
|
||||
2
src/models/mod.rs
Normal file
2
src/models/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod recipe;
|
||||
pub mod recipev2;
|
||||
1897
src/models/recipe.rs
Normal file
1897
src/models/recipe.rs
Normal file
File diff suppressed because it is too large
Load diff
93
src/models/recipev2.rs
Normal file
93
src/models/recipev2.rs
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::models::recipe::*;
|
||||
use crate::recipe_functions::common::*;
|
||||
|
||||
/// Version 2 of `models::Recipe`
|
||||
///
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct VersionRecipe {
|
||||
pub currentVersion: Value,
|
||||
pub knownVersions: Vec<Value>,
|
||||
pub recipesByCategory: HashMap<String, Vec<RecipeV2>>,
|
||||
}
|
||||
|
||||
impl VersionRecipe {
|
||||
// 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 {
|
||||
let mut path = String::from(RECIPES_DIR);
|
||||
path.push_str(country);
|
||||
path.push('/');
|
||||
|
||||
// read dir
|
||||
let files = read_all_files_in_directory(&path.clone());
|
||||
let expected_file_format = "coffeethai02";
|
||||
let filtered = filter_files_by_pattern(files, expected_file_format);
|
||||
|
||||
// create recipes vector
|
||||
let mut recipes = Vec::new();
|
||||
let mut known_versions = Vec::new();
|
||||
for file in filtered {
|
||||
// try create model
|
||||
let mut source_path = path.clone();
|
||||
source_path.push_str(&file);
|
||||
let current_recipe_path = create_recipe_model_from_file(source_path);
|
||||
known_versions.push(current_recipe_path.clone().MachineSetting.configNumber);
|
||||
recipes.push(current_recipe_path.clone());
|
||||
}
|
||||
|
||||
// find current
|
||||
//
|
||||
let versions = grep_latest_versions(&path.clone()).unwrap();
|
||||
let expected_version = versions.get(country).unwrap_or(&0);
|
||||
|
||||
VersionRecipe {
|
||||
currentVersion: serde_json::json!(format!("{}", expected_version)),
|
||||
knownVersions: known_versions,
|
||||
recipesByCategory: break_down_recipe_into_category(recipes),
|
||||
}
|
||||
}
|
||||
// export
|
||||
// export_full
|
||||
// export_full_with_history
|
||||
}
|
||||
|
||||
pub fn break_down_recipe_into_category(recipes: Vec<Recipe>) -> HashMap<String, Vec<RecipeV2>> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
// Steps
|
||||
// 1.
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Based on `models::Recipe`, this excluded some fields
|
||||
/// for more efficient serialization and deserialization.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct RecipeV2 {
|
||||
pub Description: Option<String>,
|
||||
pub LastChange: Option<Value>,
|
||||
pub id: Value,
|
||||
pub isUse: bool,
|
||||
pub name: Option<String>,
|
||||
pub otherName: Option<String>,
|
||||
pub productCode: String,
|
||||
pub recipes: Vec<RecipeListWithHistory>,
|
||||
pub ToppingSet: Option<Vec<MenuToppingListWithHistory>>,
|
||||
pub total_time: Value,
|
||||
pub changeLog: Vec<HashMap<String, Value>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct RecipeListWithHistory {
|
||||
pub recipeList: RecipeList,
|
||||
pub history: Vec<HashMap<String, Value>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct MenuToppingListWithHistory {
|
||||
pub menuToppingList: MenuToppingList,
|
||||
pub history: Vec<HashMap<String, Value>>,
|
||||
}
|
||||
97
src/previews/csvf.rs
Normal file
97
src/previews/csvf.rs
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
// format function
|
||||
//
|
||||
// target csv
|
||||
|
||||
use log::warn;
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub enum AutoFixSizeStrategy {
|
||||
#[default]
|
||||
Strict,
|
||||
FillHeaderToMatchRow {
|
||||
default_value: String,
|
||||
},
|
||||
FillRowToMatchHeader {
|
||||
default_value: String,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct TableConfig {
|
||||
pub allow_row_length_exceeds_header: bool,
|
||||
pub auto_fix_size: bool,
|
||||
pub auto_fix_size_strategy: AutoFixSizeStrategy,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Table {
|
||||
pub header: Vec<String>,
|
||||
pub rows: Vec<Vec<String>>,
|
||||
pub config: TableConfig,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
pub fn new() -> Table {
|
||||
Table::default()
|
||||
}
|
||||
|
||||
pub fn set_config(&mut self, config: TableConfig) {
|
||||
self.config = config;
|
||||
}
|
||||
|
||||
pub fn add_header(&mut self, header: &str) {
|
||||
self.header.push(header.to_string());
|
||||
}
|
||||
|
||||
pub fn set_header(&mut self, header: Vec<&str>) {
|
||||
self.header = header
|
||||
.iter()
|
||||
.map(|x| x.to_string())
|
||||
.collect::<Vec<String>>();
|
||||
}
|
||||
|
||||
pub fn get_current_header(self) -> Vec<String> {
|
||||
self.header
|
||||
}
|
||||
|
||||
pub fn add_row(&mut self, mut row: Vec<String>) {
|
||||
if (self.clone().config.auto_fix_size) {
|
||||
match self.clone().config.auto_fix_size_strategy {
|
||||
AutoFixSizeStrategy::Strict => {
|
||||
if (row.len() != self.header.len()) {
|
||||
panic!("Row length does not match header length");
|
||||
}
|
||||
}
|
||||
AutoFixSizeStrategy::FillHeaderToMatchRow { default_value } => {
|
||||
if (row.len() > self.header.len()) {
|
||||
warn!("Row length exceeds header length");
|
||||
}
|
||||
self.add_header(&default_value);
|
||||
}
|
||||
AutoFixSizeStrategy::FillRowToMatchHeader { default_value } => {
|
||||
if (row.len() < self.header.len()) {
|
||||
warn!("Row length is less than header length");
|
||||
}
|
||||
row.push(default_value.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
self.rows.push(row);
|
||||
}
|
||||
|
||||
pub fn add_column_desciption(&mut self, row_pos: usize, row: Vec<String>) {
|
||||
self.rows.insert(row_pos, row);
|
||||
}
|
||||
|
||||
pub fn generate_save_file(&mut self, output: &str) {
|
||||
let mut csv = String::new();
|
||||
csv.push_str(&self.header.join("\t"));
|
||||
csv.push('\n');
|
||||
for row in &self.rows {
|
||||
csv.push_str(&row.join("\t"));
|
||||
csv.push('\n');
|
||||
}
|
||||
|
||||
std::fs::write(output, csv).unwrap();
|
||||
}
|
||||
}
|
||||
255
src/previews/header.rs
Normal file
255
src/previews/header.rs
Normal file
|
|
@ -0,0 +1,255 @@
|
|||
// sample header for csvf
|
||||
pub struct Headers {}
|
||||
|
||||
impl Headers {
|
||||
// will be deprecated by next version
|
||||
pub fn get_recipe_table_sgp_24022025() -> Vec<&'static str> {
|
||||
[
|
||||
"Name",
|
||||
"ProductCode",
|
||||
"521001",
|
||||
"521002",
|
||||
"521004",
|
||||
"521005",
|
||||
"521006",
|
||||
"521003",
|
||||
"521007",
|
||||
"521008",
|
||||
"521009",
|
||||
"521101",
|
||||
"521102",
|
||||
"521103",
|
||||
"521104",
|
||||
"521105",
|
||||
"521106",
|
||||
"521107",
|
||||
"521108",
|
||||
"521020",
|
||||
"521021",
|
||||
"521022",
|
||||
"521023",
|
||||
"521024",
|
||||
"521025",
|
||||
"521027",
|
||||
"521028",
|
||||
"521029",
|
||||
"521030",
|
||||
"521200",
|
||||
"521201",
|
||||
"521202",
|
||||
"521203",
|
||||
"521205",
|
||||
"521206",
|
||||
"521207",
|
||||
"521208",
|
||||
"521210",
|
||||
"521211",
|
||||
"521212",
|
||||
"521213",
|
||||
"521214",
|
||||
"521215",
|
||||
"521216",
|
||||
"521301",
|
||||
"521041",
|
||||
"521042",
|
||||
"521043",
|
||||
"521044",
|
||||
"521045",
|
||||
"521046",
|
||||
"521048",
|
||||
"521047",
|
||||
"521049",
|
||||
"521050",
|
||||
"521051",
|
||||
"521052",
|
||||
"521053",
|
||||
"521054",
|
||||
"521055",
|
||||
"521056",
|
||||
"521057",
|
||||
"521058",
|
||||
"521059",
|
||||
"521061",
|
||||
"521060",
|
||||
"521062",
|
||||
"521063",
|
||||
"521064",
|
||||
"521065",
|
||||
"521066",
|
||||
"521067",
|
||||
"521068",
|
||||
"521069",
|
||||
"521070",
|
||||
"521071",
|
||||
"521072",
|
||||
"521073",
|
||||
"2101",
|
||||
"1031",
|
||||
"521032",
|
||||
"521036",
|
||||
"521034",
|
||||
"521035",
|
||||
"521033",
|
||||
"529501",
|
||||
"529505",
|
||||
"529502",
|
||||
"529503",
|
||||
"529506",
|
||||
"529601",
|
||||
"529701",
|
||||
"529702",
|
||||
"1",
|
||||
"9100",
|
||||
"8101",
|
||||
"8102",
|
||||
"8111",
|
||||
"8112",
|
||||
"8113",
|
||||
"8114",
|
||||
"8115",
|
||||
"8116",
|
||||
"8117",
|
||||
"8118",
|
||||
"8119",
|
||||
"8120",
|
||||
"8001",
|
||||
"8002",
|
||||
"8888",
|
||||
"8889",
|
||||
"200000",
|
||||
"201001",
|
||||
"201002",
|
||||
"100004",
|
||||
"522201",
|
||||
"521217",
|
||||
"521038",
|
||||
"521037",
|
||||
]
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
pub fn get_recipe_table_dubai_16052025() -> Vec<&'static str> {
|
||||
[
|
||||
"Name",
|
||||
"ProductCode",
|
||||
"531001",
|
||||
"531002",
|
||||
"531004",
|
||||
"531005",
|
||||
"531006",
|
||||
"531003",
|
||||
"531007",
|
||||
"531008",
|
||||
"531009",
|
||||
"531101",
|
||||
"531102",
|
||||
"531103",
|
||||
"531104",
|
||||
"531105",
|
||||
"531106",
|
||||
"531107",
|
||||
"531108",
|
||||
"531020",
|
||||
"531021",
|
||||
"531022",
|
||||
"531023",
|
||||
"531024",
|
||||
"531025",
|
||||
"531027",
|
||||
"531028",
|
||||
"531029",
|
||||
"531030",
|
||||
"531200",
|
||||
"531201",
|
||||
"531202",
|
||||
"531203",
|
||||
"531205",
|
||||
"531206",
|
||||
"531207",
|
||||
"531208",
|
||||
"531210",
|
||||
"531211",
|
||||
"531212",
|
||||
"531213",
|
||||
"531214",
|
||||
"531215",
|
||||
"531216",
|
||||
"531301",
|
||||
"531041",
|
||||
"531042",
|
||||
"531043",
|
||||
"531044",
|
||||
"531045",
|
||||
"531046",
|
||||
"531048",
|
||||
"531047",
|
||||
"531049",
|
||||
"531050",
|
||||
"531051",
|
||||
"531052",
|
||||
"531053",
|
||||
"531054",
|
||||
"531055",
|
||||
"531056",
|
||||
"531057",
|
||||
"531058",
|
||||
"531059",
|
||||
"531061",
|
||||
"531060",
|
||||
"531062",
|
||||
"531063",
|
||||
"531064",
|
||||
"531065",
|
||||
"531066",
|
||||
"531067",
|
||||
"531068",
|
||||
"531069",
|
||||
"531070",
|
||||
"531071",
|
||||
"531072",
|
||||
"531073",
|
||||
"2101",
|
||||
"1031",
|
||||
"531032",
|
||||
"531036",
|
||||
"531034",
|
||||
"531035",
|
||||
"531033",
|
||||
"539501",
|
||||
"539505",
|
||||
"539502",
|
||||
"539503",
|
||||
"539506",
|
||||
"539601",
|
||||
"539701",
|
||||
"539702",
|
||||
"1",
|
||||
"9100",
|
||||
"8101",
|
||||
"8102",
|
||||
"8111",
|
||||
"8112",
|
||||
"8113",
|
||||
"8114",
|
||||
"8115",
|
||||
"8116",
|
||||
"8117",
|
||||
"8118",
|
||||
"8119",
|
||||
"8120",
|
||||
"8001",
|
||||
"8002",
|
||||
"8888",
|
||||
"8889",
|
||||
"200000",
|
||||
"201001",
|
||||
"201002",
|
||||
"100004",
|
||||
"532201",
|
||||
"531217",
|
||||
"531038",
|
||||
"531037",
|
||||
]
|
||||
.to_vec()
|
||||
}
|
||||
}
|
||||
2
src/previews/mod.rs
Normal file
2
src/previews/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod csvf;
|
||||
pub mod header;
|
||||
199
src/recipe_functions/common.rs
Normal file
199
src/recipe_functions/common.rs
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
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 const RECIPES_DIR: &str = "/Users/pkntd/Codes/mk4/cofffeemachineConfig/";
|
||||
|
||||
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(RECIPES_DIR);
|
||||
|
||||
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 read_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() {
|
||||
files.push(path.to_string_lossy().into_owned());
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
592
src/recipe_functions/import.rs
Normal file
592
src/recipe_functions/import.rs
Normal file
|
|
@ -0,0 +1,592 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use log::{debug, info};
|
||||
use serde_json::{Number, Value};
|
||||
|
||||
use super::common::*;
|
||||
use crate::{
|
||||
models::recipe::{self, PartialRecipe},
|
||||
previews::{csvf::*, header::Headers},
|
||||
};
|
||||
|
||||
pub fn import_menu(main_version: usize, country_name: &str, into_version: usize) {
|
||||
let latest_recipe_thai = create_recipe_model_from_file(create_recipe_path("tha", main_version));
|
||||
|
||||
// let mut latest_recipe_mys =
|
||||
// create_recipe_model_from_file(create_recipe_path("mys", *mys_version.unwrap()));
|
||||
|
||||
let mut latest_recipe_sgp =
|
||||
create_recipe_model_from_file(create_recipe_path(country_name, into_version));
|
||||
|
||||
let diff_list = latest_recipe_thai.list_diff_pd_ignore_country_code(&latest_recipe_sgp);
|
||||
|
||||
let mut menu_no_sugar_table = Table::new();
|
||||
let insert_later_config = TableConfig {
|
||||
allow_row_length_exceeds_header: false,
|
||||
auto_fix_size: true,
|
||||
auto_fix_size_strategy: AutoFixSizeStrategy::FillRowToMatchHeader {
|
||||
default_value: "".to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
let mut sg_price_table = menu_no_sugar_table.clone();
|
||||
let mut recipe_table = menu_no_sugar_table.clone();
|
||||
|
||||
menu_no_sugar_table.set_config(insert_later_config.clone());
|
||||
sg_price_table.set_config(insert_later_config.clone());
|
||||
recipe_table.set_config(insert_later_config.clone());
|
||||
|
||||
menu_no_sugar_table.set_header(["Product Code", "Name"].to_vec());
|
||||
sg_price_table.set_header(["SKU", "English Name", "Thai Name"].to_vec());
|
||||
|
||||
recipe_table.set_header(Headers::get_recipe_table_sgp_24022025());
|
||||
|
||||
let modified_recipes = change_prefix_by_country(
|
||||
country_name,
|
||||
latest_recipe_thai.search_multi_in_parallel(diff_list),
|
||||
);
|
||||
|
||||
// also clone mat setting
|
||||
// ** Will removed this
|
||||
let from_tha_mat_settings = [
|
||||
latest_recipe_thai.search_material_settings("2201".to_string()),
|
||||
latest_recipe_thai.search_material_settings("1217".to_string()),
|
||||
latest_recipe_thai.search_material_settings("1038".to_string()),
|
||||
latest_recipe_thai.search_material_settings("1037".to_string()),
|
||||
];
|
||||
|
||||
let mut formatted_mat_settings = Vec::new();
|
||||
from_tha_mat_settings.iter().for_each(|mat_smth| {
|
||||
let new_mat_smth = *mat_smth;
|
||||
if let Some(x) = new_mat_smth {
|
||||
let mut cl_x = x.clone();
|
||||
let mut new_mat_id = cl_x.id.clone().as_i64().unwrap().to_string();
|
||||
// new_product_code = format!("{}-{}", "sgp", new_product_code.split_once('-').unwrap().1);
|
||||
new_mat_id = format!("{}{}", get_mat_prefix(country_name), new_mat_id);
|
||||
cl_x.id = Value::Number(Number::from_str(&new_mat_id).unwrap()).clone();
|
||||
// debug!("new formatted mat settings [SGP] -> {:?}", cl_x);
|
||||
formatted_mat_settings.push(cl_x);
|
||||
}
|
||||
});
|
||||
|
||||
latest_recipe_sgp
|
||||
.MaterialSetting
|
||||
.extend(formatted_mat_settings.clone());
|
||||
|
||||
// debug!("modified recipes: {:#?}", modified_recipes);
|
||||
|
||||
// process: generate table
|
||||
modified_recipes.iter().enumerate().for_each(|mr| {
|
||||
menu_no_sugar_table.add_row(vec![
|
||||
mr.1.productCode.clone(),
|
||||
mr.1.name.clone().unwrap().to_string().replace("\n", "\\n"),
|
||||
]);
|
||||
sg_price_table.add_row(vec![
|
||||
mr.1.productCode.clone(),
|
||||
mr.1.otherName
|
||||
.clone()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.replace("\n", "\\n"),
|
||||
mr.1.name.clone().unwrap().to_string().replace("\n", "\\n"),
|
||||
]);
|
||||
|
||||
// Pre process for recipe table
|
||||
|
||||
// let mut missing_support_mats = Vec::new();
|
||||
let binding = mr.1.clone();
|
||||
let mat_list = binding
|
||||
.recipes
|
||||
.iter()
|
||||
.filter(|r| r.isUse)
|
||||
.map(|r| {
|
||||
// debug!(
|
||||
// "r->{:?}",
|
||||
// r.materialPathId
|
||||
// .clone()
|
||||
// .as_number()
|
||||
// .unwrap()
|
||||
// .as_i64()
|
||||
// .unwrap()
|
||||
// .to_string()
|
||||
// );
|
||||
|
||||
r.materialPathId
|
||||
.as_number()
|
||||
.unwrap()
|
||||
.as_i64()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
let mut mapping_mats = Vec::new();
|
||||
// let mut missing_header = Vec::new();
|
||||
|
||||
mat_list.iter().enumerate().for_each(|(idx, mat)| {
|
||||
// if (!mat.parse::<i64>().unwrap().eq(&0i64)
|
||||
// && !recipe_table
|
||||
// .clone()
|
||||
// .get_current_header()
|
||||
// .contains(&mat.to_string()))
|
||||
// {
|
||||
// // missing_support_mats.push((idx, mat.to_string()));
|
||||
// // add to header
|
||||
|
||||
// // recipe_table.add_header(mat);
|
||||
// missing_header.push(mat);
|
||||
// }
|
||||
|
||||
// skip zero
|
||||
if !mat.eq("0") {
|
||||
mapping_mats.push((idx, mat));
|
||||
}
|
||||
});
|
||||
|
||||
// if (!missing_header.is_empty()) {
|
||||
// missing_header.iter().for_each(|mh| {
|
||||
// if (!recipe_table
|
||||
// .clone()
|
||||
// .get_current_header()
|
||||
// .contains(mh.clone()))
|
||||
// {
|
||||
// recipe_table.add_header(mh);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
let inter_name_empty = mr.1.otherName.clone().unwrap().is_empty();
|
||||
let used_name = if inter_name_empty {
|
||||
mr.1.name.clone().unwrap().to_string().replace("\n", "\\n")
|
||||
} else {
|
||||
mr.1.otherName
|
||||
.clone()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.replace("\n", "\\n")
|
||||
};
|
||||
let mut used_mats = vec![used_name, mr.1.productCode.clone()];
|
||||
|
||||
// add by using mat
|
||||
|
||||
// let mut reorder1 = Vec::new();
|
||||
// let mut add_last = Vec::new();
|
||||
|
||||
// reorder by header
|
||||
// recipe_table.clone().get_current_header().iter().for_each(|h| {
|
||||
// let mut found = false;
|
||||
// mapping_mats.iter().for_each(|(idx, mat)| {
|
||||
// if (h.eq(mat)) {
|
||||
// found = true;
|
||||
// reorder1.push((idx, mat));
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
// recipe
|
||||
let mut recipe_brew_values_only = vec![0; recipe_table.clone().get_current_header().len()];
|
||||
let recipe_list = mr.1.clone().recipes;
|
||||
|
||||
let mut add_more_to_blender = 0i64;
|
||||
|
||||
for repl in recipe_list.iter() {
|
||||
let current_mat = repl.materialPathId.as_number().unwrap().as_i64().unwrap();
|
||||
if repl.isUse {
|
||||
recipe_table
|
||||
.clone()
|
||||
.get_current_header()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(header_idx, header)| {
|
||||
if header_idx > 1 && header.eq(¤t_mat.to_string()) {
|
||||
// search mat settings for further info
|
||||
let mat_setting =
|
||||
latest_recipe_sgp.search_material_settings(current_mat.to_string());
|
||||
|
||||
if let Some(mat_s) = mat_setting {
|
||||
match mat_s.clone().get_definition_type() {
|
||||
recipe::MaterialType::Bean => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.powderGram.as_i64().unwrap();
|
||||
|
||||
// check if there is mix order
|
||||
if repl
|
||||
.MixOrder
|
||||
.as_number()
|
||||
.unwrap()
|
||||
.as_i64()
|
||||
.unwrap()
|
||||
.eq(&0i64)
|
||||
{
|
||||
// add to blender index
|
||||
add_more_to_blender = repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
}
|
||||
recipe::MaterialType::Syrup => {
|
||||
// debug
|
||||
println!(
|
||||
"SYRUP [{}]: {} --> {} = {:?}",
|
||||
mr.1.productCode.clone(),
|
||||
header_idx,
|
||||
repl.materialPathId.clone(),
|
||||
repl.syrupGram
|
||||
);
|
||||
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.syrupGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Soda => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.syrupGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Powder => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.powderGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Water => todo!(),
|
||||
recipe::MaterialType::Ice => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.waterCold.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Cup => {
|
||||
recipe_brew_values_only[header_idx] += 1;
|
||||
}
|
||||
recipe::MaterialType::Lid => {}
|
||||
recipe::MaterialType::Straw => {}
|
||||
recipe::MaterialType::Whipper => {
|
||||
let water_yield = repl.waterYield.as_i64().unwrap();
|
||||
let water_cold = repl.waterCold.as_i64().unwrap();
|
||||
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
water_yield + water_cold;
|
||||
|
||||
if add_more_to_blender > 0i64 {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
add_more_to_blender;
|
||||
add_more_to_blender = 0i64;
|
||||
}
|
||||
}
|
||||
recipe::MaterialType::Leaves => {}
|
||||
recipe::MaterialType::Clean => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::CleanV2 => {
|
||||
recipe_brew_values_only[header_idx] +=
|
||||
repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Unknown => {
|
||||
recipe_brew_values_only[header_idx] += 0i64;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// suspect new mat or not found
|
||||
debug!("mat error [NotFound/Unknown] ==> {}", repl.materialPathId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (vidx, val) in recipe_brew_values_only.iter().enumerate() {
|
||||
// skip first 2
|
||||
if vidx <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if val > &0i64 {
|
||||
used_mats.push(val.to_string());
|
||||
} else {
|
||||
used_mats.push(String::from(""));
|
||||
}
|
||||
}
|
||||
|
||||
// debug!("Used Materials: \n{:?}", used_mats);
|
||||
|
||||
recipe_table.add_row(used_mats);
|
||||
});
|
||||
|
||||
// Exclusive only for SGP
|
||||
if country_name.eq_ignore_ascii_case("sgp") {
|
||||
menu_no_sugar_table.generate_save_file("./test_result/menu_no_sugar.csv");
|
||||
|
||||
// process: generate table for price
|
||||
sg_price_table.generate_save_file("./test_result/sg_price.csv");
|
||||
|
||||
// process: generate table for recipe
|
||||
recipe_table.generate_save_file("./test_result/sg_recipe.csv");
|
||||
|
||||
// final process
|
||||
|
||||
let mut pr = PartialRecipe::default();
|
||||
pr.sync_new(modified_recipes, formatted_mat_settings.clone());
|
||||
// export file for recipe json
|
||||
pr.export("./test_result/grep_into_modified_new_recipe_for_sgp.json");
|
||||
} else {
|
||||
sg_price_table.generate_save_file("./test_result/o1_price.csv");
|
||||
|
||||
// process: generate table for recipe
|
||||
recipe_table.generate_save_file("./test_result/o1_recipe.csv");
|
||||
|
||||
// final process
|
||||
|
||||
let mut pr = PartialRecipe::default();
|
||||
pr.sync_new(modified_recipes, formatted_mat_settings.clone());
|
||||
// export file for recipe json
|
||||
pr.export("./test_result/grep_into_modified_new_recipe_for_o1.json");
|
||||
}
|
||||
|
||||
// WIP other countries
|
||||
}
|
||||
|
||||
pub fn generate_recipe_sheet_table(country_name: &str, into_version: usize) {
|
||||
let mut latest_recipe =
|
||||
create_recipe_model_from_file(create_recipe_path(country_name, into_version));
|
||||
|
||||
let mut recipe_table = Table::new();
|
||||
let insert_later_config = TableConfig {
|
||||
allow_row_length_exceeds_header: false,
|
||||
auto_fix_size: true,
|
||||
auto_fix_size_strategy: AutoFixSizeStrategy::FillRowToMatchHeader {
|
||||
default_value: "".to_string(),
|
||||
},
|
||||
};
|
||||
|
||||
recipe_table.set_config(insert_later_config);
|
||||
|
||||
match country_name {
|
||||
"sgp" => {
|
||||
info!("SGP last update [24.02.2025]");
|
||||
recipe_table.set_header(Headers::get_recipe_table_sgp_24022025());
|
||||
}
|
||||
"dubai" => {
|
||||
info!("UAE last update [16.05.2025]");
|
||||
recipe_table.set_header(Headers::get_recipe_table_dubai_16052025());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let mut material_names = Vec::new();
|
||||
|
||||
for (idx, header) in recipe_table.clone().get_current_header().iter().enumerate() {
|
||||
if idx <= 1 {
|
||||
material_names.push("".to_string());
|
||||
} else {
|
||||
// do search from recipe first
|
||||
|
||||
let searched_result = latest_recipe.search_material_settings(header.to_string());
|
||||
|
||||
// material_names.push(header.to_string());
|
||||
match searched_result {
|
||||
Some(sr) => {
|
||||
if sr.clone().materialOtherName.is_some() {
|
||||
material_names.push(format!(
|
||||
"{} ({})",
|
||||
sr.clone().materialOtherName.unwrap(),
|
||||
header
|
||||
));
|
||||
} else {
|
||||
material_names.push(format!(
|
||||
"{} ({})",
|
||||
sr.clone().materialName.unwrap(),
|
||||
header
|
||||
));
|
||||
}
|
||||
}
|
||||
None => {
|
||||
material_names.push(header.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
latest_recipe.clone().Recipe01.iter_mut().for_each(|rpl| {
|
||||
let binding = rpl.clone();
|
||||
let mat_list = binding
|
||||
.recipes
|
||||
.iter()
|
||||
.filter(|r| r.isUse)
|
||||
.map(|r| {
|
||||
r.materialPathId
|
||||
.as_number()
|
||||
.unwrap()
|
||||
.as_i64()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
})
|
||||
.collect::<Vec<String>>();
|
||||
|
||||
let mut mapping_materials = Vec::new();
|
||||
|
||||
mat_list.iter().enumerate().for_each(|(idx, mat)| {
|
||||
if !mat.eq("0") {
|
||||
mapping_materials.push((idx, mat));
|
||||
}
|
||||
});
|
||||
|
||||
let inter_name_empty = rpl.otherName.clone().unwrap().is_empty();
|
||||
let used_name = if inter_name_empty {
|
||||
rpl.name.clone().unwrap().to_string().replace("\n", "\\n")
|
||||
} else {
|
||||
rpl.otherName
|
||||
.clone()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.replace("\n", "\\n")
|
||||
};
|
||||
|
||||
let mut used_materials = vec![used_name, rpl.productCode.clone()];
|
||||
let mut recipe_brewing_values_only =
|
||||
vec![0; recipe_table.clone().get_current_header().len()];
|
||||
let recipe_list = rpl.clone().recipes;
|
||||
|
||||
let mut add_more_to_blender = 0i64;
|
||||
|
||||
for repl in recipe_list.iter() {
|
||||
let current_material = repl.materialPathId.as_number().unwrap().as_i64().unwrap();
|
||||
if repl.isUse {
|
||||
recipe_table
|
||||
.clone()
|
||||
.get_current_header()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.for_each(|(header_idx, header)| {
|
||||
if header_idx > 1 && header.eq(¤t_material.to_string()) {
|
||||
// search mat settings for further info
|
||||
|
||||
if rpl.productCode.clone().ends_with("0090") {
|
||||
debug!(
|
||||
"MAT [{}]: {} --> {} = pow:{:?},sy:{:?}",
|
||||
rpl.productCode.clone(),
|
||||
header_idx,
|
||||
repl.materialPathId.clone(),
|
||||
repl.powderGram,
|
||||
repl.syrupGram
|
||||
);
|
||||
}
|
||||
|
||||
let mat_setting = latest_recipe
|
||||
.search_material_settings(current_material.to_string());
|
||||
|
||||
if let Some(mat_s) = mat_setting {
|
||||
match mat_s.clone().get_definition_type() {
|
||||
recipe::MaterialType::Bean => {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.powderGram.as_i64().unwrap();
|
||||
|
||||
// check if there is mix order
|
||||
if repl
|
||||
.MixOrder
|
||||
.as_number()
|
||||
.unwrap()
|
||||
.as_i64()
|
||||
.unwrap()
|
||||
.eq(&0i64)
|
||||
{
|
||||
// add to blender index
|
||||
add_more_to_blender = repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
}
|
||||
recipe::MaterialType::Syrup => {
|
||||
// debug
|
||||
if rpl.productCode.clone().ends_with("0090") {
|
||||
println!(
|
||||
"SYRUP [{}]: {} --> {} = {:?}",
|
||||
rpl.productCode.clone(),
|
||||
header_idx,
|
||||
repl.materialPathId.clone(),
|
||||
repl.syrupGram
|
||||
);
|
||||
}
|
||||
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.syrupGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Soda => {
|
||||
println!(
|
||||
"SODA [{}]: {} --> {} = {:?}",
|
||||
rpl.productCode.clone(),
|
||||
header_idx,
|
||||
repl.materialPathId.clone(),
|
||||
repl.syrupGram
|
||||
);
|
||||
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.syrupGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Powder => {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.powderGram.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Water => todo!(),
|
||||
recipe::MaterialType::Ice => {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.waterCold.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Cup => {
|
||||
recipe_brewing_values_only[header_idx] += 1;
|
||||
}
|
||||
recipe::MaterialType::Lid => {}
|
||||
recipe::MaterialType::Straw => {}
|
||||
recipe::MaterialType::Whipper => {
|
||||
let water_yield = repl.waterYield.as_i64().unwrap();
|
||||
let water_cold = repl.waterCold.as_i64().unwrap();
|
||||
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
water_yield + water_cold;
|
||||
|
||||
if add_more_to_blender > 0i64 {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
add_more_to_blender;
|
||||
add_more_to_blender = 0i64;
|
||||
}
|
||||
}
|
||||
recipe::MaterialType::Leaves => {}
|
||||
recipe::MaterialType::Clean => {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::CleanV2 => {
|
||||
recipe_brewing_values_only[header_idx] +=
|
||||
repl.waterYield.as_i64().unwrap();
|
||||
}
|
||||
recipe::MaterialType::Unknown => {
|
||||
if rpl.productCode.clone().ends_with("0090") {
|
||||
println!(
|
||||
"UNK [{}]: {} --> {} = {:?}",
|
||||
rpl.productCode.clone(),
|
||||
header_idx,
|
||||
repl.materialPathId.clone(),
|
||||
repl.syrupGram
|
||||
);
|
||||
}
|
||||
recipe_brewing_values_only[header_idx] += 0i64;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// suspect new mat or not found
|
||||
debug!("mat error [NotFound/Unknown] ==> {}", repl.materialPathId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (vidx, val) in recipe_brewing_values_only.iter().enumerate() {
|
||||
if vidx <= 1 {
|
||||
continue;
|
||||
}
|
||||
|
||||
if val > &0i64 {
|
||||
used_materials.push(val.to_string());
|
||||
} else {
|
||||
used_materials.push(String::from(""));
|
||||
}
|
||||
}
|
||||
|
||||
recipe_table.add_row(used_materials);
|
||||
});
|
||||
|
||||
// generate row description
|
||||
recipe_table.add_column_desciption(0, material_names);
|
||||
recipe_table.generate_save_file("./test_result/recipe.csv");
|
||||
}
|
||||
122
src/recipe_functions/list_fields.rs
Normal file
122
src/recipe_functions/list_fields.rs
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
use crate::models::recipe::{Recipe, Recipe01};
|
||||
|
||||
impl Recipe {
|
||||
/// The function `list_menu_product_code` returns a vector of product codes from a list of recipes.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// a vector of string references (`&str`) representing the product codes of the recipes in
|
||||
/// `Recipe01`.
|
||||
pub fn list_menu_product_code(&self) -> Vec<&str> {
|
||||
self.Recipe01
|
||||
.iter()
|
||||
.map(|r| r.productCode.as_str())
|
||||
.collect()
|
||||
}
|
||||
/// The function `list_material_settings` returns a vector of strings containing the IDs of material
|
||||
/// settings.
|
||||
///
|
||||
/// Returns:
|
||||
///
|
||||
/// The function `list_material_settings` returns a `Vec<String>` which contains the IDs of the material
|
||||
/// settings.
|
||||
|
||||
pub fn list_material_settings(&self) -> Vec<String> {
|
||||
self.MaterialSetting
|
||||
.iter()
|
||||
.map(|r| r.id.to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn list_topping_list(&self) -> Vec<String> {
|
||||
self.Topping
|
||||
.ToppingList
|
||||
.iter()
|
||||
.map(|r| r.id.clone().to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn list_topping_group(&self) -> Vec<String> {
|
||||
self.Topping
|
||||
.ToppingGroup
|
||||
.iter()
|
||||
.map(|r| r.groupID.clone().to_string())
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[cfg(feature = "diff")]
|
||||
pub fn list_diff_pd_between_recipes(&self, another_recipe: &Recipe) -> Vec<String> {
|
||||
let mut list = Vec::new();
|
||||
|
||||
self.Recipe01.iter().for_each(|r| {
|
||||
if !another_recipe.diff_pd_between_recipes(another_recipe, r.productCode.clone()) {
|
||||
list.push(r.productCode.clone());
|
||||
}
|
||||
});
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
pub fn list_diff_pd_ignore_country_code(&self, another_recipe: &Recipe) -> Vec<String> {
|
||||
let mut list = Vec::new();
|
||||
|
||||
self.Recipe01.iter().for_each(|r| {
|
||||
// clean before search
|
||||
let rpl = r.clone();
|
||||
|
||||
// grep only recipe without country code
|
||||
let pd = rpl.productCode;
|
||||
let pd_split = pd.split("-").collect::<Vec<&str>>();
|
||||
|
||||
// combine without first elem
|
||||
let mut new_pd = String::new();
|
||||
for (i, ele) in pd_split.iter().enumerate() {
|
||||
if i != 0 {
|
||||
new_pd.push_str(ele);
|
||||
if i != pd_split.len() - 1 {
|
||||
new_pd.push('-');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !another_recipe
|
||||
.diff_pd_between_recipes_ignore_country(another_recipe, new_pd.clone())
|
||||
{
|
||||
list.push(new_pd.clone());
|
||||
}
|
||||
});
|
||||
|
||||
list
|
||||
}
|
||||
|
||||
pub fn find_recipe_by_material_path_id(&self, material_path_id: &str) -> Vec<&Recipe01> {
|
||||
// let mut res = Vec::new();
|
||||
|
||||
let total: Vec<&Recipe01> = self
|
||||
.Recipe01
|
||||
.iter()
|
||||
.filter(|r| {
|
||||
for ele in r.recipes.clone() {
|
||||
if ele.materialPathId.as_i64().unwrap()
|
||||
== material_path_id.parse::<i64>().unwrap()
|
||||
{
|
||||
// res.push(r.clone());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
})
|
||||
.collect();
|
||||
|
||||
total
|
||||
}
|
||||
}
|
||||
|
||||
impl Recipe01 {
|
||||
pub fn list_recipe_only_id(&self) -> Vec<String> {
|
||||
self.recipes
|
||||
.iter()
|
||||
.map(|rpl| rpl.materialPathId.clone().to_string())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
159
src/recipe_functions/merge.rs
Normal file
159
src/recipe_functions/merge.rs
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
use std::{
|
||||
fmt,
|
||||
fs::File,
|
||||
io::{self, Read},
|
||||
};
|
||||
|
||||
use super::list_fields;
|
||||
use crate::models::{
|
||||
merge_model::{MergeResult, MergeStatus},
|
||||
recipe::{CommonRecipeTrait, Recipe, Recipe01Trait},
|
||||
};
|
||||
|
||||
// compare between two recipe, and wait for user input to continue compare or quit
|
||||
// return status
|
||||
pub fn precise_merge(master: &mut Recipe, dev: &mut Recipe) -> MergeResult {
|
||||
let mut merge_status = MergeResult::new();
|
||||
|
||||
if master.Timestamp != dev.Timestamp {
|
||||
println!(
|
||||
"\n\nmaster.Timestamp => {:?} but dev.Timestamp => {:?}",
|
||||
master.Timestamp, dev.Timestamp
|
||||
);
|
||||
|
||||
// do change if need
|
||||
merge_status.accept(dev.Timestamp.clone());
|
||||
}
|
||||
|
||||
let machine_setting_diff = master.MachineSetting.compare(&dev.MachineSetting);
|
||||
println!("machine_setting_diff => {:?}", machine_setting_diff);
|
||||
|
||||
let product_codes = dev.list_menu_product_code();
|
||||
|
||||
let mut user_input = String::new();
|
||||
println!("** Recip01 ** Sensitive data, enter 'm' (manual) or 'a' (auto) for safe comparing");
|
||||
match io::stdin().read_line(&mut user_input) {
|
||||
Ok(_m) => {}
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
user_input = user_input.trim_end().to_string();
|
||||
|
||||
println!(
|
||||
"mode: {}, valid: {}",
|
||||
user_input,
|
||||
user_input.eq_ignore_ascii_case("m")
|
||||
);
|
||||
|
||||
for product_code in product_codes {
|
||||
println!("** {} **", product_code);
|
||||
let menu_master = master.clone();
|
||||
let menu1 = menu_master.search_pd(product_code.clone().to_owned());
|
||||
let menu_dev = dev.clone();
|
||||
let menu2 = menu_dev.search_pd(product_code.clone().to_owned());
|
||||
|
||||
// exist in both
|
||||
if menu1.is_some() && menu2.is_some() {
|
||||
let menu_diff = menu1.unwrap().compare(menu2.unwrap());
|
||||
|
||||
if !menu_diff.is_empty()
|
||||
&& menu1.unwrap().clone().is_replacable(
|
||||
menu2.unwrap().to_owned(),
|
||||
user_input.eq_ignore_ascii_case("m"),
|
||||
)
|
||||
{
|
||||
master.update_menu(dev, product_code.clone().to_owned(), None);
|
||||
println!("updated menu => {:?}\t\t{:?}", product_code, menu_diff);
|
||||
merge_status.change(product_code.to_owned());
|
||||
}
|
||||
|
||||
// check content of diff
|
||||
} else if menu1.is_none() && menu2.is_some() {
|
||||
// new menu
|
||||
|
||||
let new_menu = menu2.unwrap();
|
||||
if user_input.contains('m') {
|
||||
println!(
|
||||
"found new menu from dev => {}, add to master ? (y,n)",
|
||||
product_code
|
||||
);
|
||||
|
||||
let mut user_input2 = String::new();
|
||||
match io::stdin().read_line(&mut user_input2) {
|
||||
Ok(_m) => {}
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if user_input.eq_ignore_ascii_case("y") {
|
||||
master.Recipe01.push(new_menu.clone());
|
||||
merge_status.add(product_code.to_owned());
|
||||
}
|
||||
} else {
|
||||
master.Recipe01.push(new_menu.clone());
|
||||
merge_status.add(product_code.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let material_settings = dev.list_material_settings();
|
||||
|
||||
for material_setting in material_settings {
|
||||
println!("material_setting => {}", material_setting);
|
||||
let menu_master = master.clone();
|
||||
let menu1 = menu_master.search_material_settings(material_setting.to_string());
|
||||
let menu_dev = dev.clone();
|
||||
let menu2 = menu_dev.search_material_settings(material_setting.to_string());
|
||||
|
||||
// exist in both
|
||||
if menu1.is_some() && menu2.is_some() {
|
||||
let menu_diff = menu1.unwrap().compare(menu2.unwrap());
|
||||
|
||||
if !menu_diff.is_empty() {
|
||||
master.update_material_settings(dev, material_setting.to_string());
|
||||
println!(
|
||||
"updated material => {:?}\t\t{:?}",
|
||||
material_setting, menu_diff
|
||||
);
|
||||
merge_status.change(material_setting.to_string());
|
||||
}
|
||||
|
||||
// check content of diff
|
||||
} else if menu1.is_none() && menu2.is_some() {
|
||||
// new material
|
||||
|
||||
let new_material = menu2.unwrap();
|
||||
if user_input.contains('m') {
|
||||
println!(
|
||||
"found new material from dev => {}, add to master ? (y,n)",
|
||||
material_setting
|
||||
);
|
||||
|
||||
let mut user_input2 = String::new();
|
||||
match io::stdin().read_line(&mut user_input2) {
|
||||
Ok(_m) => {}
|
||||
Err(e) => {
|
||||
println!("{:?}", e);
|
||||
}
|
||||
}
|
||||
|
||||
if user_input.eq_ignore_ascii_case("y") {
|
||||
master.MaterialSetting.push(new_material.clone());
|
||||
merge_status.add(material_setting.to_string());
|
||||
}
|
||||
} else {
|
||||
master.MaterialSetting.push(new_material.clone());
|
||||
merge_status.add(material_setting.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// not exist in both
|
||||
}
|
||||
|
||||
for topp_list in dev.Topping.ToppingList.clone() {}
|
||||
|
||||
merge_status.finalize()
|
||||
}
|
||||
4
src/recipe_functions/mod.rs
Normal file
4
src/recipe_functions/mod.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
pub mod translator;
|
||||
|
||||
pub mod common;
|
||||
pub mod import;
|
||||
20
src/recipe_functions/translator.rs
Normal file
20
src/recipe_functions/translator.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use serde_json::Number;
|
||||
|
||||
use crate::models::recipe::Recipe;
|
||||
|
||||
pub fn matIdToName(source: &mut Recipe, material_path_id: &str) -> String {
|
||||
let mut name = String::new();
|
||||
|
||||
source.MaterialSetting.iter().for_each(|r| {
|
||||
if r.id.as_i64().is_some()
|
||||
&& r.id.as_i64().unwrap() == material_path_id.parse::<i64>().unwrap()
|
||||
{
|
||||
// name = r.materialName;
|
||||
if let Some(mat_name) = r.materialName.clone() {
|
||||
name = mat_name;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
name
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue