Compare commits

...

6 Commits

Author SHA1 Message Date
yuvlian
89b8e5f0ef default trait because i felt like it 2026-02-21 14:31:55 +07:00
yuvlian
633228af42 anyhow, cargo fmt 2026-02-21 14:25:20 +07:00
yuvlian
603ebb826c test messy res -> types::item 2026-02-21 14:06:28 +07:00
yuvlian
cac15def52 update image struct 2026-02-21 11:26:26 +07:00
yuvlian
0e70a0bb48 add copy trait for copyable 2026-02-14 17:56:14 +07:00
yuvlian
448bbe5bda singleton macro thing 2026-02-14 17:55:54 +07:00
13 changed files with 273 additions and 45 deletions

1
.gitignore vendored
View File

@@ -1,2 +1,3 @@
**/target
**/*.lock
Resources-DUMP

View File

@@ -4,4 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
anyhow = "1.0.102"
paste = "1.0.15"
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"

View File

@@ -3,5 +3,10 @@ mod singleton;
mod types;
fn main() {
println!("Hello, world!");
let tm = res_parser::text_map::TextMaps::parse().unwrap();
let item_search = res_parser::item::ItemConfigs::parse_to_api_type(&tm).unwrap();
singleton::set_item_search(item_search).ok();
let stellar_jade = singleton::get_item_mini_by_id(&1).unwrap();
dbg!(stellar_jade);
println!("{}", res_parser::common::Hash::from_str("HelLONi1"));
}

View File

@@ -0,0 +1,27 @@
use serde::{Deserialize, Serialize};
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Hash {
#[serde(rename = "Hash")]
pub hash: i32,
}
impl Hash {
pub const fn from_str(s: &str) -> i32 {
let mut hash1 @ mut hash2 = 5381i32;
let bytes = s.as_bytes();
let length = bytes.len();
let mut i = 0;
while i < length {
hash1 = ((hash1 << 5).wrapping_add(hash1)) ^ (bytes[i] as i32);
if i + 1 < length {
hash2 = ((hash2 << 5).wrapping_add(hash2)) ^ (bytes[i + 1] as i32);
}
i += 2;
}
hash1.wrapping_add(hash2.wrapping_mul(1566083941))
}
}

View File

@@ -0,0 +1,50 @@
use super::common::Hash;
use super::text_map::TextMaps;
use crate::types::common::Image;
use crate::types::item::{ItemMini, ItemSearch};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ItemConfigs(pub Vec<ItemConfig>);
impl ItemConfigs {
pub fn parse_to_api_type(tm: &TextMaps) -> Result<ItemSearch> {
let path = "../Resources-DUMP/ExcelOutput/ItemConfig.json";
let file = std::fs::File::open(path).with_context(|| format!("Failed to open {}", path))?;
let reader = std::io::BufReader::new(file);
let cfg: Vec<ItemConfig> =
serde_json::from_reader(reader).with_context(|| format!("Failed to parse {}", path))?;
let item_search = cfg
.into_iter()
.map(|item| {
let id = item.id;
let name = tm.get_by_hash(item.item_name).unwrap_or_default();
let img = Image {
path: String::new(),
filename: String::new(),
author_info: None,
};
(
id,
ItemMini {
name: name.text.clone(),
image: img,
},
)
})
.collect();
Ok(ItemSearch(item_search))
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ItemConfig {
#[serde(rename = "ID")]
pub id: i32,
#[serde(rename = "ItemName")]
pub item_name: Hash,
}

View File

@@ -1 +1,3 @@
// TODO
pub mod common;
pub mod item;
pub mod text_map;

View File

@@ -0,0 +1,48 @@
use super::common::Hash;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fs::File;
use std::io::BufReader;
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct TextMaps(HashMap<i32, TextMap>);
impl TextMaps {
pub fn parse() -> Result<Self> {
let path = "../Resources-DUMP/TextMap/TextMapEN.json";
let file = File::open(path).with_context(|| format!("Failed to open {}", path))?;
let reader = BufReader::new(file);
let v: Vec<TextMap> =
serde_json::from_reader(reader).with_context(|| format!("Failed to parse {}", path))?;
let map = v.into_iter().map(|t| (t.id.hash, t)).collect();
Ok(TextMaps(map))
}
pub fn get_by_str(&self, s: &str) -> Option<TextMap> {
let hash = Hash::from_str(s);
self.get_by_i32(hash)
}
pub fn get_by_i32(&self, i: i32) -> Option<TextMap> {
self.get_by_hash(Hash { hash: i })
}
pub fn get_by_hash(&self, h: Hash) -> Option<TextMap> {
if h.hash == 0 {
return None;
}
self.0.get(&h.hash).cloned()
}
}
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct TextMap {
#[serde(rename = "ID")]
pub id: Hash,
#[serde(rename = "Text")]
pub text: String,
#[serde(rename = "HasParam")]
pub has_param: bool,
}

View File

@@ -1 +1,70 @@
// TODO
#![allow(unused)]
use crate::types::{
CharacterDetail, CharacterFull, CharacterMini, CharacterSearch, Id, ItemMini, ItemSearch,
LightconeDetail, LightconeFull, LightconeMini, LightconeSearch, RelicMini, RelicSearch,
};
use paste::paste;
use std::sync::OnceLock;
macro_rules! define_data_store {
($base:ident, full) => {
paste::item! {
pub static [<$base:upper _DETAIL>]: OnceLock<[<$base Detail>]> = OnceLock::new();
pub static [<$base:upper _SEARCH>]: OnceLock<[<$base Search>]> = OnceLock::new();
pub fn [<get_ $base:lower _detail>]() -> &'static [<$base Detail>] {
[<$base:upper _DETAIL>]
.get()
.expect(concat!(stringify!([<$base:upper _DETAIL>]), " not initialized"))
}
pub fn [<get_ $base:lower _search>]() -> &'static [<$base Search>] {
[<$base:upper _SEARCH>]
.get()
.expect(concat!(stringify!([<$base:upper _SEARCH>]), " not initialized"))
}
pub fn [<get_ $base:lower full_by_id>](id: &Id) -> Option<&[<$base Full>]> {
[<get_ $base:lower _detail>]().0.get(id)
}
pub fn [<get_ $base:lower _mini_by_id>](id: &Id) -> Option<&[<$base Mini>]> {
[<get_ $base:lower _search>]().0.get(id)
}
pub fn [<set_ $base:lower _detail>](data: [<$base Detail>]) -> Result<(), [<$base Detail>]> {
[<$base:upper _DETAIL>].set(data)
}
pub fn [<set_ $base:lower _search>](data: [<$base Search>]) -> Result<(), [<$base Search>]> {
[<$base:upper _SEARCH>].set(data)
}
}
};
($base:ident, mini) => {
paste::item! {
pub static [<$base:upper _SEARCH>]: OnceLock<[<$base Search>]> = OnceLock::new();
pub fn [<get_ $base:lower _search>]() -> &'static [<$base Search>] {
[<$base:upper _SEARCH>]
.get()
.expect(concat!(stringify!([<$base:upper _SEARCH>]), " not initialized"))
}
pub fn [<get_ $base:lower _mini_by_id>](id: &Id) -> Option<&[<$base Mini>]> {
[<get_ $base:lower _search>]().0.get(id)
}
pub fn [<set_ $base:lower _search>](data: [<$base Search>]) -> Result<(), [<$base Search>]> {
[<$base:upper _SEARCH>].set(data)
}
}
};
}
define_data_store!(Character, full);
define_data_store!(Lightcone, full);
define_data_store!(Relic, mini);
define_data_store!(Item, mini);

View File

@@ -1,39 +1,39 @@
use super::common::{
Ascension, Count, Desc, Element, Id, Level, Path, Rarity, StatType, StatValue, Uri,
Ascension, Count, Desc, Element, Id, Image, Level, Path, Rarity, StatType, StatValue,
};
use super::item::ItemMini;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Eidolon {
pub name: String,
pub desc: Desc,
pub img_url: Uri,
pub image: Image,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CharacterSearch(pub BTreeMap<Id, CharacterMini>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CharacterMini {
pub name: String,
pub path: Path,
pub rarity: Rarity,
pub element: Element,
pub img_url: Uri,
pub image: Image,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CharacterDetail(pub HashMap<Id, CharacterFull>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct CharacterFull {
pub name: String,
pub path: Path,
pub rarity: Rarity,
pub element: Element,
pub img_url: String,
pub images: Vec<Image>,
pub max_hp: StatValue,
pub max_def: StatValue,
pub max_atk: StatValue,

View File

@@ -4,17 +4,29 @@ pub type Id = i32;
pub type Level = i32;
pub type Count = i32;
pub type Desc = String;
pub type Uri = String;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct Image {
pub path: String,
pub filename: String,
pub author_info: Option<String>,
}
#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum StatValue {
#[default]
NoneType,
Flat(f32),
Percent(f32),
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum StatType {
#[default]
NoneType = 0,
Aggro = 1,
AtkFlat = 2,
AtkPercent = 3,
@@ -42,17 +54,25 @@ pub enum StatType {
Vulnerability = 25,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum Ascension {
#[default]
NoneType = 0,
A2 = 1,
A4 = 2,
A6 = 3,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum Path {
#[default]
NoneType = 0,
Destruction = 1,
Hunt = 2,
Erudition = 3,
@@ -64,17 +84,25 @@ pub enum Path {
Elation = 9,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum Rarity {
#[default]
NoneType = 0,
ThreeStar = 3,
FourStar = 4,
FiveStar = 5,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum Element {
#[default]
NoneType = 0,
Physical = 1,
Fire = 2,
Ice = 3,
@@ -84,9 +112,13 @@ pub enum Element {
Imaginary = 7,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(
Default, Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash,
)]
#[repr(u8)]
pub enum RelicType {
#[default]
NoneType = 0,
Relic = 1,
Planar = 2,
}

View File

@@ -1,12 +1,12 @@
use super::common::{Id, Uri};
use super::common::{Id, Image};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ItemSearch(pub BTreeMap<Id, ItemMini>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct ItemMini {
pub name: String,
pub img_url: Uri,
pub image: Image,
}

View File

@@ -1,28 +1,28 @@
use super::common::{Count, Desc, Id, Level, Path, Rarity, StatValue, Uri};
use super::common::{Count, Desc, Id, Image, Level, Path, Rarity, StatValue};
use super::item::ItemMini;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct LightconeSearch(pub BTreeMap<Id, LightconeMini>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct LightconeMini {
pub name: String,
pub path: Path,
pub rarity: Rarity,
pub img_url: Uri,
pub image: Image,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct LightconeDetail(pub HashMap<Id, LightconeFull>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct LightconeFull {
pub name: String,
pub path: Path,
pub rarity: Rarity,
pub img_url: Uri,
pub images: Vec<Image>,
pub max_hp: StatValue,
pub max_def: StatValue,
pub max_atk: StatValue,

View File

@@ -1,25 +1,16 @@
use super::common::{Desc, Id, RelicType, Uri};
use super::common::{Desc, Id, Image, RelicType};
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RelicSearch(pub BTreeMap<Id, RelicMini>);
#[derive(Debug, Clone, Serialize, Deserialize)]
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct RelicMini {
pub name: String,
pub r#type: RelicType,
pub img_url: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelicDetail(pub HashMap<Id, RelicFull>);
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelicFull {
pub name: String,
pub r#type: RelicType,
pub img_url: Uri,
pub image: Image,
// lets just display these in the search page
pub two_pc: Desc,
pub four_pc: Option<Desc>,
}