joymap
Version:
A Gamepad API wrapper and mapping tool.
70 lines (58 loc) • 1.7 kB
text/typescript
import { split, reduce, filter, flow, map, isString } from 'lodash/fp';
import { nameIsValid } from '../common/utils';
import shuntingYard, { operators } from './shuntingYard';
import { EventToken } from '../types';
/**
* Returns EventToken[] in reverse polish notation (RPN)
*/
export function getEventTokens(name: string) {
return flow(
split(/([^a-zA-Z0-9.&&||])/g),
filter((value) => !!value && value !== ' '),
shuntingYard,
map((value) => {
if (operators.includes(value)) {
return value;
}
return {
inputName: split('.', value)[0],
inputState: split('.', value)[1] || 'pressed',
};
}),
)(name) as EventToken[];
}
export function eventIsValid(inputs: EventToken[]) {
const eventTokens = Array.isArray(inputs) ? inputs : getEventTokens(inputs);
return reduce(
(result, token) => {
if (!result) {
return result;
}
if (isString(token)) {
return operators.includes(token);
}
return nameIsValid(token.inputName);
},
true,
eventTokens,
);
}
export function verifyTokens(arr: (string | boolean)[]) {
const stack: boolean[] = [];
arr.forEach((token) => {
if (typeof token === 'boolean') {
stack.push(token);
} else {
const elem1 = stack.pop();
const elem2 = stack.pop();
if (token === '&&') {
stack.push(!!(elem1 && elem2));
} else if (token === '||') {
stack.push(!!(elem1 || elem2));
} else {
throw new Error(`verifyTokens: invalid operator ${token} was used`);
}
}
});
return stack[0];
}