tiger_lib/vic3/data/
provinces.rs1use std::path::PathBuf;
2
3use image::{DynamicImage, Rgb};
4use itertools::Itertools;
5
6use crate::everything::Everything;
7use crate::fileset::{FileEntry, FileHandler};
8use crate::helpers::TigerHashSet;
9use crate::item::{Item, ItemExt};
10use crate::parse::ParserMemory;
11use crate::report::{ErrorKey, Severity, err, report};
12use crate::token::Token;
13
14#[derive(Clone, Debug, Default)]
15pub struct Vic3Provinces {
16 colors: TigerHashSet<Rgb<u8>>,
18
19 provinces_png: Option<FileEntry>,
21}
22
23impl Vic3Provinces {
24 pub fn verify_exists_implied(&self, key: &str, item: &Token, max_sev: Severity) {
25 if !self.exists(key) {
26 let msg = "province not found on map";
28 let sev = Item::Province.severity().at_most(max_sev);
29 report(ErrorKey::MissingItem, sev).msg(msg).loc(item).push();
30 }
31 }
32
33 pub fn exists(&self, key: &str) -> bool {
34 if self.provinces_png.is_none() {
36 return true;
37 }
38 if key.len() != 7 {
39 return false; }
41 if let Some(hexid) = key.strip_prefix('x')
42 && let Ok(r) = u8::from_str_radix(&hexid[0..2], 16)
43 && let Ok(g) = u8::from_str_radix(&hexid[2..4], 16)
44 && let Ok(b) = u8::from_str_radix(&hexid[4..6], 16)
45 {
46 return self.colors.contains(&Rgb([r, g, b]));
47 }
48 false
49 }
50
51 #[allow(clippy::unused_self)]
52 pub fn validate(&self, _data: &Everything) {}
53}
54
55impl FileHandler<DynamicImage> for Vic3Provinces {
56 fn subpath(&self) -> PathBuf {
57 PathBuf::from("map_data/provinces.png")
58 }
59
60 fn load_file(&self, entry: &FileEntry, _parser: &ParserMemory) -> Option<DynamicImage> {
61 if entry.path().components().count() == 2 {
62 let img = match image::open(entry.fullpath()) {
63 Ok(img) => img,
64 Err(e) => {
65 let msg = format!("could not read `{}`: {e:#}", entry.path().display());
66 err(ErrorKey::ReadError).msg(msg).loc(entry).push();
68 return None;
69 }
70 };
71 if let DynamicImage::ImageRgb8(_) = img {
72 return Some(img);
73 }
74 let msg = format!(
75 "`{}` has wrong color format `{:?}`, should be Rgb8",
76 entry.path().display(),
77 img.color()
78 );
79 err(ErrorKey::ImageFormat).msg(msg).loc(entry).push();
81 }
82 None
83 }
84
85 fn handle_file(&mut self, entry: &FileEntry, img: DynamicImage) {
86 self.provinces_png = Some(entry.clone());
87 if let DynamicImage::ImageRgb8(img) = img {
88 for pixel in img.pixels().dedup() {
89 self.colors.insert(*pixel);
90 }
91 }
92 }
93}