UNPKG

@sportloop/mrc

Version:

Workout file parser library, suitable for `.mrc` and `.erg` files, with first-class TypeScript support.

178 lines (174 loc) 5.96 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var parseNumber = function (numberlike) { var num = parseFloat(numberlike); if (Number.isNaN(num)) { throw new TypeError("could not parse value: " + numberlike + " as an integer"); } return num; }; // TODO(danielkov): [MODE DATA]? var getSection = function (raw, sectionName, required) { if (required === void 0) { required = false; } var re = new RegExp("^\\[" + sectionName + "\\]((.|\\n)+)\\[END " + sectionName + "\\]$", "m"); var parsed = re.exec(raw); if (!parsed) { if (required) { throw new TypeError("section: " + sectionName + " was not found"); } return undefined; } var value = parsed[1]; if (!value) { if (required) { throw new TypeError("section: " + sectionName + " could not be read"); } return undefined; } return value.trim(); }; var getField = function (raw, fieldName, required) { if (required === void 0) { required = false; } var re = new RegExp("^" + fieldName + "\\s?=\\s?((.)+)$", "m"); var parsed = re.exec(raw); if (!parsed) { if (required) { throw new TypeError("field: " + fieldName + " was not specified"); } return ""; } var value = parsed[1]; if (!value) { if (required) { throw new TypeError("field: " + fieldName + " could not be read"); } return ""; } return value.trim(); }; var dataTypesRegexp = /^MINUTES\s(\w+)$/m; var getDataTypes = function (raw) { var parsed = dataTypesRegexp.exec(raw); if (!parsed) { throw new TypeError("data types should be in the format: `MINUTES <DATA TYPE, e.g.: PERCENT>`"); } var value = parsed[1]; if (!value) { throw new TypeError("data types should be in the format: `MINUTES <DATA TYPE, e.g.: PERCENT>`"); } return ["MINUTES", value]; }; var getHeader = function (raw) { var rawHeader = getSection(raw, "COURSE HEADER", true); var version = parseNumber(getField(rawHeader, "VERSION", true)); var units = getField(rawHeader, "UNITS", true); var description = getField(rawHeader, "DESCRIPTION"); var fileName = getField(rawHeader, "FILE NAME"); var dataTypes = getDataTypes(rawHeader); var ftpString = getField(rawHeader, "FTP"); if (ftpString) { var ftp = parseNumber(ftpString); return { version: version, units: units, description: description, fileName: fileName, ftp: ftp, dataTypes: dataTypes, }; } return { version: version, units: units, description: description, fileName: fileName, dataTypes: dataTypes, }; }; var getCourseData = function (raw) { var rawCourseData = getSection(raw, "COURSE DATA", true); var lines = rawCourseData.split("\n"); return lines.map(function (line) { var values = line.split("\t"); if (values.length !== 2) { throw new TypeError("expected COURSE DATA to be in format number\tnumber, got: " + line); } var minutes = parseNumber(values[0]); var value = parseNumber(values[1]); return [minutes, value]; }); }; var getCourseText = function (raw) { var rawCourseText = getSection(raw, "COURSE TEXT"); if (!rawCourseText) { return undefined; } var lines = rawCourseText.split("\n"); return lines.map(function (line) { var split = line.split("\t"); return [parseNumber(split[0]), split[1], parseNumber(split[2])]; }); }; var getIntervalData = function (raw) { var rawIntervalData = getSection(raw, "INTERVAL DATA"); if (!rawIntervalData) { return undefined; } var lines = rawIntervalData.split("\n"); return lines.map(function (line) { var split = line.split("\t"); return [parseNumber(split[0]), parseNumber(split[1]), split[2]]; }); }; var parse = function (raw) { var courseHeader = getHeader(raw); var courseData = getCourseData(raw); var result = { courseHeader: courseHeader, courseData: courseData }; var courseText = getCourseText(raw); if (courseText) { result.courseText = courseText; } var intervalData = getIntervalData(raw); if (intervalData) { result.intervalData = intervalData; } return result; }; var writeNameRegexp = /[A-Z]/g; var writeName = function (name) { return name.replace(writeNameRegexp, function (match) { return " " + match; }).toUpperCase(); }; var writeValue = function (_a) { var name = _a[0], value = _a[1]; if (Array.isArray(value)) { return value.join(" "); } return writeName(name) + " = " + value; }; var writePossibleNumber = function (value) { return typeof value === "number" ? value.toFixed(2) : value; }; var writeSection = function (_a) { var name = _a[0], data = _a[1]; var formattedName = writeName(name); var values = (Array.isArray(data) ? data.map(function (stringOrNumber) { if (stringOrNumber.length > 2) { return stringOrNumber.map(writePossibleNumber).join("\t"); } return [stringOrNumber[0].toFixed(2), stringOrNumber[1]].join("\t"); }) : Object.entries(data).map(writeValue)).join("\n"); return "[" + formattedName + "]\n" + values + "\n[END " + formattedName + "]"; }; var stringify = function (parsed) { return Object.entries(parsed) .filter(function (_a) { var value = _a[1]; return value; }) .map(writeSection) .join("\n") + "\n"; }; exports.parse = parse; exports.stringify = stringify;