diff options
author | cyfraeviolae <cyfraeviolae> | 2022-02-26 17:15:47 -0500 |
---|---|---|
committer | cyfraeviolae <cyfraeviolae> | 2022-02-26 17:15:47 -0500 |
commit | e2f8db4d3d842292e3b021866e3e243b94e92e11 (patch) | |
tree | b5062e50e7696bcc019d1ae85ffff63192897842 | |
parent | 945d31e400b4fa1f8bd7dea745b267d7c7beb0ea (diff) |
kbd hl
-rw-r--r-- | index.html | 97 | ||||
-rw-r--r-- | static/poems.js | 3 | ||||
-rw-r--r-- | static/script.js | 122 | ||||
-rw-r--r-- | static/styles.css | 96 |
4 files changed, 179 insertions, 139 deletions
@@ -18,66 +18,67 @@ <a href="https://cyfraeviolae.org/git/prosodyle">source code</a> </div> <p> - The dithyrambic sorcerer Roseacrucis has breached the Library’s security measures and encrypted its - treasured poetry collections. As our newest acolyte, your task is to decode one secret line of poetry each day. + 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. </p> <p> - For the ransom price of one new line with the same metrical and syllabic structure as today’s secret - line, Roseacrucis will reveal which letters are in the right place 🟩, in the right word but in a different + 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 ⬜. </p> + <p> + Each word is annotated with the number of required syllables and their stress marks. For example, + <span class="scansion">×/</span> indicates that the word has two syllables, the first unstressed and the second + stressed (such as in <em>por-TRAY</em>). + </p> <noscript>Sorry, JavaScript is required to play Prosodyle.</noscript> <br> <form id="game" action="javascript:void(0);" method="none"> - <p> - Write a line of poetry. Syllables in dark boxes should be stressed. - </p> - <br> <div id="entry"></div> <div id="btns"> + <div style="text-align: center;"> + <div class="keyboard"> + <div class="kbrow"> + <div class="key" data-key="Q">Q</div> + <div class="key" data-key="W">W</div> + <div class="key" data-key="E">E</div> + <div class="key" data-key="R">R</div> + <div class="key" data-key="T">T</div> + <div class="key" data-key="Y">Y</div> + <div class="key" data-key="U">U</div> + <div class="key" data-key="I">I</div> + <div class="key" data-key="O">O</div> + <div class="key" data-key="P">P</div> + </div> + <div class="kbrow"> + <div class="key" data-key="A">A</div> + <div class="key" data-key="S">S</div> + <div class="key" data-key="D">D</div> + <div class="key" data-key="F">F</div> + <div class="key" data-key="G">G</div> + <div class="key" data-key="H">H</div> + <div class="key" data-key="J">J</div> + <div class="key" data-key="K">K</div> + <div class="key" data-key="L">L</div> + <div class="key" data-key="Backspace">⇤</div> + </div> + <div class="kbrow"> + <div class="key" data-key="Z">Z</div> + <div class="key" data-key="X">X</div> + <div class="key" data-key="C">C</div> + <div class="key" data-key="V">V</div> + <div class="key" data-key="B">B</div> + <div class="key" data-key="N">N</div> + <div class="key" data-key="M">M</div> + <div class="key" data-key="ArrowLeft">←</div> + <div class="key" data-key="ArrowRight">→</div> + </div> + </div> + </div> <button id="check" type="submit">Check</button> <button id="clear">Clear</button> </div> - <br> - <div style="text-align: center;"> - <div class="keyboard"> - <div class="kbrow"> - <div class="key" data-key="Q">Q</div> - <div class="key" data-key="W">W</div> - <div class="key" data-key="E">E</div> - <div class="key" data-key="R">R</div> - <div class="key" data-key="T">T</div> - <div class="key" data-key="Y">Y</div> - <div class="key" data-key="U">U</div> - <div class="key" data-key="I">I</div> - <div class="key" data-key="O">O</div> - <div class="key" data-key="P">P</div> - </div> - <div class="kbrow"> - <div class="key" data-key="A">A</div> - <div class="key" data-key="S">S</div> - <div class="key" data-key="D">D</div> - <div class="key" data-key="F">F</div> - <div class="key" data-key="G">G</div> - <div class="key" data-key="H">H</div> - <div class="key" data-key="J">J</div> - <div class="key" data-key="K">K</div> - <div class="key" data-key="L">L</div> - <div class="key" data-key="Backspace">⇤</div> - </div> - <div class="kbrow"> - <div class="key" data-key="Z">Z</div> - <div class="key" data-key="X">X</div> - <div class="key" data-key="C">C</div> - <div class="key" data-key="V">V</div> - <div class="key" data-key="B">B</div> - <div class="key" data-key="N">N</div> - <div class="key" data-key="M">M</div> - <div class="key" data-key="ArrowLeft">←</div> - <div class="key" data-key="ArrowRight">→</div> - </div> - </div> - </div> <hr> <div id="win" style="display: none;"> <p> diff --git a/static/poems.js b/static/poems.js index 89e8701..26ec581 100644 --- a/static/poems.js +++ b/static/poems.js @@ -1,6 +1,7 @@ var challenges = [ { - "line": [["A"], ["/pre", "sence"], ["/that"], ["dis", "/turbs"], ["me"], ["/with"], ["the"], ["/joy"]], + "line": ["A", "presence", "that", "disturbs", "me", "with", "the", "joy"], + "scansion": ["x", "/x", "/", "x/", "x", "/", "x", "/"], "title": "Lines written a few miles above Tintern Abbey", "collection": "Lyrical Ballads", "author": "William Wordsworth", diff --git a/static/script.js b/static/script.js index 7ed08db..caea216 100644 --- a/static/script.js +++ b/static/script.js @@ -4,40 +4,39 @@ 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) { + if (c == '/') { + s += '/' + } else { + s += '×' + } + } + return s; +} + function renderWord(word, wordIdx, guess, score, offset) { var els = [] - var c = 0; - for (var syllable of word) { - var sylEls = [] - - var shouldStress = syllable[0] == "/"; - if (shouldStress) { - syllable = syllable.slice(1) - } - var stress = shouldStress ? "stress" : "" - for (var _ in syllable) { - var charclass = '' - var able = '' - if (score) { - if (score.greens[c]) { - charclass += 'green' - } else if (score.yellows[c]) { - charclass += 'yellow' - } else if (score.greys[c]) { - charclass += 'grey' - } - able = 'disabled' + for (var c in word) { + c = parseInt(c) + var charclass = '' + if (score) { + if (score.greens[c]) { + charclass += 'green' + } else if (score.yellows[c]) { + charclass += 'yellow' + } else if (score.greys[c]) { + charclass += 'grey' } - var val = guess ? guess[wordIdx][c] : '' - var typ = guess ? 'solbox' : 'entrybox' - sylEls.push(`<div data-word="${wordIdx}" data-character="${c}" data-offset="${c+offset}" class="box ${typ} ${charclass}">${val}</div>`) - c++; } - - els.push(`<div class="syllable ` + stress + `">` + sylEls.join('') + `</div>`) + var val = guess ? guess[wordIdx][c] : '' + var typ = guess ? 'solbox' : 'entrybox' + els.push(`<div data-word="${wordIdx}" data-offset="${c+offset}" class="box ${typ} ${charclass}">${val}</div>`) } - - return `<div class="word">` + els.join('') + `</div>` + var scansion = renderScansion(challenge.scansion[wordIdx]) + var scansionBox = guess ? '' : `<div class="scansion-box"><span class="scansion">${scansion}</span></div>` + return `<div class="word">${scansionBox}${els.join('')}</div>` } function renderLine(line, guess, scores) { @@ -46,7 +45,7 @@ function renderLine(line, guess, scores) { for (var wordIdx in line) { var word = line[wordIdx] els.push(renderWord(word, wordIdx, guess, scores && scores[wordIdx], offset)) - offset += word.join('').replaceAll('/', '').length + offset += word.length } return `<div class="line">` + els.join('') + `</div>` } @@ -60,9 +59,9 @@ function consumeInput() { } els.sort((x, y) => { var xword = x.getAttribute('data-word') - var xchar = x.getAttribute('data-character') + var xchar = x.getAttribute('data-offset') var yword = y.getAttribute('data-word') - var ychar = y.getAttribute('data-character') + var ychar = y.getAttribute('data-offset') if (xword != yword) { return xword - yword; @@ -81,8 +80,21 @@ function scoreLine(guess, answer) { var scores = [] for (var idx in guess) { var guessword = guess[idx] - var answerword = answer[idx].join('').replaceAll('/', '').toUpperCase() - scores.push(scoreWord(guessword, answerword)) + var answerword = answer[idx].toUpperCase() + var score = scoreWord(guessword, answerword) + scores.push(score) + if (!information[idx]) { + information[idx] = {greens:{}, yellows:{}, greys:{}} + } + for (var i in score.greens) { + information[idx].greens[guessword[i]] = 1 + } + for (var i in score.yellows) { + information[idx].yellows[guessword[i]] = 1 + } + for (var i in score.greys) { + information[idx].greys[guessword[i]] = 1 + } } return scores } @@ -114,6 +126,37 @@ function scoreWord(guess, answer) { return {greens: greens, yellows: yellows, greys: greys} } +function renderKeyboardLights() { + for (var kel of document.getElementsByClassName('key')) { + kel.classList.remove('yellowkey') + kel.classList.remove('greenkey') + kel.classList.remove('greykey') + } + var el = document.querySelector(`[data-offset="${focused}"]`); + if (!el) { + return + } + var info = information[el.getAttribute('data-word')] + if (!info) { + return + } + for (var kel of document.getElementsByClassName('key')) { + if (info.greens[kel.getAttribute('data-key')]) { + kel.classList.remove('greykey') + kel.classList.remove('yellowkey') + kel.classList.add('greenkey') + } else if (info.yellows[kel.getAttribute('data-key')]) { + kel.classList.remove('greykey') + kel.classList.remove('greenkey') + kel.classList.add('yellowkey') + } else if (info.greys[kel.getAttribute('data-key')]) { + kel.classList.remove('yellowkey') + kel.classList.remove('greenkey') + kel.classList.add('greykey') + } + } +} + var focused = null; document.getElementById('clear').onclick = function(e) { @@ -135,6 +178,7 @@ document.getElementById('check').addEventListener('click', function(e) { var linehtml = renderLine(challenge.line, guess, 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; @@ -182,12 +226,6 @@ function keyHandler(key) { } document.addEventListener('keydown', function(e) { - // if (!Array.from(e.target.classList).includes('entrybox')) { - // return; - // } - // if (e.ctrlKey || e.altKey || (e.key.length != 1 && e.key != 'Backspace')) { - // return; - // } if (e.ctrlKey || e.altKey || (!"ABCDEFGHIJKLMNOPQRSTUVWXYZ".includes(e.key.toUpperCase()) && e.key != 'Backspace' && e.key != 'Enter' && e.key != 'ArrowLeft' && e.key != 'ArrowRight')) { return; } @@ -211,7 +249,7 @@ document.addEventListener('mousedown', function(e) { }) function getDailyChallenge() { - // https://stackoverflow.com/a/8619946 + // begin snippet from https://stackoverflow.com/a/8619946 var now = new Date(); var start = new Date(now.getFullYear(), 0, 0); var diff = now - start; @@ -230,6 +268,7 @@ document.getElementById('copy').addEventListener('click', function(e) { function focus(el) { focused = parseInt(el.getAttribute('data-offset')) el.classList.add('focus') + renderKeyboardLights() } function unfocus(el) { @@ -238,6 +277,7 @@ function unfocus(el) { var guesses = [] +var information = {} var challenge = getDailyChallenge() entryEl.innerHTML = renderLine(challenge.line) focus(document.querySelector(`[data-offset="0"]`)); diff --git a/static/styles.css b/static/styles.css index 14d27d0..11a4cbb 100644 --- a/static/styles.css +++ b/static/styles.css @@ -1,85 +1,54 @@ -button { - margin-right: 10px; -} - .box { display: inline-block; - width: 25px; - height: 25px; + width: 30px; + height: 30px; text-align: center; font-weight: bold; - font-size: 14px; - border: 2px lightgrey solid; + font-size: 18px; + border: 1px DarkSlateGrey solid; margin-right: 0px; margin-left: 0px; color: black; background-color: white; vertical-align: top; - line-height: 25px; + line-height: 29px; font-family: Cantarell; } .focus { - background-color: #fff079; + background-color: #ffda00 } -.syllable .box:not(:first-child) { +.word :not(:first-child) { margin-left: -1px; - border-left-style: dotted; } -.syllable .box:not(:last-child) { +.word :not(:last-child) { margin-right: -1px; - border-right-style: dotted; -} - -.word .syllable:not(:first-child) { - margin-left: -1px; -} - -.word .syllable:not(:last-child) { - margin-right: -1px; -} - -.syllable.stress + .syllable .entrybox:first-child { - border-left-color: darkslategrey; -} - -.stress { - z-index: 9999; } -.syllable { - display: inline-block; -} -.syllable-sep { - display: inline-block; - font-size: 30px; - margin: 1px; -} .word { display: inline-block; - margin-right: 40px; + margin-right: 20px; margin-bottom: 5px; } + .line { margin-bottom: 15px; } -.stress>.entrybox { - border-color: darkslategrey; -} - .green { background-color: rgb(106, 170, 100); color: white; border-color: rgb(106, 170, 100); } + .yellow { background-color: rgb(201, 180, 88); color: white; border-color: rgb(201,180,88); } + .grey { background-color: rgb(120, 124, 126); color: white; @@ -113,11 +82,6 @@ hr { } @media only screen and (min-width: 600px) { - .keyboard { - border: 1px darkslategrey dotted; - border-radius: 4px; - padding: 1.2em; - } form { border: 1px DarkSlateGrey solid; padding: 1em; @@ -136,8 +100,42 @@ hr { height: 35px; width: 26px; border-radius: 4px; - border: 1px black solid; + border: 1px black dotted; line-height: 33px; cursor: pointer; user-select: none; } +.key:hover{ + border-style:solid; +} + +.greenkey { + background-color: rgb(106, 170, 100); + color: white; + border-color: rgb(106, 170, 100); +} + +.yellowkey { + background-color: rgb(201, 180, 88); + color: white; + border-color: rgb(201,180,88); +} + +.greykey { + background-color: rgb(120, 124, 126); + color: white; + border-color: rgb(120,124,126); +} +} + +/* .key:hover { */ +/* background-color: #f7edd6; */ +/* } */ + +.scansion { + font-size: 90%; +} + +.scansion-box { + margin-bottom: .3em; +} |