From e166f881dc9b184cf079f5881e856e6364ca0712 Mon Sep 17 00:00:00 2001 From: cyfraeviolae Date: Thu, 21 Jul 2022 01:26:47 -0400 Subject: levels and history --- index.html | 46 ++++++----- level-select.html | 30 +++++++ static/poems.js | 30 +++---- static/script.js | 231 ++++++++++++++++++++++++++++++++++++++---------------- static/styles.css | 3 + 5 files changed, 240 insertions(+), 100 deletions(-) create mode 100644 level-select.html diff --git a/index.html b/index.html index fd12a43..c33d599 100644 --- a/index.html +++ b/index.html @@ -17,23 +17,36 @@
source code + ยท + level select
-

+

The dithyrambic sorcerer Roseacrucis has encrypted the - Library’s treasured poetry collections. As our newest - acolyte, your task is to decode one secret line of poetry each day. -

-

- Given the ransom price of one new line in the same meter as today’s secret - line, for each word, Roseacrucis will reveal which letters are in the right place ๐ŸŸฉ, in the word but in the wrong - place ๐ŸŸจ, or not in the word at all โฌœ. -

+ Library’s treasured poetry collections. + Your task is to decode one line of poetry each day, + though you may attempt previous challenges as well. +

+
+
+ + How to play + + Given the ransom price of one new line of poetry in the same meter + as today’s secret line, for each word, Roseacrucis will + reveal which letters are in the right place ๐ŸŸฉ, in the word but in + the wrong place ๐ŸŸจ, or not in the word at all โฌœ. + Accents and punctuation are ignored.

Each word is annotated with the number of required syllables and their stress marks. For example, ×/ indicates that the word has two syllables, the first unstressed and the second stressed (such as in por-TRAY).

+

+ Each guess must be a reasonable and sensible line of poetry, but + creativity and poetic license are encouraged. +

+

@@ -55,27 +68,20 @@ +

