Merge pull request #13 from opatut/refactor_tracks_logic_and_testing

Refactor tracks logic and support new CSV format
This commit is contained in:
Paul Bienkowski 2020-11-21 19:35:22 +01:00 committed by GitHub
commit 1a00e7b010
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 7113 additions and 542 deletions

4
app.js
View file

@ -18,8 +18,8 @@ app.use(cors());
// Normal express config defaults
app.use(require('morgan')('dev'));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(bodyParser.json({ limit: '50mb' }));
app.use(bodyParser.urlencoded({ limit: '50mb', extended: false }));
app.use(require('method-override')());
app.use(express.static(__dirname + '/public'));

View file

@ -1,35 +1,40 @@
version: '3'
services:
mongo:
image: mongo
tty: true
volumes:
- ./local/mongo:/data/db
ports:
- '27017:27017'
restart: on-failure
mongo:
image: mongo
tty: true
volumes:
- ./local/mongo:/data/db
ports:
- '27017:27017'
restart: on-failure
api:
image: obs-api
build:
context: .
dockerfile: ./Dockerfile
volumes:
- ./_helpers:/opt/obsAPI/_helpers
- ./_middleware:/opt/obsAPI/_middleware
- ./accounts:/opt/obsAPI/accounts
- ./config:/opt/obsAPI/config
- ./data:/opt/obsAPI/data
- ./models:/opt/obsAPI/models
- ./public:/opt/obsAPI/public
- ./routes:/opt/obsAPI/routes
- ./app.js:/opt/obsAPI/app.js
environment:
- PORT=3000
- MONGODB_URL=mongodb://mongo/obsTest
links:
- mongo
ports:
- '3000:3000'
restart: on-failure
api:
image: obs-api
build:
context: .
dockerfile: ./Dockerfile
volumes:
- ./_helpers:/opt/obsAPI/_helpers
- ./_middleware:/opt/obsAPI/_middleware
- ./accounts:/opt/obsAPI/accounts
- ./config:/opt/obsAPI/config
- ./data:/opt/obsAPI/data
- ./models:/opt/obsAPI/models
- ./logic:/opt/obsAPI/logic
- ./public:/opt/obsAPI/public
- ./routes:/opt/obsAPI/routes
- ./app.js:/opt/obsAPI/app.js
environment:
- PORT=3000
- MONGODB_URL=mongodb://mongo/obsTest
links:
- mongo
ports:
- '3000:3000'
restart: on-failure
command:
- npm
- run
- dev

8
logic/TrackInfo.js Normal file
View file

@ -0,0 +1,8 @@
class TrackInfo {
constructor(track, trackData) {
this.track = track;
this.trackData = trackData;
}
}
module.exports = TrackInfo;

353
logic/_tracks_testdata.js Normal file
View file

