eterm_parser/
fd.rs

1#[derive(Default, Debug)]
2pub struct Fd<'a> {
3    pub org: Option<&'a str>,
4    pub dst: Option<&'a str>,
5    pub query_time: Option<&'a str>,
6    pub airline: Option<&'a str>,
7    pub command: Option<&'a str>,
8    pub currency: Option<&'a str>,
9    pub tpm: Option<&'a str>,
10    pub items: Option<Vec<FdItem<'a>>>,
11    pub raw_text: &'a str,
12}
13
14impl<'a> Fd<'a> {
15    pub fn parse(text: &'a str) -> anyhow::Result<Self> {
16        if text.is_empty() {
17            return Err(anyhow::Error::msg(
18                "fd parameter shouldn't be empty.".to_owned(),
19            ));
20        }
21        let lines = text.split(&['\r', '\n']);
22
23        let mut fdinfo = Self {
24            raw_text: text,
25            ..Default::default()
26        };
27        for line in lines {
28            if line.starts_with(">") {
29                continue;
30            } else if line.starts_with("PAGE") {
31                continue;
32            } else if line.trim().is_empty() {
33                continue;
34            } else if line.starts_with("FD:") {
35                match regex::Regex::captures(
36                    &regex::Regex::new(
37                        r"(FD(?<COMMAND>.*)?)\s+/(?<CURRENCY>[^/]*)/TPM\s*(?<TPM>\d+)?",
38                    )?,
39                    line,
40                ) {
41                    Some(caps) => match (
42                        caps.name("COMMAND"),
43                        caps.name("CURRENCY"),
44                        caps.name("TPM"),
45                    ) {
46                        (Some(command), Some(currency), tpm) => {
47                            fdinfo.command = Some(command.as_str());
48                            fdinfo.currency = Some(currency.as_str());
49                            fdinfo.tpm =tpm.and_then(|x| Some(x.as_str().trim()));// crate::regex_extact_text(tpm);
50
51                            match regex::Regex::captures(
52                                &regex::Regex::new(
53                                    r"(?<ORG>[A-Z]{3})(?<DST>[A-Z]{3})/(?<QUERYTIME>\d{2}\w{3}(?:\d{2})?)(?:/(?<AIRLINE>\w{2}))?",
54                                )?,
55                                command.as_str(),
56                            ) {
57                                Some(ccaps) => match (
58                                    ccaps.name("ORG"),
59                                    ccaps.name("DST"),
60                                    ccaps.name("QUERYTIME"),
61                                    ccaps.name("AIRLINE"),
62                                ) {
63                                    (Some(org), Some(dst), Some(querytime), airline) => {
64                                        fdinfo.org = Some(org.as_str());
65                                        fdinfo.dst = Some(dst.as_str());
66                                        fdinfo.query_time = Some(querytime.as_str());
67                                        fdinfo.airline = airline.and_then(|x| Some(x.as_str().trim()));//crate::regex_extact_text(airline);
68                                    }
69                                    _ => {}
70                                },
71                                _ => {}
72                            }
73                        }
74                        _ => {}
75                    },
76                    _ => {}
77                }
78            } else {
79                let mut item = FdItem {
80                    ..Default::default()
81                };
82                let mut arr = line.split('/');
83                let index_airline = arr.next();
84                item.index = index_airline.and_then(|x| x[0..3].parse::<u8>().ok());
85                item.carrier = index_airline.and_then(|x| Some(x[3..5].trim()));
86                item.ticket_type = arr.next().and_then(|x| Some(x.trim()));
87                if let Some(ow_rt_price) = arr.next() {
88                    let mut ow_rt_price = ow_rt_price.split('=');
89                    item.ow_price_raw = ow_rt_price.next().and_then(|x| Some(x.trim()));
90                    item.rt_price_raw = ow_rt_price.next().and_then(|x| Some(x.trim()));
91                }
92                item.cabin = arr.next().and_then(|x| Some(x.trim()));
93                item.class = arr.next().and_then(|x| Some(x.trim()));
94                arr.next();
95                item.begin_date = arr.next().and_then(|x| {
96                    if x == "." {
97                        fdinfo.query_time
98                    } else {
99                        Some(x)
100                    }
101                });
102                item.end_date = arr.next().and_then(|x| Some(x.trim()));
103                item.policy_no = arr.next().and_then(|x| Some(x[0..6].trim()));
104
105                if item.index == Some(0u8) {
106                    continue;
107                }
108                match &item.ow_price_raw {
109                    Some(ow_price_raw) => {
110                        if ow_price_raw.contains('%') {
111                            if let Some(yfd) = fdinfo.items.as_ref().and_then(|x| {
112                                x.iter().find_map(|n| {
113                                    if n.carrier == item.carrier
114                                        && n.cabin == Some("Y")
115                                        && n.ow_price.is_some()
116                                    {
117                                        n.ow_price
118                                    } else {
119                                        None
120                                    }
121                                })
122                            }) {
123                                item.ow_price = Some(
124                                    yfd * ow_price_raw
125                                        .trim_end_matches('%')
126                                        .parse::<f32>()
127                                        .unwrap()
128                                        / 100.0,
129                                );
130                            }
131                        } else {
132                            item.ow_price = ow_price_raw.parse::<f32>().ok();
133                        }
134                    }
135                    _ => {}
136                }
137                match &item.rt_price_raw {
138                    Some(rt_price_raw) => {
139                        if rt_price_raw.contains('%') {
140                            if let Some(yfd) = fdinfo.items.as_ref().and_then(|x| {
141                                x.iter().find_map(|n| {
142                                    if n.carrier == item.carrier
143                                        && n.cabin == Some("Y")
144                                        && n.rt_price.is_some()
145                                    {
146                                        n.rt_price
147                                    } else {
148                                        None
149                                    }
150                                })
151                            }) {
152                                item.rt_price = Some(
153                                    yfd * rt_price_raw
154                                        .trim_end_matches('%')
155                                        .parse::<f32>()
156                                        .unwrap()
157                                        / 100.0,
158                                );
159                            }
160                        } else {
161                            item.rt_price = rt_price_raw.parse::<f32>().ok();
162                        }
163                    }
164                    _ => {}
165                }
166                fdinfo
167                    .items
168                    .as_mut()
169                    .get_or_insert(&mut Vec::new())
170                    .push(item);
171            }
172        }
173
174        Ok(fdinfo)
175    }
176}
177
178#[derive(Default, Debug)]
179pub struct FdItem<'a> {
180    pub index: Option<u8>,
181    pub carrier: Option<&'a str>,
182    pub ticket_type: Option<&'a str>,
183    pub ow_price_raw: Option<&'a str>,
184    pub ow_price: Option<f32>,
185    pub rt_price_raw: Option<&'a str>,
186    pub rt_price: Option<f32>,
187    pub cabin: Option<&'a str>,
188    pub class: Option<&'a str>,
189    pub begin_date: Option<&'a str>,
190    pub end_date: Option<&'a str>,
191    pub policy_no: Option<&'a str>,
192}