|
@@ -1,4 +1,5 @@
|
|
|
extern crate chrono;
|
|
|
+extern crate quick_xml;
|
|
|
extern crate xml;
|
|
|
|
|
|
use chrono::DateTime;
|
|
@@ -9,6 +10,8 @@ use std::fs::File;
|
|
|
use std::io::BufReader;
|
|
|
use std::time::Duration as stdDuration;
|
|
|
|
|
|
+use quick_xml::events::Event;
|
|
|
+use quick_xml::Reader;
|
|
|
use xml::reader::{EventReader, XmlEvent};
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
@@ -68,8 +71,7 @@ impl Track {
|
|
|
self.len() / (self.time().num_seconds() as f64 / 3600.0)
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- fn truncate_by_length(&mut self, length_km: f64){
|
|
|
+ fn truncate_by_length(&mut self, length_km: f64) {
|
|
|
let mut sum = 0.0;
|
|
|
let mut prev_point = &self.points[0];
|
|
|
|
|
@@ -87,13 +89,17 @@ impl Track {
|
|
|
let mut prev_point = &self.points[0];
|
|
|
let mut prev_time = &self.points[0].time;
|
|
|
|
|
|
- let mut fifo_track = Track {..Default::default()};
|
|
|
+ let mut fifo_track = Track {
|
|
|
+ ..Default::default()
|
|
|
+ };
|
|
|
|
|
|
- let mut i=0;
|
|
|
+ let mut i = 0;
|
|
|
|
|
|
for pt in &self.points {
|
|
|
- i = i+1;
|
|
|
- if i > 10 {break;}
|
|
|
+ i = i + 1;
|
|
|
+ if i > 10 {
|
|
|
+ break;
|
|
|
+ }
|
|
|
let timespan = prev_time.signed_duration_since(pt.time);
|
|
|
sum_time = sum_time.checked_sub(×pan).unwrap();
|
|
|
prev_time = &pt.time;
|
|
@@ -103,17 +109,10 @@ impl Track {
|
|
|
|
|
|
fifo_track.points.push(pt.clone());
|
|
|
println!("fifo len {:?}", fifo_track.points.len());
|
|
|
-
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
fn dist(p1: &Point, p2: &Point) -> f64 {
|
|
|
let r = 6371.0;
|
|
|
// println!("analyzing p1 {:?} p2 {:?}", p1, p2);
|
|
@@ -130,16 +129,16 @@ fn dist(p1: &Point, p2: &Point) -> f64 {
|
|
|
}
|
|
|
|
|
|
fn main() {
|
|
|
- let file = File::open("data/Day1-1.gpx").unwrap();
|
|
|
- let file = BufReader::new(file);
|
|
|
+ // let file = File::open("data/Day1-1.gpx").unwrap();
|
|
|
+ // let file = BufReader::new(file);
|
|
|
|
|
|
- let mut trk = Track {
|
|
|
- ..Default::default()
|
|
|
- };
|
|
|
+ // let mut trk = Track {
|
|
|
+ // ..Default::default()
|
|
|
+ // };
|
|
|
|
|
|
- println!("open {:?}", file);
|
|
|
- let parser = EventReader::new(file);
|
|
|
- println!("done.");
|
|
|
+ // println!("open {:?}", file);
|
|
|
+ // let parser = EventReader::new(file);
|
|
|
+ // println!("done.");
|
|
|
|
|
|
// Records for the pull parser
|
|
|
let mut current_point = Point::new();
|
|
@@ -147,68 +146,174 @@ fn main() {
|
|
|
|
|
|
println!("XML parse start.");
|
|
|
|
|
|
- for e in parser {
|
|
|
- match e {
|
|
|
-
|
|
|
- Ok(XmlEvent::StartElement {
|
|
|
- name, attributes, ..
|
|
|
- }) => {
|
|
|
- if name.local_name == "trkpt" {
|
|
|
- for attr in attributes {
|
|
|
- // println!("A\t{:?}={:?}", attr.name.local_name, attr.value);
|
|
|
- if attr.name.local_name == "lat" {
|
|
|
- current_point.lat = attr.value.parse().unwrap();
|
|
|
- }
|
|
|
- if attr.name.local_name == "lon" {
|
|
|
- current_point.long = attr.value.parse().unwrap();
|
|
|
+ // for e in parser {
|
|
|
+ // match e {
|
|
|
+
|
|
|
+ // Ok(XmlEvent::StartElement {
|
|
|
+ // name, attributes, ..
|
|
|
+ // }) => {
|
|
|
+ // if name.local_name == "trkpt" {
|
|
|
+ // for attr in attributes {
|
|
|
+ // // println!("A\t{:?}={:?}", attr.name.local_name, attr.value);
|
|
|
+ // if attr.name.local_name == "lat" {
|
|
|
+ // current_point.lat = attr.value.parse().unwrap();
|
|
|
+ // }
|
|
|
+ // if attr.name.local_name == "lon" {
|
|
|
+ // current_point.long = attr.value.parse().unwrap();
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Ok(XmlEvent::Characters(text)) => {
|
|
|
+ // // This event is the text between tags, such as <foo>text</foo>
|
|
|
+ // current_data = text;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Ok(XmlEvent::EndElement { name, .. }) => {
|
|
|
+ // // Elevation
|
|
|
+ // if name.local_name == "ele" {
|
|
|
+ // current_point.ele = current_data.parse().unwrap();
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // Parse time
|
|
|
+ // if name.local_name == "time" {
|
|
|
+ // match Utc.datetime_from_str(current_data.as_str(), "%FT%H:%M:%S%.3fZ") {
|
|
|
+ // Ok(time) => current_point.time = time,
|
|
|
+ // Err(err) => println!("=== TIME ERROR === {:?}", err),
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // The track name
|
|
|
+ // if name.local_name == "name" {
|
|
|
+ // trk.name = current_data.clone();
|
|
|
+ // }
|
|
|
+
|
|
|
+ // //Track point end event
|
|
|
+ // if name.local_name == "trkpt" {
|
|
|
+ // // push a copy of the point to the track
|
|
|
+ // trk.points.push(current_point.clone());
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // Err(e) => {
|
|
|
+ // println!("Error: {}", e);
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // _ => {}
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // for e in parser {
|
|
|
+ // match e {
|
|
|
+
|
|
|
+ // Ok(XmlEvent::StartElement {
|
|
|
+ // name, attributes, ..
|
|
|
+ // }) => {
|
|
|
+ // if name.local_name == "trkpt" {
|
|
|
+ // for attr in attributes {
|
|
|
+ // // println!("A\t{:?}={:?}", attr.name.local_name, attr.value);
|
|
|
+ // if attr.name.local_name == "lat" {
|
|
|
+ // current_point.lat = attr.value.parse().unwrap();
|
|
|
+ // }
|
|
|
+ // if attr.name.local_name == "lon" {
|
|
|
+ // current_point.long = attr.value.parse().unwrap();
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Ok(XmlEvent::Characters(text)) => {
|
|
|
+ // // This event is the text between tags, such as <foo>text</foo>
|
|
|
+ // current_data = text;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // Ok(XmlEvent::EndElement { name, .. }) => {
|
|
|
+ // // Elevation
|
|
|
+ // if name.local_name == "ele" {
|
|
|
+ // current_point.ele = current_data.parse().unwrap();
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // Parse time
|
|
|
+ // if name.local_name == "time" {
|
|
|
+ // match Utc.datetime_from_str(current_data.as_str(), "%FT%H:%M:%S%.3fZ") {
|
|
|
+ // Ok(time) => current_point.time = time,
|
|
|
+ // Err(err) => println!("=== TIME ERROR === {:?}", err),
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ // // The track name
|
|
|
+ // if name.local_name == "name" {
|
|
|
+ // trk.name = current_data.clone();
|
|
|
+ // }
|
|
|
+
|
|
|
+ // //Track point end event
|
|
|
+ // if name.local_name == "trkpt" {
|
|
|
+ // // push a copy of the point to the track
|
|
|
+ // trk.points.push(current_point.clone());
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // Err(e) => {
|
|
|
+ // println!("Error: {}", e);
|
|
|
+ // break;
|
|
|
+ // }
|
|
|
+
|
|
|
+ // _ => {}
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+
|
|
|
+ let mut reader = Reader::from_file("data/Day1-1.gpx").unwrap();
|
|
|
+ // let mut reader = Reader::from_file("data/test.xml").unwrap();
|
|
|
+
|
|
|
+ reader.trim_text(true);
|
|
|
+
|
|
|
+ let mut count = 0;
|
|
|
+ let mut txt = Vec::new();
|
|
|
+ let mut buf = Vec::new();
|
|
|
+
|
|
|
+ // The `Reader` does not implement `Iterator` because it outputs borrowed data (`Cow`s)
|
|
|
+ loop {
|
|
|
+ match reader.read_event(&mut buf) {
|
|
|
+ Ok(Event::Start(ref e)) => {
|
|
|
+ // println!("{:?}", e.unescape_and_decode(&reader).unwrap());
|
|
|
+
|
|
|
+ match e.name() {
|
|
|
+ b"trkpt" => {
|
|
|
+ for a in e.attributes() {
|
|
|
+ let unwrapped_attr = a.unwrap();
|
|
|
+ let k = reader.decode(unwrapped_attr.key);
|
|
|
+ let v = unwrapped_attr.unescape_and_decode_value(&reader).unwrap();
|
|
|
+ if k == "lat" {
|
|
|
+ current_point.lat = v.parse().unwrap();
|
|
|
+ }
|
|
|
+ if k == "lon" {
|
|
|
+ current_point.long = v.parse().unwrap();
|
|
|
+ }
|
|
|
+ // println!("{:?}: {:?}", k, v);
|
|
|
}
|
|
|
+ ()
|
|
|
}
|
|
|
+ _ => (),
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- Ok(XmlEvent::Characters(text)) => {
|
|
|
- // This event is the text between tags, such as <foo>text</foo>
|
|
|
- current_data = text;
|
|
|
- }
|
|
|
-
|
|
|
- Ok(XmlEvent::EndElement { name, .. }) => {
|
|
|
- // Elevation
|
|
|
- if name.local_name == "ele" {
|
|
|
- current_point.ele = current_data.parse().unwrap();
|
|
|
- }
|
|
|
-
|
|
|
- // Parse time
|
|
|
- if name.local_name == "time" {
|
|
|
- match Utc.datetime_from_str(current_data.as_str(), "%FT%H:%M:%S%.3fZ") {
|
|
|
- Ok(time) => current_point.time = time,
|
|
|
- Err(err) => println!("=== TIME ERROR === {:?}", err),
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // The track name
|
|
|
- if name.local_name == "name" {
|
|
|
- trk.name = current_data.clone();
|
|
|
- }
|
|
|
-
|
|
|
- //Track point end event
|
|
|
- if name.local_name == "trkpt" {
|
|
|
- // push a copy of the point to the track
|
|
|
- trk.points.push(current_point.clone());
|
|
|
- }
|
|
|
- }
|
|
|
- Err(e) => {
|
|
|
- println!("Error: {}", e);
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- _ => {}
|
|
|
+ Ok(Event::Text(e)) => txt.push(e.unescape_and_decode(&reader).unwrap()),
|
|
|
+ // Ok(Event::End(ref e)) => (),
|
|
|
+ Ok(Event::Eof) => break, // exits the loop when reaching end of file
|
|
|
+ Err(e) => panic!("Error at position {}: {:?}", reader.buffer_position(), e),
|
|
|
+ _ => (), // There are several other `Event`s we do not consider here
|
|
|
}
|
|
|
+
|
|
|
+ // print!("{:?}\n", buf);
|
|
|
+ // print!("{:?}\n", txt);
|
|
|
+ // if we don't keep a borrow elsewhere, we can clear the buffer to keep memory usage low
|
|
|
+ buf.clear();
|
|
|
}
|
|
|
+
|
|
|
println!("XML parse end.");
|
|
|
|
|
|
- println!("Track name: {:?}", trk.name);
|
|
|
- println!("Distance: {:?} km", trk.len());
|
|
|
- println!("Duration: {:?} h", trk.time().num_minutes() as f32 / 60.0);
|
|
|
- println!("Speed: {:?} Km/h", trk.speed());
|
|
|
- trk.parse();
|
|
|
+ // println!("Track name: {:?}", trk.name);
|
|
|
+ // println!("Distance: {:?} km", trk.len());
|
|
|
+ // println!("Duration: {:?} h", trk.time().num_minutes() as f32 / 60.0);
|
|
|
+ // println!("Speed: {:?} Km/h", trk.speed());
|
|
|
+ // trk.parse();
|
|
|
}
|