UNPKG

modaq

Version:

Quiz Bowl Reader using TypeScript, React, and MobX

249 lines 10.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.getBonusWords = exports.Bonus = exports.Tossup = exports.PacketState = void 0; const mobx_1 = require("mobx"); const mobx_sync_1 = require("mobx-sync"); const FormattedTextParser = __importStar(require("../parser/FormattedTextParser")); require("../parser/IFormattedText"); require("./IGameFormat"); class PacketState { constructor() { // Anything with methods/computeds not at the top level needs to use @format to deserialize correctly Object.defineProperty(this, "tossups", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "bonuses", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "name", { enumerable: true, configurable: true, writable: true, value: void 0 }); mobx_1.makeAutoObservable(this); this.tossups = []; this.bonuses = []; this.name = undefined; } setTossups(tossups) { this.tossups = tossups; } setBonuses(bonuses) { this.bonuses = bonuses; } setName(name) { this.name = name; } } __decorate([ mobx_sync_1.format((deserializedArray) => { return deserializedArray.map((deserializedTossup) => { return new Tossup(deserializedTossup.question, deserializedTossup.answer, deserializedTossup.metadata); }); }) ], PacketState.prototype, "tossups", void 0); exports.PacketState = PacketState; class Tossup { constructor(question, answer, metadata) { Object.defineProperty(this, "question", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "answer", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "metadata", { enumerable: true, configurable: true, writable: true, value: void 0 }); mobx_1.makeAutoObservable(this); this.question = question; this.answer = answer; this.metadata = metadata; } getPointsAtPosition(format, wordIndex, isCorrect = true) { // If there's no powers, default to 10 points if (format.powers.length === 0 && isCorrect) { return 10; } const tossupWords = this.getWords(format); const words = tossupWords.map((questionText) => questionText.word.reduce((result, text) => result + text.text, "").trim()); // Ignore the last word, which is an end of question marker const lastIndex = words.length - 1; let powerMarkerIndex = 0; for (let i = 0; i < format.powers.length; i++) { const powerMarker = format.powers[i].marker.trim(); const currentPowerMarkerIndex = words.findIndex((value, index) => index >= powerMarkerIndex && value.startsWith(powerMarker)); if (currentPowerMarkerIndex === -1) { continue; } powerMarkerIndex = currentPowerMarkerIndex; const powerMarkerWord = tossupWords[powerMarkerIndex]; // To get the word index, we need to subtract the count of non-words from the text index. We only have the // non-word index, so we have to add 1 to that to get the count (TI - (NWI + 1)). If we use < rather than // <=, we can remove the -1. if (isCorrect && powerMarkerIndex !== lastIndex && !powerMarkerWord.canBuzzOn && wordIndex < powerMarkerWord.textIndex - powerMarkerWord.nonWordIndex) { return format.powers[i].points; } } if (!isCorrect) { // If we're at the end of the question, don't count it as a neg // We add an extra word for the end of question marker, so remove that from the list of words, as well as all of // the power markers we skipped const lastWord = tossupWords[tossupWords.length - 1]; if (!lastWord.canBuzzOn) { // Something weird is happening, since the last word should always be buzzable (as the end marker). throw new Error("Last word not buzzable, but must be buzzable by design"); } return wordIndex >= lastWord.wordIndex ? 0 : format.negValue; } // Not in power, so return the default value return 10; } getWords(format) { const formattedTexts = this.formattedQuestionText(format); const words = []; let wordIndex = 0; let nonwordIndex = 0; for (let i = 0; i < formattedTexts.length; i++) { const word = formattedTexts[i]; const fullText = word.reduce((result, text) => result + text.text, ""); const isLastWord = i === formattedTexts.length - 1; const inPronunciationGuide = word.length > 0 && word[0].pronunciation === true; // We need to skip over power markers and not count them when we calculate buzz points let canBuzzOn = true; let index = wordIndex; const trimmedText = fullText.trim(); const powerMarkerIndex = format.powers.findIndex((power) => trimmedText.startsWith(power.marker)); if (isLastWord) { // Last word should always be the terminal character, which can't be a power or in a pronunciation guide wordIndex++; } else if (powerMarkerIndex >= 0) { // Power markers have priority over pronunciation guides, and shouldn't be treated as such for (const segment of word) { segment.pronunciation = false; } canBuzzOn = false; index = nonwordIndex; nonwordIndex++; } else if (inPronunciationGuide) { canBuzzOn = false; index = nonwordIndex; nonwordIndex++; } else { wordIndex++; } if (canBuzzOn) { words.push({ wordIndex: index, textIndex: i, word, isLastWord, canBuzzOn, }); } else { words.push({ nonWordIndex: index, textIndex: i, word, canBuzzOn, }); } } return words; } formattedQuestionText(format) { // Include the ■ to give an end of question marker return FormattedTextParser.splitFormattedTextIntoWords(this.question, { pronunciationGuideMarkers: format.pronunciationGuideMarkers, }).concat([[{ text: "■END■", bolded: true, emphasized: false, required: false, pronunciation: false }]]); } } exports.Tossup = Tossup; Object.defineProperty(Tossup, "noPronunciationGuides", { enumerable: true, configurable: true, writable: true, value: [undefined, undefined] }); class Bonus { constructor(leadin, parts, metadata) { Object.defineProperty(this, "leadin", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "parts", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "metadata", { enumerable: true, configurable: true, writable: true, value: void 0 }); // We don't use makeAutoObservable because leadin doesn't need to be observable (never changes) mobx_1.makeAutoObservable(this); this.leadin = leadin.trim(); this.parts = parts; this.metadata = metadata; } } exports.Bonus = Bonus; function getBonusWords(text, format) { return FormattedTextParser.parseFormattedText(text, { pronunciationGuideMarkers: format.pronunciationGuideMarkers, }); } exports.getBonusWords = getBonusWords; //# sourceMappingURL=PacketState.js.map