@ -0,0 +1,353 @@
const TEST_ROWS = [
'Date;Time;Latitude;Longitude;Course;Speed;Right;Left;Confirmed;insidePrivacyArea;',
'12.07.2020;09:02:59;0.000000;0.000000;0.000;0.0000;255;255;0;0;',
'12.07.2020;09:02:59;0.000000;0.000000;0.000;0.0000;255;255;0;0;',
'12.07.2020;09:03:00;0.000000;0.000000;0.000;0.0000;255;255;0;0;',
'12.07.2020;09:03:01;48.722205;9.270218;0.000;0.4260;255;255;0;0;',
'12.07.2020;09:03:02;48.722206;9.270219;0.000;0.5741;255;255;0;0;',
'12.07.2020;09:03:03;48.722204;9.270221;0.000;0.5371;255;255;0;0;',
'12.07.2020;09:03:04;48.722198;9.270229;0.000;0.7593;255;255;0;0;',
'12.07.2020;09:03:05;48.722188;9.270241;0.000;0.5556;255;255;0;0;',
'12.07.2020;09:03:06;48.722174;9.270259;0.000;0.4815;255;255;0;0;',
'12.07.2020;09:03:07;48.722158;9.270278;0.000;0.3704;255;255;0;0;',
'12.07.2020;09:03:08;48.722146;9.270293;0.000;0.5741;255;255;0;0;',
'12.07.2020;09:03:09;48.722138;9.270305;0.000;1.2594;255;255;0;0;',
'12.07.2020;09:03:10;48.722129;9.270318;0.000;1.5557;255;255;0;0;',
'12.07.2020;09:03:11;48.722122;9.270329;0.000;1.5372;255;255;0;0;',
'12.07.2020;09:03:12;48.722115;9.270339;0.000;0.4630;255;255;0;0;',
'12.07.2020;09:03:13;48.722107;9.270350;0.000;0.2963;255;255;0;0;',
'12.07.2020;09:03:14;48.722101;9.270357;0.000;0.2963;255;255;0;0;',
'12.07.2020;09:03:15;48.722092;9.270367;0.000;0.8149;255;255;0;0;',
'12.07.2020;09:03:16;48.722084;9.270377;0.000;1.2223;255;255;0;0;',
'12.07.2020;09:03:17;48.722076;9.270385;0.000;0.0926;255;255;0;0;',
'12.07.2020;09:03:18;48.722070;9.270391;0.000;1.4816;255;255;0;0;',
'12.07.2020;09:03:19;48.722070;9.270392;0.000;1.0927;255;255;0;0;',
'12.07.2020;09:03:20;48.722066;9.270395;0.000;1.6668;255;255;0;0;',
'12.07.2020;09:03:21;48.722068;9.270391;0.000;2.0742;255;255;0;0;',
'12.07.2020;09:03:22;48.722064;9.270396;0.000;1.6853;255;255;0;0;',
'12.07.2020;09:03:23;48.722060;9.270401;0.000;1.0927;255;255;0;0;',
'12.07.2020;09:03:24;48.722056;9.270406;0.000;0.9445;255;255;0;0;',
'12.07.2020;09:03:25;48.722052;9.270411;0.000;0.7964;255;255;0;0;',
'12.07.2020;09:03:26;48.722047;9.270416;0.000;0.6482;255;255;0;0;',
'12.07.2020;09:03:27;48.722042;9.270419;0.000;1.0556;255;255;0;0;',
'12.07.2020;09:03:28;48.722031;9.270433;0.000;2.0372;255;255;0;0;',
'12.07.2020;09:03:29;48.722031;9.270432;0.000;2.4261;255;255;0;0;',
'12.07.2020;09:03:30;48.722029;9.270433;0.000;0.8704;255;255;0;0;',
'12.07.2020;09:03:31;48.722029;9.270433;0.000;1.8150;255;255;0;0;',
'12.07.2020;09:03:32;48.722024;9.270439;0.000;1.2223;255;255;0;0;',
'12.07.2020;09:03:33;48.722025;9.270439;0.000;0.3889;255;255;0;0;',
'12.07.2020;09:03:34;48.722022;9.270440;0.000;0.3519;255;255;0;0;',
'12.07.2020;09:03:35;48.722020;9.270445;0.000;0.9445;255;255;0;0;',
'12.07.2020;09:03:36;48.722018;9.270447;0.000;0.9260;255;255;0;0;',
'12.07.2020;09:03:37;48.722020;9.270444;0.000;0.9075;255;255;0;0;',
'12.07.2020;09:03:38;48.722021;9.270443;0.000;1.9261;255;255;0;0;',
'12.07.2020;09:03:39;48.722018;9.270447;0.000;0.3334;255;255;0;0;',
'12.07.2020;09:03:40;48.722020;9.270445;0.000;0.1482;255;255;0;0;',
'12.07.2020;09:03:41;48.722023;9.270440;0.000;1.2594;255;255;0;0;',
'12.07.2020;09:03:42;48.722023;9.270442;0.000;0.5000;255;255;0;0;',
'12.07.2020;09:03:43;48.722025;9.270440;0.000;0.6852;220;255;0;0;',
'12.07.2020;09:03:44;48.722023;9.270441;0.000;0.8519;199;255;0;0;',
'12.07.2020;09:03:45;48.722026;9.270438;0.000;1.4075;255;255;0;0;',
'12.07.2020;09:03:46;48.722029;9.270436;0.000;0.5371;255;255;0;0;',
'12.07.2020;09:03:47;48.722028;9.270435;0.000;0.8334;97;255;0;0;',
'12.07.2020;09:03:48;48.722029;9.270435;0.000;0.3704;255;255;0;0;',
'12.07.2020;09:03:49;48.722029;9.270436;0.000;1.1112;96;255;0;0;',
'12.07.2020;09:03:50;48.722029;9.270435;0.000;1.8890;255;255;0;0;',
'12.07.2020;09:03:51;48.722034;9.270429;0.000;1.0186;255;255;0;0;',
'12.07.2020;09:03:52;48.721942;9.270529;128.450;5.2226;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;79;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;178;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;89;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;156;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;168;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;181;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;176;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;186;0;0;',
'12.07.2020;09:03:53;48.721929;9.270546;128.450;1.3520;255;255;0;0;',
'12.07.2020;09:04:10;48.721896;9.270602;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:04:11;48.721894;9.270609;916.230;0.0926;255;192;0;0;',
'12.07.2020;09:04:12;48.721892;9.270616;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:04:13;48.721890;9.270623;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:04:14;48.721888;9.270629;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:15;48.721886;9.270635;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:16;48.721883;9.270640;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:04:17;48.721881;9.270644;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:04:18;48.721879;9.270649;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:04:19;48.721877;9.270653;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:04:20;48.721876;9.270657;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:21;48.721874;9.270658;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:04:22;48.721873;9.270659;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:04:23;48.721872;9.270661;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:04:24;48.721871;9.270661;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:25;48.721870;9.270660;916.230;0.3334;255;255;0;0;',
'12.07.2020;09:04:26;48.721869;9.270658;916.230;0.5000;255;255;0;0;',
'12.07.2020;09:04:27;48.721866;9.270660;916.230;1.6853;255;255;0;0;',
'12.07.2020;09:04:28;48.721866;9.270659;916.230;0.8704;255;198;0;0;',
'12.07.2020;09:04:29;48.721867;9.270659;916.230;0.5741;255;196;0;0;',
'12.07.2020;09:04:30;48.721867;9.270660;916.230;0.3148;255;196;0;0;',
'12.07.2020;09:04:31;48.721867;9.270659;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:04:32;48.721866;9.270659;916.230;0.0556;255;199;0;0;',
'12.07.2020;09:04:33;48.721867;9.270656;916.230;0.1482;255;199;0;0;',
'12.07.2020;09:04:34;48.721867;9.270654;916.230;0.0370;255;198;0;0;',
'12.07.2020;09:04:35;48.721867;9.270653;916.230;0.1296;255;198;0;0;',
'12.07.2020;09:04:36;48.721867;9.270651;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:04:37;48.721867;9.270650;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:04:38;48.721868;9.270650;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:04:39;48.721868;9.270649;916.230;0.1667;255;201;0;0;',
'12.07.2020;09:04:40;48.721868;9.270647;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:41;48.721869;9.270644;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:04:42;48.721869;9.270641;916.230;0.0185;255;198;0;0;',
'12.07.2020;09:04:43;48.721870;9.270638;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:44;48.721870;9.270635;916.230;0.0370;255;199;0;0;',
'12.07.2020;09:04:45;48.721871;9.270632;916.230;0.1482;255;204;0;0;',
'12.07.2020;09:04:46;48.721871;9.270630;916.230;0.0185;255;201;0;0;',
'12.07.2020;09:04:47;48.721873;9.270630;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:04:48;48.721873;9.270629;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:04:49;48.721874;9.270628;916.230;0.4074;255;255;0;0;',
'12.07.2020;09:04:50;48.721875;9.270627;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:04:51;48.721876;9.270625;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:04:52;48.721877;9.270623;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:04:53;48.721877;9.270622;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:04:54;48.721879;9.270621;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:04:55;48.721881;9.270618;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:04:56;48.721883;9.270615;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:04:57;48.721884;9.270612;916.230;0.2778;255;255;0;0;',
'12.07.2020;09:04:58;48.721885;9.270609;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:04:59;48.721886;9.270606;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:05:00;48.721888;9.270602;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:05:01;48.721889;9.270598;916.230;0.1111;255;191;0;0;',
'12.07.2020;09:05:02;48.721890;9.270595;916.230;0.1482;255;193;0;0;',
'12.07.2020;09:05:03;48.721891;9.270593;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:05:04;48.721891;9.270591;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:05;48.721891;9.270589;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:05:06;48.721891;9.270587;916.230;0.3519;255;199;0;0;',
'12.07.2020;09:05:07;48.721891;9.270586;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:08;48.721891;9.270588;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:09;48.721890;9.270589;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:10;48.721889;9.270589;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:11;48.721888;9.270589;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:05:12;48.721887;9.270589;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:05:13;48.721886;9.270590;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:14;48.721885;9.270591;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:05:15;48.721885;9.270592;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:05:16;48.721885;9.270596;916.230;0.5556;255;255;0;0;',
'12.07.2020;09:05:17;48.721885;9.270598;916.230;0.3519;255;255;0;0;',
'12.07.2020;09:05:18;48.721884;9.270600;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:05:19;48.721882;9.270600;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:20;48.721881;9.270602;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:05:21;48.721879;9.270603;916.230;0.0185;255;206;0;0;',
'12.07.2020;09:05:22;48.721878;9.270605;916.230;0.0556;255;203;0;0;',
'12.07.2020;09:05:23;48.721876;9.270606;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:05:24;48.721874;9.270605;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:05:25;48.721873;9.270605;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:05:26;48.721872;9.270605;916.230;0.1296;255;209;0;0;',
'12.07.2020;09:05:27;48.721870;9.270606;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:05:28;48.721869;9.270608;916.230;0.1111;255;206;0;0;',
'12.07.2020;09:05:29;48.721868;9.270610;916.230;0.3148;255;209;0;0;',
'12.07.2020;09:05:30;48.721867;9.270610;916.230;0.2593;255;208;0;0;',
'12.07.2020;09:05:31;48.721866;9.270611;916.230;0.0556;255;210;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:32;48.721866;9.270612;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:44;48.721855;9.270602;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:44;48.721855;9.270602;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:05:46;48.721854;9.270602;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:46;48.721854;9.270602;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:05:48;48.721852;9.270606;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:05:49;48.721851;9.270611;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:05:50;48.721851;9.270615;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:05:51;48.721851;9.270616;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:05:52;48.721851;9.270617;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:05:53;48.721852;9.270617;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:05:54;48.721853;9.270616;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:05:55;48.721855;9.270613;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:05:56;48.721858;9.270609;916.230;0.6482;255;255;0;0;',
'12.07.2020;09:05:57;48.721860;9.270606;916.230;0.4260;255;255;0;0;',
'12.07.2020;09:05:58;48.721864;9.270601;916.230;0.6297;255;255;0;0;',
'12.07.2020;09:05:59;48.721867;9.270595;916.230;0.4260;255;255;0;0;',
'12.07.2020;09:06:00;48.721872;9.270589;916.230;0.5000;255;255;0;0;',
'12.07.2020;09:06:01;48.721875;9.270584;916.230;0.2593;255;255;0;0;',
'12.07.2020;09:06:02;48.721880;9.270578;916.230;0.5186;255;255;0;0;',
'12.07.2020;09:06:03;48.721883;9.270574;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:06:04;48.721886;9.270570;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:06:05;48.721890;9.270565;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:06:06;48.721893;9.270562;916.230;0.2593;255;255;0;0;',
'12.07.2020;09:06:07;48.721893;9.270560;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:08;48.721894;9.270559;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:09;48.721894;9.270557;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:07;48.721896;9.270556;916.230;0.2778;255;255;0;0;',
'12.07.2020;09:06:08;48.721896;9.270556;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:06:09;48.721895;9.270557;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:10;48.721894;9.270559;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:06:11;48.721892;9.270560;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:06:12;48.721891;9.270561;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:06:13;48.721892;9.270562;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:06:14;48.721891;9.270564;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:15;48.721889;9.270566;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:06:16;48.721888;9.270568;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:17;48.721888;9.270570;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:06:18;48.721888;9.270572;916.230;0.4630;255;255;0;0;',
'12.07.2020;09:06:19;48.721887;9.270573;916.230;0.4815;255;255;0;0;',
'12.07.2020;09:06:20;48.721886;9.270574;916.230;0.3334;255;255;0;0;',
'12.07.2020;09:06:21;48.721885;9.270576;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:06:22;48.721884;9.270579;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:23;48.721882;9.270581;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:24;48.721881;9.270584;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:25;48.721880;9.270589;916.230;0.2963;255;255;0;0;',
'12.07.2020;09:06:26;48.721879;9.270596;916.230;0.3519;255;255;0;0;',
'12.07.2020;09:06:27;48.721878;9.270602;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:06:28;48.721876;9.270601;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:29;48.721874;9.270603;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:30;48.721873;9.270607;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:31;48.721872;9.270614;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:06:32;48.721870;9.270613;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:33;48.721869;9.270614;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:06:34;48.721868;9.270616;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:06:35;48.721867;9.270617;916.230;0.2593;255;255;0;0;',
'12.07.2020;09:06:36;48.721867;9.270618;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:06:37;48.721867;9.270618;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:06:38;48.721867;9.270616;916.230;0.2963;255;255;0;0;',
'12.07.2020;09:06:39;48.721867;9.270613;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:06:40;48.721867;9.270607;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:06:41;48.721866;9.270601;916.230;0.5186;255;255;0;0;',
'12.07.2020;09:06:42;48.721866;9.270593;916.230;0.2963;255;255;0;0;',
'12.07.2020;09:06:43;48.721866;9.270587;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:44;48.721866;9.270581;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:45;48.721866;9.270576;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:46;48.721866;9.270567;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:06:47;48.721866;9.270558;916.230;0.4074;255;255;0;0;',
'12.07.2020;09:06:48;48.721866;9.270550;916.230;0.4260;255;255;0;0;',
'12.07.2020;09:06:49;48.721866;9.270543;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:50;48.721867;9.270537;916.230;0.2778;255;255;0;0;',
'12.07.2020;09:06:51;48.721867;9.270532;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:06:52;48.721867;9.270526;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:06:53;48.721868;9.270522;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:54;48.721868;9.270517;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:06:55;48.721869;9.270512;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:06:56;48.721869;9.270506;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:06:57;48.721869;9.270503;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:06:58;48.721870;9.270500;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:06:59;48.721870;9.270497;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:07:00;48.721871;9.270494;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:07:01;48.721871;9.270493;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:07:02;48.721871;9.270492;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:07:03;48.721872;9.270490;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:07:04;48.721873;9.270489;916.230;0.6667;255;255;0;0;',
'12.07.2020;09:07:05;48.721873;9.270487;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:07:06;48.721873;9.270486;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:07:07;48.721873;9.270486;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:07:08;48.721873;9.270485;916.230;0.1852;255;255;0;0;',
'12.07.2020;09:07:09;48.721873;9.270485;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:07:10;48.721872;9.270485;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:07:11;48.721870;9.270486;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:07:12;48.721869;9.270489;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:07:13;48.721867;9.270492;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:07:14;48.721865;9.270494;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:07:15;48.721863;9.270495;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:07:16;48.721861;9.270497;916.230;0.0000;255;255;0;0;',
'12.07.2020;09:07:17;48.721860;9.270496;916.230;0.4074;255;255;0;0;',
'12.07.2020;09:07:18;48.721859;9.270495;916.230;0.4445;255;255;0;0;',
'12.07.2020;09:07:19;48.721857;9.270496;916.230;0.3889;255;255;0;0;',
'12.07.2020;09:07:20;48.721856;9.270496;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:07:21;48.721854;9.270494;916.230;0.7593;255;255;0;0;',
'12.07.2020;09:07:22;48.721851;9.270496;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:07:23;48.721850;9.270497;916.230;0.1667;255;255;0;0;',
'12.07.2020;09:07:24;48.721848;9.270501;916.230;0.4074;255;255;0;0;',
'12.07.2020;09:07:25;48.721847;9.270504;916.230;0.4074;255;255;0;0;',
'12.07.2020;09:07:26;48.721846;9.270505;916.230;0.2037;255;255;0;0;',
'12.07.2020;09:07:27;48.721844;9.270508;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:07:28;48.721843;9.270507;916.230;0.4630;255;255;0;0;',
'12.07.2020;09:07:29;48.721842;9.270509;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:07:30;48.721841;9.270512;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:07:31;48.721840;9.270515;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:07:32;48.721839;9.270517;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:07:33;48.721838;9.270522;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:07:34;48.721838;9.270527;916.230;0.3889;255;255;0;0;',
'12.07.2020;09:07:35;48.721837;9.270530;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:07:36;48.721836;9.270532;916.230;0.1111;255;255;0;0;',
'12.07.2020;09:07:37;48.721835;9.270536;916.230;0.6112;255;255;0;0;',
'12.07.2020;09:07:38;48.721835;9.270541;916.230;1.1668;255;255;0;0;',
'12.07.2020;09:07:39;48.721835;9.270543;916.230;0.3889;255;255;0;0;',
'12.07.2020;09:07:40;48.721834;9.270545;916.230;0.5000;255;255;0;0;',
'12.07.2020;09:07:41;48.721834;9.270544;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:07:42;48.721834;9.270545;916.230;0.7593;255;255;0;0;',
'12.07.2020;09:07:43;48.721834;9.270545;916.230;0.8890;255;255;0;0;',
'12.07.2020;09:07:44;48.721834;9.270543;916.230;0.4260;255;255;0;0;',
'12.07.2020;09:07:45;48.721834;9.270541;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:07:46;48.721834;9.270540;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:07:47;48.721835;9.270538;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:07:48;48.721835;9.270535;916.230;0.0556;255;255;0;0;',
'12.07.2020;09:07:49;48.721835;9.270534;916.230;0.8890;255;255;0;0;',
'12.07.2020;09:07:50;48.721835;9.270534;916.230;0.5926;255;255;0;0;',
'12.07.2020;09:07:51;48.721835;9.270534;916.230;0.7593;255;255;0;0;',
'12.07.2020;09:07:52;48.721836;9.270533;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:07:53;48.721836;9.270531;916.230;0.0741;255;255;0;0;',
'12.07.2020;09:07:54;48.721836;9.270529;916.230;0.3889;255;255;0;0;',
'12.07.2020;09:07:55;48.721836;9.270530;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:07:56;48.721836;9.270530;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:07:57;48.721837;9.270531;916.230;0.0185;255;255;0;0;',
'12.07.2020;09:07:58;48.721837;9.270530;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:07:59;48.721838;9.270526;916.230;0.3519;255;255;0;0;',
'12.07.2020;09:08:00;48.721838;9.270521;916.230;0.4260;255;255;0;0;',
'12.07.2020;09:08:01;48.721839;9.270522;916.230;0.5556;255;255;0;0;',
'12.07.2020;09:08:02;48.721840;9.270524;916.230;0.3519;255;255;0;0;',
'12.07.2020;09:08:03;48.721842;9.270525;916.230;0.2963;255;255;0;0;',
'12.07.2020;09:08:04;48.721843;9.270525;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:08:05;48.721844;9.270524;916.230;0.2222;255;255;0;0;',
'12.07.2020;09:08:06;48.721846;9.270522;916.230;0.3704;255;255;0;0;',
'12.07.2020;09:08:07;48.721847;9.270519;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:08:08;48.721848;9.270516;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:08:09;48.721849;9.270514;916.230;0.1296;255;255;0;0;',
'12.07.2020;09:08:10;48.721850;9.270512;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:08:11;48.721851;9.270513;916.230;0.3334;255;255;0;0;',
'12.07.2020;09:08:12;48.721851;9.270512;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:08:13;48.721851;9.270512;916.230;0.2593;255;255;0;0;',
'12.07.2020;09:08:14;48.721852;9.270511;916.230;0.0926;255;255;0;0;',
'12.07.2020;09:08:15;48.721853;9.270512;916.230;0.0370;255;255;0;0;',
'12.07.2020;09:08:16;48.721852;9.270515;916.230;0.5371;255;255;0;0;',
'12.07.2020;09:08:17;48.721853;9.270517;916.230;0.1482;255;255;0;0;',
'12.07.2020;09:08:18;48.721854;9.270519;916.230;0.3148;255;255;0;0;',
'12.07.2020;09:08:19;48.721855;9.270520;916.230;0.2408;255;255;0;0;',
'12.07.2020;09:08:20;48.721856;9.270523;916.230;0.3704;255;255;0;0;',
];
const test1 = TEST_ROWS.join('$');
const test2 = `OBSFirmwareVersion=v0.3.999&OBSDataFormat=2&DataPerMeasurement=3&MaximumMeasurementsPerLine=60&OffsetLeft=30&OffsetRight=30&NumberOfDefinedPrivacyAreas=3&PrivacyLevelApplied=AbsolutePrivacy&MaximumValidFlightTimeMicroseconds=18560&DistanceSensorsUsed=HC-SR04/JSN-SR04T&DeviceId=ECEC&OBSUserID=32423432342234
Date;Time;Millis;Comment;Latitude;Longitude;Altitude;Course;Speed;HDOP;Satellites;BatteryLevel;Left;Right;Confirmed;Marked;Invalid;InsidePrivacyArea;Factor;Measurements;Tms1;Lus1;Rus1;Tms2;Lus2;Rus2;Tms3;Lus3;Rus3;Tms4;Lus4;Rus4;Tms5;Lus5;Rus5;Tms6;Lus6;Rus6;Tms7;Lus7;Rus7;Tms8;Lus8;Rus8;Tms9;Lus9;Rus9;Tms10;Lus10;Rus10;Tms11;Lus11;Rus11;Tms12;Lus12;Rus12;Tms13;Lus13;Rus13;Tms14;Lus14;Rus14;Tms15;Lus15;Rus15;Tms16;Lus16;Rus16;Tms17;Lus17;Rus17;Tms18;Lus18;Rus18;Tms19;Lus19;Rus19;Tms20;Lus20;Rus20;Tms21;Lus21;Rus21;Tms22;Lus22;Rus22;Tms23;Lus23;Rus23;Tms24;Lus24;Rus24;Tms25;Lus25;Rus25;Tms26;Lus26;Rus26;Tms27;Lus27;Rus27;Tms28;Lus28;Rus28;Tms29;Lus29;Rus29;Tms30;Lus30;Rus30;Tms31;Lus31;Rus31;Tms32;Lus32;Rus32;Tms33;Lus33;Rus33;Tms34;Lus34;Rus34;Tms35;Lus35;Rus35;Tms36;Lus36;Rus36;Tms37;Lus37;Rus37;Tms38;Lus38;Rus38;Tms39;Lus39;Rus39;Tms40;Lus40;Rus40;Tms41;Lus41;Rus41;Tms42;Lus42;Rus42;Tms43;Lus43;Rus43;Tms44;Lus44;Rus44;Tms45;Lus45;Rus45;Tms46;Lus46;Rus46;Tms47;Lus47;Rus47;Tms48;Lus48;Rus48;Tms49;Lus49;Rus49;Tms50;Lus50;Rus50;Tms51;Lus51;Rus51;Tms52;Lus52;Rus52;Tms53;Lus53;Rus53;Tms54;Lus54;Rus54;Tms55;Lus55;Rus55;Tms56;Lus56;Rus56;Tms57;Lus57;Rus57;Tms58;Lus58;Rus58;Tms59;Lus59;Rus59;Tms60;Lus60;Rus60
18.11.2020;16:05:59;1265034;;48.723224;9.094103;495.3;189.86;3.2;1.01;7;3.74;770;;0;0;58;54;0;6231;;16;;;36;6350;;52;;;72;6263;;87;;;107;6828;;122;;;143;6836;;158;;;178;6936;;193;;;213;7094;;228;;;248;6822;;263;;;284;7019;;299;;;319;6942;;334;;;354;7110;;370;;;390;7203;;405;;;425;7758;;440;;;461;7266;;476;;;496;7499;;511;;;531;7328;;546;;;567;7354;;582;;;602;7397;;617;;;637;;;664;;;684;16615;;708;;;728;9161;;745;;;765;10238;;783;;;802;8525;;818;;;839;7756;;854;;;875;7580;;890;;;910;7926;;925;;;945;7624;;960;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:00;1266041;DEVELOP: GPSMessages: 2587 GPS crc errors: 0;48.723205;9.0941;495.4;189.86;2.87;1.01;7;3.74;1020;;0;0;58;53;0;8012;;27;;;47;7999;;62;;;83;7660;;98;;;118;7698;;133;;;158;1252;;169;;;194;1146;;204;;;229;1173;;239;;;264;1173;;274;;;300;1147;;310;;;335;7943;;352;;;371;8713;;387;;;407;8005;;423;;;443;8021;;458;;;478;;;505;;;525;8111;;541;;;560;8074;;576;;;596;8254;;612;;;632;8514;;647;;;667;8195;;682;;;703;8094;;718;;;738;8123;;754;;;774;8330;;789;;;810;8966;;826;;;846;9066;;862;;;882;10553;;899;;;920;8345;;935;;;955;9219;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:01;1267037;DEVELOP: Mem: 45k Buffer: 4k last write time: 58;48.723197;9.094089;495.7;189.86;2.93;1.01;7;3.74;1090;;0;0;58;53;0;8164;;18;;;39;8184;;53;;;74;16305;;98;;;118;8658;;135;;;155;8198;;170;;;190;8133;;205;;;226;8536;;241;;;261;8676;;276;;;296;8516;;314;;;334;8114;;350;;;370;8294;;385;;;405;8751;;422;;;441;8163;;457;;;478;8062;;493;;;513;8093;;528;;;549;8060;;564;;;584;8085;;599;;;619;8071;;634;;;655;8262;;671;;;690;8746;;707;;;726;9116;;742;;;762;;;789;;;808;8121;;825;;;845;8113;;860;;;881;8129;;896;;;916;8096;;932;;;952;10617;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:02;1268027;;48.723185;9.094076;496.1;189.86;3.02;1.01;7;3.74;980;;0;0;58;55;0;8173;;18;;;37;8535;;53;;;73;8435;;88;;;109;8592;;124;;;144;8012;;159;;;180;8037;;195;;;215;7975;;230;;;250;7970;;265;;;286;7850;;301;;;321;7861;;336;;;356;7826;;371;;;392;8097;;407;;;427;8467;;443;;;463;7763;;478;;;498;7687;;513;;;534;7950;;549;;;569;7806;;584;;;604;8253;;620;;;640;7753;;656;;;676;8188;;692;;;711;7533;;727;;;747;7791;;763;;;783;7460;;798;;;825;9827;;843;;;863;7432;;878;;;904;7646;;919;;;939;7538;;955;;;974;7508;;;;;;;;;;;;;;;;
18.11.2020;16:06:03;1269096;;48.723177;9.094068;496.2;189.86;3;1.01;7;3.74;920;;0;0;58;51;0;7218;;19;;;38;8144;;54;;;74;7463;;89;;;110;7856;;125;;;145;7869;;161;;;181;7422;;196;;;216;7934;;232;;;252;7363;;267;;;293;7297;;307;;;332;8105;;348;;;367;7468;;383;;;403;7213;;418;;;439;7172;;454;;;478;7184;;489;;;514;7312;;528;;;550;7175;;565;;;585;7180;;600;;;620;7013;;635;;;655;7154;;670;;;691;7240;;706;;;726;7075;;741;;;761;7133;;776;;;801;7511;;815;;;836;7639;;851;;;872;8891;;888;;;908;7070;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:04;1270033;;48.723167;9.094056;496.6;189.86;3.19;1.01;7;3.74;870;;0;0;58;53;0;7617;;19;;;39;6812;;55;;;80;1173;;90;;;116;8173;;133;;;152;7431;;168;;;188;7197;;203;;;223;6984;;238;;;259;7218;;274;;;294;6881;;309;;;329;7111;;344;;;365;7500;;380;;;400;7462;;415;;;435;7094;;450;;;471;6820;;486;;;506;7147;;521;;;541;9156;;558;;;578;6961;;594;;;614;;;641;;;660;7176;;676;;;696;7177;;712;;;732;7199;;747;;;767;7218;;782;;;802;7360;;817;;;838;;;865;;;884;;;904;;;924;;;943;;;962;7252;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:05;1271032;;48.723153;9.094046;496.5;189.86;3.48;1.01;7;3.74;940;;0;0;58;54;0;7295;;14;;;35;7183;;50;;;71;7283;;85;;;106;8957;;122;;;142;8178;;158;;;178;7814;;194;;;213;7495;;229;;;249;7713;;265;;;285;7305;;300;;;320;7654;;335;;;356;7687;;371;;;391;7634;;406;;;426;7167;;441;;;461;;;488;;;508;7245;;524;;;544;7283;;559;;;580;7150;;595;;;615;7194;;630;;;650;7410;;665;;;686;7670;;702;;;721;7421;;737;;;757;7588;;772;;;792;7452;;809;;;828;8162;;844;;;865;9078;;881;;;901;7563;;917;;;936;7775;;952;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:06;1272031;;48.723146;9.094036;496.5;189.86;2.44;1.01;7;3.74;1000;;0;0;58;54;0;8193;;18;;;39;7629;;54;;;74;;;102;;;121;7778;;137;;;157;7773;;172;;;193;7922;;208;;;228;7706;;243;;;263;8881;;280;;;299;7776;;315;;;334;7797;;350;;;370;8683;;386;;;406;7863;;422;;;441;7901;;457;;;477;7747;;492;;;513;8246;;529;;;549;7756;;564;;;585;7667;;600;;;620;7657;;635;;;655;;;682;;;702;8193;;719;;;738;7751;;754;;;774;7731;;789;;;809;8109;;825;;;845;7623;;860;;;880;7883;;895;;;916;7579;;931;;;951;7514;;966;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:07;1273044;;48.723134;9.094026;496.7;189.86;3.44;1.01;7;3.74;990;;0;0;58;53;0;7543;;15;;;37;7535;;52;;;72;9628;;90;;;109;8166;;125;;;146;7469;;161;;;181;7923;;197;;;216;7651;;232;;;252;7594;;267;;;288;7796;;303;;;323;7960;;338;;;359;7862;;373;;;394;7633;;409;;;429;7926;;444;;;465;7661;;479;;;500;7546;;515;;;535;7522;;550;;;570;8461;;587;;;606;7520;;622;;;643;;;668;;;688;7495;;704;;;723;7672;;739;;;759;7964;;774;;;795;8725;;811;;;831;7366;;847;;;867;7586;;882;;;902;8634;;919;;;938;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:08;1274030;;48.723126;9.094013;496.7;230.11;3.54;1.01;7;3.74;850;;0;0;58;53;0;7452;;29;;;49;7446;;65;;;91;1147;;102;;;127;7517;;143;;;163;7411;;178;;;204;1148;;214;;;240;7282;;256;;;281;1201;;291;;;316;1144;;326;;;351;1173;;362;;;386;6718;;401;;;422;7303;;437;;;461;7621;;476;;;497;7557;;511;;;532;7451;;547;;;567;7658;;583;;;603;7534;;618;;;638;7306;;653;;;673;7222;;688;;;709;7169;;724;;;744;7115;;759;;;779;7277;;794;;;815;;;841;;;861;;;881;;;900;7403;;916;;;936;7356;;951;;;972;7030;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:09;1275038;;48.723121;9.093994;496.9;237.39;3.33;1.01;7;3.74;730;;0;0;58;54;0;7327;;16;;;36;6876;;52;;;72;6953;;87;;;107;7261;;122;;;142;6702;;158;;;178;7286;;193;;;213;6605;;228;;;249;7168;;264;;;284;6641;;299;;;324;7059;;339;;;359;7568;;374;;;394;6476;;409;;;430;6589;;445;;;470;1174;;480;;;505;1173;;515;;;541;1175;;551;;;576;1149;;586;;;611;6222;;626;;;647;6722;;661;;;687;5939;;700;;;723;5989;;735;;;760;6144;;773;;;795;6019;;808;;;830;6306;;844;;;866;6169;;879;;;901;6288;;914;;;936;9882;;954;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:10;1276038;;48.723117;9.093979;497.4;247.62;2.96;1.01;7;3.74;7;69;0;;0;0;58;52;0;;;30;;;50;;;69;;;89;;;109;;6187;124;9730;;144;;6203;160;14558;;182;;6178;195;;;222;;6233;235;;;257;;6323;275;;;295;;6379;311;;;331;;6371;346;8588;;366;;6330;381;2150;;401;;6275;417;1200;;437;;6184;461;;;488;;6033;505;;;525;;5943;543;2550;;561;;5872;579;2563;;596;;5844;614;1225;;631;;5835;650;1173;;667;;5799;685;2243;;702;;5804;720;2275;;737;;5798;759;;;785;;5854;805;;;825;;5984;840;;;860;;5979;875;;;895;;6027;911;7850;;931;;6001;946;13531;;969;;5957;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:11;1277041;;48.723117;9.093965;497.5;247.62;2.74;1.01;7;3.74;143;72;0;;0;0;58;48;0;;;30;;5966;43;;;65;;5940;78;12209;;101;;5923;113;;;140;;7918;155;18175;;182;;6159;199;;;226;;6047;239;;;261;;6283;274;;;297;;;328;;;348;;6015;364;;;384;;;418;1174;;428;;6166;453;;;480;;6265;498;;;518;;6241;536;9449;;553;;6311;571;17498;;597;;6394;611;;;638;;6380;652;;;673;;6408;687;;;708;;7059;722;7897;;744;;7059;759;10810;;779;;6459;794;;;822;;6680;841;15140;;864;;;891;6403;;906;;9053;930;10084;;948;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:12;1278045;;48.723109;9.093963;498;247.62;2.17;1.79;7;3.74;143;76;0;;0;0;58;48;0;;;30;;6485;52;;;71;;6321;93;;;113;;6283;128;;;148;;6319;164;10355;;184;;6232;199;17561;;225;;6259;238;;;265;;;292;16478;;317;;;344;8916;;361;;6160;379;;;406;;6242;426;;;445;;6318;461;;;481;;6172;496;;;516;;6271;534;;;554;;6184;571;10174;;590;;6204;607;14878;;630;;6333;643;;;670;;6332;683;;;705;;6231;718;;;740;;6227;753;;;776;;;803;;;822;;6469;844;;;864;;6215;879;;;899;;;927;;;946;;6326;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:13;1279029;;48.723109;9.093963;498;247.62;0;1.79;7;3.74;116;79;0;;0;0;58;47;0;;;20;;6783;41;;;61;;6343;81;;;101;;6506;121;11871;;142;;6364;162;16368;;185;;6365;197;;;224;;;250;15312;;274;;6698;295;12786;;315;;6428;330;;;357;;6556;375;17429;;401;;6426;418;16587;;444;;6539;462;;;488;;;515;18278;;542;;6507;556;;;584;;6506;593;;;619;;6774;632;;;654;;6775;668;;;690;;;717;;;737;;;764;;;784;;6708;799;;;819;;6908;840;8503;;856;;;882;1202;;893;;6729;917;13601;;939;;;974;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:14;1280049;;48.723109;9.093963;498;247.62;0;1.1;7;3.74;121;92;0;;0;0;58;45;0;;;33;;7087;56;;;75;;7170;94;;;113;;7158;129;;;149;;7575;164;;;184;;7233;204;13424;;226;;7616;248;18289;;282;;;315;;;342;;7353;357;;;377;;7521;400;;;419;;7510;435;;;455;;;481;;;500;;7484;516;12940;;537;;;571;8777;;588;;;615;11659;;634;;;660;1174;;670;;;696;;;723;;;742;;;762;;7640;778;;;797;;7980;819;;;839;;8759;855;;;875;;7752;890;11740;;910;;7612;929;12291;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:15;1281028;;48.723109;9.093963;498;247.62;0;1.01;7;3.74;133;95;0;;0;0;58;48;0;;;30;;7564;49;12590;;70;;7576;84;;;111;;7584;120;;;146;;7794;161;;;182;;7826;196;;;217;;;244;;;264;;8057;286;;;305;;7525;321;8033;;340;;7657;360;11295;;380;;;407;9480;;423;;;451;12842;;472;;7540;487;16790;;512;;;538;1175;;549;;;574;1175;;584;;7788;609;1175;;619;;;647;;;673;;7354;697;;;716;;7287;738;;;758;;7454;773;;;793;;7286;812;9244;;829;;7388;848;17471;;874;;7246;893;;;919;;;952;8724;;968;;7324;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18.11.2020;16:06:16;1282037;;48.723109;9.093963;498;247.62;0;1.01;7;3.74;5;89;20;;0;0;58;49;0;;;31;;7290;44;;;66;;7277;80;;;101;;;128;;;148;;7213;164;;;183;;6901;202;10902;;223;;7060;242;2257;;258;;7057;277;2124;;293;;7045;313;1201;;328;;;361;2137;;371;;6931;396;2055;;407;;6910;432;1201;;442;;;468;2042;;478;;6961;503;1201;;513;;;548;12669;;568;;6909;590;;;617;;7063;636;;;656;;7148;672;;;691;;6777;707;;;727;;6903;747;11631;;767;;;793;1174;;803;;7283;828;;;856;;;889;9154;;908;;7489;929;9129;;943;;7430;965;14679;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
`;
module.exports = { test1, test2 };

