@rasifix/orienteering-utils 1.0.6 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,11 +1,16 @@
1
1
  {
2
2
  "name": "@rasifix/orienteering-utils",
3
- "version": "1.0.6",
3
+ "version": "2.0.1",
4
4
  "description": "utility functions for orienteering result analyzis",
5
- "main": "index",
6
- "typings": "index",
5
+ "main": "lib/index.js",
6
+ "types": "lib/index.d.ts",
7
+ "files": [
8
+ "lib/**/*.js",
9
+ "lib/**/*.d.ts"
10
+ ],
7
11
  "scripts": {
8
- "test": "mocha test/test.js"
12
+ "test": "mocha test/test.js",
13
+ "build": "tsc"
9
14
  },
10
15
  "keywords": [
11
16
  "orienteering"
@@ -19,5 +24,12 @@
19
24
  "dependencies": {
20
25
  "chai": "^4.3.6",
21
26
  "mocha": "^9.2.1"
27
+ },
28
+ "devDependencies": {
29
+ "@types/chai": "^5.2.3",
30
+ "@types/mocha": "^10.0.10",
31
+ "@types/node": "^16.0.2",
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^4.5.5"
22
34
  }
23
35
  }
package/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- export declare const oware;
2
- export declare const kraemer;
3
- export declare const solv;
4
- export declare const time;
package/index.js DELETED
@@ -1,11 +0,0 @@
1
- const oware = require('./lib/oware');
2
- const kraemer = require('./lib/kraemer');
3
- const solv = require('./lib/solv');
4
- const time = require('./lib/time');
5
-
6
- module.exports = {
7
- oware: oware,
8
- kraemer: kraemer,
9
- solv: solv,
10
- time: time
11
- };
package/lib/anonymizer.js DELETED
@@ -1,72 +0,0 @@
1
- const names = [
2
- 'Gustavson', 'Hendrikson', 'Meyer', 'Marlovic', 'Torres', 'Huber',
3
- 'Wüst', 'Zürcher', 'Berner', 'Rufer', 'Gutmann', 'Hübscher',
4
- 'Schneller', 'Widemar', 'Rohrer', 'Kunz', 'Kinzle', 'Steinle',
5
- 'Allemann', 'Röhrig', 'Meyer', 'Uhlmann', 'Garaio', 'Regazoni',
6
- 'Maudet', 'Zoja'
7
- ];
8
-
9
- const firstNames = {
10
- f: [
11
- 'Anna', 'Alia', 'Ava', 'Berta', 'Benita', 'Carla', 'Cloe',
12
- 'Dina', 'Daria', 'Eva', 'Esther', 'Elin', 'Franca', 'Franziska',
13
- 'Gaby', 'Gerta', 'Gudrun', 'Hanna', 'Isabel', 'Ilda', 'Kim', 'Kathrin',
14
- 'Lia', 'Lisa', 'Lena', 'Liselotte', 'Lara', 'Mia', 'Marla', 'Nele', 'Olga',
15
- 'Pia', 'Rahel', 'Sara', 'Simona', 'Sina', 'Siri', 'Xenia', 'Zoé'
16
- ],
17
- m: [
18
- 'Albert', 'Bruno', 'Chris', 'Dirk', 'David', 'Erwin', 'Francesco',
19
- 'Fritz', 'Gianni', 'Gustav', 'Hans', 'Ian', 'Jan', 'Karl', 'Lars',
20
- 'Martin', 'Marco', 'Markus', 'Nico', 'Nino', 'Otto', 'Olav',
21
- 'Patric', 'Pablo', 'Quentin', 'Ralf', 'Rudolf', 'Simon', 'Steve',
22
- 'Thomas', 'Tim', 'Urs', 'Udo'
23
- ]
24
- };
25
-
26
- const cities = [
27
- 'Aarberg', 'Bern', 'Colombier', 'Diemerswil', 'Elm', 'Fribourg',
28
- 'Goldiwil', 'Heimiswil', 'Illiswil', 'Konolfingen', 'Lausanne',
29
- 'Lugano', 'Martigny', 'Neuchatel', 'Orbe', 'Zürich'
30
- ];
31
-
32
- const clubs = {
33
- prefixes: [ 'OLG', 'OLV', 'OL', 'CA' ],
34
- names: ['Bernstein', 'Erdmannlistein', 'Blanc', 'Piz Balü', 'Bartli und Most', 'Aare', 'Reuss' ]
35
- };
36
-
37
- function random(arr) {
38
- if (arr.lenght === 0) {
39
- return null;
40
- }
41
- const idx = Math.floor(Math.random() * (arr.length - 1));
42
- return arr[idx];
43
- }
44
-
45
- function randInt(from, to) {
46
- return from + Math.round(Math.random() * (to - from));
47
- }
48
-
49
- module.exports.anonymize = function(event) {
50
- event.categories.forEach(category => {
51
- category.runners.forEach(runner => {
52
- runner.name = random(names);
53
-
54
- if (runner.sex === 'M' || runner.sex === 'm') {
55
- runner.firstName = random(firstNames.m);
56
- runner.sex = 'M';
57
- } else {
58
- runner.firstName = random(firstNames.f);
59
- runner.sex = 'F';
60
- }
61
-
62
- runner.fullName = runner.firstName + ' ' + runner.name;
63
-
64
- runner.city = random(cities);
65
- runner.club = random(clubs.prefixes) + ' ' + random(clubs.names);
66
- runner.yearOfBirth = randInt(1925, 2010);
67
- runner.nation = 'SUI';
68
- runner.ecard = Math.round(Math.random() * 1000000);
69
- });
70
- });
71
- return event;
72
- };
package/lib/butterfly.js DELETED
@@ -1,59 +0,0 @@
1
- function extractCourses(category) {
2
- var courses = { };
3
- category.runners.forEach(function(runner) {
4
- const course = runner.splits.map(function(split, index, splits) {
5
- return split.code;
6
- });
7
- const key = 'St-' + course.join('-');
8
- if (!courses[key]) {
9
- courses[key] = {
10
- runners: [],
11
- controls: course.map(function(c) {
12
- return { code: c };
13
- })
14
- };
15
- }
16
- courses[key].runners.push(runner);
17
- });
18
- const coursesArray = Object.keys(courses).map(function(course) {
19
- return courses[course];
20
- });
21
-
22
- for (var i = 0; i < coursesArray[0].controls.length; i++) {
23
- const base = coursesArray[0].controls[i].code;
24
- const shared = coursesArray.every(function(course) {
25
- return course.controls[i].code === base;
26
- });
27
- coursesArray.forEach(function(course) {
28
- course.controls[i].shared = shared;
29
- });
30
- }
31
-
32
- return coursesArray;
33
- };
34
-
35
- module.exports.extractCourses = extractCourses;
36
-
37
- /**
38
- * A category is classified as "fair" if all the runners have the exact same legs, although
39
- * potentially in different order.
40
- */
41
- module.exports.isFair = function(category) {
42
- const courses = extractCourses(category);
43
- const courseLegs = courses.map(function(course) {
44
- const legs = [];
45
- for (var i = 0; i < course.controls.length - 1; i++) {
46
- const from = course.controls[i].code;
47
- const to = course.controls[i + 1].code;
48
- legs.push(from + '-' + to);
49
- }
50
- return legs.sort().join(':');
51
- });
52
-
53
- const grouped = { };
54
- courseLegs.forEach(function(course) {
55
- grouped[course] = true;
56
- });
57
-
58
- return Object.keys(grouped).length === 1;
59
- };
package/lib/kraemer.js DELETED
@@ -1,125 +0,0 @@
1
- var { parseTime, formatTime } = require('./time');
2
-
3
- function strip(str) {
4
- if (!str) {
5
- return '';
6
- } else if (str.length > 0 && str[0] === '"') {
7
- return str.substring(1, str.length - 1);
8
- } else {
9
- return str;
10
- }
11
- }
12
-
13
- // OE0014;Stnr;XStnr;Chipnr;Datenbank Id;Nachname;Vorname;Jg;G;Block; AK; Start;Ziel; Zeit; Wertung;Gutschrift -;Zuschlag +;Kommentar;Club-Nr.;Abk; Ort; Nat; Sitz;Region;Katnr;Kurz; Lang; MeldeKat. Nr;MeldeKat. (kurz);MeldeKat. (lang);Rang;Ranglistenpunkte;Num1;Num2; Num3; Text1; Text2; Text3; Adr. Nachname;Adr. Vorname;Straße;Zeile2;PLZ; Adr. Ort;Tel; Mobil; Fax; EMail; Gemietet;Startgeld;Bezahlt;Mannschaft;Bahnnummer;Bahn; km; Hm; Bahn Posten;Platz; Startstempel;Zielstempel;Posten1;Stempel1;Posten2;Stempel2;Posten3; Stempel3;Posten4;Stempel4;Posten5;Stempel5;Posten6;Stempel6;Posten7;Stempel7;Posten8;Stempel8;Posten9;Stempel9;Posten10;Stempel10;Posten11;Stempel11;Posten12;Stempel12;Posten13;Stempel13;Posten14;Stempel14;Posten15;Stempel15;Posten16;Stempel16;Posten17;Stempel17;Posten18;Stempel18;Posten19;Stempel19;Posten20;Stempel20;Posten21;Stempel21;Posten22;Stempel22;Posten23;Stempel23;Posten24;Stempel24;Posten25;Stempel25;Posten26;Stempel26;Posten27;Stempel27;Posten28;Stempel28;Posten29;Stempel29;Posten30;Stempel30;Posten31;Stempel31;Posten32;Stempel32;Posten33;Stempel33;Posten34;Stempel34;Posten35;Stempel35;Posten36;Stempel36;Posten37;Stempel37;Posten38;Stempel38;Posten39;Stempel39;Posten40;Stempel40;Posten41;Stempel41;Posten42;Stempel42;Posten43;Stempel43;Posten44;Stempel44;Posten45;Stempel45;Posten46;Stempel46;Posten47;Stempel47;Posten48;Stempel48;Posten49;Stempel49;Posten50;Stempel50;Posten51;Stempel51;Posten52;Stempel52;Posten53;Stempel53;Posten54;Stempel54;Posten55;Stempel55;Posten56;Stempel56;Posten57;Stempel57;Posten58;Stempel58;Posten59;Stempel59;Posten60;Stempel60;Posten61;Stempel61;Posten62;Stempel62;Posten63;Stempel63;Posten64;Stempel64;
14
- // Stnr ;Chip;Datenbank Id;Nachname;Vorname;Jg;G;Block;AK;Start;Ziel;Zeit; Wertung;Club-Nr.;Abk; Ort; Nat; Katnr; Kurz; Lang;Num1;Num2;Num3;Text1; Text2;Text3;Adr. Name;Straße; Zeile2; PLZ; Ort; Tel; Fax; EMail;Id/Verein;Gemietet;Startgeld;Bezahlt;Bahnnummer; Bahn; km; Hm; Bahn Posten;Pl; Startstempel;Zielstempel;Posten1;Stempel1;Posten2; Stempel2; Posten3;Stempel3; Posten4; Stempel4;Posten5;Stempel5;Posten6; Stempel6;Posten7; Stempel7; Posten8;Stempel8;Posten9;Stempel9;Posten10;Stempel10;(und weitere)...
15
- module.exports.parse = function(text, options = {}) {
16
- // split text into lines
17
- var lines = text.split('[\r\n]+');
18
-
19
- // extract header
20
- var header = lines[0].split(";");
21
- var firstTimeIdx;
22
-
23
- // trying to get hold of correct column indices
24
- var indices = { };
25
- indices['Nachname'] = header.indexOf('Nachname');
26
- indices['Vorname'] = header.indexOf('Vorname');
27
- indices['Jg'] = header.indexOf('Jg');
28
- indices['G'] = header.indexOf('G');
29
- indices['Datenbank Id'] = header.indexOf('Datenbank Id');
30
- indices['Abk'] = header.indexOf('Abk');
31
- indices['Club'] = header.indexOf('Ort');
32
- indices['Ort'] = header.indexOf('Adr. Ort');
33
- indices['Nat'] = header.indexOf('Nat');
34
- indices['Start'] = header.indexOf('Start');
35
- indices['Ziel'] = header.indexOf('Ziel');
36
- indices['Zeit'] = header.indexOf('Zeit');
37
- indices['Katnr'] = header.indexOf('Kurz');
38
- indices['Wertung'] = header.indexOf('Wertung');
39
- indices['Posten'] = header.indexOf('Bahn Posten');
40
- indices['km'] = header.indexOf('km');
41
- indices['hm'] = header.indexOf('Hm');
42
- firstTimeIdx = header.indexOf('Posten1');
43
-
44
- if (header[0] === 'OE0014') {
45
- indices['Chip'] = header.indexOf('Chipnr');
46
- } else {
47
- indices['Chip'] = header.indexOf('Chip');
48
- }
49
-
50
- lines = lines.slice(1);
51
-
52
- // the result object
53
- var categories = { };
54
-
55
- function objectify(cols) {
56
- var result = { };
57
- Object.keys(indices).forEach(function(key) {
58
- result[key] = cols[indices[key]];
59
- });
60
- return result;
61
- }
62
-
63
- lines.forEach(function(line) {
64
- var cols = line.split(";");
65
- var lineObj = objectify(cols);
66
-
67
- if (lineObj['Wertung'] !== '0') {
68
- return;
69
- }
70
-
71
- let runnerName = strip(lineObj['Nachname']);
72
- let runnerFirstname = strip(lineObj['Vorname']);
73
- var runner = {
74
- name: runnerName,
75
- firstName: runnerFirstname,
76
- fullName: [runnerFirstname, runnerName].join(' '),
77
- yearOfBirth: lineObj['Jg'],
78
- sex: strip(lineObj['G']),
79
- club: (strip(lineObj['Abk']) + ' ' + strip(lineObj['Club'])).trim(),
80
- city: strip(lineObj['Ort']),
81
- nation: strip(lineObj['Nat']),
82
- time: formatTime(parseTime(lineObj['Zeit'])),
83
- startTime: formatTime(parseTime(lineObj['Start'])),
84
- ecard: strip(lineObj['Chip']),
85
- splits: []
86
- };
87
-
88
- var category = categories[strip(lineObj['Katnr'])];
89
- if (typeof category === 'undefined') {
90
- category = {
91
- name: strip(lineObj['Katnr']),
92
- distance: parseInt(strip(lineObj['km']), 10) * 1000,
93
- ascent: strip(lineObj['hm']),
94
- controls: strip(lineObj['Posten']),
95
- runners: []
96
- };
97
- categories[category.name] = category;
98
- }
99
-
100
- var times = cols.slice(firstTimeIdx);
101
- for (var idx = 0; idx < parseInt(lineObj['Posten'], 10) * 2; idx += 2) {
102
- if (idx === times.length - 1) {
103
- continue;
104
- }
105
- runner.splits.push([times[idx], formatTime(parseTime(times[idx + 1]))]);
106
- }
107
- runner.course = runner.splits.map(function(split) { return split[0]; }).join(',');
108
-
109
- category.runners.push(runner);
110
- });
111
-
112
- return {
113
- name: options.event || 'Anonymous Event',
114
- map: options.map || 'Unknown Map',
115
- date: date || '',
116
- startTime: startTime || '',
117
- categories: Object.keys(categories).map(function(category) {
118
- return categories[category];
119
- })
120
- };
121
- };
122
-
123
- module.exports.formatCheck = function(text) {
124
- return text.substring(0, 6) === 'OE0014' || text.substring(0, 23) === 'Stnr;Chip;Datenbank Id;';
125
- };
package/lib/oware.js DELETED
@@ -1,105 +0,0 @@
1
- function parseCategory(row) {
2
- return {
3
- name: row[0],
4
- distance: parseInt(row[1], 10),
5
- ascent: parseInt(row[2], 10),
6
- controls: parseInt(row[3], 10),
7
- runners: []
8
- };
9
- }
10
-
11
- function parseRunner(row, category, id) {
12
- var headerLength = 15;
13
- var i;
14
-
15
- var splits = [];
16
- for (i = headerLength; i < row.length; i += 2) {
17
- splits.push({ 'code': row[i], 'time': row[i + 1] });
18
- }
19
-
20
- // split cleanup - detect two following splits with identical time
21
- // --> control not working properly; set 's' as split time (substitute)
22
- // going from back to front to catch several not working controls
23
- for (i = splits.length - 1; i > 0; i--) {
24
- if (splits[i].time === splits[i - 1].time && splits[i].time !== '-') {
25
- splits[i].time = 's';
26
- }
27
- }
28
-
29
- return {
30
- id: id,
31
- category: category,
32
- rank: row[0] ? parseInt(row[0]) : null,
33
- name: row[1],
34
- firstName: row[2],
35
- fullName: [row[2], row[1]].join(' '),
36
- yearOfBirth: row[3],
37
- sex: row[4],
38
- club: row[8],
39
- city: row[7],
40
- nation: row[9],
41
- time: row[12],
42
- startTime: row[13],
43
- ecard: row[11],
44
- splits: splits
45
- };
46
- }
47
-
48
- module.exports.parse = function(text) {
49
- // split text into lines
50
- var lines = text.trim().split(/[\r\n]+/);
51
-
52
- // throw away first row containing headers
53
- lines = lines.splice(1);
54
-
55
- // second row contains information about the event
56
- var header = lines[0].split(';');
57
-
58
- var event = {
59
- // row starts with a double slash
60
- name: header[0].substring(2, header[0].length),
61
- map: header[1],
62
- date: header[2],
63
- startTime: header[3],
64
- categories: [ ]
65
- };
66
-
67
- // throw a way the now parsed header
68
- lines = lines.splice(1);
69
-
70
- var category = null;
71
-
72
- let idx = 0;
73
- lines.filter(line => line.trim().length > 0).forEach(function(line) {
74
- var cols = line.split(';');
75
- if (cols.length === 4) {
76
- category = parseCategory(cols);
77
- event.categories.push(category);
78
- } else {
79
- category.runners.push(parseRunner(cols, category.name, ++idx));
80
- }
81
- });
82
-
83
- return event;
84
- };
85
-
86
- module.exports.serialize = function(event) {
87
- var result = '//Format: Rank;Name;Firstname;YearOfBirth;SexMF;FedNr;Zip;Town;Club;NationIOF;StartNr;eCardNr;RunTime;StartTime;FinishTime;CtrlCode;SplitTime; ...\n';
88
- result += '//' + [event.name, event.map, event.date, event.startTime, ''].join(';') + '\n';
89
-
90
- event.categories.forEach(function(category) {
91
- result += [category.name, category.distance, category.ascent, category.controls].join(';') + '\n';
92
- category.runners.forEach(function(runner) {
93
- result += [runner.rank, runner.name, runner.firstName, runner.yearOfBirth, runner.sex, '', runner.zip, runner.city, runner.club, runner.nation, '', runner.ecard, runner.time, runner.startTime, ''].join(';');
94
- result += ';' + runner.splits.map(function(split) {
95
- return split.code + ';' + split.time;
96
- }).join(';') + '\n';
97
- });
98
- });
99
-
100
- return result;
101
- };
102
-
103
- module.exports.formatCheck = function(text) {
104
- return text.substring(0, 8) === '//Format';
105
- };