scarlet_queen_entrypoint/
pokemon_type.rs1use std::{
2 collections::HashMap,
3 fmt::Debug,
4 fs::{self, File},
5 io::BufWriter,
6};
7
8use plotters::{
9 chart::{ChartBuilder, ChartContext},
10 prelude::{BitMapBackend, Cartesian2d, Circle, DrawingArea, IntoDrawingArea},
11 series::LineSeries,
12 style::{IntoFont, ShapeStyle, WHITE},
13};
14use scarlet_queen_core::pokemon_type::PokemonTypeTrait;
15use scarlet_queen_generation::group::PokemonTypeGroup;
16use scarlet_queen_initializer::group::InitializerSample;
17
18use crate::{
19 error::Error,
20 find_cycle::find_tail_cycle,
21 function::{main_loop, MAIN_LOOP},
22};
23
24pub fn count<P>(loop_result: Vec<Vec<P>>) -> Vec<HashMap<P, usize>>
25where
26 P: PokemonTypeTrait,
27{
28 loop_result
29 .into_iter()
30 .map(|v| {
31 v.iter().fold(HashMap::new(), |mut state, u| {
32 *state.entry(u.clone()).or_insert(0) += 1;
33 state
34 })
35 })
36 .collect::<Vec<HashMap<P, usize>>>()
37}
38
39pub fn draw_graph<P>(loop_result_count: &[HashMap<P, usize>], img_name: &str)
40where
41 P: PokemonTypeTrait,
42{
43 let graph_data: Vec<(P, Vec<(i32, i32)>)> = P::ALL
44 .into_iter()
45 .flatten()
46 .map(|v| {
47 let data: Vec<(i32, i32)> = loop_result_count
48 .iter()
49 .enumerate()
50 .map(|(i, hash_map)| (i as i32, hash_map.get(&v).map_or(0, |u| *u) as i32))
51 .collect::<Vec<(i32, i32)>>();
52 (v, data)
53 })
54 .collect::<Vec<(P, Vec<(i32, i32)>)>>();
55
56 let y_max: i32 = 100;
57 let root: DrawingArea<BitMapBackend<'_>, plotters::coord::Shift> =
58 BitMapBackend::new(img_name, (1080, 720)).into_drawing_area();
59 root.fill(&WHITE).unwrap();
60 let mut chart: ChartContext<
61 '_,
62 BitMapBackend<'_>,
63 Cartesian2d<plotters::coord::types::RangedCoordi32, plotters::coord::types::RangedCoordi32>,
64 > = ChartBuilder::on(&root)
65 .caption("Sample", ("sans-serif", 20).into_font())
66 .x_label_area_size(40)
67 .y_label_area_size(40)
68 .build_cartesian_2d(0..((MAIN_LOOP as i32) + 1), 0..(y_max + 1))
69 .unwrap();
70 chart.configure_mesh().draw().unwrap();
71
72 for (p, data) in graph_data.into_iter() {
73 let line_1: LineSeries<BitMapBackend, (i32, i32)> =
74 LineSeries::new(data.iter().map(|&(x, y)| (x, y)), p.color_map());
75 chart.draw_series(line_1).unwrap();
76 let point_1 = data
77 .iter()
78 .map(|&(x, y)| Circle::new((x, y), 4, ShapeStyle::from(p.color_map()).filled()));
79 chart.draw_series(point_1).unwrap();
80 }
81}
82
83pub fn test_and_draw<P, const N: usize, const R: usize>(test_name: &str) -> Result<(), Error>
84where
85 P: PokemonTypeTrait + Debug,
86{
87 let dir_path: String = format!("./out/{test_name}");
88 fs::create_dir_all(&dir_path)?;
89 let mut file: BufWriter<File> = BufWriter::new(File::create(format!(
90 "{}/res_{}.txt",
91 &dir_path, test_name
92 ))?);
93 let result: Vec<Vec<P>> =
94 main_loop::<P, InitializerSample<N>, PokemonTypeGroup<P, N, R>, BufWriter<File>, N, R>(
95 &mut file,
96 )
97 .unwrap();
98 let count: Vec<HashMap<P, usize>> = count(result);
99 draw_graph(&count, &format!("{}/img_{}.png", &dir_path, test_name));
100 find_tail_cycle(&count, &mut file).unwrap();
101 Ok(())
102}