From 245a133c97c614c781b7a2839c3a90d647200e03 Mon Sep 17 00:00:00 2001 From: Raj Chaudhuri Date: Thu, 8 Aug 2024 16:39:48 +0530 Subject: [PATCH] Improved chancerollplugin to add decisions --- assets/sampledata.html | 4 +- src/chancerollplugin.js | 147 +++++++++++++++++++++++++++++++++++++--- src/defaultview.js | 22 ++++-- src/diceboardplugin.js | 32 ++++++--- src/player.js | 5 +- src/transformers.js | 27 -------- src/types.js | 1 + 7 files changed, 182 insertions(+), 56 deletions(-) delete mode 100644 src/transformers.js diff --git a/assets/sampledata.html b/assets/sampledata.html index cc3b4aa..60f48cd 100644 --- a/assets/sampledata.html +++ b/assets/sampledata.html @@ -21,9 +21,7 @@ You are confused. - You should try to roll three dice. - If your score is 3 or less, you should [[go back to optimism->Next-1]]. - If your score is more, you should [[proceed->100]]. + Roll three dice. If you roll 12 to 18, you should [[go back to optimism->Next-1]]. If you roll 1 to 10, you should turn to 100. If you roll 11, you are stunned and need to roll again. True to form, it is time for a boss fight. diff --git a/src/chancerollplugin.js b/src/chancerollplugin.js index 2864992..e2a85be 100644 --- a/src/chancerollplugin.js +++ b/src/chancerollplugin.js @@ -6,10 +6,14 @@ import { BBScannerPlugin } from "./plugin"; import './types' +const chanceRegEx = /(?:[Rr]oll|[Tt]hrow) (\S*?) di(?:c?)e\.(.*?)(?:\n|$)/ + export class ChanceRollPlugin extends BBScannerPlugin { /** @type {DiceBoardPlugin} */ #diceboard + #chanceroll + constructor() { super('chancerollplugin') } @@ -27,10 +31,92 @@ export class ChanceRollPlugin extends BBScannerPlugin { } this.#diceboard.addEventListener('roll', (e) => { - if (this.active) { - this.setCurrentState(e.detail) + if (!this.active) { + return + } + + this.setCurrentState(e.detail) + + const rollResult = parseInt(e.detail.total) + + const chanceroll = this.#chanceroll + if (!chanceroll || !chanceroll.numDice) { + return + } + + const view = this.player.view + + view.hideSelectedContent('p.cr-result') + + let rowToShow + for (let i = 0; i < chanceroll.actions.length; i++) { + const action = chanceroll.actions[i] + // if ( + // (!action.rangeEnd && rollResult == action.rangeStart) + // || (rollResult >= action.rangeStart && rollResult <= action.rangeEnd) + // || (rollResult == action.rangeStart || rollResult == action.rangeEnd) + // ) { + if (rollInRange(action, rollResult)) { + console.log(`Going to show ${JSON.stringify(action)}`) + rowToShow = view.content.querySelector(`p.chanceroll-result-${i}`) + break; + } + } + + if (rowToShow) { + view.show(rowToShow) } }) + + this.player.addTransformer( + /** + * + * @param {string} input + */ + (input) => { + if (!this.active) { + return input + } + + const chanceroll = this.#chanceroll + + if (!chanceroll || !chanceroll.numDice) { + return input + } + + const diceString = chanceroll.numDice == '1' || chanceroll.numDice === 'one' + ? `one die` + : `${chanceroll.numDice} dice` + + const currentState = this.getCurrentState() + const introStatement = currentState && currentState.total + ? `You had rolled ${diceString} for a result of ${currentState.total}` + : `Roll ${diceString}` + + let result = `
${introStatement}.` + if (chanceroll.restOfParagraph !== '') { + result = result + ` ${chanceroll.restOfParagraph}\n` + } + result = result + '
' + + for (let i = 0; i < chanceroll.actions.length; i++) { + const action = chanceroll.actions[i] + const ishidden = currentState && currentState.total + ? rollInRange(action, currentState.total) + ? '' + : 'hidden' + : 'hidden' + + result = result + `

${action.sentence}` + if (action.destination) { + result = result.trimEnd() + ` [[go to ${action.destination}|${action.destination}]]` + } + result = result + '

' + } + + return input.replace(chanceRegEx, result) + } + ) } /** @@ -41,13 +127,16 @@ export class ChanceRollPlugin extends BBScannerPlugin { scan (passage) { const passageBody = passage.body - const phrase1 = /[Rr]oll\s{1}(\S*?)\s{1}di(c{0,1})e\./ - let match = passageBody.match(phrase1) + // const phrase1 = /[Rr]oll\s{1}(\S*?)\s{1}di(c{0,1})e\./ + // let match = passageBody.match(phrase1) - if (!match) { - const phrase2 = /[Tt]hrow\s{1}(\S*?)\s{1}di(c{0,1})e\./ - match = passageBody.match(phrase2) - } + // if (!match) { + // const phrase2 = /[Tt]hrow\s{1}(\S*?)\s{1}di(c{0,1})e\./ + // match = passageBody.match(phrase2) + // } + + + const match = passageBody.match(chanceRegEx) if (!match) { this.#diceboard.hide('chanceroll') @@ -55,8 +144,42 @@ export class ChanceRollPlugin extends BBScannerPlugin { } const numdice = match[1].trim().toLowerCase() - this.#diceboard.setDice(numdice) + if (!this.#diceboard.validateDice(numdice)) { + this.#diceboard.hide('chanceroll') + return false + } + + const chanceroll = { + numDice: numdice, + actions: [], + restOfParagraph: '' + } + let restOfParagraph = match[2] + + const actionRegEx = /If you roll (?:a )?(\d{1,2})( or(?: a)? | to |)(\d{0,2}),([^\.\n]*?)(?: [Tt]urn to (\d{1,3}))?\./g + + let destMatch + while ((destMatch = actionRegEx.exec(match[2])) !== null) { + const chanceAction = { + rangeStart: destMatch[1], + rangeEnd: destMatch[3], + rangeOperator: destMatch[2].trim().toLocaleLowerCase(), + sentence: destMatch[4], + destination: destMatch[5] + } + chanceroll.actions.push(chanceAction) + restOfParagraph = restOfParagraph.replace(destMatch[0], '') + } + + restOfParagraph = restOfParagraph.trim() + if (restOfParagraph !== '') { + chanceroll.restOfParagraph = restOfParagraph + } + + this.#chanceroll = chanceroll + + this.#diceboard.setDice(numdice) this.#diceboard.show('chanceroll') const currentState = this.getCurrentState() @@ -67,3 +190,9 @@ export class ChanceRollPlugin extends BBScannerPlugin { return true } } + +const rollInRange = (action, rollResult) => { + return (!action.rangeEnd && rollResult == action.rangeStart) + || (rollResult >= action.rangeStart && rollResult <= action.rangeEnd) + || (rollResult == action.rangeStart || rollResult == action.rangeEnd) +} \ No newline at end of file diff --git a/src/defaultview.js b/src/defaultview.js index 502f86f..0ea106f 100644 --- a/src/defaultview.js +++ b/src/defaultview.js @@ -38,6 +38,7 @@ export class DefaultView { } + /** * * @param {HTMLElement} element @@ -70,24 +71,35 @@ export class DefaultView { element.setAttribute('disabled', 'true') } + /** + * Hides all elements that match the selector + * @param {string} selector + */ + hideSelectedContent (selector) { + this.#contentelement.querySelectorAll(selector) + .forEach((item) => { + this.hide(item) + }) + } + /** * @returns {HTMLButtonElement} */ - get backButton() { + get backButton () { return document.getElementById('backButton') } /** * @returns {HTMLButtonElement} */ - get forwardButton() { + get forwardButton () { return document.getElementById('forwardButton') } /** * @returns {HTMLButtonElement} */ - get restartButton() { + get restartButton () { return document.getElementById('restartButton') } @@ -163,7 +175,7 @@ export class DefaultView { * specified classname under section.sidebar-1 * @param {*} panelName */ - getToolPanel(panelName) { + getToolPanel (panelName) { return document.querySelector(`section.sidebar-1 div.${panelName}`) } @@ -175,7 +187,7 @@ export class DefaultView { * * @param {*} dialogId */ - getDialog(dialogId) { + getDialog (dialogId) { return document.getElementById(dialogId) } } \ No newline at end of file diff --git a/src/diceboardplugin.js b/src/diceboardplugin.js index 77cf877..3599cb0 100644 --- a/src/diceboardplugin.js +++ b/src/diceboardplugin.js @@ -115,15 +115,6 @@ export class DiceBoardPlugin extends BBScannerPlugin { rollDice() }) - const matchMap = { - "0": 0, - "2": 2, - "two": 2, - "3": 3, - "three": 3, - "some": 3 - } - this.#setdice = (number) => { number = matchMap[number] ?? 1 @@ -224,6 +215,20 @@ export class DiceBoardPlugin extends BBScannerPlugin { console.log(`Dice shown by ${owner}`) } + + /** + * Validates whether the string parameter would correctly translate to + * a non-zero number of dice. + * + * @param {string} number + * @returns {boolean} + */ + validateDice (number) { + return matchMap[number] + ? true + : false + } + /** * Sets up the diceboard to show and roll the specified number of dice. * @@ -253,6 +258,15 @@ export class DiceBoardPlugin extends BBScannerPlugin { } } +const matchMap = { + "0": 0, + "2": 2, + "two": 2, + "3": 3, + "three": 3, + "some": 3 +} + const dieTemplate = `
diff --git a/src/player.js b/src/player.js index 5a9670c..1add46c 100644 --- a/src/player.js +++ b/src/player.js @@ -1,8 +1,7 @@ 'use strict' import { BBPlugin } from "./plugin" -import { processHTML, processTwineLinks, addParagraphTags } from './transformers' -import { Passage } from "./passage" + import './types' @@ -88,7 +87,7 @@ export class Player { // This will read and sanitise any HTML in // the passage body. From this point, it's // all unencoded HTML. - // We are not doing this any, for for this + // We are not doing this any more for this // particular format. // bodystr = processHTML(bodystr) diff --git a/src/transformers.js b/src/transformers.js deleted file mode 100644 index b51fe3f..0000000 --- a/src/transformers.js +++ /dev/null @@ -1,27 +0,0 @@ -'use strict' - -// Passage body text to HTML transformation -export const processHTML = (input) => { - // The following will decode HTML-encoded content - const element = document.createElement('div'); - element.innerHTML = input; - // TODO: strip unwated tags here - return element.textContent; -} - -// Convert text in all known Twine link formats to hyperlinks -export const processTwineLinks = (input) => { - return input - .replaceAll(/\[\[(.*?)-(>|>)(.*?)\]\]/g, '$1') - .replaceAll(/\[\[(.*?)(<|<)-(.*?)\]\]/g, '$3') - .replaceAll(/\[\[(.*?)\|(.*?)\]\]/g, '$1') - .replaceAll(/\[\[(.*?)\]\]/g, '$1') -} - -// Convert all line breaks in the input text to HTML paragraphs -export const addParagraphTags = (input) => { - return input - .split(/\r?\n|\r|\n/g) - .map((row) => `

${row}

`) - .join(''); -} \ No newline at end of file diff --git a/src/types.js b/src/types.js index 3d795a4..b3368b9 100644 --- a/src/types.js +++ b/src/types.js @@ -77,6 +77,7 @@ * @property {FuncHTMLElementVoid} show * @property {FuncHTMLElementVoid} disable * @property {FuncHTMLElementVoid} enable + * @property {FuncStringVoid} hideSelectedContent * @property {HTMLButtonElement} backButton * @property {HTMLButtonElement} forwardButton * @property {HTMLButtonElement} restartButton