Skip to main content

plot/lib/logic/
engine_multiple.rs

1use crate::lib::logic::{ConfigJob, ConfigManifest, DocEngine, IoConfig, JobMode, JobSpec, MX, RenderFlags};
2/// Orchestrator zadań wsadowych.
3/// Pobiera konfigurację z plików TOML, tłumaczy ją na silnie typowane obiekty
4/// JobSpec i zleca ich wykonanie do rdzennego DocEngine.
5pub struct DocEngineMultiple {
6	pub manifest: ConfigManifest,
7}
8
9impl DocEngineMultiple {
10	// ============================================================================
11	// LOADERY (Odczyt konfiguracji za pomocą IoConfig)
12	// ============================================================================
13
14	/// Wczytuje konfigurację z domyślnego pliku (np. ./.x-do.toml)
15	pub fn loader_default() -> Result<Self, String> {
16		let manifest = IoConfig::default_config_loader()?;
17		Ok(Self { manifest })
18	}
19
20	/// Wczytuje konfigurację ze wskazanej ścieżki
21	pub fn loader_from_toml(path: &str) -> Result<Self, String> {
22		let manifest = IoConfig::config_loader_from(path)?;
23		Ok(Self { manifest })
24	}
25
26	// ============================================================================
27	// PARSERY (Tłumaczenie ConfigJob z TOML na nasz domenowy JobSpec)
28	// ============================================================================
29
30	/// Parsuje pojedynczy surowy obiekt konfiguracji TOML na silnie typowany
31	/// JobSpec
32	pub fn parse(&self, cfg: &ConfigJob) -> Result<JobSpec, String> { JobSpec::from_config(cfg) }
33
34	/// Szuka zadania po ID i parsuje je do JobSpec (nie wykonując go)
35	pub fn parse_for(&self, id: &str) -> Result<JobSpec, String> {
36		let cfg_job = self
37			.manifest
38			.job
39			.iter()
40			.find(|j| j.id == id)
41			.ok_or_else(|| format!("❌ Nie znaleziono zadania o ID: '{}'", id))?;
42
43		JobSpec::from_config(cfg_job)
44	}
45
46	// ============================================================================
47	// EXECUTORY (Wykonywanie zadań za pomocą DocEngine)
48	// ============================================================================
49
50	/// Mapuje i wykonuje w pętli wszystkie zadania zdefiniowane w pliku TOML
51	pub fn jobs(&self) -> Result<(), String> {
52		for cfg_job in &self.manifest.job {
53			let spec = self.parse(cfg_job)?;
54			self.execute_spec(spec)?;
55		}
56		Ok(())
57	}
58
59	/// Wyszukuje zadanie po ID, mapuje na JobSpec i wykonuje je
60	pub fn job_id(&self, id: &str) -> Result<(), String> {
61		let spec = self.parse_for(id)?;
62		self.execute_spec(spec)?;
63		Ok(())
64	}
65
66	// ============================================================================
67	// SILNIK WYKONAWCZY (Delegacja do DocEngine)
68	// ============================================================================
69
70	/// Bierze gotowy i bezpieczny JobSpec, a następnie karmi nim DocEngine
71	fn execute_spec(&self, spec: JobSpec) -> Result<(), String> {
72		if !spec.quiet_work {
73			let name = spec.name.as_deref().unwrap_or("Brak nazwy");
74			println!("🚀 Uruchamianie zadania: {} ({})", spec.id, name);
75		}
76
77		// 1. Przekładamy JobMode na stare MX dla silnika renderującego
78		let mx_mode = match spec.mode {
79			JobMode::Matched => MX::Matched,
80			JobMode::Mismatched => MX::Mismatched,
81		};
82
83		// 2. Inicjujemy rdzewny DocEngine przekazując mu od razu obiekt ScanSpec i
84		//    TabSpec
85		let mut engine = DocEngine::new(spec.scan.clone()).spec(spec.table.clone());
86
87		// 3. Widok w terminalu (lub cichy stan dla plików)
88		if !spec.quiet_work {
89			if let Some(size) = spec.table.trim_size {
90				let page = Some(spec.table.trim_page);
91				engine = engine.view_trimmed(mx_mode, spec.hide_stats, spec.hide_promo, size, page);
92			} else {
93				engine = engine.view(mx_mode, spec.hide_stats, spec.hide_promo);
94			}
95		} else {
96			// Nawet w trybie cichym zapisujemy konfigurację renderowania na wypadek zapisu
97			// do pliku
98			engine.last_render =
99				Some(RenderFlags { hide_stats: spec.hide_stats, hide_promo: spec.hide_promo, mode: mx_mode });
100		}
101
102		// 4. Eksport do plików (niezależnie od trybu quiet)
103		if let Some(sotc_path) = &spec.save_sotc_at {
104			engine = engine.save_structure_of_the_content(sotc_path, spec.title_sotc.as_deref());
105		}
106		if let Some(cots_path) = &spec.save_cots_at {
107			engine = engine.save_content_of_the_structure(cots_path, spec.title_cots.as_deref());
108		}
109
110		let _ = engine;
111
112		if !spec.quiet_work {
113			println!("✨ Ukończono zadanie: {}", spec.id);
114		}
115
116		Ok(())
117	}
118}