123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- /* global process */
- /*
- * A nodejs app that puts in time order gps points exported from PhoneTrack in NextCloud
- * so that they can be correctly imported in JOSM
- *
- * author: Florian ANAYA
- * date: 2023/08/31
- */
- const fileSystemLib = require('fs');
- const xmlJsLib = require('xml-js');
- // @type String The path of the file to read
- var filePath;
- // @type Array[Track] List of tracks read from the file
- const tracks = [];
- // @type Date The starting time of the script so that we can calculate the ellapsed time at the end of the script
- var startTime;
- function main()
- {
- startTime = new Date();
- console.log("Started PhoneTrack GPX file fixer");
- if (process.argv.length <= 2)
- {
- console.log("Please specify file path");
- return;
- }
- filePath = process.argv[2];
- console.log("Reading file located at \"" + filePath + "\"...");
-
- // We read the file
- fileSystemLib.readFile(filePath, onFileRead);
- }
- function onFileRead(error, fileData)
- {
- if (error)
- {
- throw error;
- }
- // We read XML dazta from the file (this will throw if the file is not XML)
- console.log("File has been read, loading XML...");
- let xmlData = xmlJsLib.xml2js(fileData);
- console.log("XML has been loaded, reading PhoneTrack data...");
-
-
- let rootElements = xmlData.elements;
- let gpxData = rootElements[0];
- let gpxElements = gpxData.elements;
-
- for (let index in gpxElements)
- {
- let gpxChildData = gpxElements[index];
- if (gpxChildData.name === "trk")
- {
- loadTrack(gpxChildData);
- }
- }
- sortTracks();
- updateXml(xmlData);
- }
- function loadTrack(trackData)
- {
- let track = new Track(trackData);
- tracks.push(track);
- }
- function sortTracks()
- {
- console.log("Sorting all points...");
- for (let index in tracks)
- {
- let track = tracks[index];
- track.sort();
- }
- console.log("Done sorting all points");
- };
- function updateXml(xmlData)
- {
- console.log("Updating XML...");
- for (let index in tracks)
- {
- let track = tracks[index];
- track.sortXml();
- }
- console.log("Done updating XML");
- let newFilePath = filePath + "2";
- console.log("Writing to new file \"" + newFilePath + "\"");
-
- let xmlBack = xmlJsLib.js2xml(xmlData, {spaces: 2, indentCdata: true});
- fileSystemLib.writeFile(newFilePath, xmlBack, function(error, data)
- {
- if (error)
- {
- throw error;
- }
- console.log("Data written to file");
- let endTime = new Date();
- let timeDiff = (endTime - startTime) / 1000; //in sec
- console.log("Done in " + timeDiff + " sec");
- });
- };
- function Track(trackData)
- {
- this.m_points = [];
-
- let elementsData = trackData.elements;
- for (let index in elementsData)
- {
- let elementData = elementsData[index];
- if (elementData.name === "name")
- {
- this.m_trackName = elementData.elements[0].text;
- }
- else if (elementData.name === "trkseg")
- {
- this.m_pointsData = elementData.elements;
- }
- }
- console.log("Loading track \"" + this.m_trackName + "\" with " + this.m_pointsData.length + " points");
-
- for (let index in this.m_pointsData)
- {
- let pointData = this.m_pointsData[index];
- let point = new Point(pointData);
- this.m_points.push(point);
- }
- console.log("Done loading track \"" + this.m_trackName + "\"");
- }
- Track.prototype.m_name;
- // @type Array[Point]
- Track.prototype.m_points;
- Track.prototype.sort = function()
- {
- console.log("Sorting points...");
- this.m_points.sort(function(pointA, pointB)
- {
- return pointA.getTimestamp() - pointB.getTimestamp();
- });
- console.log("Done reading and sorting track \"" + this.m_trackName + "\"");
- };
- Track.prototype.sortXml = function()
- {
- // We empty the original array of points data (we don't use this.m_pointsData=[] because we want to update the original array instead of creating a new one)
- this.m_pointsData.splice(0, this.m_pointsData.length);
- for (let index in this.m_points)
- {
- let point = this.m_points[index];
- this.m_pointsData.push(point.getData());
- }
- };
- function Point(pointData)
- {
- this.m_data = pointData;
- this.m_timestamp = new Date(this.m_data.elements[0].elements[0].text).getTime();
- }
- Point.prototype.m_data;
- Point.prototype.m_timestamp;
- Point.prototype.getData = function()
- {
- return this.m_data;
- };
- Point.prototype.getTimestamp = function()
- {
- return this.m_timestamp;
- };
- // Execution of the script
- main();
|