1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/**
Module for loading `project.yaml`, which has necessary information to control
the program.
*/
extern crate serde;
use std::{collections::HashMap, error::Error, fs, path::Path};

use serde::{Deserialize, Serialize};

use super::YamlTable;

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct ProjectInfo {
    base_model_loc: String,
    element_table_loc: String,
    adsorbate_table_loc: String,
    potentials_loc: String,
    export_loc: String,
    coord_sites: Vec<CoordSite>,
    coord_cases: Vec<CoordCase>,
}

impl ProjectInfo {
    pub fn element_table_loc(&self) -> &str {
        self.element_table_loc.as_ref()
    }

    pub fn adsorbate_table_loc(&self) -> &str {
        self.adsorbate_table_loc.as_ref()
    }

    pub fn potentials_loc(&self) -> &str {
        self.potentials_loc.as_ref()
    }

    pub fn coord_sites(&self) -> &[CoordSite] {
        self.coord_sites.as_ref()
    }
    pub fn hash_coord_site(&self) -> HashMap<u32, String> {
        let mut hash_tab: HashMap<u32, String> = HashMap::new();
        self.coord_sites().iter().for_each(|coord_site| {
            hash_tab.insert(coord_site.atom_id, coord_site.name.to_string());
        });
        hash_tab
    }

    pub fn export_loc(&self) -> &str {
        self.export_loc.as_ref()
    }

    pub fn base_model_loc(&self) -> &str {
        self.base_model_loc.as_ref()
    }

    pub fn coord_cases(&self) -> &[CoordCase] {
        self.coord_cases.as_ref()
    }
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct CoordSite {
    name: String,
    atom_id: u32,
}

#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)]
pub struct CoordCase {
    name: String,
    cases: Vec<(u32, Option<u32>)>,
}

impl CoordCase {
    pub fn get_cases(&self, reverse: bool) -> Vec<(u32, Option<u32>)> {
        if reverse {
            let reversed_cases: Vec<(u32, Option<u32>)> = self
                .cases
                .iter()
                .map(|(s1, s2)| (s2.unwrap(), Some(*s1)))
                .collect();
            reversed_cases
        } else {
            self.cases.clone()
        }
    }
}

/**
Load project `yaml` from given path
# Arguments
* `filepath` - Type that has trait `AsRef<Path>`
# Returns
* `Result<ProjectInfo, Box<dyn Error>`
*/
pub fn load_project_info<P: AsRef<Path>>(filepath: P) -> Result<ProjectInfo, Box<dyn Error>> {
    let project_yaml = fs::File::open(filepath)?;
    let project_table = serde_yaml::from_reader(project_yaml)?;
    Ok(project_table)
}

impl YamlTable for ProjectInfo {
    type Table = ProjectInfo;

    type TableItem = String;

    type HashKey = u32;

    fn load_table<P: AsRef<Path>>(filepath: P) -> Result<Self::Table, Box<dyn Error>> {
        let project_yaml = fs::File::open(filepath)?;
        let project_table = serde_yaml::from_reader(project_yaml)?;
        Ok(project_table)
    }
    /// HashMap for `atom_id: name`
    fn hash_table(&self) -> Result<HashMap<Self::HashKey, Self::TableItem>, Box<dyn Error>> {
        let mut hash_tab: HashMap<u32, String> = HashMap::new();
        self.coord_sites().iter().for_each(|coord_site| {
            hash_tab.insert(coord_site.atom_id, coord_site.name.to_string());
        });
        Ok(hash_tab)
    }
}