UNPKG

universal-siteswap

Version:

A library for parsing, validating, examining and finding transitions between all types of siteswaps

262 lines 11.3 kB
"use strict"; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); exports.VanillaSiteswap = exports.VanillaState = void 0; var common_1 = require("./common"); function sum(arr) { return arr.reduce(function (a, b) { return a + b; }, 0); } var VanillaState = /** @class */ (function () { function VanillaState(state) { this.isGround = false; this.numObjects = 0; this.maxHeight = 0; this.state = state; while (this.state.length > 0) { var test_1 = this.state.pop(); if (test_1 !== 0) { this.state.push(test_1); break; } } this.numObjects = sum(this.state); this.maxHeight = this.state.length; this.isGround = this.state.every(function (x) { return x === 1; }); } VanillaState.prototype.toString = function () { return this.state.join(''); }; VanillaState.prototype.entry = function (from) { return VanillaState.ShortestTransition(from ? from : VanillaState.GroundState(this.numObjects), this); }; VanillaState.prototype.exit = function (to) { return VanillaState.ShortestTransition(this, to ? to : VanillaState.GroundState(this.numObjects)); }; VanillaState.GroundState = function (numObjects) { return new VanillaState(new Array(numObjects).fill(1)); }; VanillaState.IsShiftValid = function (s1, s2, shift) { // Shift is valid when s2 is >= s1 at all points for (var i = 0; i < Math.min(s2.maxHeight, s1.maxHeight - shift); i++) { if (i + shift < s1.state.length && s1.state[i + shift] > s2.state[i]) return false; } return true; }; VanillaState.ShortestTransitionLength = function (s1, s2) { if (s1.numObjects !== s2.numObjects) { throw Error('States must be for the same number of objects.'); } var shift = Math.max(0, s1.maxHeight - s2.maxHeight); while (!this.IsShiftValid(s1, s2, shift)) shift++; return shift; }; VanillaState.FindLandings = function (s1, s2, shift) { var lands = []; for (var i = 0; i < s2.maxHeight; i++) { var newLanding = s2.state[i]; var alreadyLanding = i + shift >= s1.maxHeight ? 0 : s1.state[i + shift]; lands.push.apply(lands, Array(newLanding - alreadyLanding).fill(i + shift)); } return lands; }; VanillaState.GetTransition = function (s, length, land_times) { var upto = 0; var throws = []; for (var i = 0; i < length; i++) { var beat = []; for (var k = 0; k < s.state[i]; k++) { beat.push(land_times[upto++] - i); } throws.push(beat.length > 0 ? beat : [0]); } return new VanillaSiteswap(throws); }; VanillaState.ShortestTransition = function (s1, s2) { var length = VanillaState.ShortestTransitionLength(s1, s2); var lands = VanillaState.FindLandings(s1, s2, length); return VanillaState.GetTransition(s1, length, lands); }; VanillaState.AllTransitionsOfLength = function (s1, s2, length) { var land_times, perm_length, c, i, k, p; return __generator(this, function (_a) { switch (_a.label) { case 0: if (s1.numObjects !== s2.numObjects) { throw Error('States must be for the same number of objects.'); } if (!VanillaState.IsShiftValid(s1, s2, length)) { return [2 /*return*/]; } land_times = VanillaState.FindLandings(s1, s2, length); return [4 /*yield*/, VanillaState.GetTransition(s1, length, land_times)]; case 1: _a.sent(); perm_length = land_times.length; c = new Array(perm_length).fill(0); i = 1; _a.label = 2; case 2: if (!(i < perm_length)) return [3 /*break*/, 6]; if (!(c[i] < i)) return [3 /*break*/, 4]; k = i % 2 && c[i]; p = land_times[i]; land_times[i] = land_times[k]; land_times[k] = p; ++c[i]; i = 1; return [4 /*yield*/, VanillaState.GetTransition(s1, length, land_times)]; case 3: _a.sent(); return [3 /*break*/, 5]; case 4: c[i] = 0; ++i; _a.label = 5; case 5: return [3 /*break*/, 2]; case 6: return [2 /*return*/]; } }); }; return VanillaState; }()); exports.VanillaState = VanillaState; var VanillaSiteswap = /** @class */ (function () { function VanillaSiteswap(throws) { this.numObjects = 0; this.period = 0; this.maxHeight = 0; this.maxMultiplex = 0; this.isValid = false; this.errorMessage = ''; this.throws = throws; this.state = new VanillaState([]); // Make compiler happy this.validate(); } VanillaSiteswap.prototype.validate = function () { this.isValid = false; this.errorMessage = ''; this.period = this.throws.length; this.maxMultiplex = Math.max.apply(Math, this.throws.map(function (j) { return j.length; })); this.maxHeight = Math.max.apply(Math, this.throws.map(function (j) { return Math.max.apply(Math, j); })); this.numObjects = sum(this.throws.map(sum)) / this.period; if (this.numObjects % 1 !== 0) { this.errorMessage = 'Invalid pattern average'; return false; } // `check` stores the number of throws which should land for beat var check = this.throws.map(function (j) { return j.length; }); var state = new Array(this.maxHeight).fill(0); for (var i = 0; i < this.period; i++) { for (var _i = 0, _a = this.throws[i]; _i < _a.length; _i++) { var th = _a[_i]; var landTime = (i + th) % this.period; // Check landing position if (check[landTime] === 0) { this.errorMessage = "Collision at time ".concat(landTime); return false; } check[landTime]--; // Add to state, first at original land time, ignoring those landing before the end of the siteswap for (var curTime = i + th - this.period; curTime >= 0; curTime -= this.period) { state[curTime]++; } } } this.state = new VanillaState(state); this.isValid = true; return true; }; VanillaSiteswap.prototype.toString = function () { return this.throws.map(function (th) { return th.length === 1 ? (0, common_1.intToSS)(th[0]) : '[' + th.map(common_1.intToSS).join('') + ']'; }).join(''); }; VanillaSiteswap.prototype.toStack = function () { if (this.maxMultiplex > 1) { throw "Stack notation cannot deal with multiplexes"; } // For each throw, for each beat before it lands, subtract one if the throw at that beat lands before it var stack = []; for (var i = 0; i < this.period; i++) { var n = this.throws[i][0]; for (var j = 1; j < this.throws[i][0]; j++) { if (j + this.throws[(i + j) % this.period][0] < this.throws[i][0]) n--; } stack.push(n); } return stack; }; VanillaSiteswap.prototype.toStackString = function () { return this.toStack().map(function (x) { return (0, common_1.intToSS)(x); }).join(''); }; VanillaSiteswap.ParseStack = function (input) { var stack = input.replace(/ /g, ''); var throws = []; for (var i = 0; i < stack.length; i++) { var ss = (0, common_1.ssToInt)(stack[i]); var place = ss; for (var j = 1; place > 0; j++) { if ((0, common_1.ssToInt)(stack[(i + j) % stack.length]) < place) ss++; else place--; } throws.push([ss]); } return new VanillaSiteswap(throws); }; VanillaSiteswap.Parse = function (input) { var multiplex = false; var throws = []; var multiplexThrows = []; for (var _i = 0, _a = input.replace(/ /g, ''); _i < _a.length; _i++) { var i = _a[_i]; if (i == '[') { multiplex = true; multiplexThrows = []; } else if (multiplex && i == ']') { multiplex = false; throws.push(multiplexThrows); } else if (multiplex) { multiplexThrows.push((0, common_1.ssToInt)(i)); } else { throws.push([(0, common_1.ssToInt)(i)]); } } return new VanillaSiteswap(throws); ; }; return VanillaSiteswap; }()); exports.VanillaSiteswap = VanillaSiteswap; //# sourceMappingURL=vanilla-siteswap.js.map