sct_reader/loaders/euroscope/
loader.rs1use std::{collections::HashMap, fs::File, io::{BufRead, BufReader}, path::{Path, PathBuf}, str::FromStr};
2use std::fs::read_dir;
3use anyhow::Context;
4use directories::UserDirs;
5
6use crate::loaders::ese::{self, reader::EseReader, Ese};
7
8use super::{colour::Colour, reader::SctReader, sector::Sector, symbology::{SymbologyAttribute, SymbologyInfo, SymbologyItem}, EsAsr};
9
10#[derive(Debug, Default)]
11pub struct EuroScopeResultProfile {
12 pub prf_name: String,
13 pub prf_file: String,
14 pub default_sector_id: String,
15 pub symbology: SymbologyInfo,
16 pub asrs: HashMap<String, EsAsr>
17}
18
19#[derive(Debug, Default)]
20pub struct EuroScopeResult {
21 pub profiles: Vec<EuroScopeResultProfile>,
22 pub sectors: HashMap<String, (Sector, Option<Ese>)>,
23}
24
25#[derive(Debug)]
26pub struct EuroScopeLoader {
27 pub prfs: Vec<EuroScopeLoaderPrf>
28}
29
30#[derive(Debug)]
31pub struct EuroScopeLoaderPrf {
32 pub prf_file: String,
33 pub symbology_file: String,
34 pub sector_file: String,
35 pub asr_files: Vec<(String, String)>
36}
37
38impl EuroScopeLoaderPrf {
39 pub fn try_new_from_prf(prf_file: impl AsRef<Path>) -> anyhow::Result<EuroScopeLoaderPrf> {
40 let mut symbology_file = "".to_string();
42 let mut sector_file = "".to_string();
43 let mut asrs: Vec<(String, String)> = Vec::new();
44
45 let reader = BufReader::new(File::open(&prf_file)?);
47
48 for line in reader.lines() {
49 if let Ok(ln) = line {
50 let items = ln.split("\t").collect::<Vec<&str>>();
51 if items.len() > 0 {
52 match items[0].to_lowercase().as_str() {
53 "settings" => {
54 if items.len() >= 3 {
55 match items[1].to_lowercase().as_str() {
56 "settingsfilesymbology" => {
57 symbology_file =
58 EuroScopeLoader::try_convert_es_path(&prf_file, items[2])?
59 .canonicalize()?
60 .to_str()
61 .unwrap()
62 .to_owned();
63 }
64 "sector" => {
65 sector_file =
66 EuroScopeLoader::try_convert_es_path(&prf_file, items[2])?
67 .canonicalize().context(format!("Error opening sector file {:?}!", items[2]))?
68 .to_str()
69 .unwrap()
70 .to_owned();
71 }
72 &_ => {}
73 }
74 }
75 }
76 "asrfastkeys" => {
77 let asr_path = EuroScopeLoader::try_convert_es_path(&prf_file, items[2]);
78 if let Ok(asr_path_res) = asr_path {
79 let canon_path = asr_path_res.canonicalize();
80 if let Ok(canon_res) = canon_path {
81 asrs.push((items[1].to_owned(), canon_res.to_str().unwrap().to_owned()));
82 }
83 }
84 },
85 &_ => {}
86 }
87 }
88 }
89 }
90
91 Ok(EuroScopeLoaderPrf {
92 prf_file: prf_file
93 .as_ref()
94 .canonicalize()?
95 .to_str()
96 .unwrap()
97 .to_string(),
98 symbology_file: symbology_file.to_string(),
99 sector_file: sector_file.to_string(),
100 asr_files: asrs
101 })
102 }
103}
104
105impl EuroScopeLoader {
106 pub fn try_new_from_dir(package_dir: impl AsRef<Path>) -> anyhow::Result<EuroScopeLoader> {
107 let mut results = Vec::new();
108 if package_dir.as_ref().is_dir() {
109 for entry in read_dir(package_dir)? {
110 let entry = entry?;
111 let path = entry.path();
112 if path.is_dir() {
113 results.append(&mut Self::try_new_from_dir(&path)?.prfs);
114 } else if entry.file_name().to_str().unwrap().contains(".prf"){
115 if let Ok(result) = EuroScopeLoaderPrf::try_new_from_prf(&path) {
116 results.push(result);
117 }
118 }
119 }
120 }
121
122 Ok(EuroScopeLoader {
123 prfs: results
124 })
125 }
126
127 pub fn try_read(&mut self) -> anyhow::Result<EuroScopeResult> {
128 let mut ret_val = EuroScopeResult::default();
129
130 for prf in &self.prfs {
131 let mut res_prf = EuroScopeResultProfile::default();
132
133 res_prf.prf_file = prf.prf_file.to_string();
134 res_prf.prf_name = Path::new(&prf.prf_file).file_stem().unwrap_or_default().to_str().unwrap().to_string();
135
136 res_prf.symbology = SymbologyInfo::try_from_file(&prf.symbology_file)?;
138
139 res_prf.default_sector_id = prf.sector_file.to_string();
140
141 if (!ret_val.sectors.contains_key(&prf.sector_file)){
143 let sct_reader = SctReader::new(BufReader::new(File::open(&prf.sector_file)?));
144 let sct_result = sct_reader.try_read()?;
145 let ese_file = prf.sector_file.replace(".sct", ".ese");
146 let sct_ese_result = match std::fs::exists(&ese_file) {
147 Ok(true) => {
148 if let Ok(file) = File::open(&ese_file) {
149 let reader = EseReader::new(BufReader::new(file));
150 reader.try_read().ok()
151 } else{
152 None
153 }
154 },
155 _ => None
156 };
157
158 ret_val.sectors.insert(prf.sector_file.to_string(), (sct_result, sct_ese_result));
159 }
160
161 for asr_source in &prf.asr_files {
163 let mut asr = EsAsr::try_from_asr_file(&asr_source.1)?;
164 if !asr.1.is_empty() {
165 if let Ok(asr_sector_pbuf) = Self::try_convert_es_path(&prf.prf_file, &asr.1)?.canonicalize() {
166 let asr_sector_path = asr_sector_pbuf.as_os_str().to_str().unwrap_or_default().to_string();
167 if !ret_val.sectors.contains_key(&asr_sector_path) {
168 let asr_sct_reader = SctReader::new(BufReader::new(File::open(&asr_sector_path)?));
169 let asr_sct_result = asr_sct_reader.try_read()?;
170
171 let asr_ese_file = asr_sector_path.replace(".sct", ".ese");
172 let asr_sct_ese_result = match std::fs::exists(&asr_ese_file) {
173 Ok(true) => {
174 if let Ok(file) = File::open(&asr_ese_file) {
175 let reader = EseReader::new(BufReader::new(file));
176 reader.try_read().ok()
177 } else {
178 None
179 }
180 },
181 _ => None
182 };
183 ret_val.sectors.insert(asr_sector_path.to_string(), (asr_sct_result, asr_sct_ese_result));
184 }
185 asr.0.sector_file_id = Some(asr_sector_path.to_string());
186 } else {
187 asr.0.sector_file_id = Some(res_prf.default_sector_id.clone());
188 }
189 } else {
190 asr.0.sector_file_id = Some(res_prf.default_sector_id.clone());
191 }
192 asr.0.name = Path::new(&asr_source.1).file_stem().unwrap_or_default().to_str().unwrap().to_string();
193
194 res_prf.asrs.insert(asr_source.0.to_string(), asr.0);
195 }
196
197 ret_val.profiles.push(res_prf);
198 }
199
200 Ok(ret_val)
201 }
202
203 pub fn try_convert_es_path(
204 prf_file_path: impl AsRef<Path>,
205 es_path: &str,
206 ) -> anyhow::Result<PathBuf> {
207 let split_es_path = es_path.split("\\").collect::<Vec<&str>>();
208 let mut new_es_path = PathBuf::from("");
209 for item in &split_es_path {
210 new_es_path.push(item);
211 }
212
213 if split_es_path.len() > 0 && split_es_path[0] == "" {
215 return Ok(prf_file_path
216 .as_ref()
217 .parent()
218 .context("Could not get parent dir of prf file!")?
219 .join(new_es_path));
220 }
221
222 let path =
223 directories::BaseDirs::new()
224 .context("Failed to get User Directories")?
225 .config_dir()
226 .join("EuroScope")
227 .join(new_es_path.clone());
228
229
230 if path.exists() {
231 return Ok(path);
232 }
233
234 Ok(UserDirs::new()
235 .context("Failed to get User Directories")?
236 .document_dir()
237 .context("Could not get Documents dir!")?
238 .join("EuroScope")
239 .join(new_es_path))
240 }
241}