UNPKG

tetris-fumen

Version:
259 lines (258 loc) 9.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.decode = exports.extract = exports.Page = void 0; var inner_field_1 = require("./inner_field"); var buffer_1 = require("./buffer"); var defines_1 = require("./defines"); var action_1 = require("./action"); var comments_1 = require("./comments"); var quiz_1 = require("./quiz"); var field_1 = require("./field"); var Page = /** @class */ (function () { function Page(index, field, operation, comment, flags, refs) { this.index = index; this.operation = operation; this.comment = comment; this.flags = flags; this.refs = refs; this._field = field.copy(); } Object.defineProperty(Page.prototype, "field", { get: function () { return new field_1.Field(this._field.copy()); }, set: function (field) { this._field = (0, inner_field_1.createInnerField)(field); }, enumerable: false, configurable: true }); Page.prototype.mino = function () { return field_1.Mino.from(this.operation); }; return Page; }()); exports.Page = Page; var FieldConstants = { GarbageLine: 1, Width: 10, }; function extract(str) { var format = function (version, data) { var trim = data.trim().replace(/[?\s]+/g, ''); return { version: version, data: trim }; }; var data = str; // url parameters var paramIndex = data.indexOf('&'); if (0 <= paramIndex) { data = data.substring(0, paramIndex); } // v115@~ { var match = str.match(/[vmd]115@/); if (match !== undefined && match !== null && match.index !== undefined) { var sub = data.substr(match.index + 5); return format('115', sub); } } // v110@~ { var match = str.match(/[vmd]110@/); if (match !== undefined && match !== null && match.index !== undefined) { var sub = data.substr(match.index + 5); return format('110', sub); } } throw new Error('Unsupported fumen version'); } exports.extract = extract; function decode(fumen) { var _a = extract(fumen), version = _a.version, data = _a.data; switch (version) { case '115': return innerDecode(data, 23); case '110': return innerDecode(data, 21); } throw new Error('Unsupported fumen version'); } exports.decode = decode; function innerDecode(data, fieldTop) { var fieldMaxHeight = fieldTop + FieldConstants.GarbageLine; var numFieldBlocks = fieldMaxHeight * FieldConstants.Width; var buffer = new buffer_1.Buffer(data); var updateField = function (prev) { var result = { changed: true, field: prev, }; var index = 0; while (index < numFieldBlocks) { var diffBlock = buffer.poll(2); var diff = Math.floor(diffBlock / numFieldBlocks); var numOfBlocks = diffBlock % numFieldBlocks; if (diff === 8 && numOfBlocks === numFieldBlocks - 1) { result.changed = false; } for (var block = 0; block < numOfBlocks + 1; block += 1) { var x = index % FieldConstants.Width; var y = fieldTop - Math.floor(index / FieldConstants.Width) - 1; result.field.addNumber(x, y, diff - 8); index += 1; } } return result; }; var pageIndex = 0; var prevField = (0, inner_field_1.createNewInnerField)(); var store = { repeatCount: -1, refIndex: { comment: 0, field: 0, }, quiz: undefined, lastCommentText: '', }; var pages = []; var actionDecoder = (0, action_1.createActionDecoder)(FieldConstants.Width, fieldTop, FieldConstants.GarbageLine); var commentDecoder = (0, comments_1.createCommentParser)(); while (!buffer.isEmpty()) { // Parse field var currentFieldObj = void 0; if (0 < store.repeatCount) { currentFieldObj = { field: prevField, changed: false, }; store.repeatCount -= 1; } else { currentFieldObj = updateField(prevField.copy()); if (!currentFieldObj.changed) { store.repeatCount = buffer.poll(1); } } // Parse action var actionValue = buffer.poll(3); var action = actionDecoder.decode(actionValue); // Parse comment var comment = void 0; if (action.comment) { // コメントに更新があるとき var commentValues = []; var commentLength = buffer.poll(2); for (var commentCounter = 0; commentCounter < Math.floor((commentLength + 3) / 4); commentCounter += 1) { var commentValue = buffer.poll(5); commentValues.push(commentValue); } var flatten = ''; for (var _i = 0, commentValues_1 = commentValues; _i < commentValues_1.length; _i++) { var value = commentValues_1[_i]; flatten += commentDecoder.decode(value); } var commentText = unescape(flatten.slice(0, commentLength)); store.lastCommentText = commentText; comment = { text: commentText }; store.refIndex.comment = pageIndex; var text = comment.text; if (quiz_1.Quiz.isQuizComment(text)) { try { store.quiz = new quiz_1.Quiz(text); } catch (e) { store.quiz = undefined; } } else { store.quiz = undefined; } } else if (pageIndex === 0) { // コメントに更新がないが、先頭のページのとき comment = { text: '' }; } else { // コメントに更新がないとき comment = { text: store.quiz !== undefined ? store.quiz.format().toString() : undefined, ref: store.refIndex.comment, }; } // Quiz用の操作を取得し、次ページ開始時点のQuizに1手進める var quiz = false; if (store.quiz !== undefined) { quiz = true; if (store.quiz.canOperate() && action.lock) { if ((0, defines_1.isMinoPiece)(action.piece.type)) { try { var nextQuiz = store.quiz.nextIfEnd(); var operation = nextQuiz.getOperation(action.piece.type); store.quiz = nextQuiz.operate(operation); } catch (e) { // console.error(e.message); // Not operate store.quiz = store.quiz.format(); } } else { store.quiz = store.quiz.format(); } } } // データ処理用に加工する var currentPiece = void 0; if (action.piece.type !== defines_1.Piece.Empty) { currentPiece = action.piece; } // pageの作成 var field = void 0; if (currentFieldObj.changed || pageIndex === 0) { // フィールドに変化があったとき // フィールドに変化がなかったが、先頭のページだったとき field = {}; store.refIndex.field = pageIndex; } else { // フィールドに変化がないとき field = { ref: store.refIndex.field }; } pages.push(new Page(pageIndex, currentFieldObj.field, currentPiece !== undefined ? field_1.Mino.from({ type: (0, defines_1.parsePieceName)(currentPiece.type), rotation: (0, defines_1.parseRotationName)(currentPiece.rotation), x: currentPiece.x, y: currentPiece.y, }) : undefined, comment.text !== undefined ? comment.text : store.lastCommentText, { quiz: quiz, lock: action.lock, mirror: action.mirror, colorize: action.colorize, rise: action.rise, }, { field: field.ref, comment: comment.ref, })); // callback( // currentFieldObj.field.copy() // , currentPiece // , store.quiz !== undefined ? store.quiz.format().toString() : store.lastCommentText, // ); pageIndex += 1; if (action.lock) { if ((0, defines_1.isMinoPiece)(action.piece.type)) { currentFieldObj.field.fill(action.piece); } currentFieldObj.field.clearLine(); if (action.rise) { currentFieldObj.field.riseGarbage(); } if (action.mirror) { currentFieldObj.field.mirror(); } } prevField = currentFieldObj.field; } return pages; }