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
use crate::{common::TspRecord, TspDistance, TspError, TspResult, TspSolver};
use ndarray::{Array1, ArrayView1};
use rand::{rngs::SmallRng, thread_rng, SeedableRng};
use serde::{
    de::{DeserializeOwned, MapAccess, Visitor},
    Deserialize, Deserializer,
};
use std::{fmt::Formatter, fs::read_to_string, path::Path};

impl<T> TspSolver<T>
where
    T: TspDistance,
{
    pub fn load_or_create<P: AsRef<Path>>(dir: P, objects: ArrayView1<T>) -> Self
    where
        T: DeserializeOwned + Clone,
    {
        let path = dir.as_ref();
        match Self::load(path) {
            Ok(o) => o,
            Err(_) => Self::new(path, objects.to_owned()),
        }
    }

    pub fn load<P: AsRef<Path>>(dir: P) -> TspResult<Self>
    where
        T: DeserializeOwned,
    {
        let path = dir.as_ref().canonicalize()?;
        if !path.exists() || !path.is_dir() {
            Err(TspError::io_error(&path, "Directory not found"))?
        }
        let content = read_to_string(path.join("main.json"))?;
        let mut this = serde_json::from_str::<Self>(&content)?;
        this.check_points = path.to_path_buf();
        this.load_record(this.improves)?;
        Ok(this)
    }
    pub fn load_record(&mut self, improves: usize) -> TspResult<()> {
        let record = TspRecord::load(self.check_points.clone(), improves)?;
        self.steps = record.steps;
        self.best_distance = record.best_distance;
        self.best_path = record.best_path;
        Ok(())
    }
}

impl TspRecord {
    pub fn load<P: AsRef<Path>>(dir: P, improves: usize) -> TspResult<Self> {
        let file = dir.as_ref().join(format!("step_{}.json", improves));
        // println!("{:?}", file.canonicalize()?.display());
        let content = read_to_string(file)?;
        Ok(serde_json::from_str(&content)?)
    }
}

impl<'de, T> Deserialize<'de> for TspSolver<T>
where
    T: Deserialize<'de> + TspDistance,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let mut this = TspSolver {
            problem_id: "".to_string(),
            objects: Array1::from_shape_vec((0,), vec![]).unwrap(),
            best_path: Default::default(),
            best_distance: 0.0,
            rng: SmallRng::from_rng(thread_rng()).unwrap(),
            steps: 0,
            improves: 0,
            check_points: Default::default(),
        };
        TspSolver::deserialize_in_place(deserializer, &mut this)?;
        Ok(this)
    }

    fn deserialize_in_place<D>(deserializer: D, place: &mut Self) -> Result<(), D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(TspDeserializer { ptr: place })
    }
}

pub struct TspDeserializer<'i, T: TspDistance> {
    ptr: &'i mut TspSolver<T>,
}

impl<'i, 'de, T> Visitor<'de> for TspDeserializer<'i, T>
where
    T: Deserialize<'de> + TspDistance,
{
    type Value = ();

    fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
        formatter.write_str("expect `TspSolver` object")
    }

    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
    where
        A: MapAccess<'de>,
    {
        while let Some(key) = map.next_key::<String>()? {
            match key.as_str() {
                "problem_id" => self.ptr.problem_id = map.next_value()?,
                "objects" => self.ptr.objects = map.next_value()?,
                "improves" => self.ptr.improves = map.next_value()?,
                _ => {}
            }
        }
        Ok(())
    }
}