1use crate::p02::DayLoadProf;
2use crate::p02::DrawLoadProf;
3use crate::p02::FeederLoadProf;
4use crate::p02::LoadProf;
5use crate::p02::SubLoadProf;
6use crate::p02::DAY_VAL_PNTS;
7use bincode::{Decode, Encode};
8use std::collections::HashMap;
9use std::error::Error;
10pub const LOAD_PROF_MIN_DAYS: usize = 5;
11pub const LOAD_PROF_MAX_DAYS: usize = 30;
12pub const LOAD_PROF_MIN_HOUR: usize = 18;
13
14impl DayLoadProf {
15 fn is_valid(&self) -> bool {
16 let mut hrls = vec![];
17 for (vi, v) in self.val.iter().enumerate() {
18 if v.is_some() {
19 let hr = vi / 4;
20 if !hrls.contains(&hr) {
21 hrls.push(vi);
22 }
23 }
24 }
25 hrls.len() > LOAD_PROF_MIN_HOUR
26 }
27}
28
29pub fn p03_calc_lp_1(lp: &FeederLoadProf) -> Result<(Vec<usize>, Vec<usize>), Box<dyn Error>> {
30 let mut po_lst = Vec::<(f32, usize)>::new();
31 let mut ne_lst = Vec::<(f32, usize)>::new();
32 for (di, dlp) in lp.days.iter().enumerate() {
33 if let Some(dlp) = dlp {
34 let mut po_pw = 0.0;
35 let mut ne_pw = 0.0;
36 for v in dlp.val.into_iter().flatten() {
37 if v > 0.0 {
38 po_pw += v;
39 }
40 if v < 0.0 {
41 ne_pw += -v;
42 }
43 }
44 if po_pw > 0.0 {
45 po_lst.push((po_pw, di));
46 }
47 if ne_pw > 0.0 {
48 ne_lst.push((ne_pw, di));
49 }
50 }
51 }
52 po_lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
53 let mut po_lst2 = Vec::<usize>::new();
54 for (_v, i) in po_lst {
55 if let Some(dlp) = &lp.days[i] {
56 if !dlp.is_valid() {
57 break;
58 }
59 }
60 po_lst2.push(i);
61 }
62 ne_lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
63 let mut ne_lst2 = Vec::<usize>::new();
64 for (_v, i) in ne_lst {
65 if let Some(dlp) = &lp.days[i] {
66 if !dlp.is_valid() {
67 break;
68 }
69 }
70 ne_lst2.push(i);
71 }
72 Ok((po_lst2, ne_lst2))
73}
74
75#[derive(Encode, Decode, PartialEq, Debug, Clone, Default)]
76pub struct LoadProfRepr {
77 pub val: Option<[Option<f32>; DAY_VAL_PNTS]>,
78 pub rep: Option<Vec<usize>>,
79}
80
81#[derive(Encode, Decode, PartialEq, Debug, Clone, Default)]
82pub struct SubLoadProfRepr {
83 pub sub: String,
84 pub year: String,
85 pub pos_rep: LoadProfRepr,
86 pub neg_rep: LoadProfRepr,
87}
88
89pub fn p03_draw_sub_av(
90 ldpf: &FeederLoadProf,
91 po: &[usize],
92 pn: &str,
93) -> Result<LoadProfRepr, Box<dyn Error>> {
94 let mut lpre = LoadProfRepr::default();
95 let s = ldpf.sub.to_string();
96 let f = ldpf.feed.to_string();
97 let yr = ldpf.year.to_string();
98 if po.len() >= LOAD_PROF_MIN_DAYS {
99 let mut avls = Vec::<usize>::new();
100 for ii in po.iter().take(LOAD_PROF_MAX_DAYS) {
101 avls.push(*ii);
102 }
103 let mut avdlp = ldpf.days[avls[0]].clone();
104 for ii in &avls[1..] {
105 let fdlp = &ldpf.days[*ii];
106 if let (Some(slp), Some(flp)) = (&mut avdlp, fdlp) {
107 for (sva, fva) in slp.val.iter_mut().zip(flp.val.iter()) {
108 if let (None, Some(fva)) = (&sva, &fva) {
109 *sva = Some(*fva);
110 } else if let (Some(sv), Some(fv)) = (&sva, &fva) {
111 *sva = Some(*sv + *fv);
112 }
113 }
114 }
115 }
116 let ln = avls.len() as f32;
117 if let Some(slp) = &mut avdlp {
118 for sva in slp.val.iter_mut() {
119 if let Some(sv) = &sva {
120 *sva = Some(*sv / ln);
121 }
122 }
123 let val = slp.val;
124 lpre.val = Some(slp.val);
125 lpre.rep = Some(avls.clone());
126 let dnm = format!("/mnt/e/CHMBACK/pea-data/sbdrlp/{yr}/{s}");
127 std::fs::create_dir_all(&dnm)?;
128 let fnm = format!("{dnm}/{s}-{f}-{pn}.jpg");
129 let sz = (400, 300);
131 let rf = Vec::<(String, f32)>::new();
132
133 let drlp = LoadProf {
134 lb1: s.to_string(),
135 lb2: yr.to_string(),
136 fnm,
137 val,
138 sz,
139 rf,
140 };
141 drlp.draw_prof()?;
142 }
143 }
144 Ok(lpre)
145}
146pub fn p03_load_lp(yr: &str) -> HashMap<String, SubLoadProfRepr> {
149 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p03_lp_repr_{yr}.bin");
151 let bytes = std::fs::read(fnm).unwrap();
152 let (subh, _): (HashMap<String, SubLoadProfRepr>, usize) =
153 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
154 subh
155}
156
157pub fn p03_calc_lp2(yr: &str, s: &str) -> Result<(), Box<dyn Error>> {
158 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p02_sub_lp_{yr}.bin");
159 let bytes = std::fs::read(fnm).unwrap();
160 let (subh, _): (HashMap<String, SubLoadProf>, usize) =
161 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
162
163 let mut p03_lp_repr = HashMap::<String, SubLoadProfRepr>::new();
164 {
166 let sub = subh.get(s).unwrap();
167 if let Some(ldpf) = &sub.ldpf {
168 print!("{s} ");
169 let (po, ne) = p03_calc_lp_1(ldpf)?;
170 let sbre = SubLoadProfRepr {
171 sub: s.to_string(),
172 year: yr.to_string(),
173 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
174 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
175 };
176 p03_lp_repr.insert(s.to_string(), sbre);
177
178 print!(" p:{} [", po.len());
179 for (pi, ii) in po.iter().enumerate() {
180 if pi >= LOAD_PROF_MIN_DAYS {
181 break;
182 }
183 if pi > 0 {
184 print!(",");
185 }
186 print!("{ii}");
187 }
188 print!("] n:{} [", ne.len());
189 for (ni, ii) in ne.iter().enumerate() {
190 if ni >= LOAD_PROF_MIN_DAYS {
191 break;
192 }
193 if ni > 0 {
194 print!(",");
195 }
196 print!("{ii}");
197 }
198 print!("]");
199 println!();
200 }
201 for ldpf in sub.fdldp.values() {
202 let f = &ldpf.feed;
203 let (po, ne) = p03_calc_lp_1(ldpf)?;
205 let sbre = SubLoadProfRepr {
206 sub: s.to_string(),
207 year: yr.to_string(),
208 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
209 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
210 };
211 p03_lp_repr.insert(format!("{s}-{f}"), sbre);
212 }
213 }
214 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p03_lp_repr_{yr}.bin");
215 println!("write pre {} to {fnm}", p03_lp_repr.len());
216 let bin: Vec<u8> = bincode::encode_to_vec(&p03_lp_repr, bincode::config::standard()).unwrap();
217 std::fs::write(fnm, bin).unwrap();
218 Ok(())
219}
220
221pub fn p03_calc_lp_3(lp: &FeederLoadProf) -> Result<(Vec<usize>, Vec<usize>), Box<dyn Error>> {
222 let mut po_lst = Vec::<(f32, usize)>::new();
223 let mut ne_lst = Vec::<(f32, usize)>::new();
224 for (di, dlp) in lp.days.iter().enumerate() {
225 if let Some(dlp) = dlp {
226 let mut po_pw = 0.0;
227 let mut ne_pw = 0.0;
228 for v in dlp.val.into_iter().flatten() {
229 if v > 0.0 {
230 po_pw += v;
231 }
232 if v < 0.0 {
233 ne_pw += -v;
234 }
235 }
236 if po_pw > 0.0 {
237 po_lst.push((po_pw, di));
238 }
239 if ne_pw > 0.0 {
240 ne_lst.push((ne_pw, di));
241 }
242 }
243 }
244 po_lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
245 let mut po_lst2 = Vec::<usize>::new();
246 for (_v, i) in po_lst {
247 if let Some(dlp) = &lp.days[i] {
248 if !dlp.is_valid() {
249 break;
250 }
251 }
252 po_lst2.push(i);
253 }
254 ne_lst.sort_by(|a, b| b.0.partial_cmp(&a.0).unwrap());
255 let mut ne_lst2 = Vec::<usize>::new();
256 for (_v, i) in ne_lst {
257 if let Some(dlp) = &lp.days[i] {
258 if !dlp.is_valid() {
259 break;
260 }
261 }
262 ne_lst2.push(i);
263 }
264 Ok((po_lst2, ne_lst2))
265}
266
267pub fn p03_calc_lp3(yr: &str) -> Result<(), Box<dyn Error>> {
268 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p02_sub_lp_{yr}.bin");
269 let bytes = std::fs::read(fnm).unwrap();
270 let (subh, _): (HashMap<String, SubLoadProf>, usize) =
271 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
272 let mut p03_lp_repr = HashMap::<String, SubLoadProfRepr>::new();
273 let mut dy_cn = HashMap::<usize, usize>::new();
274 for (s, sub) in subh {
275 if let Some(ldpf) = &sub.ldpf {
276 print!("{s} ");
277 let (po, ne) = p03_calc_lp_3(ldpf)?;
278 let sbre = SubLoadProfRepr {
279 sub: s.to_string(),
280 year: yr.to_string(),
281 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
282 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
283 };
284 p03_lp_repr.insert(s.to_string(), sbre);
285
286 print!(" p:{} [", po.len());
287 for (pi, ii) in po.iter().enumerate() {
288 if pi >= LOAD_PROF_MIN_DAYS {
289 break;
290 }
291 if let Some(cn) = dy_cn.get_mut(ii) {
292 *cn += 1;
293 } else {
294 dy_cn.insert(*ii, 1);
295 }
296 if pi > 0 {
297 print!(",");
298 }
299 print!("{ii}");
300 }
301 print!("] n:{} [", ne.len());
302 for (ni, ii) in ne.iter().enumerate() {
303 if ni >= LOAD_PROF_MIN_DAYS {
304 break;
305 }
306 if let Some(cn) = dy_cn.get_mut(ii) {
307 *cn += 1;
308 } else {
309 dy_cn.insert(*ii, 1);
310 }
311 if ni > 0 {
312 print!(",");
313 }
314 print!("{ii}");
315 }
316 print!("]");
317 println!();
318 }
319 for ldpf in sub.fdldp.values() {
320 let f = &ldpf.feed;
321 let (po, ne) = p03_calc_lp_3(ldpf)?;
323 let sbre = SubLoadProfRepr {
324 sub: s.to_string(),
325 year: yr.to_string(),
326 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
327 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
328 };
329 p03_lp_repr.insert(format!("{s}-{f}"), sbre);
330 }
331 }
332 let mut dycn = dy_cn.iter().map(|(a, b)| (*a, *b)).collect::<Vec<_>>();
334 dycn.sort_by(|a, b| b.1.cmp(&a.1));
335 for (d, c) in dycn {
336 println!("{d} - {c}");
337 }
338 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p03_lp_repr_{yr}.bin");
339 println!("write pre {} to {fnm}", p03_lp_repr.len());
340 let bin: Vec<u8> = bincode::encode_to_vec(&p03_lp_repr, bincode::config::standard()).unwrap();
341 std::fs::write(fnm, bin).unwrap();
342 Ok(())
343}
344
345pub fn p03_calc_lp(yr: &str) -> Result<(), Box<dyn Error>> {
346 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p02_sub_lp_{yr}.bin");
347 let bytes = std::fs::read(fnm).unwrap();
348 let (subh, _): (HashMap<String, SubLoadProf>, usize) =
349 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
350 let mut p03_lp_repr = HashMap::<String, SubLoadProfRepr>::new();
351 for (s, sub) in subh {
352 if let Some(ldpf) = &sub.ldpf {
353 print!("{s} ");
354 let (po, ne) = p03_calc_lp_1(ldpf)?;
355 let sbre = SubLoadProfRepr {
356 sub: s.to_string(),
357 year: yr.to_string(),
358 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
359 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
360 };
361 p03_lp_repr.insert(s.to_string(), sbre);
362
363 print!(" p:{} [", po.len());
364 for (pi, ii) in po.iter().enumerate() {
365 if pi >= LOAD_PROF_MIN_DAYS {
366 break;
367 }
368 if pi > 0 {
369 print!(",");
370 }
371 print!("{ii}");
372 }
373 print!("] n:{} [", ne.len());
374 for (ni, ii) in ne.iter().enumerate() {
375 if ni >= LOAD_PROF_MIN_DAYS {
376 break;
377 }
378 if ni > 0 {
379 print!(",");
380 }
381 print!("{ii}");
382 }
383 print!("]");
384 println!();
385 }
386 for ldpf in sub.fdldp.values() {
387 let f = &ldpf.feed;
388 let (po, ne) = p03_calc_lp_1(ldpf)?;
390 let sbre = SubLoadProfRepr {
391 sub: s.to_string(),
392 year: yr.to_string(),
393 pos_rep: p03_draw_sub_av(ldpf, &po, "PO")?,
394 neg_rep: p03_draw_sub_av(ldpf, &ne, "NE")?,
395 };
396 p03_lp_repr.insert(format!("{s}-{f}"), sbre);
397 }
398 }
399 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p03_lp_repr_{yr}.bin");
400 println!("write pre {} to {fnm}", p03_lp_repr.len());
401 let bin: Vec<u8> = bincode::encode_to_vec(&p03_lp_repr, bincode::config::standard()).unwrap();
402 std::fs::write(fnm, bin).unwrap();
403 Ok(())
404}
405
406use std::path::Path;
407
408pub fn p03_draw_all() -> Result<(), Box<dyn Error>> {
409 for yr in ["2023", "2024"] {
410 println!("{yr}");
411 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p02_sub_lp_{yr}.bin");
412 let bytes = std::fs::read(fnm).unwrap();
413 let (subh, _): (HashMap<String, SubLoadProf>, usize) =
414 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
415 println!("sub {}", subh.len());
416 let mut keys: Vec<_> = subh.keys().collect();
418 keys.sort();
419 for sb in &keys {
420 let ddr = format!("/mnt/e/CHMBACK/pea-data/lpdrw/{yr}/{sb}/364_12-31");
422 if Path::new(&ddr).exists() {
423 println!("{yr}-{sb} {ddr} exists");
424 continue;
425 }
426 let sb = sb.to_string();
427 let sub = subh.get(&sb).unwrap();
428 println!(">>> {yr}-{sb} NEW");
455 for f in &sub.feeds {
456 let f = f.to_string();
457 let flp = sub.fdldp.get(&f).unwrap();
458 println!(" f:{f} - {}", flp.days.len());
459 for (di, dlp) in flp.days.iter().enumerate() {
460 if let Some(dlp) = dlp {
461 let lb1 = format!("{sb}-{f}");
462 let mon = dlp.mon;
463 let mdt = dlp.mdt;
464 let lb2 = format!("{yr}-{mon:02}-{mdt:02}");
465 let val = dlp.val;
466 let dnm = format!(
467 "/mnt/e/CHMBACK/pea-data/lpdrw/{yr}/{sb}/{di:03}_{mon:02}-{mdt:02}"
468 );
469 std::fs::create_dir_all(&dnm)?;
470 let fnm = format!("{dnm}/{lb1}.jpg");
471 let sz = (400, 300);
473 let rf = Vec::<(String, f32)>::new();
474
475 let drlp = LoadProf {
476 lb1,
477 lb2,
478 fnm,
479 val,
480 sz,
481 rf,
482 };
483 drlp.draw_prof()?;
484 }
485 }
486 }
487 if let Some(ldpf) = &sub.ldpf {
488 for (di, dlp) in ldpf.days.iter().enumerate() {
489 if let Some(dlp) = dlp {
490 let lb1 = sb.to_string();
492 let mon = dlp.mon;
493 let mdt = dlp.mdt;
494 let lb2 = format!("{yr}-{mon:02}-{mdt:02}");
495 let val = dlp.val;
496 let dnm = format!(
497 "/mnt/e/CHMBACK/pea-data/lpdrw/{yr}/{sb}/{di:03}_{mon:02}-{mdt:02}"
498 );
499 std::fs::create_dir_all(&dnm)?;
500 let fnm = format!("{dnm}/{lb1}.jpg");
501 let sz = (400, 300);
503 let rf = Vec::<(String, f32)>::new();
504
505 let drlp = LoadProf {
506 lb1,
507 lb2,
508 fnm,
509 val,
510 sz,
511 rf,
512 };
513 drlp.draw_prof()?;
514 }
515 }
516 }
517 }
518 }
519 Ok(())
520}
521
522pub fn p03_draw_slp(yr: &str, sb: &str) -> Result<(), Box<dyn Error>> {
523 let fnm = format!("/mnt/e/CHMBACK/pea-data/data2/p02_sub_lp_{yr}.bin");
524 let bytes = std::fs::read(fnm).unwrap();
525 let (subh, _): (HashMap<String, SubLoadProf>, usize) =
526 bincode::decode_from_slice(&bytes[..], bincode::config::standard()).unwrap();
527 println!("sub {}", subh.len());
528 let mut keys: Vec<_> = subh.keys().collect();
530 keys.sort();
531 {
533 let sb = sb.to_string();
534 let sub = subh.get(&sb).unwrap();
535 println!("s: {}", sub.sub);
536 if let Some(ldpf) = &sub.ldpf {
537 for (di, dlp) in ldpf.days.iter().enumerate() {
538 if let Some(dlp) = dlp {
539 let lb1 = format!("{sb}");
540 let mon = dlp.mon;
541 let mdt = dlp.mdt;
542 let lb2 = format!("{yr}-{mon:02}-{mdt:02}");
543 let val = dlp.val;
544 let dnm = format!(
545 "/mnt/e/CHMBACK/pea-data/lpdrw/{yr}/{sb}/{di:03}_{mon:02}-{mdt:02}"
546 );
547 std::fs::create_dir_all(&dnm)?;
548 let fnm = format!("{dnm}/{lb1}.jpg");
549 let sz = (400, 300);
551 let rf = Vec::<(String, f32)>::new();
552
553 let drlp = LoadProf {
554 lb1,
555 lb2,
556 fnm,
557 val,
558 sz,
559 rf,
560 };
561 drlp.draw_prof()?;
562 }
563 }
564 } else {
565 println!(" NO SUB SUM");
566 }
567 for f in &sub.feeds {
568 let f = f.to_string();
569 let flp = sub.fdldp.get(&f).unwrap();
570 println!(" f:{f} - {}", flp.days.len());
571 for (di, dlp) in flp.days.iter().enumerate() {
572 if let Some(dlp) = dlp {
573 let lb1 = format!("{sb}-{f}");
574 let mon = dlp.mon;
575 let mdt = dlp.mdt;
576 let lb2 = format!("{yr}-{mon:02}-{mdt:02}");
577 let val = dlp.val;
578 let dnm = format!(
579 "/mnt/e/CHMBACK/pea-data/lpdrw/{yr}/{sb}/{di:03}_{mon:02}-{mdt:02}"
580 );
581 std::fs::create_dir_all(&dnm)?;
582 let fnm = format!("{dnm}/{lb1}.jpg");
583 let sz = (400, 300);
585 let rf = Vec::<(String, f32)>::new();
586
587 let drlp = LoadProf {
588 lb1,
589 lb2,
590 fnm,
591 val,
592 sz,
593 rf,
594 };
595 drlp.draw_prof()?;
596 }
597 }
598 }
599 }
600
601 Ok(())
602}