dvcompute_experiment_cons/simulation/experiment/
rendering.rs

1// Copyright (c) 2020-2022  David Sorokin <davsor@mail.ru>, based in Yoshkar-Ola, Russia
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::io;
8use std::io::*;
9use std::path::Path;
10use std::result;
11use std::fs;
12use std::fs::File;
13
14use dvcompute::simulation;
15
16use crate::simulation::experiment::*;
17use crate::simulation::utils;
18use crate::simulation::utils::html::*;
19use crate::simulation::utils::convert::convert_result;
20
21/// It defines the web page rendering.
22pub struct WebPageRendering<T> {
23
24    /// The provided parameter.
25    pub arg: T,
26
27    /// The experiment file path.
28    pub path: Box<Path>
29}
30
31/// It replies to the requests made by the web page renderer.
32pub trait WebPageWriter {
33
34    /// Write the TOC (Table of Contents) item in the HTML index file
35    /// after the finalisation function is called, i.e. in the very end.
36    /// The index parameter specifies the ordered number of the item.
37    /// You should start the HTML code with call of
38    /// the `begin_html_list_item` function.
39    fn write_toc_html(&self, w: &mut dyn Write, index: usize) -> io::Result<()>;
40
41    /// Write the HTML code in the index file after the finalisation
42    /// function is called. The index parameter specifies the ordered
43    /// number of the item.
44    fn write_html(&self, w: &mut dyn Write, index: usize) -> io::Result<()>;
45}
46
47/// A convenient type synonym for describing the web page generator.
48pub type WebPageGenerator<T> = dyn ExperimentGenerator<WebPageRendering<T>>;
49
50impl<T> ExperimentRendering for WebPageRendering<T> {
51
52    type ExperimentContext = Box<dyn WebPageWriter + Send>;
53
54    type ExperimentEnvironment = Box<Path>;
55
56    fn prepare(&self, _experiment: &Experiment) -> simulation::Result<Self::ExperimentEnvironment> {
57        utils::path::resolve_file_path(&self.path)
58    }
59
60    fn render(&self, experiment: &Experiment, reporters: &Vec<Box<dyn ExperimentReporter<Self> + Sync + Send>>, env: &Self::ExperimentEnvironment) -> simulation::Result<()>
61        where Self: Sized
62    {
63        convert_result(fs::create_dir_all(env))?;
64        let mut buf = env.to_path_buf();
65        buf.push("index.html");
66        let path = buf.into_boxed_path();
67        let mut file: File = convert_result(File::create(&path))?;
68
69        convert_result(begin_html_document(&mut file, &experiment.title))?;
70        for i in 0 .. reporters.len() {
71            let reporter = &reporters[i];
72            convert_result(reporter.context().write_toc_html(&mut file, 1 + i))?;
73        }
74        convert_result(write_html_break(&mut file))?;
75        if let Some(description) = &experiment.description {
76            convert_result(begin_html_paragraph(&mut file))?;
77            convert_result(write_html_text(&mut file, description))?;
78            convert_result(end_html_paragraph(&mut file))?;
79        }
80        for i in 0 .. reporters.len() {
81            let reporter = &reporters[i];
82            convert_result(reporter.context().write_html(&mut file, 1 + i))?;
83        }
84        convert_result(end_html_document(&mut file))?;
85
86        if experiment.verbose {
87            println!("Generated file {}", path.display());
88        }
89
90        result::Result::Ok(())
91    }
92
93    fn on_completed(&self, _experiment: &Experiment, _env: &Self::ExperimentEnvironment) -> simulation::Result<()> {
94        result::Result::Ok(())
95    }
96
97    fn on_failed(&self, _experiment: &Experiment, _env: &Self::ExperimentEnvironment, _err: &simulation::error::Error) -> simulation::Result<()> {
98        result::Result::Ok(())
99    }
100}