254
logic/tracks.js Normal file
View file

@ -0,0 +1,254 @@
const csvParse = require('csv-parse/lib/sync');
function _parseFloat(token) {
if (typeof token !== 'string') {
return null
}
token = token.trim()
if (token === '') {
return null
}
if (/^nan$/i.test(token)) {
return null
}
let f = parseFloat(token);
if (isNaN(f)) {
f = parseFloat(token.substring(0, 10));
}
if (isNaN(f)) {
f = 0.0;
}
return f;
}
function _parseInt(token) {
const asFloat = parseFloat(token)
if (asFloat !== null) {
return Math.floor(asFloat)
} else{
return asFloat
}
}
function _parseString(token) {
if (typeof token !== 'string') {
return null
}
// This time we do not trim -- because we assume that the quoting mechanism
// from CSV might have kicked in and we actually want the spacing around the
// token.
if (token === '') {
return null
}
return token
}
function replaceDollarNewlinesHack(body) {
// see if we are using the hack with $ as newlines, replace them for the csv parser
if (body.endsWith('$')) {
return body.replace(/\$/g, '\n');
}
return body;
}
function addPointsToTrack(trackInfo, body, format = null) {
body = replaceDollarNewlinesHack(body);
const detectedFormat = format != null ? format : detectFormat(body);
let parser;
switch (detectedFormat) {
case 'invalid':
throw new Error('track format cannot be detected');
case 1:
parser = parseObsver1;
break;
case 2:
parser = parseObsver2;
break;
}
const points = trackInfo.trackData.points;
for (const newPoint of parser(body)) {
points.push(newPoint);
}
}
function detectFormat(body) {
body = replaceDollarNewlinesHack(body)
if (!body.length) {
return 'invalid';
}
const firstLinebreakIndex = body.indexOf('\n');
if (firstLinebreakIndex === -1) {
// We need at least one linebreak in the whole file, to separate header and
// data. If the file contains no header, it is in valid.
return 'invalid'
}
const firstLine = body.substring(0, firstLinebreakIndex);
const match = firstLine.match(/(^|&)OBSDataFormat=([\d]+)($|&)/);
if (match) {
return Number(match[2]);
}
// If we have no metadata line, but start immediately with a header, it is
// format version 1.
if (/^Date;Time/.test(firstLine)) {
return 1;
}
// If we immediately start with data (a date, formatted as DD.MM.YYYY), then
// we have an old OBS not sending the header. It must therefore be old
// format, too.
if (/^[0-9]{2}\.[0-9]{2}\.[0-9]{4};/.test(firstLine)) {
return 1;
}
return 'invalid';
}
function* parseObsver1(body) {
for (const record of csvParse(body, {
delimiter: ';',
encoding: 'utf8',
// We specify different column names here, as the order of columns was
// always the same, but their naming was different. By enforicing these
// column names we don't have to translate between them. Then we just
// ignore the first line (or any line that starts with "Date;").
// Original header usually is:
// Date;Time;Latitude;Longitude;Course;Speed;Right;Left;Confirmed;insidePrivacyArea
columns: ['date', 'time', 'latitude', 'longitude', 'course', 'speed', 'd1', 'd2', 'flag', 'private'],
relax_column_count: true,
cast(value, { column }) {
if (['latitude', 'longitude', 'course', 'speed'].includes(column)) {
return _parseFloat(value);
} else if (['d1', 'd2', 'flag'].includes(column)) {
return _parseInt(value);
} else if (column === 'private') {
return Boolean(_parseInt(value));
} else {
return _parseString(value);
}
},
})) {
if (record.date === 'Date') {
// ignore header line
continue;
}
if (!record.latitude && !record.longitude) {
// invalid record, make sure lat/lng say `null` instead of `0`
record.latitude = null
record.longitude = null
}
// in old format, 255 or 999 means "no measurement"
if (record.d1 === 255 || record.d1 === 999) {
record.d1 = null
}
if (record.d2 === 255 || record.d2 === 999) {
record.d2 = null
}
yield record;
}
}
function* parseObsver2(body) {
for (const record of csvParse(body, {
from_line: 2,
trim: true,
columns: true,
skip_empty_lines: true,
delimiter: ';',
encoding: 'utf8',
relax_column_count: true,
cast(value, context) {
if (value === '') {
return null;
}
let type;
switch (context.column) {
case 'Millis':
case 'Left':
case 'Right':
case 'Confirmed':
case 'Invalid':
case 'InsidePrivacyArea':
case 'Measurements':
case 'Satellites':
type = 'int';
break;
case 'Date':
case 'Time':
case 'Comment':
case 'Marked':
type = 'string';
break;
case 'Latitude':
case 'Longitude':
case 'Altitude':
case 'Course':
case 'Speed':
case 'HDOP':
case 'BatteryLevel':
case 'Factor':
type = 'float';
break;
default:
type = /^(Tms|Lus|Rus)/.test(context.column) ? 'int' : 'string';
}
switch (type) {
case 'int':
return parseInt(value);
case 'float':
return parseFloat(value);
case 'string':
return value;
}
},
})) {
// We convert the new format back to the old format for storage here, until
// we upgrade the storage format as well to include all data. But we'll
// have to upgrade the obsApp first.
yield {
date: record.Date,
time: record.Time,
latitude: record.Latitude,
longitude: record.Longitude,
course: record.Course,
speed: record.Speed,
d1: record.Left,
d2: record.Right,
flag: Boolean(record.Confirmed),
private: Boolean(record.InsidePrivacyArea),
};
}
}
module.exports = { addPointsToTrack, detectFormat, parseObsver1, parseObsver2 };