diff --git a/level-select.html b/level-select.html new file mode 100644 index 0000000..71f368f --- /dev/null +++ b/level-select.html @@ -0,0 +1,30 @@ + + + + Prosodyle + + + + + + + +
+
+ +
+ source code + ยท + level select +
+
+ +
    +
    + + + + diff --git a/static/poems.js b/static/poems.js index 8599215..b60f31b 100644 --- a/static/poems.js +++ b/static/poems.js @@ -37,11 +37,11 @@ And their hearts but once heaved, and for ever grew still! }, { "line": "Infinite wrath and infinite despair".split(' '), - "scansion": ['x/x', '/', 'x', '/x/', 'x/'], + "scansion": '/xx / x //x x/', "title": "Book IV", "collection": "Paradise Lost", "author": "John Milton", - "meter": "iambic pentameter", + "meter": "iambic pentameter with trochaic substitution", "ctx": ` Me miserable! which way shall I flie Infinite wrauth, and infinite despaire? @@ -237,12 +237,6 @@ Faint as shed flowers, the attenuated dream. `, "link": "http://www.rossettiarchive.org/docs/sonnets.lcms.rad.html#21-1871", }, - {}, - {}, - {}, - {}, - {}, - {}, { "line": "The art of losing isnt hard to master".split(' '), "scansion": 'x / x /x /x / x /x', @@ -376,12 +370,6 @@ Rage, rage against the dying of the light. `, "link": "https://poets.org/poem/do-not-go-gentle-good-night", }, - {}, - {}, - {}, - {}, - {}, - {}, { "line": "Now is the winter of our discontent".split(' '), "scansion": '/ x x /x / x /x/', @@ -518,6 +506,20 @@ As Housewives do, a Fly. `, "link": "https://allpoetry.com/If-you-were-coming-in-the-fall,", }, + { + "line": "Grace was in all her steps Heaven in her eye".split(' '), + "renderLine": "Grace was in all her steps, Heaven in her eye", + "scansion": '/ x x / x / / x x /', + "title": "Book VIII", + "collection": "Paradise Lost", + "author": "John Milton", + "meter": "iambic pentameter with trochaic substitution", + "ctx": ` +Grace was in all her steps, Heaven in her eye, +In every gesture dignity and love. +`, + "link": "https://www.bartleby.com/360/2/277.html", + }, ] /* { diff --git a/static/script.js b/static/script.js index 70c17d1..9d8acdc 100644 --- a/static/script.js +++ b/static/script.js @@ -1,9 +1,5 @@ "use strict"; -var entryEl = document.getElementById("entry") -var guessesEl = document.getElementById("guesses") -var winEl = document.getElementById("win") - function renderScansion(scansion) { var s = '' for (var c of scansion) { @@ -46,13 +42,21 @@ function renderWord(word, wordIdx, guess, score, offset) { return `
    ${scansionBox}${els.join('')}
    ` } +function renderGuessIdxBox(guessIdx) { + return `
    ๐Ÿ“‹ ${guessIdx+1}
    ` +} + +function renderChallengeIdxBox() { + return `
    #${challengeIdx + 1}
    ` +} + function renderLine(line, guess, guessIdx, scores) { var els = [] var offset = 0; if (guessIdx || guessIdx === 0) { - els.push(`
    ๐Ÿ“‹ ${guessIdx+1}
    `) + els.push(renderGuessIdxBox(guessIdx)) } else { - els.push(`
    #${getChallengeIdx() + 1}
    `) + els.push(renderChallengeIdxBox()) } for (var wordIdx in line) { var word = line[wordIdx] @@ -172,67 +176,26 @@ function renderKeyboardLights() { var focused = null; -document.getElementById('clear').onclick = function(e) { - e.preventDefault(); - for (var el of document.getElementsByClassName('entrybox')) { - el.innerText = '' - } - unfocus(document.querySelector(`[data-offset="${focused}"]`)); - focus(document.querySelector(`[data-offset="0"]`)) -} - -document.getElementById('fill-green').addEventListener('click', function(e) { - e.preventDefault(); - var el = document.querySelector(`[data-offset="${focused}"]`) - if (!el) { - return - } - var w = el.getAttribute('data-word') - for (var el of document.getElementsByClassName('entrybox')) { - if (el.getAttribute('data-word') != w) { - continue - } - var c = information[el.getAttribute('data-word')].greensrev[el.getAttribute('data-word-offset')] - if (c) { - el.innerText = c - } else { - el.innerText = '' - } - } -}) -document.getElementById('check').addEventListener('click', function(e) { - var guess = consumeInput() - if (guess == null) { - return; - } - var guessIdx = guesses.length; - guesses.push(guess) - var scores = scoreLine(guess, challenge.line) - var linehtml = renderLine(challenge.line, guess, guessIdx, scores) - guessesEl.innerHTML = linehtml + guessesEl.innerHTML - var win = true; - renderKeyboardLights() +function hasWon(scores) { for (var score of scores) { if (Object.keys(score.yellows).length || Object.keys(score.greys).length) { - win = false; + return false; } } - if (win) { - entryEl.style = 'display: none;' - winGame(challenge) - } -}) + return true; +} function winGame(challenge) { winEl.style = 'display: block;' + document.getElementById('win-idx-box').innerHTML = renderChallengeIdxBox() document.getElementById('btns').style = 'display: none;' document.getElementById('meter').innerText = challenge.meter var collection = challenge.collection ? `${challenge.collection}, ` : "" var ctx = challenge.ctx.replace(/^\n/, '').replace(/\n$/, '').replaceAll(/^(.*)/gm, ' $1') document.getElementById('ctx').innerHTML = ctx + `\n\t${challenge.title}\n\t\t${collection}${challenge.author}` var firstguess = Object.values(guesses[0]).join(' ') - document.getElementById('share').value = `I solved Prosodyle #${getChallengeIdx()+1} at cyfraeviolae.org/prosodyle. My first guess was: "${firstguess}."` + document.getElementById('share').value = `I solved Prosodyle #${challengeIdx+1} at cyfraeviolae.org/prosodyle. My first guess was: "${firstguess}."` } function keyHandler(key) { @@ -314,16 +277,6 @@ function getChallengeIdx() { return Math.min(idx, challenges.length-1) } -function getDailyChallenge() { - return challenges[getChallengeIdx()] -} - -document.getElementById('copy').addEventListener('click', function(e) { - e.preventDefault(); - document.getElementById('share').select() - document.execCommand('copy'); -}) - function focus(el) { focused = parseInt(el.getAttribute('data-offset')) el.classList.add('focus') @@ -335,8 +288,154 @@ function unfocus(el) { } +function renderLevels() { + var s = ''; + console.log('ok') + for (var idx in challenges) { + console.log(idx) + var challenge = challenges[idx] + s += `
  1. ${challenge.meter}` + var stored = localStorage.getItem("challenge" + idx) + console.log(stored) + if (stored) { + var store = JSON.parse(stored) + guesses = store.guesses + information = store.information + if (guesses.length) { + if (hasWon(scoreLine(guesses[guesses.length - 1], challenge.line))) { + s += ' · ' + s += challenge.author + s += ' · ' + if (challenge.renderLine) { + s += '' + challenge.renderLine + '' + } else { + s += '' + challenge.line.join(' ') + '' + } + } + } + } + s += '
  2. ' + } + return s +} + +var levelsEl = document.getElementById('levels') +var isLevelSelect = !!levelsEl + + var guesses = [] var information = {} -var challenge = getDailyChallenge() -entryEl.innerHTML = renderLine(challenge.line) -focus(document.querySelector(`[data-offset="0"]`)); + +if (isLevelSelect) { + levelsEl.innerHTML = renderLevels() +} else { + var entryEl = document.getElementById("entry") + var guessesEl = document.getElementById("guesses") + var winEl = document.getElementById("win") + + document.getElementById('copy').addEventListener('click', function(e) { + e.preventDefault(); + document.getElementById('share').select() + document.execCommand('copy'); + }) + + + document.getElementById('clear').onclick = function(e) { + e.preventDefault(); + for (var el of document.getElementsByClassName('entrybox')) { + el.innerText = '' + } + unfocus(document.querySelector(`[data-offset="${focused}"]`)); + focus(document.querySelector(`[data-offset="0"]`)) + } + + Array.from(document.getElementsByClassName('reset-level')).forEach(function(element) { + element.addEventListener('click', function(e) { + e.preventDefault(); + if (window.confirm("Are you sure you want to reset this level? All data will be permanently lost.")) { + var stored = localStorage.removeItem("challenge" + challengeIdx) + location.reload(); + } + }); + }); + + document.getElementById('fill-green').addEventListener('click', function(e) { + e.preventDefault(); + var el = document.querySelector(`[data-offset="${focused}"]`) + if (!el) { + return + } + var w = el.getAttribute('data-word') + for (var el of document.getElementsByClassName('entrybox')) { + if (el.getAttribute('data-word') != w) { + continue + } + var c = information[el.getAttribute('data-word')].greensrev[el.getAttribute('data-word-offset')] + if (c) { + el.innerText = c + } else { + el.innerText = '' + } + } + }) + + document.getElementById('check').addEventListener('click', function(e) { + var guess = consumeInput() + if (guess == null) { + return; + } + var guessIdx = guesses.length; + guesses.push(guess) + var scores = scoreLine(guess, challenge.line) + + localStorage.setItem("challenge" + challengeIdx, JSON.stringify({guesses: guesses, information: information})) + + var linehtml = renderLine(challenge.line, guess, guessIdx, scores) + guessesEl.innerHTML = linehtml + guessesEl.innerHTML + renderKeyboardLights() + var win = hasWon(scores) + if (win) { + entryEl.style = 'display: none;' + winGame(challenge) + } + }) + + var urlParams = new URLSearchParams(window.location.search); + var challengeRequest = urlParams.get('challenge'); + var challenge; + var challengeIdx; + if (challengeRequest) { + challengeIdx = Number(challengeRequest) - 1 + } else { + challengeIdx = getChallengeIdx() + } + challenge = challenges[challengeIdx] + entryEl.innerHTML = renderLine(challenge.line) + + var stored = localStorage.getItem("challenge" + challengeIdx) + if (stored) { + var store = JSON.parse(stored) + guesses = store.guesses + information = store.information + + for (var [guessIdx, guess] of guesses.entries()) { + var scores = scoreLine(guess, challenge.line) + var linehtml = renderLine(challenge.line, guess, guessIdx, scores) + guessesEl.innerHTML = linehtml + guessesEl.innerHTML + } + + var win = true; + renderKeyboardLights() + for (var score of scores) { + if (Object.keys(score.yellows).length || Object.keys(score.greys).length) { + win = false; + } + } + if (win) { + entryEl.style = 'display: none;' + winGame(challenge) + } + } + + focus(document.querySelector(`[data-offset="0"]`)); +} diff --git a/static/styles.css b/static/styles.css index c8628cc..ca10d75 100644 --- a/static/styles.css +++ b/static/styles.css @@ -126,6 +126,9 @@ .numbering { background-color: transparent; width: 60px; +} + +.idxbox { cursor: pointer; user-select: none; } -- cgit v1.2.3