Split logic to multiple files

This commit is contained in:
Rene Saarsoo 2020-09-17 23:45:51 +03:00
parent 29f12552ec
commit a588432516
3 changed files with 96 additions and 92 deletions

38
src/ast.ts Normal file
View File

@ -0,0 +1,38 @@
export enum RuleType {
Name = "Name",
Author = "Author",
Description = "Description",
Warmup = "Warmup",
Rest = "Rest",
Interval = "Interval",
Cooldown = "Cooldown",
}
export type Rule = {
type: RuleType;
params: Param[];
};
export enum ParamType {
Text = "Text",
Power = "Power",
PowerRange = "PowerRange",
Cadence = "Cadence",
Duration = "Duration",
}
export type TextParam = { type: ParamType.Text; value: string };
export type PowerParam = { type: ParamType.Power; value: number };
export type PowerRangeParam = {
type: ParamType.PowerRange;
value: [number, number];
};
export type CadenceParam = { type: ParamType.Cadence; value: number };
export type DurationParam = { type: ParamType.Duration; value: number };
export type Param =
| TextParam
| PowerParam
| PowerRangeParam
| CadenceParam
| DurationParam;

View File

@ -1,96 +1,5 @@
import * as fs from "fs";
enum RuleType {
Name = "Name",
Author = "Author",
Description = "Description",
Warmup = "Warmup",
Rest = "Rest",
Interval = "Interval",
Cooldown = "Cooldown",
}
type Rule = {
type: RuleType;
params: Param[];
};
enum ParamType {
Text = "Text",
Power = "Power",
PowerRange = "PowerRange",
Cadence = "Cadence",
Duration = "Duration",
}
type TextParam = { type: ParamType.Text; value: string };
type PowerParam = { type: ParamType.Power; value: number };
type PowerRangeParam = { type: ParamType.PowerRange; value: [number, number] };
type CadenceParam = { type: ParamType.Cadence; value: number };
type DurationParam = { type: ParamType.Duration; value: number };
type Param =
| TextParam
| PowerParam
| PowerRangeParam
| CadenceParam
| DurationParam;
const toInteger = (str: string): number => {
return parseInt(str.replace(/[^0-9]/, ""), 10);
};
const toSeconds = (str: string): number => {
const [seconds, minutes, hours] = str.split(":").map(toInteger).reverse();
return seconds + minutes * 60 + (hours || 0) * 60 * 60;
};
const parseValueParam = (text: string): Param => {
if (/^[0-9:]+$/.test(text)) {
return { type: ParamType.Duration, value: toSeconds(text) };
}
if (/^[0-9]+rpm$/.test(text)) {
return { type: ParamType.Cadence, value: toInteger(text) };
}
if (/^[0-9]+%..[0-9]+%$/.test(text)) {
const [from, to] = text.split("..").map(toInteger);
return { type: ParamType.PowerRange, value: [from, to] };
}
if (/^[0-9]+%$/.test(text)) {
return { type: ParamType.Power, value: toInteger(text) };
}
throw new Error(`Unrecognized parameter "${text}"`);
};
const parseParams = (type: RuleType, text: string): Param[] => {
switch (type) {
case RuleType.Name:
case RuleType.Author:
case RuleType.Description:
return [{ type: ParamType.Text, value: text }];
case RuleType.Warmup:
case RuleType.Rest:
case RuleType.Interval:
case RuleType.Cooldown:
return text.split(" ").map(parseValueParam);
}
};
const parseRule = (line: string): Rule | undefined => {
const matches = line.match(/^(\w+):(.*)$/);
if (!matches) {
return undefined;
}
if (!Object.keys(RuleType).includes(matches[1])) {
return undefined;
}
const type: RuleType = matches[1] as RuleType;
return {
type,
params: parseParams(type, matches[2].trim()),
};
};
import { parseRule } from "./parser";
const isDefined = <T>(x: T | undefined): x is T => Boolean(x);

57
src/parser.ts Normal file
View File

@ -0,0 +1,57 @@
import { Param, ParamType, RuleType, Rule } from "./ast";
const toInteger = (str: string): number => {
return parseInt(str.replace(/[^0-9]/, ""), 10);
};
const toSeconds = (str: string): number => {
const [seconds, minutes, hours] = str.split(":").map(toInteger).reverse();
return seconds + minutes * 60 + (hours || 0) * 60 * 60;
};
const parseValueParam = (text: string): Param => {
if (/^[0-9:]+$/.test(text)) {
return { type: ParamType.Duration, value: toSeconds(text) };
}
if (/^[0-9]+rpm$/.test(text)) {
return { type: ParamType.Cadence, value: toInteger(text) };
}
if (/^[0-9]+%..[0-9]+%$/.test(text)) {
const [from, to] = text.split("..").map(toInteger);
return { type: ParamType.PowerRange, value: [from, to] };
}
if (/^[0-9]+%$/.test(text)) {
return { type: ParamType.Power, value: toInteger(text) };
}
throw new Error(`Unrecognized parameter "${text}"`);
};
const parseParams = (type: RuleType, text: string): Param[] => {
switch (type) {
case RuleType.Name:
case RuleType.Author:
case RuleType.Description:
return [{ type: ParamType.Text, value: text }];
case RuleType.Warmup:
case RuleType.Rest:
case RuleType.Interval:
case RuleType.Cooldown:
return text.split(" ").map(parseValueParam);
}
};
export const parseRule = (line: string): Rule | undefined => {
const matches = line.match(/^(\w+):(.*)$/);
if (!matches) {
return undefined;
}
if (!Object.keys(RuleType).includes(matches[1])) {
return undefined;
}
const type: RuleType = matches[1] as RuleType;
return {
type,
params: parseParams(type, matches[2].trim()),
};
};