Skip to content

Commit 169b9ce

Browse files
graylikemeclaude
andcommitted
fix: correct off-by-one rules level mapping in MegaMek parser
MegaMek uses 1-based rules level numbering (1=Introductory through 5=Unofficial) but both from_int and from_type_str were treating values as 0-based, shifting every unit up one level. This resulted in zero Introductory units in the database. Also adds Level 4/5 and Advanced/Experimental keyword handling for BLK Mixed types. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b8c4f1b commit 169b9ce

1 file changed

Lines changed: 75 additions & 10 deletions

File tree

crates/scraper/src/parse.rs

Lines changed: 75 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -108,29 +108,35 @@ pub enum RulesLevel {
108108
}
109109

110110
impl RulesLevel {
111-
/// Parse from the integer used in MTF `rules level:N`
111+
/// Parse from the integer used in MTF `rules level:N` (MegaMek uses 1-based numbering)
112112
pub fn from_int(n: i32) -> Self {
113113
match n {
114-
0 => RulesLevel::Introductory,
115-
1 => RulesLevel::Standard,
116-
2 => RulesLevel::Advanced,
117-
3 => RulesLevel::Experimental,
118-
4 | 5 => RulesLevel::Unofficial,
114+
1 => RulesLevel::Introductory,
115+
2 => RulesLevel::Standard,
116+
3 => RulesLevel::Advanced,
117+
4 => RulesLevel::Experimental,
118+
5 => RulesLevel::Unofficial,
119119
_ => RulesLevel::Standard,
120120
}
121121
}
122122

123-
/// Parse from the BLK `<type>` string like "IS Level 2"
123+
/// Parse from the BLK `<type>` string like "IS Level 2" or "Mixed (IS Chassis) Advanced"
124124
pub fn from_type_str(s: &str) -> Self {
125125
let lower = s.to_lowercase();
126126
if lower.contains("level 1") {
127-
RulesLevel::Standard
127+
RulesLevel::Introductory
128128
} else if lower.contains("level 2") {
129-
RulesLevel::Advanced
129+
RulesLevel::Standard
130130
} else if lower.contains("level 3") {
131+
RulesLevel::Advanced
132+
} else if lower.contains("level 4") {
131133
RulesLevel::Experimental
132-
} else if lower.contains("unofficial") {
134+
} else if lower.contains("level 5") || lower.contains("unofficial") {
133135
RulesLevel::Unofficial
136+
} else if lower.contains("experimental") {
137+
RulesLevel::Experimental
138+
} else if lower.contains("advanced") {
139+
RulesLevel::Advanced
134140
} else {
135141
RulesLevel::Standard
136142
}
@@ -814,3 +820,62 @@ pub fn equipment_tech_base(name: &str) -> &'static str {
814820
"inner_sphere"
815821
}
816822
}
823+
824+
#[cfg(test)]
825+
mod tests {
826+
use super::*;
827+
828+
#[test]
829+
fn from_int_maps_megamek_1based_values() {
830+
assert_eq!(RulesLevel::from_int(1), RulesLevel::Introductory);
831+
assert_eq!(RulesLevel::from_int(2), RulesLevel::Standard);
832+
assert_eq!(RulesLevel::from_int(3), RulesLevel::Advanced);
833+
assert_eq!(RulesLevel::from_int(4), RulesLevel::Experimental);
834+
assert_eq!(RulesLevel::from_int(5), RulesLevel::Unofficial);
835+
}
836+
837+
#[test]
838+
fn from_int_defaults_to_standard() {
839+
assert_eq!(RulesLevel::from_int(0), RulesLevel::Standard);
840+
assert_eq!(RulesLevel::from_int(6), RulesLevel::Standard);
841+
assert_eq!(RulesLevel::from_int(-1), RulesLevel::Standard);
842+
}
843+
844+
#[test]
845+
fn from_type_str_is_levels() {
846+
assert_eq!(RulesLevel::from_type_str("IS Level 1"), RulesLevel::Introductory);
847+
assert_eq!(RulesLevel::from_type_str("IS Level 2"), RulesLevel::Standard);
848+
assert_eq!(RulesLevel::from_type_str("IS Level 3"), RulesLevel::Advanced);
849+
assert_eq!(RulesLevel::from_type_str("IS Level 4"), RulesLevel::Experimental);
850+
assert_eq!(RulesLevel::from_type_str("IS Level 5"), RulesLevel::Unofficial);
851+
}
852+
853+
#[test]
854+
fn from_type_str_clan_levels() {
855+
assert_eq!(RulesLevel::from_type_str("Clan Level 2"), RulesLevel::Standard);
856+
assert_eq!(RulesLevel::from_type_str("Clan Level 3"), RulesLevel::Advanced);
857+
assert_eq!(RulesLevel::from_type_str("Clan Level 4"), RulesLevel::Experimental);
858+
assert_eq!(RulesLevel::from_type_str("Clan Level 5"), RulesLevel::Unofficial);
859+
}
860+
861+
#[test]
862+
fn from_type_str_mixed_with_keywords() {
863+
assert_eq!(RulesLevel::from_type_str("Mixed (IS Chassis) Advanced"), RulesLevel::Advanced);
864+
assert_eq!(RulesLevel::from_type_str("Mixed (IS Chassis) Experimental"), RulesLevel::Experimental);
865+
assert_eq!(RulesLevel::from_type_str("Mixed (Clan Chassis) Advanced"), RulesLevel::Advanced);
866+
assert_eq!(RulesLevel::from_type_str("Mixed (Clan Chassis) Experimental"), RulesLevel::Experimental);
867+
}
868+
869+
#[test]
870+
fn from_type_str_defaults_to_standard() {
871+
assert_eq!(RulesLevel::from_type_str("Mixed (IS Chassis)"), RulesLevel::Standard);
872+
assert_eq!(RulesLevel::from_type_str("Mixed (Clan Chassis)"), RulesLevel::Standard);
873+
assert_eq!(RulesLevel::from_type_str("IS"), RulesLevel::Standard);
874+
assert_eq!(RulesLevel::from_type_str("Clan"), RulesLevel::Standard);
875+
}
876+
877+
#[test]
878+
fn from_type_str_unofficial() {
879+
assert_eq!(RulesLevel::from_type_str("IS Unofficial"), RulesLevel::Unofficial);
880+
}
881+
}

0 commit comments

Comments
 (0)