96
logic/tracks.test.js Normal file
View file

@ -0,0 +1,96 @@
const { addPointsToTrack, parseObsver1, detectFormat, parseObsver2 } = require('./tracks');
const TrackInfo = require('./TrackInfo');
const { test1, test2 } = require('./_tracks_testdata');
describe('addPointsToTrack', () => {
it('is a function', () => {
expect(typeof addPointsToTrack).toBe('function');
});
it('works on the sample data with an empty track', () => {
const trackInfo = new TrackInfo({}, { points: [] });
addPointsToTrack(trackInfo, test1);
const points = trackInfo.trackData.points;
expect(points).toHaveLength(324);
expect(points[0]).toEqual({
date: '12.07.2020',
time: '09:02:59',
latitude: 0,
longitude: 0,
course: 0,
speed: 0,
d1: '255',
d2: '255',
flag: '0',
private: '0',
});
});
});
describe('parseObsver1', () => {
it('can parse sample data', () => {
const points = Array.from(parseObsver1(test1));
expect(points).toHaveLength(324);
expect(points[0]).toEqual({
date: '12.07.2020',
time: '09:02:59',
latitude: 0,
longitude: 0,
course: 0,
speed: 0,
d1: '255',
d2: '255',
flag: '0',
private: '0',
});
});
});
describe('parseObsver2', () => {
it('can parse sample data', () => {
const points = Array.from(parseObsver2(test2));
expect(points).toHaveLength(18);
expect(points[0]).toEqual({
date: '18.11.2020',
time: '16:05:59',
latitude: 48.723224,
longitude: 9.094103,
course: 189.86,
speed: 3.2,
d1: 770,
d2: null,
flag: false,
private: true,
});
// this is a non-private, flagged point (i.e. "Confirmed" overtaking)
expect(points[17]).toEqual({
date: '18.11.2020',
time: '16:06:16',
latitude: 48.723109,
longitude: 9.093963,
course: 247.62,
speed: 0,
d1: 5,
d2: 89,
flag: true,
private: false,
});
});
});
describe('detectFormat', () => {
it('detects format 1', () => {
expect(detectFormat(test1)).toBe(1);
});
it('detects format 2', () => {
expect(detectFormat(test2)).toBe(2);
});
it('detects invalid format', () => {
expect(detectFormat('foobar\nbaz')).toBe('invalid');
expect(detectFormat('')).toBe('invalid');
});
});

