open-epsilon
Version:
empty-epsilon / open-sound-control bidirectional proxy
135 lines • 7.06 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MessageTranslator = void 0;
const empty_epsilon_js_1 = require("empty-epsilon-js");
const ee_schema_1 = require("./ee-schema");
const naming = require("naming");
function translatePrimitiveType(pt) {
return pt.charAt(0);
}
function translateType(pt) {
return pt instanceof Array ? pt.map(translatePrimitiveType).join('') : translatePrimitiveType(pt);
}
function enumAddresItemToArgument(addressItem, enumObj, enumName) {
const name = naming(addressItem, 'pascal');
if (typeof enumObj[name] === 'undefined') {
throw new Error(`bad ${enumName} name ${name}`);
}
return '"' + name + '"';
}
function addressItemToArgument(addressItem, argumentSchema) {
switch (argumentSchema) {
case "float":
return Number.parseFloat(addressItem).toFixed(2);
case "integer":
case "bool":
return addressItem;
case "ESystem":
return enumAddresItemToArgument(addressItem, empty_epsilon_js_1.ESystem, "ESystem");
case "EMissileWeapons":
return enumAddresItemToArgument(addressItem, empty_epsilon_js_1.EMissileWeapons, "EMissileWeapons");
default:
throw new Error(`unknown type: ${argumentSchema}`);
}
}
function addressArrToArguments(addressParts, argumentsSchema) {
return argumentsSchema.map((t, i) => addressItemToArgument(addressParts[i], t));
}
class MessageTranslator {
constructor(apiModel, namespace) {
this.apiModel = apiModel;
this.namespace = namespace;
this.translateOscMessageToGameCommand = (message) => {
const addressArr = message.address.split('/');
const oscArgs = message.args instanceof Array ? message.args : [message.args];
const vals = addressArr.concat(oscArgs.map(arg => '' + (arg.value == undefined ? arg : arg.value)));
// console.info(`handling command: ${vals.join('/')}`);
this.assertNamespaceAddress(addressArr);
let addrIdx = 2;
let path = [];
let currentType = this.apiModel.global;
while (addrIdx < addressArr.length) {
if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) {
throw new Error(`reached a primitive result ${currentType} before address is finished ${message.address}`);
}
else {
const symbolName = addressArr[addrIdx++];
const symbol = currentType[symbolName];
if (symbol) {
// the +1 makes us not use getters that exhaust the entire address. the last part needs to be a setter.
if (symbol && symbol.get && addrIdx < addressArr.length - symbol.get.arguments.length) {
currentType = symbol.get.type;
const lastArdIdx = addrIdx + symbol.get.arguments.length;
path.push(`${symbol.get.methodName}(${addressArrToArguments(addressArr.slice(addrIdx, lastArdIdx), symbol.get.arguments).join(',')})`);
addrIdx = lastArdIdx;
}
else if (symbol && symbol.set && addrIdx <= vals.length - symbol.set.arguments.length) { // last one is a setter, its arguments are taken from the vals array
const lastArdIdx = addrIdx + symbol.set.arguments.length;
path.push(symbol.set.methodName);
const setter = path.join(':');
const values = addressArrToArguments(vals.slice(addrIdx, lastArdIdx), symbol.set.arguments);
const numOfStaticValues = addressArr.length - addrIdx;
return {
template: `${setter}(${values.map((v, idx) => idx >= numOfStaticValues ? `{${idx - numOfStaticValues}}` : v).join(', ')})`,
values: values.slice(numOfStaticValues)
};
}
else {
throw new Error(`reached a symbol with no matching methods '${symbolName}' in ${vals}`);
}
}
else {
throw new Error(`reached an unknown symbol '${symbolName}' in ${message.address}`);
}
}
}
throw new Error(`reached a non-primitive result ${currentType} but address is finished ${message.address}`);
};
this.translateAddressToGameQuery = (address) => {
const addressArr = address.split('/');
this.assertNamespaceAddress(addressArr);
let addrIdx = 2;
let path = [];
let currentType = this.apiModel.global;
while (addrIdx < addressArr.length) {
if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) {
throw new Error(`reached a primitive result ${currentType} before address is finished ${address}`);
}
else {
const symbolName = addressArr[addrIdx++];
const symbol = currentType[symbolName];
if (symbol && symbol.get && addrIdx <= addressArr.length - symbol.get.arguments.length) {
currentType = symbol.get.type;
const lastArdIdx = addrIdx + symbol.get.arguments.length;
path.push(`${symbol.get.methodName}(${addressArrToArguments(addressArr.slice(addrIdx, lastArdIdx), symbol.get.arguments).join(',')})`);
addrIdx = lastArdIdx;
}
else {
throw new Error(`reached an unknown symbol '${symbolName}' in ${address}`);
}
}
}
if (ee_schema_1.isPrimitiveOrArrayOfPrimitiveType(currentType)) {
return {
address: address,
expr: path.join(':'),
type: translateType(currentType)
};
}
else {
throw new Error(`reached a non-primitive result ${currentType} but address is finished ${address}`);
}
};
if (~namespace.indexOf('/')) {
throw new Error(`namespace '${namespace}' contains address delimiter '/'`);
}
}
assertNamespaceAddress(addressArr) {
// assert address begins with namespace
if (addressArr[0] !== '' || addressArr[1] !== this.namespace) {
throw new Error(`ilegal address prefix ${addressArr.join('/')}`);
}
}
}
exports.MessageTranslator = MessageTranslator;
//# sourceMappingURL=translate.js.map