311 lines
10 KiB
Markdown
311 lines
10 KiB
Markdown
# libtbr
|
|
|
|
`libtbr` is swiss-knife toolbox for Taobin project.
|
|
|
|
```
|
|
cargo add --git https://gitlab.forthrd.io/Pakin/libtbr.git
|
|
```
|
|
|
|
```
|
|
cargo update
|
|
```
|
|
|
|
## Examples
|
|
|
|
### Initialize Config
|
|
|
|
```rust
|
|
use libtbr::recipe_functions::common;
|
|
|
|
// this read file `.tbcfg` in the current directory
|
|
let cfg = common::get_config();
|
|
|
|
let recipe_dir = cfg.get("RECIPE_DIR").unwrap();
|
|
```
|
|
|
|
---
|
|
|
|
### Get recipe from specific country (latest)
|
|
|
|
```rust
|
|
...
|
|
let latest_versions = grep_latest_versions(recipe_dir).unwrap();
|
|
|
|
// try get malaysia recipe, may fail if country does not exist
|
|
let mys_version = latest_versions.get("mys");
|
|
// try to create malaysia recipe model
|
|
let mys_recipe_model = common::create_recipe_model_from_file(common::create_recipe_path(
|
|
"mys",
|
|
*mys_version.unwrap(),
|
|
));
|
|
|
|
...
|
|
```
|
|
|
|
### Get list of material settings
|
|
|
|
```rust
|
|
// get current material settings including empty (0)
|
|
let mut used_in_mys = mys_recipe_model.list_material_settings();
|
|
used_in_mys.push("0".to_string());
|
|
```
|
|
|
|
### Get all recipe of expected material id
|
|
|
|
```rust
|
|
let aus_latest = common::create_recipe_model_from_file(common::create_recipe_path(
|
|
"aus",
|
|
*aus_version.unwrap(),
|
|
));
|
|
|
|
let prod_list = aus_latest.find_recipe_by_material_path_id("511214");
|
|
```
|
|
|
|
### Generate google sheet style table of recipe from file
|
|
|
|
```rust
|
|
// Experimental: expect current execution path to have `./test_result` folder first, and `config.RECIPE_DIR/{country}/{version_file_format}` must exist.
|
|
import::generate_recipe_sheet_table("mys", 626);
|
|
```
|
|
|
|
### Notes
|
|
|
|
Simple Snippet Patterns
|
|
|
|
```rust
|
|
// =============================================
|
|
// Get current material and convert to thai id
|
|
// =============================================
|
|
let curr_rpl_mat_id = rpl.materialPathId.as_i64().unwrap_or(0);
|
|
|
|
// strip off first 2
|
|
let pure_mat_id = if curr_rpl_mat_id > 300000 {
|
|
//
|
|
curr_rpl_mat_id.to_string()[2..]
|
|
.parse::<i64>()
|
|
.expect("not a number")
|
|
} else {
|
|
curr_rpl_mat_id
|
|
};
|
|
```
|
|
|
|
---
|
|
|
|
### XML Parser (Experimental)
|
|
|
|
This will parse xml file and create node structure type `Vec<Node>` where `Node` is from `crate::xml::node`
|
|
|
|
Xml-related functions
|
|
|
|
- `parse_xml_to_tree`: this will parse raw xml string into node structure.
|
|
- `print_tree`: printing node structure to xml
|
|
- `generate_nodes_from_xml`: generate node index map from list of `(catalog_name, catalog_path)`
|
|
|
|
Node functions
|
|
|
|
- `find_by_child_value`: search expected value from node (`parent_node`) which this value should be in node named `child_name`.
|
|
- `get_child`: get child node from current node's children
|
|
|
|
Shortcut Macro
|
|
|
|
- `get_path`: macro for accessing the node inner child by provided key `key1.key2.key3...`
|
|
|
|
Example of parsing xml layout v3 and generate into `new-layout-v2` format
|
|
|
|
```rust
|
|
use libtbr::xml::*;
|
|
|
|
|
|
// ...
|
|
|
|
let taobin_dir = cfg
|
|
.get("TAOBIN_REPO")
|
|
.expect("Taobin directory path not provided");
|
|
let v3_dir = format!("{taobin_dir}/inter/ltu/xml/multi/v3");
|
|
|
|
// pre-defined paths configuration in format (catalog_name, catalog_path)
|
|
let v3_catalogs = vec![
|
|
(
|
|
"recommend",
|
|
format!("{ltu_v3_dir}/event/event_v3/active_promotions.lxml"),
|
|
),
|
|
(
|
|
"coffee",
|
|
format!("{ltu_v3_dir}/page_catalog_group_coffee.lxml"),
|
|
),
|
|
("milk", format!("{ltu_v3_dir}/page_catalog_group_milk.lxml")),
|
|
("tea", format!("{ltu_v3_dir}/page_catalog_group_tea.lxml")),
|
|
(
|
|
"health",
|
|
format!("{ltu_v3_dir}/page_catalog_group_health.lxml"),
|
|
),
|
|
(
|
|
"other",
|
|
format!("{ltu_v3_dir}/page_catalog_group_other.lxml"),
|
|
),
|
|
];
|
|
|
|
// input must be `Vec<(&str, String)>`
|
|
let mut v3_catalog_nodes: IndexMap<String, Vec<Node>> =
|
|
generate_nodes_from_xml(v3_catalogs)?;
|
|
|
|
for (_, (catalog_name, catalog_nodes)) in v3_catalog_nodes.iter().enumerate() {
|
|
if catalog_nodes.len() == 1
|
|
&& let Some(root_node) = catalog_nodes.first()
|
|
{
|
|
// get_path is a macro for accessing the node inner child
|
|
//
|
|
// usage: get_path!(root_node, key1.key2.key3...);
|
|
//
|
|
let current_menus_result: Option<&Node> = get_path!(root_node, ScrollableCatalog.Menus);
|
|
if let Some(current_menus) = current_menus_result {
|
|
println!(
|
|
"Name={},file=page_catalog_group_{}.skt",
|
|
catalog_name, catalog_name
|
|
);
|
|
|
|
let ccm = current_menus.clone();
|
|
|
|
for menu_block in ccm.children.clone() {
|
|
let mut name_row = String::from("\tname\t");
|
|
let mut desc_row = String::from("\tdesc\t");
|
|
let mut img_row = String::from("\timg\t");
|
|
|
|
let tag_filter_option = get_path!(menu_block, TagFilter);
|
|
let idle_image_tag = match get_path!(menu_block, IdleImage) {
|
|
Some(img_path) => {
|
|
let img_path = img_path.clone().value.unwrap_or("".to_string());
|
|
let img_path_spl: Vec<String> = img_path
|
|
.trim()
|
|
.replace("\"", "")
|
|
.split("/")
|
|
.map(|x| x.to_string())
|
|
.collect();
|
|
img_path_spl
|
|
.last()
|
|
.unwrap()
|
|
.replace("[amp]", "&")
|
|
.to_string()
|
|
}
|
|
None => "".to_string(),
|
|
};
|
|
|
|
img_row.push_str(format!("{idle_image_tag}\t-\t-\t-\t\t\t||||||||||||||||||||||||||\t||||||||||||||||||||||||||\t||||||||||||||||||||||||||\t\t\t\t\t\t\t\t-\t-\t-\t-\t-\t").as_str());
|
|
|
|
let hot_state_val = match get_path!(menu_block, HotState) {
|
|
Some(state) => state
|
|
.clone()
|
|
.value
|
|
.and_then(|x| {
|
|
if x.to_string().contains("Disable2") {
|
|
return Some("-".to_string());
|
|
} else {
|
|
return Some(x.replace("$", "").replace(".Button", ""));
|
|
}
|
|
})
|
|
.unwrap()
|
|
.trim()
|
|
.to_string(),
|
|
None => "-".to_string(),
|
|
};
|
|
let ice_state_val = match get_path!(menu_block, IceState) {
|
|
Some(state) => state
|
|
.clone()
|
|
.value
|
|
.and_then(|x| {
|
|
if x.to_string().contains("Disable2") {
|
|
return Some("-".to_string());
|
|
} else {
|
|
return Some(x.replace("$", "").replace(".Button", ""));
|
|
}
|
|
})
|
|
.unwrap()
|
|
.trim()
|
|
.to_string(),
|
|
None => "-".to_string(),
|
|
};
|
|
let blend_state_val = match get_path!(menu_block, BlendState) {
|
|
Some(state) => state
|
|
.clone()
|
|
.value
|
|
.and_then(|x| {
|
|
if x.to_string().contains("Disable2") {
|
|
return Some("-".to_string());
|
|
} else {
|
|
return Some(x.replace("$", "").replace(".Button", ""));
|
|
}
|
|
})
|
|
.unwrap()
|
|
.trim()
|
|
.to_string(),
|
|
None => "-".to_string(),
|
|
};
|
|
|
|
let names = match get_path!(menu_block, Name.LanguageGroup) {
|
|
Some(names) => names.clone(),
|
|
None => Node::default(),
|
|
};
|
|
|
|
// Description
|
|
let descs = match get_path!(menu_block, Description.LanguageGroup) {
|
|
Some(descs) => descs.clone(),
|
|
None => Node::default(),
|
|
};
|
|
|
|
for name in names.children.clone() {
|
|
if let Some(value) = name.value {
|
|
name_row.push_str(format!("{value}\t").replace("[amp]", "&").as_str());
|
|
} else {
|
|
name_row.push_str(format!("\t").as_str());
|
|
}
|
|
}
|
|
|
|
name_row.push_str(
|
|
format!(
|
|
"{},-\t{},-\t{},-\t\t\t\t\t\t\t\t-\t-\t-\t-\t{}",
|
|
hot_state_val,
|
|
ice_state_val,
|
|
blend_state_val,
|
|
tag_filter_option
|
|
.clone()
|
|
.unwrap_or(&Node::default())
|
|
.value
|
|
.clone()
|
|
.unwrap_or("-".to_string())
|
|
.trim()
|
|
.replace("\"", "")
|
|
)
|
|
.as_str(),
|
|
);
|
|
|
|
for desc in descs.children.clone() {
|
|
if let Some(value) = desc.value {
|
|
desc_row.push_str(format!("{value}\t").replace("[amp]", "&").as_str());
|
|
} else {
|
|
desc_row.push_str(format!("\t").as_str());
|
|
}
|
|
}
|
|
|
|
desc_row.push_str(
|
|
format!(
|
|
"||||||||||||||||||||||||||\t||||||||||||||||||||||||||\t||||||||||||||||||||||||||\t\t\t\t\t\t\t\t-\t-\t-\t-\t-\t"
|
|
)
|
|
.as_str(),
|
|
);
|
|
|
|
//||||||||||||||||||||||||||
|
|
|
|
println!("{name_row}");
|
|
println!("{desc_row}");
|
|
println!("{img_row}");
|
|
|
|
println!("");
|
|
}
|
|
|
|
// name Americano อเมริกาโน Amerikano Americano 59-01-01-0003,59-21-01-0003 59-01-02-0001,59-21-02-0001 -,- - - Signature - CoffeeNoMilk,Recommend
|
|
// desc Espresso, Water กาแฟ และน้ำ Espresas, vanduo Espresso, Apă |||||||||||||||||||||||||| |||||||||||||||||||||||||| |||||||||||||||||||||||||| - - - - -
|
|
// img bn_hot_americano.png - bn_hot_america_no.png bn_hot_america_no.png posi1 |||||||||||||||||||||||||| |||||||||||||||||||||||||| - - - - -
|
|
}
|
|
}
|
|
}
|
|
```
|