View file

@ -30,7 +30,7 @@ TrackSchema.methods.slugify = function() {
this.slug = slug(this.title) + '-' + (Math.random() * Math.pow(36, 6) | 0).toString(36);
};
TrackSchema.methods.toJSONFor = function(user){
TrackSchema.methods.toJSONFor = function (user, include) {
return {
slug: this.slug,
title: this.title,
@ -39,7 +39,8 @@ TrackSchema.methods.toJSONFor = function(user){
updatedAt: this.updatedAt,
visibleForAll: this.author ? this.author.areTracksVisibleForAll : false,
visible: this.visible,
author: this.author.toProfileJSONFor(user)
author: this.author.toProfileJSONFor(user),
...(include && include.body ? { body: this.body } : {}),
};
};

6017
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,9 @@
"mongo:start": "docker run --name realworld-mongo -p 27017:27017 mongo & sleep 5",
"start": "node ./app.js",
"dev": "nodemon ./app.js",
"mongo:stop": "docker stop realworld-mongo && docker rm realworld-mongo"
"mongo:stop": "docker stop realworld-mongo && docker rm realworld-mongo",
"autoformat": "eslint --fix logic routes/api/tracks.js",
"test": "jest"
},
"repository": {
"type": "git",
@ -17,11 +19,13 @@
"dependencies": {
"body-parser": "1.19.0",
"cors": "2.8.5",
"csv-parse": "^4.14.1",
"ejs": "^3.1.5",
"errorhandler": "1.5.1",
"express": "4.17.1",
"express-jwt": "^6.0.0",
"express-session": "1.17.1",
"jest": "^26.6.3",
"joi": "^17.2.1",
"jsonwebtoken": "8.5.1",
"latest": "^0.2.0",
@ -38,7 +42,51 @@
"underscore": "^1.11.0"
},
"devDependencies": {
"eslint": "^7.13.0",
"eslint-config-prettier": "^6.15.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-jest": "^24.1.3",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-promise": "^4.2.1",
"newman": "^5.2.0",
"nodemon": "^2.0.4"
"nodemon": "^2.0.4",
"prettier": "^2.1.2"
},
"jest": {
"modulePathIgnorePatterns": [
"local"
]
},
"prettier": {
"useTabs": false,
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 120
},
"eslintConfig": {
"extends": [
"standard",
"prettier"
],
"plugins": [
"jest",
"prettier"
],
"env": {
"browser": false,
"node": true,
"jest/globals": true
},
"rules": {
"prettier/prettier": "error",
"standard/array-bracket-even-spacing": 0,
"standard/computed-property-even-spacing": 0,
"standard/object-curly-even-spacing": 0
},
"root": true
}
}

View file

@ -1,387 +1,264 @@
var router = require('express').Router();
var mongoose = require('mongoose');
var TrackData = mongoose.model('TrackData');
var Track = mongoose.model('Track');
var Comment = mongoose.model('Comment');
var User = mongoose.model('User');
var auth = require('../auth');
var currentTracks = new Map();
class trackInfo {
constructor (track,trackData)
{
this.track = track;
this.trackData = trackData;
}
}
const router = require('express').Router();
const mongoose = require('mongoose');
const TrackData = mongoose.model('TrackData');
const Track = mongoose.model('Track');
const Comment = mongoose.model('Comment');
const User = mongoose.model('User');
const auth = require('../auth');
const currentTracks = new Map();
const TrackInfo = require('../../logic/TrackInfo');
const { addPointsToTrack } = require('../../logic/tracks');
function addPointsToTrack(track,body)
{
var num = 0;
var start = 0;
var end = 0;
//console.log("len"+body.length);
while (end < body.length) {
start = end;
while (body[end] != ";" && body[end] != "$" && end < body.length) {
end++;
}
if(body[end] == "$") // $ is replacing \n as newlines are not allowed in json strings
{
num=0;
}
if(end < body.length)
{
var token = body.substr(start, end - start);
end++;
if(token.length>0)
{
//console.log(token);
//console.log("num:"+num);
//console.log("end:"+end);
if((num == 0) && (token == "Date"))
{
// we have a header line, ignore it for now, TODO parse it
if (end < body.length) {
while (body[end] != ";" && body[end] != "$" && end < body.length) {
end++;
}
start = end;
num=100;
}
}
if (num == 0) {
track.trackData.points.push({ date: "dummy", time: "", latitude: "", longitude: "", course: "", speed: "", d1: "", d2: "", flag: "", private: ""});
track.trackData.points[track.trackData.points.length - 1].date = token;
num++;
}
else if (num == 1) {
track.trackData.points[track.trackData.points.length - 1].time = token;
num++;
}
else if (num == 2) {
var f = parseFloat(token);
if(isNaN(f))
{
f = parseFloat(token.substring(0,10));
}
if(isNaN(f))
{
f=0.0;
}
track.trackData.points[track.trackData.points.length - 1].latitude = f;
num++;
}
else if (num == 3) {
var f = parseFloat(token);
if(isNaN(f))
{
f = parseFloat(token.substring(0,10));
}
if(isNaN(f))
{
f=0.0;
}
track.trackData.points[track.trackData.points.length - 1].longitude = f;
num++;
}
else if (num == 4) {
var f = parseFloat(token);
if(isNaN(f))
{
f = parseFloat(token.substring(0,10));
}
if(isNaN(f))
{
f=0.0;
}
track.trackData.points[track.trackData.points.length - 1].course = f;
num++;
}
else if (num == 5) {
var f = parseFloat(token);
if(isNaN(f))
{
f = parseFloat(token.substring(0,10));
}
if(isNaN(f))
{
f=0.0;
}
track.trackData.points[track.trackData.points.length - 1].speed = f;
num++;
}
else if (num == 6) {
track.trackData.points[track.trackData.points.length - 1].d1 = token;
num++;
}
else if (num == 7) {
track.trackData.points[track.trackData.points.length - 1].d2 = token;
num++;
}
else if (num == 8) {
track.trackData.points[track.trackData.points.length - 1].flag = token;
num++;
}
else if (num == 9) {
track.trackData.points[track.trackData.points.length - 1].private = token;
num++;
}
}
}
const wrapRoute = (fn) => async (req, res, next) => {
try {
return await fn(req, res);
} catch (err) {
next(err);
}
}
};
// Preload track objects on routes with ':track'
router.param('track', function(req, res, next, slug) {
Track.findOne({ slug: slug})
.populate('author')
.then(function (track) {
if (!track) { return res.sendStatus(404); }
router.param('track', async (req, res, next, slug) => {
try {
const track = await Track.findOne({ slug }).populate('author');
req.track = track;
if (!track) {
return res.sendStatus(404);
}
return next();
}).catch(next);
req.track = track;
return next();
} catch (err) {
return next(err);
}
});
router.param('comment', function(req, res, next, id) {
Comment.findById(id).then(function(comment){
if(!comment) { return res.sendStatus(404); }
router.param('comment', async (req, res, next, id) => {
try {
const comment = await Comment.findById(id);
if (!comment) {
return res.sendStatus(404);
}
req.comment = comment;
return next();
}).catch(next);
} catch (err) {
return next(err);
}
});
router.get('/', auth.optional, function(req, res, next) {
var query = {};
var limit = 20;
var offset = 0;
router.get(
'/',
auth.optional,
wrapRoute(async (req, res) => {
const query = {};
let limit = 20;
let offset = 0;
if(typeof req.query.limit !== 'undefined'){
limit = req.query.limit;
}
if (typeof req.query.limit !== 'undefined') {
limit = req.query.limit;
}
if(typeof req.query.offset !== 'undefined'){
offset = req.query.offset;
}
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
if( typeof req.query.tag !== 'undefined' ){
query.tagList = {"$in" : [req.query.tag]};
}
if (typeof req.query.tag !== 'undefined') {
query.tagList = { $in: [req.query.tag] };
}
Promise.all([
req.query.author ? User.findOne({username: req.query.author}) : null,
req.query.favorited ? User.findOne({username: req.query.favorited}) : null
]).then(function(results){
var author = results[0];
var favoriter = results[1];
const [author, favoriter] = await Promise.all([
req.query.author ? User.findOne({ username: req.query.author }) : null,
req.query.favorited ? User.findOne({ username: req.query.favorited }) : null,
]);
if(author){
if (author) {
query.author = author._id;
}
if(favoriter){
query._id = {$in: favoriter.favorites};
} else if(req.query.favorited){
query._id = {$in: []};
if (favoriter) {
query._id = { $in: favoriter.favorites };
} else if (req.query.favorited) {
query._id = { $in: [] };
}
return Promise.all([
const results = await Promise.all([
Track.find(query)
.limit(Number(limit))
.skip(Number(offset))
.sort({createdAt: 'desc'})
.sort({ createdAt: 'desc' })
.populate('author')
.where('visible').equals(true)
.where('visible')
.equals(true)
.exec(),
Track.countDocuments(query).exec(),
req.payload ? User.findById(req.payload.id) : null,
]).then(function(results){
var tracks = results[0];
var tracksCount = results[1];
var user = results[2];
//console.log(tracks);
var retTracks = [];
for (t of tracks) {
//console.log(t);
//if (t.author.areTracksVisibleForAll || t.author == user) {
retTracks.push(t);
//}
}
return res.json({
tracks: retTracks.map(function(track){
return track.toJSONFor(user);
}),
tracksCount: retTracks.length
});
]);
const [tracks, tracksCount, user] = results;
return res.json({
tracks: tracks.map((track) => track.toJSONFor(user)),
tracksCount,
});
}).catch(next);
});
}),
);
router.get('/feed', auth.required, function(req, res, next) {
var limit = 20;
var offset = 0;
router.get(
'/feed',
auth.required,
wrapRoute(async (req, res) => {
let limit = 20;
let offset = 0;
if(typeof req.query.limit !== 'undefined'){
limit = req.query.limit;
}
if (typeof req.query.limit !== 'undefined') {
limit = req.query.limit;
}
if(typeof req.query.offset !== 'undefined'){
offset = req.query.offset;
}
if (typeof req.query.offset !== 'undefined') {
offset = req.query.offset;
}
User.findById(req.payload.id).then(function(user){
if (!user) { return res.sendStatus(401); }
if(user.following != '')
{
Promise.all([
Track.find({ author: {$in: user.following}})
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
const showByUserIds = [req.payload.id, ...(user.following || [])];
const [tracks, tracksCount] = await Promise.all([
Track.find({ author: { $in: showByUserIds } })
.limit(Number(limit))
.skip(Number(offset))
.populate('author')
.exec(),
Track.countDocuments({ author: {$in: user.following}})
]).then(function(results){
var tracks = results[0];
var tracksCount = results[1];
Track.countDocuments({ author: { $in: showByUserIds } }),
]);
return res.json({
tracks: tracks.map(function(track){
return track.toJSONFor(user);
}),
tracksCount: tracksCount
});
}).catch(next);
}
else
{
Promise.all([
Track.find({ author: {$in: req.payload.id}})
.limit(Number(limit))
.skip(Number(offset))
.populate('author')
.exec(),
Track.countDocuments({ author: {$in: req.payload.id}})
]).then(function(results){
var tracks = results[0];
var tracksCount = results[1];
return res.json({
tracks: tracks.map(function (track) {
return track.toJSONFor(user);
}),
tracksCount: tracksCount,
});
}),
);
return res.json({
tracks: tracks.map(function(track){
return track.toJSONFor(user);
}),
tracksCount: tracksCount
});
}).catch(next);
router.post(
'/',
auth.required,
wrapRoute(async (req, res) => {
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
});
});
router.post('/', auth.required, function(req, res, next) {
User.findById(req.payload.id).then(function(user){
if (!user) { return res.sendStatus(401); }
var track = new Track(req.body.track);
var trackData = new TrackData();
const track = new Track(req.body.track);
const trackData = new TrackData();
track.trackData = trackData._id;
if (req.body.track.body && req.body.track.body.trim()) {
trackData.points = [];
addPointsToTrack({ trackData }, track.body);
}
track.author = user;
track.visible = track.author.areTracksVisibleForAll;
trackData.save(function (err){
if(err){
console.log("failed to save trackData");
await trackData.save();
await track.save();
// console.log(track.author);
return res.json({ track: track.toJSONFor(user) });
}),
);
router.post(
'/add',
auth.optional,
wrapRoute(async (req, res) => {
// console.log("Add");
// console.log(req.payload);
const user = await User.findById(req.body.id);
if (!user) {
return res.sendStatus(401);
}
});
return track.save().then(function(){
//console.log(track.author);
return res.json({track: track.toJSONFor(user)});
});
return res.json({track: track.toJSONFor(user)});
}).catch(next);
});
let ti = null;
if (currentTracks.has(req.body.id)) ti = currentTracks.get(req.body.id);
router.post('/add', auth.optional, function(req, res, next) {
//console.log("Add");
//console.log(req.payload);
User.findById(req.body.id).then(function (user) {
if (!user) { return res.sendStatus(401); }
var ti = null;
if (currentTracks.has(req.body.id))
ti = currentTracks.get(req.body.id);
//console.log("TI" + ti);
//console.log("TILen" + ti.trackData.points.length);
//console.log("TITrack" + ti.track);
//console.log("Body" + req.body.track.body);
// console.log("TI" + ti);
// console.log("TILen" + ti.trackData.points.length);
// console.log("TITrack" + ti.track);
// console.log("Body" + req.body.track.body);
if (ti.track) {
addPointsToTrack(ti, req.body.track.body);
//console.log("TLen" + ti.trackData.points.length);
// console.log("TLen" + ti.trackData.points.length);
ti.track.author = user;
}
//return track.save().then(function(){
// console.log(track.author);
//return res.json({ track: track.toJSONFor(user) });
return res.sendStatus(200);
//});
}).catch(next);
});
// await track.save()
// return res.json({ track: track.toJSONFor(user) });
return res.sendStatus(200);
}),
);
router.post('/begin', auth.optional, function (req, res, next) {
//console.log("Begin");
//console.log(req.payload);
User.findById(req.body.id).then(function (user) {
if (!user) { return res.sendStatus(401); }
router.post(
'/begin',
auth.optional,
wrapRoute(async (req, res) => {
// console.log("Begin");
// console.log(req.payload);
const user = await User.findById(req.body.id);
if(currentTracks.has(req.body.id))
currentTracks.delete(req.body.id); // delete old parts if there are leftovers
var ti = new trackInfo(new Track(req.body.track),new TrackData());
ti.track.trackData = ti.trackData._id;
if (!user) {
return res.sendStatus(401);
}
if (currentTracks.has(req.body.id)) currentTracks.delete(req.body.id); // delete old parts if there are leftovers
const ti = new TrackInfo(new Track(req.body.track), new TrackData());
ti.track.trackData = ti.trackData._id;
currentTracks.set(req.body.id, ti);
//console.log("addToTrack"+req.body);
// console.log("addToTrack"+req.body);
addPointsToTrack(ti, ti.track.body);
//console.log("TLen" + ti.track);
//console.log("TLen" + ti.trackData);
//console.log("TLen" + ti.trackData.points.length);
// console.log("TLen" + ti.track);
// console.log("TLen" + ti.trackData);
// console.log("TLen" + ti.trackData.points.length);
//console.log(track.trackData.points[0].date);
// console.log(track.trackData.points[0].date);
ti.track.author = user;
//return track.save().then(function () {
// console.log(track.author);
return res.sendStatus(200);
//});
}).catch(next);
});
// await track.save()
// console.log(track.author);
return res.sendStatus(200);
}),
);
router.post('/end', auth.optional, function (req, res, next) {
//console.log("End");
//console.log(req.payload);
User.findById(req.body.id).then(function (user) {
if (!user) { return res.sendStatus(401); }
router.post(
'/end',
auth.optional,
wrapRoute(async (req, res) => {
const user = await User.findById(req.body.id);
if (!user) {
return res.sendStatus(401);
}
var track = null;
if (currentTracks.has(req.body.id))
{
let ti;
if (currentTracks.has(req.body.id)) {
ti = currentTracks.get(req.body.id);
addPointsToTrack(ti, req.body.track.body);
}
else
{
var ti = new trackInfo(new Track(req.body.track),new TrackData());
} else {
ti = new TrackInfo(new Track(req.body.track), new TrackData());
ti.track.trackData = ti.trackData._id;
addPointsToTrack(ti, ti.track.body);
}
@ -392,174 +269,202 @@ router.post('/end', auth.optional, function (req, res, next) {
currentTracks.delete(req.body.id); // we are done with this track, it is complete
ti.track.author = user;
//console.log(track);
//console.log("user:"+user);
return ti.track.save().then(function () {
//console.log("TLen" + ti.track);
//console.log("TLen" + ti.trackData);
//console.log("TLen" + ti.trackData.points.length);
ti.trackData.save(function (err){
if(err){
console.log("failed to save trackData"+err.toString());
}
});
// console.log(track);
// console.log("user:"+user);
await ti.track.save();
console.log("successfulSave:");
return res.sendStatus(200);
});
}).catch(next);
});
// console.log("TLen" + ti.track);
// console.log("TLen" + ti.trackData);
// console.log("TLen" + ti.trackData.points.length);
await ti.trackData.save();
return res.sendStatus(200);
}),
);
// return a track
router.get('/:track', auth.optional, function(req, res, next) {
Promise.all([
req.payload ? User.findById(req.payload.id) : null,
req.track.populate('author').execPopulate()
]).then(function(results){
var user = results[0];
return res.json({track: req.track.toJSONFor(user)});
}).catch(next);
});
router.get(
'/:track',
auth.optional,
wrapRoute(async (req, res) => {
const [user] = await Promise.all([
req.payload ? User.findById(req.payload.id) : null,
req.track.populate('author').execPopulate(),
]);
return res.json({ track: req.track.toJSONFor(user, { body: true }) });
}),
);
// update track
router.put('/:track', auth.required, function(req, res, next) {
User.findById(req.payload.id).then(function(user){
if(req.track.author._id.toString() === req.payload.id.toString()){
if(typeof req.body.track.title !== 'undefined'){
req.track.title = req.body.track.title;
}
router.put('/:track', auth.required, async function (req, res, next) {
const user = await User.findById(req.payload.id);
if(typeof req.body.track.description !== 'undefined'){
req.track.description = req.body.track.description;
}
if (req.track.author._id.toString() !== req.payload.id.toString()) {
return res.sendStatus(403);
}
if(typeof req.body.track.body !== 'undefined'){
req.track.body = req.body.track.body;
}
if (typeof req.body.track.title !== 'undefined') {
req.track.title = req.body.track.title;
}
if(typeof req.body.track.tagList !== 'undefined'){
req.track.tagList = req.body.track.tagList;
}
req.track.visible = req.body.track.visible;
console.log("saving track");
if (typeof req.body.track.description !== 'undefined') {
req.track.description = req.body.track.description;
}
req.track.save().then(function(track){
return res.json({track: track.toJSONFor(user)});
}).catch(next);
} else {
return res.sendStatus(403);
if (req.body.track.body && req.body.track.body.trim()) {
req.track.body = req.body.track.body.trim();
let trackData = await TrackData.findById(req.track.trackData);
if (!trackData) {
trackData = new TrackData();
req.track.trackData = trackData._id;
}
});
trackData.points = [];
addPointsToTrack({ trackData }, req.track.body);
await trackData.save();
}
if (typeof req.body.track.tagList !== 'undefined') {
req.track.tagList = req.body.track.tagList;
}
req.track.visible = req.body.track.visible;
const track = await req.track.save();
return res.json({ track: track.toJSONFor(user) });
});
// delete track
router.delete('/:track', auth.required, function(req, res, next) {
User.findById(req.payload.id).then(function(user){
if (!user) { return res.sendStatus(401); }
if(req.track.author._id.toString() === req.payload.id.toString()){
TrackData.findByIdAndDelete(req.track.trackData, function (err, td) {console.log("doneDelete");}); // delet our track data
return req.track.remove().then(function(){
return res.sendStatus(204);
});
router.delete(
'/:track',
auth.required,
wrapRoute(async (req, res) => {
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
if (req.track.author._id.toString() === req.payload.id.toString()) {
await TrackData.findByIdAndDelete(req.track.trackData);
await req.track.remove();
return res.sendStatus(204);
} else {
return res.sendStatus(403);
}
}).catch(next);
});
}),
);
// Favorite an track
router.post('/:track/favorite', auth.required, function(req, res, next) {
var trackId = req.track._id;
router.post(
'/:track/favorite',
auth.required,
wrapRoute(async (req, res) => {
const trackId = req.track._id;
User.findById(req.payload.id).then(function(user){
if (!user) { return res.sendStatus(401); }
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
return user.favorite(trackId).then(function(){
return req.track.updateFavoriteCount().then(function(track){
return res.json({track: track.toJSONFor(user)});
});
});
}).catch(next);
});
await user.favorite(trackId);
const track = await req.track.updateFavoriteCount();
return res.json({ track: track.toJSONFor(user) });
}),
);
// Unfavorite an track
router.delete('/:track/favorite', auth.required, function(req, res, next) {
var trackId = req.track._id;
router.delete(
'/:track/favorite',
auth.required,
wrapRoute(async (req, res) => {
const trackId = req.track._id;
User.findById(req.payload.id).then(function (user){
if (!user) { return res.sendStatus(401); }
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
return user.unfavorite(trackId).then(function(){
return req.track.updateFavoriteCount().then(function(track){
return res.json({track: track.toJSONFor(user)});
});
});
}).catch(next);
});
await user.unfavorite(trackId);
const track = await req.track.updateFavoriteCount();
return res.json({ track: track.toJSONFor(user) });
}),
);
// return an track's comments
router.get('/:track/comments', auth.optional, function(req, res, next){
Promise.resolve(req.payload ? User.findById(req.payload.id) : null).then(function(user){
return req.track.populate({
path: 'comments',
populate: {
path: 'author'
},
options: {
sort: {
createdAt: 'desc'
}
}
}).execPopulate().then(function(track) {
return res.json({comments: req.track.comments.map(function(comment){
router.get(
'/:track/comments',
auth.optional,
wrapRoute(async (req, res) => {
const user = await Promise.resolve(req.payload ? User.findById(req.payload.id) : null);
await req.track
.populate({
path: 'comments',
populate: {
path: 'author',
},
options: {
sort: {
createdAt: 'desc',
},
},
})
.execPopulate();
return res.json({
comments: req.track.comments.map(function (comment) {
return comment.toJSONFor(user);
})});
}),
});
}).catch(next);
});
}),
);
// create a new comment
router.post('/:track/comments', auth.required, function(req, res, next) {
User.findById(req.payload.id).then(function(user){
if(!user){ return res.sendStatus(401); }
router.post(
'/:track/comments',
auth.required,
wrapRoute(async (req, res) => {
const user = await User.findById(req.payload.id);
if (!user) {
return res.sendStatus(401);
}
var comment = new Comment(req.body.comment);
const comment = new Comment(req.body.comment);
comment.track = req.track;
comment.author = user;
return comment.save().then(function(){
req.track.comments.push(comment);
await comment.save();
return req.track.save().then(function(track) {
res.json({comment: comment.toJSONFor(user)});
});
});
}).catch(next);
});
req.track.comments.push(comment);
router.delete('/:track/comments/:comment', auth.required, function(req, res, next) {
if(req.comment.author.toString() === req.payload.id.toString()){
req.track.comments.remove(req.comment._id);
req.track.save()
.then(Comment.find({_id: req.comment._id}).remove().exec())
.then(function(){
res.sendStatus(204);
});
} else {
res.sendStatus(403);
}
});
await req.track.save();
return res.json({ comment: comment.toJSONFor(user) });
}),
);
router.delete(
'/:track/comments/:comment',
auth.required,
wrapRoute(async (req, res) => {
if (req.comment.author.toString() === req.payload.id.toString()) {
req.track.comments.remove(req.comment._id);
await req.track.save();
await Comment.find({ _id: req.comment._id }).remove();
res.sendStatus(204);
} else {
res.sendStatus(403);
}
}),
);
// return an track's trackData
router.get('/:track/TrackData', auth.optional, function(req, res, next){
Promise.resolve(req.payload ? User.findById(req.payload.id) : null).then(function(user){
//console.log("requestTrackData"+req.track);
TrackData.findById(req.track.trackData,function(err,trackData){
//console.log({trackData: trackData});
return res.json({trackData: trackData});
});
}).catch(next);
});
router.get(
'/:track/TrackData',
auth.optional,
wrapRoute(async (req, res) => {
// console.log("requestTrackData"+req.track);
const trackData = await TrackData.findById(req.track.trackData);
// console.log({trackData: trackData});
return res.json({ trackData: trackData });
}),
);
module.exports = router;