UNPKG

step-sequence-generator

Version:

A step sequence generator for figure skating programs

115 lines (114 loc) 5.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StepTracker = void 0; const utils_1 = require("./utils"); const custom_errors_1 = require("../../errors/custom-errors"); const random_generator_1 = require("../../utils/random-generator"); const rb_vector_key_percentage_1 = require("../../shared/constants/rb-percentage/rb-vector-key-percentage"); const extractors_1 = require("../roulette/weight-calculator/extractors"); const weight_key_creators_1 = require("../roulette/number-generator/weight-key-creators"); class StepTracker { constructor(data) { const { standardStartCoordinates, vectorsTrack, vectorAngles, vectorKeyChanceRatioMapGenerator, roulette, } = data; this.startCoordinates = standardStartCoordinates; this.vectorsTrack = vectorsTrack; this.vectorAngles = vectorAngles; this.vectorKeyChanceRatioMapGenerator = vectorKeyChanceRatioMapGenerator; this.roulette = roulette; } /** * @arg data * @arg {VectorKey | null} data.currentVectorKey ключ вектора движения относительно поля * @arg {ArcVectorIndexType} data.currentAcrVectorIndex индекс дуги: по часовой или против часовой стрелки * @arg {DescartesCoordinatesType} data.currentCoordinates текущий координаты * @arg {number} data.distance расстояние, которое покрывает движение * */ getNextPosition(data) { const { currentVectorKey, currentAcrVectorIndex, currentCoordinates, distance } = data; const triedVectorKeys = new Set(); let availableVectorKeys = this.getAllowedVectorKeys(currentVectorKey); while (availableVectorKeys.length > 0) { const vectorKeyChanceRatioMap = this.vectorKeyChanceRatioMapGenerator.getChanceRatioMap({ currentVectorKey, vectorKeys: availableVectorKeys, currentAcrVectorIndex, rbPercentage: rb_vector_key_percentage_1.RB_VECTOR_KEY_PERCENTAGE, }); const vectorKey = this.getNextMovementVector(availableVectorKeys, vectorKeyChanceRatioMap); triedVectorKeys.add(vectorKey); const vectorCursor = this.getNextTrackVector(vectorKey); const newCoordinates = this.getNewCoordinates({ vectorCursor, currentCoordinates, distance, }); if (newCoordinates) return { vector: vectorKey, coordinates: newCoordinates, }; availableVectorKeys = this.filterVectorKeys(triedVectorKeys, availableVectorKeys); } console.debug('getNextPosition: Новые координаты не найдены'); throw new custom_errors_1.SequenceTrackerError('Unable to find next coordinates within bounds.', 'NO_VALID_COORDINATES'); } filterVectorKeys(triedVectorKeys, vectorKeys) { return vectorKeys.filter((vectorKey) => !triedVectorKeys.has(vectorKey)); } getNewCoordinates(data) { const { vectorCursor, currentCoordinates, distance } = data; const newX = this.calcCoordinate({ cursor: vectorCursor.x, coord: currentCoordinates.x, distance, }); const newY = this.calcCoordinate({ cursor: vectorCursor.y, coord: currentCoordinates.y, distance, }); try { return (0, utils_1.createCoordinates)(newX, newY); } catch (error) { if (error instanceof custom_errors_1.CoordinatesError && error.code === 'OUTSIDE_BOUNDS') return null; console.debug('getNewCoordinates; Неизвестная ошибка'); throw error; } } calcCoordinate(data) { const { cursor, coord, distance } = data; return distance * cursor + coord; } getNextTrackVector(vectorKey) { return this.vectorsTrack[vectorKey]; } getNextMovementVector(vectors, chanceRatioMap) { if (vectors.length === 0) throw new custom_errors_1.SequenceTrackerError('vectors.length should be more than 0', 'NO_VECTOR_FOR_CHOICE'); const index = this.roulette.spinWheel({ selection: vectors, chanceRatioMap, itemKeyExtractor: extractors_1.vectorKeyKeyExtractor, weightKeyCreator: weight_key_creators_1.vectorWeightKeyCreator, }); return vectors[index]; } getAllowedVectorKeys(currentVector, maxTurnAngle = 90) { return currentVector === null ? Object.keys(this.vectorAngles) : Object.keys(this.vectorAngles).filter((key) => { const absoluteAngelDiff = Math.abs(this.vectorAngles[currentVector] - this.vectorAngles[key]); const normalizeAngleDiff = Math.min(absoluteAngelDiff, 360 - absoluteAngelDiff); return normalizeAngleDiff <= maxTurnAngle; }); } getStartCoordinates() { return this.startCoordinates[this.getRandom(0, this.startCoordinates.length - 1)]; } getRandom(min, max) { return (0, random_generator_1.randomGenerator)(min, max); } } exports.StepTracker = StepTracker;