diff --git a/client/multiplayer/room.html b/client/multiplayer/room.html index 5bdad285..ab18acdd 100644 --- a/client/multiplayer/room.html +++ b/client/multiplayer/room.html @@ -178,6 +178,8 @@

+ +
View more settings here.
diff --git a/client/multiplayer/room.jsx b/client/multiplayer/room.jsx index 428b3b75..5c33afe8 100644 --- a/client/multiplayer/room.jsx +++ b/client/multiplayer/room.jsx @@ -1,5 +1,3 @@ -/* globals WebSocket */ - import account from '../scripts/accounts.js'; import questionStats from '../scripts/auth/question-stats.js'; import api from '../scripts/api/index.js'; @@ -26,7 +24,7 @@ let tossup = {}; let USER_ID = window.localStorage.getItem('USER_ID') || 'unknown'; let username = window.localStorage.getItem('multiplayer-username') || api.getRandomName(); -const socket = new WebSocket( +const socket = new window.WebSocket( window.location.href.replace('http', 'ws') + (window.location.href.endsWith('?private=true') ? '&' : '?') + new URLSearchParams({ @@ -74,6 +72,7 @@ socket.onmessage = function (event) { case 'set-difficulties': return setDifficulties(data); case 'set-reading-speed': return setReadingSpeed(data); case 'set-packet-numbers': return setPacketNumbers(data); + case 'set-strictness': return setStrictness(data); case 'set-set-name': return setSetName(data); case 'set-username': return setUsername(data); case 'set-year-range': return setYearRange(data); @@ -207,6 +206,8 @@ function connectionAcknowledged ({ document.getElementById('reading-speed').value = settings.readingSpeed; document.getElementById('reading-speed-display').textContent = settings.readingSpeed; + document.getElementById('strictness').value = settings.strictness; + document.getElementById('strictness-display').textContent = settings.strictness; document.getElementById('toggle-rebuzz').checked = settings.rebuzz; @@ -574,6 +575,12 @@ function setReadingSpeed ({ username, readingSpeed }) { document.getElementById('reading-speed-display').textContent = readingSpeed; } +function setStrictness ({ strictness, username }) { + logEvent(username, `changed the strictness to ${strictness}`); + document.getElementById('strictness').value = strictness; + document.getElementById('strictness-display').textContent = strictness; +} + function setSetName ({ username, setName }) { logEvent(username, setName.length > 0 ? `changed set name to ${setName}` : 'cleared set name'); document.getElementById('set-name').value = setName; @@ -858,6 +865,15 @@ document.getElementById('set-name').addEventListener('change', async function () })); }); +document.getElementById('strictness').addEventListener('change', function () { + this.blur(); + socket.send(JSON.stringify({ type: 'set-strictness', strictness: this.value })); +}); + +document.getElementById('strictness').addEventListener('input', function () { + document.getElementById('strictness-display').textContent = this.value; +}); + document.getElementById('toggle-lock').addEventListener('click', function () { this.blur(); socket.send(JSON.stringify({ type: 'toggle-lock', lock: this.checked })); diff --git a/client/multiplayer/room.min.js b/client/multiplayer/room.min.js index f6621d41..96de647b 100644 --- a/client/multiplayer/room.min.js +++ b/client/multiplayer/room.min.js @@ -1,8 +1,8 @@ -/* globals WebSocket */import account from"../scripts/accounts.js";import questionStats from"../scripts/auth/question-stats.js";import api from"../scripts/api/index.js";import audio from"../audio/index.js";import CategoryManager from"../../quizbowl/category-manager.js";import{getDropdownValues}from"../scripts/utilities/dropdown-checklist.js";import{arrayToRange,createTossupCard,rangeToArray}from"../scripts/utilities/index.js";import{escapeHTML}from"../scripts/utilities/strings.js";import CategoryModal from"../scripts/components/CategoryModal.min.js";import DifficultyDropdown from"../scripts/components/DifficultyDropdown.min.js";const categoryManager=new CategoryManager;let oldCategories=JSON.stringify(categoryManager.export()),maxPacketNumber=24;/** +import account from"../scripts/accounts.js";import questionStats from"../scripts/auth/question-stats.js";import api from"../scripts/api/index.js";import audio from"../audio/index.js";import CategoryManager from"../../quizbowl/category-manager.js";import{getDropdownValues}from"../scripts/utilities/dropdown-checklist.js";import{arrayToRange,createTossupCard,rangeToArray}from"../scripts/utilities/index.js";import{escapeHTML}from"../scripts/utilities/strings.js";import CategoryModal from"../scripts/components/CategoryModal.min.js";import DifficultyDropdown from"../scripts/components/DifficultyDropdown.min.js";const categoryManager=new CategoryManager;let oldCategories=JSON.stringify(categoryManager.export()),maxPacketNumber=24;/** * userId to player object - */const players={},ROOM_NAME=decodeURIComponent(window.location.pathname.substring(13));let tossup={},USER_ID=window.localStorage.getItem("USER_ID")||"unknown",username=window.localStorage.getItem("multiplayer-username")||api.getRandomName();const socket=new WebSocket(window.location.href.replace("http","ws")+(window.location.href.endsWith("?private=true")?"&":"?")+new URLSearchParams({roomName:ROOM_NAME,userId:USER_ID,username}).toString()),PING_INTERVAL_ID=setInterval(()=>socket.send(JSON.stringify({type:"ping"})),45e3);// Ping server every 45 seconds to prevent socket disconnection -socket.onclose=function(a){const{code:b}=a;3e3!==b&&window.alert("Disconnected from server"),clearInterval(PING_INTERVAL_ID)},socket.onmessage=function(a){const b=JSON.parse(a.data);switch(b.type){case"buzz":return buzz(b);case"force-username":return forceUsername(b);case"chat":return chat(b,!1);case"chat-live-update":return chat(b,!0);case"clear-stats":return clearStats(b);case"connection-acknowledged":return connectionAcknowledged(b);case"connection-acknowledged-query":return connectionAcknowledgedQuery(b);case"connection-acknowledged-tossup":return connectionAcknowledgedTossup(b);case"end-of-set":return endOfSet(b);case"error":return handleError(b);case"give-answer":return giveAnswer(b);case"give-answer-live-update":return logGiveAnswer(b,!0);case"join":return join(b);case"leave":return leave(b);case"lost-buzzer-race":return lostBuzzerRace(b);case"next":return next(b);case"no-questions-found":return noQuestionsFound(b);case"pause":return pause(b);case"reveal-answer":return revealAnswer(b);case"set-categories":return setCategories(b);case"set-difficulties":return setDifficulties(b);case"set-reading-speed":return setReadingSpeed(b);case"set-packet-numbers":return setPacketNumbers(b);case"set-set-name":return setSetName(b);case"set-username":return setUsername(b);case"set-year-range":return setYearRange(b);case"skip":return next(b);case"start":return next(b);case"timer-update":return updateTimerDisplay(b.timeRemaining);case"toggle-lock":return toggleLock(b);case"toggle-login-required":return toggleLoginRequired(b);case"toggle-powermark-only":return togglePowermarkOnly(b);case"toggle-public":return togglePublic(b);case"toggle-rebuzz":return toggleRebuzz(b);case"toggle-select-by-set-name":return toggleSelectBySetName(b);case"toggle-skip":return toggleSkip(b);case"toggle-standard-only":return toggleStandardOnly(b);case"toggle-timer":return toggleTimer(b);case"update-question":return updateQuestion(b)}};function buzz({userId:a,username:b}){logEvent(b,"buzzed"),document.getElementById("buzz").disabled=!0,document.getElementById("pause").disabled=!0,document.getElementById("next").disabled=!0,document.getElementById("skip").disabled=!0,a===USER_ID&&(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus())}function chat({message:a,userId:c,username:d},e=!1){if(!e&&""===a)return void document.getElementById("live-chat-"+c).parentElement.remove();if(!e&&a)return document.getElementById("live-chat-"+c).className="",void(document.getElementById("live-chat-"+c).id="");if(document.getElementById("live-chat-"+c))return void(document.getElementById("live-chat-"+c).textContent=a);const f=document.createElement("b");f.textContent=d;const b=document.createElement("span");b.classList.add("text-muted"),b.id="live-chat-"+c,b.textContent=a;const g=document.createElement("li");g.appendChild(f),g.appendChild(document.createTextNode(" ")),g.appendChild(b),document.getElementById("room-history").prepend(g)}function clearStats({userId:a}){for(const b of["celerity","negs","points","powers","tens","tuh","zeroes"])players[a][b]=0;upsertPlayerItem(players[a]),sortPlayerListGroup()}function connectionAcknowledged({buzzedIn:a,canBuzz:b,isPermanent:c,players:d,questionProgress:e,settings:f,userId:g}){document.getElementById("buzz").disabled=!b,c&&(document.getElementById("category-select-button").disabled=!0,document.getElementById("toggle-public").disabled=!0,document.getElementById("toggle-select-by-set-name").disabled=!0,document.getElementById("private-chat-warning").innerHTML="This is a permanent room. Some settings have been restricted."),Object.keys(d).forEach(a=>{d[a].celerity=d[a].celerity.correct.average,players[a]=d[a],upsertPlayerItem(players[a])}),sortPlayerListGroup();0===e?(document.getElementById("next").textContent="Start",document.getElementById("next").classList.remove("btn-primary"),document.getElementById("next").classList.add("btn-success")):1===e?(showSkipButton(),document.getElementById("settings").classList.add("d-none"),a?(document.getElementById("buzz").disabled=!0,document.getElementById("next").disabled=!0,document.getElementById("pause").disabled=!0):(document.getElementById("buzz").disabled=!1,document.getElementById("pause").disabled=!1)):2===e?(showNextButton(),document.getElementById("settings").classList.add("d-none")):void 0;document.getElementById("toggle-lock").checked=f.lock,document.getElementById("toggle-login-required").checked=f.loginRequired,document.getElementById("chat").disabled=f.public,document.getElementById("toggle-lock").disabled=f.public,document.getElementById("toggle-login-required").disabled=f.public,document.getElementById("toggle-timer").disabled=f.public,document.getElementById("toggle-public").checked=f.public,document.getElementById("reading-speed").value=f.readingSpeed,document.getElementById("reading-speed-display").textContent=f.readingSpeed,document.getElementById("toggle-rebuzz").checked=f.rebuzz,document.getElementById("toggle-skip").checked=f.skip,document.getElementById("timer").classList.toggle("d-none",!f.timer),document.getElementById("toggle-timer").checked=f.timer,USER_ID=g,window.localStorage.setItem("USER_ID",USER_ID)}async function connectionAcknowledgedQuery({difficulties:i=[],minYear:a,maxYear:b,packetNumbers:j=[],powermarkOnly:c,selectBySetName:d,setName:k="",standardOnly:e,validAlternateSubcategories:f,validCategories:g,validSubcategories:h}){setDifficulties({difficulties:i}),$("#slider").slider("values",0,a),$("#slider").slider("values",1,b),document.getElementById("year-range-a").textContent=a,document.getElementById("year-range-b").textContent=b,document.getElementById("packet-number").value=arrayToRange(j),document.getElementById("toggle-powermark-only").checked=c,document.getElementById("difficulty-settings").classList.toggle("d-none",d),document.getElementById("set-settings").classList.toggle("d-none",!d),document.getElementById("toggle-select-by-set-name").checked=d,document.getElementById("toggle-powermark-only").disabled=d,document.getElementById("toggle-standard-only").disabled=d,document.getElementById("set-name").value=k,maxPacketNumber=await api.getNumPackets(k),""!==k&&0===maxPacketNumber&&document.getElementById("set-name").classList.add("is-invalid"),document.getElementById("toggle-standard-only").checked=e,categoryManager.import(g,h,f),categoryManager.loadCategoryModal()}function connectionAcknowledgedTossup({tossup:a}){tossup=a,document.getElementById("set-name-info").textContent=tossup?.set?.name??"",document.getElementById("packet-number-info").textContent=tossup?.packet?.number??"-",document.getElementById("question-number-info").textContent=tossup?.number??"-"}function endOfSet(){window.alert("You have reached the end of the set")}function forceUsername({message:a,username:b}){window.alert(a),window.localStorage.setItem("multiplayer-username",b),document.querySelector("#username").value=b}async function giveAnswer({celerity:a,directive:b,directedPrompt:c,givenAnswer:d,perQuestionCelerity:e,score:f,tossup:g,userId:h,username:i}){document.getElementById("answer-input").value="",document.getElementById("answer-input-group").classList.add("d-none"),document.getElementById("answer-input").blur(),logGiveAnswer({directive:b,message:d,username:i}),"prompt"===b&&c?logEvent(i,`was prompted with "${c}"`):"prompt"===b?logEvent(i,"was prompted"):logEvent(i,`${0{a.textContent=parseInt(a.innerHTML)+1})),"reject"===b&&(document.getElementById("buzz").disabled=!document.getElementById("toggle-rebuzz").checked&&h===USER_ID),10f&&players[h].negs++,players[h].points+=f,players[h].tuh++,players[h].celerity=a,upsertPlayerItem(players[h]),sortPlayerListGroup()),"prompt"!==b&&h===USER_ID&&(await account.getUsername())&&questionStats.recordTossup(g,0{const b=parseInt(document.getElementById("points-"+d.id.substring(f)).innerHTML),e=parseInt(document.getElementById("points-"+a.id.substring(f)).innerHTML);// if points are equal, sort alphabetically by username -if(b===e){const b=document.getElementById("username-"+d.id.substring(f)).innerHTML,e=document.getElementById("username-"+a.id.substring(f)).innerHTML;return c?b.localeCompare(e):e.localeCompare(b)}return c?e-b:b-e}).forEach(a=>{d.appendChild(a)})}function setCategories({alternateSubcategories:a,categories:b,subcategories:c,username:d}){logEvent(d,"updated the categories"),categoryManager.import(b,c,a),categoryManager.loadCategoryModal()}function setDifficulties({difficulties:a,username:b=void 0}){b&&logEvent(b,0{const c=b.querySelector("input");a.includes(parseInt(c.value))?(c.checked=!0,b.classList.add("active")):(c.checked=!1,b.classList.remove("active"))})}function setPacketNumbers({username:a,packetNumbers:b}){b=arrayToRange(b),logEvent(a,0socket.send(JSON.stringify({type:"ping"})),45e3);// Ping server every 45 seconds to prevent socket disconnection +socket.onclose=function(a){const{code:b}=a;3e3!==b&&window.alert("Disconnected from server"),clearInterval(PING_INTERVAL_ID)},socket.onmessage=function(a){const b=JSON.parse(a.data);switch(b.type){case"buzz":return buzz(b);case"force-username":return forceUsername(b);case"chat":return chat(b,!1);case"chat-live-update":return chat(b,!0);case"clear-stats":return clearStats(b);case"connection-acknowledged":return connectionAcknowledged(b);case"connection-acknowledged-query":return connectionAcknowledgedQuery(b);case"connection-acknowledged-tossup":return connectionAcknowledgedTossup(b);case"end-of-set":return endOfSet(b);case"error":return handleError(b);case"give-answer":return giveAnswer(b);case"give-answer-live-update":return logGiveAnswer(b,!0);case"join":return join(b);case"leave":return leave(b);case"lost-buzzer-race":return lostBuzzerRace(b);case"next":return next(b);case"no-questions-found":return noQuestionsFound(b);case"pause":return pause(b);case"reveal-answer":return revealAnswer(b);case"set-categories":return setCategories(b);case"set-difficulties":return setDifficulties(b);case"set-reading-speed":return setReadingSpeed(b);case"set-packet-numbers":return setPacketNumbers(b);case"set-strictness":return setStrictness(b);case"set-set-name":return setSetName(b);case"set-username":return setUsername(b);case"set-year-range":return setYearRange(b);case"skip":return next(b);case"start":return next(b);case"timer-update":return updateTimerDisplay(b.timeRemaining);case"toggle-lock":return toggleLock(b);case"toggle-login-required":return toggleLoginRequired(b);case"toggle-powermark-only":return togglePowermarkOnly(b);case"toggle-public":return togglePublic(b);case"toggle-rebuzz":return toggleRebuzz(b);case"toggle-select-by-set-name":return toggleSelectBySetName(b);case"toggle-skip":return toggleSkip(b);case"toggle-standard-only":return toggleStandardOnly(b);case"toggle-timer":return toggleTimer(b);case"update-question":return updateQuestion(b)}};function buzz({userId:a,username:b}){logEvent(b,"buzzed"),document.getElementById("buzz").disabled=!0,document.getElementById("pause").disabled=!0,document.getElementById("next").disabled=!0,document.getElementById("skip").disabled=!0,a===USER_ID&&(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus())}function chat({message:a,userId:c,username:d},e=!1){if(!e&&""===a)return void document.getElementById("live-chat-"+c).parentElement.remove();if(!e&&a)return document.getElementById("live-chat-"+c).className="",void(document.getElementById("live-chat-"+c).id="");if(document.getElementById("live-chat-"+c))return void(document.getElementById("live-chat-"+c).textContent=a);const f=document.createElement("b");f.textContent=d;const b=document.createElement("span");b.classList.add("text-muted"),b.id="live-chat-"+c,b.textContent=a;const g=document.createElement("li");g.appendChild(f),g.appendChild(document.createTextNode(" ")),g.appendChild(b),document.getElementById("room-history").prepend(g)}function clearStats({userId:a}){for(const b of["celerity","negs","points","powers","tens","tuh","zeroes"])players[a][b]=0;upsertPlayerItem(players[a]),sortPlayerListGroup()}function connectionAcknowledged({buzzedIn:a,canBuzz:b,isPermanent:c,players:d,questionProgress:e,settings:f,userId:g}){document.getElementById("buzz").disabled=!b,c&&(document.getElementById("category-select-button").disabled=!0,document.getElementById("toggle-public").disabled=!0,document.getElementById("toggle-select-by-set-name").disabled=!0,document.getElementById("private-chat-warning").innerHTML="This is a permanent room. Some settings have been restricted."),Object.keys(d).forEach(a=>{d[a].celerity=d[a].celerity.correct.average,players[a]=d[a],upsertPlayerItem(players[a])}),sortPlayerListGroup();0===e?(document.getElementById("next").textContent="Start",document.getElementById("next").classList.remove("btn-primary"),document.getElementById("next").classList.add("btn-success")):1===e?(showSkipButton(),document.getElementById("settings").classList.add("d-none"),a?(document.getElementById("buzz").disabled=!0,document.getElementById("next").disabled=!0,document.getElementById("pause").disabled=!0):(document.getElementById("buzz").disabled=!1,document.getElementById("pause").disabled=!1)):2===e?(showNextButton(),document.getElementById("settings").classList.add("d-none")):void 0;document.getElementById("toggle-lock").checked=f.lock,document.getElementById("toggle-login-required").checked=f.loginRequired,document.getElementById("chat").disabled=f.public,document.getElementById("toggle-lock").disabled=f.public,document.getElementById("toggle-login-required").disabled=f.public,document.getElementById("toggle-timer").disabled=f.public,document.getElementById("toggle-public").checked=f.public,document.getElementById("reading-speed").value=f.readingSpeed,document.getElementById("reading-speed-display").textContent=f.readingSpeed,document.getElementById("strictness").value=f.strictness,document.getElementById("strictness-display").textContent=f.strictness,document.getElementById("toggle-rebuzz").checked=f.rebuzz,document.getElementById("toggle-skip").checked=f.skip,document.getElementById("timer").classList.toggle("d-none",!f.timer),document.getElementById("toggle-timer").checked=f.timer,USER_ID=g,window.localStorage.setItem("USER_ID",USER_ID)}async function connectionAcknowledgedQuery({difficulties:i=[],minYear:a,maxYear:b,packetNumbers:j=[],powermarkOnly:c,selectBySetName:d,setName:k="",standardOnly:e,validAlternateSubcategories:f,validCategories:g,validSubcategories:h}){setDifficulties({difficulties:i}),$("#slider").slider("values",0,a),$("#slider").slider("values",1,b),document.getElementById("year-range-a").textContent=a,document.getElementById("year-range-b").textContent=b,document.getElementById("packet-number").value=arrayToRange(j),document.getElementById("toggle-powermark-only").checked=c,document.getElementById("difficulty-settings").classList.toggle("d-none",d),document.getElementById("set-settings").classList.toggle("d-none",!d),document.getElementById("toggle-select-by-set-name").checked=d,document.getElementById("toggle-powermark-only").disabled=d,document.getElementById("toggle-standard-only").disabled=d,document.getElementById("set-name").value=k,maxPacketNumber=await api.getNumPackets(k),""!==k&&0===maxPacketNumber&&document.getElementById("set-name").classList.add("is-invalid"),document.getElementById("toggle-standard-only").checked=e,categoryManager.import(g,h,f),categoryManager.loadCategoryModal()}function connectionAcknowledgedTossup({tossup:a}){tossup=a,document.getElementById("set-name-info").textContent=tossup?.set?.name??"",document.getElementById("packet-number-info").textContent=tossup?.packet?.number??"-",document.getElementById("question-number-info").textContent=tossup?.number??"-"}function endOfSet(){window.alert("You have reached the end of the set")}function forceUsername({message:a,username:b}){window.alert(a),window.localStorage.setItem("multiplayer-username",b),document.querySelector("#username").value=b}async function giveAnswer({celerity:a,directive:b,directedPrompt:c,givenAnswer:d,perQuestionCelerity:e,score:f,tossup:g,userId:h,username:i}){document.getElementById("answer-input").value="",document.getElementById("answer-input-group").classList.add("d-none"),document.getElementById("answer-input").blur(),logGiveAnswer({directive:b,message:d,username:i}),"prompt"===b&&c?logEvent(i,`was prompted with "${c}"`):"prompt"===b?logEvent(i,"was prompted"):logEvent(i,`${0{a.textContent=parseInt(a.innerHTML)+1})),"reject"===b&&(document.getElementById("buzz").disabled=!document.getElementById("toggle-rebuzz").checked&&h===USER_ID),10f&&players[h].negs++,players[h].points+=f,players[h].tuh++,players[h].celerity=a,upsertPlayerItem(players[h]),sortPlayerListGroup()),"prompt"!==b&&h===USER_ID&&(await account.getUsername())&&questionStats.recordTossup(g,0{const b=parseInt(document.getElementById("points-"+d.id.substring(f)).innerHTML),e=parseInt(document.getElementById("points-"+a.id.substring(f)).innerHTML);// if points are equal, sort alphabetically by username +if(b===e){const b=document.getElementById("username-"+d.id.substring(f)).innerHTML,e=document.getElementById("username-"+a.id.substring(f)).innerHTML;return c?b.localeCompare(e):e.localeCompare(b)}return c?e-b:b-e}).forEach(a=>{d.appendChild(a)})}function setCategories({alternateSubcategories:a,categories:b,subcategories:c,username:d}){logEvent(d,"updated the categories"),categoryManager.import(b,c,a),categoryManager.loadCategoryModal()}function setDifficulties({difficulties:a,username:b=void 0}){b&&logEvent(b,0{const c=b.querySelector("input");a.includes(parseInt(c.value))?(c.checked=!0,b.classList.add("active")):(c.checked=!1,b.classList.remove("active"))})}function setPacketNumbers({username:a,packetNumbers:b}){b=arrayToRange(b),logEvent(a,0 @@ -32,4 +32,4 @@ k.className=`list-group-item ${b===USER_ID?"user-score":""} clickable`,k.id=`lis ${j.toFixed(3)} - `),document.getElementById("player-list-group").appendChild(k),new bootstrap.Popover(k)}function setYearRange({minYear:a,maxYear:b,username:c}){c&&logEvent(c,`changed the year range to ${a}-${b}`),$("#slider").slider("values",0,a),$("#slider").slider("values",1,b),document.getElementById("year-range-a").textContent=a,document.getElementById("year-range-b").textContent=b}document.getElementById("answer-form").addEventListener("submit",function(a){a.preventDefault(),a.stopPropagation();const b=document.getElementById("answer-input").value;socket.send(JSON.stringify({type:"give-answer",givenAnswer:b}))}),document.getElementById("answer-input").addEventListener("input",function(){socket.send(JSON.stringify({type:"give-answer-live-update",message:this.value}))}),document.getElementById("buzz").addEventListener("click",function(){this.blur(),audio.soundEffects&&audio.buzz.play(),socket.send(JSON.stringify({type:"buzz"})),socket.send(JSON.stringify({type:"give-answer-live-update",message:""}))}),document.getElementById("chat").addEventListener("click",function(){this.blur(),document.getElementById("chat-input-group").classList.remove("d-none"),document.getElementById("chat-input").focus(),socket.send(JSON.stringify({type:"chat-live-update",message:""}))}),document.getElementById("chat-form").addEventListener("submit",function(a){a.preventDefault(),a.stopPropagation();const b=document.getElementById("chat-input").value;document.getElementById("chat-input").value="",document.getElementById("chat-input-group").classList.add("d-none"),document.getElementById("chat-input").blur(),socket.send(JSON.stringify({type:"chat",message:b}))}),document.getElementById("chat-input").addEventListener("input",function(){socket.send(JSON.stringify({type:"chat-live-update",message:this.value}))}),document.getElementById("clear-stats").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"clear-stats"}))}),document.getElementById("next").addEventListener("click",function(){switch(this.blur(),this.innerHTML){case"Start":socket.send(JSON.stringify({type:"start"}));break;case"Next":socket.send(JSON.stringify({type:"next"}))}}),document.getElementById("skip").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"skip"}))}),document.getElementById("packet-number").addEventListener("change",function(){const a=rangeToArray(this.value,maxPacketNumber);return a.some(a=>1>a||a>maxPacketNumber)?void document.getElementById("packet-number").classList.add("is-invalid"):void(document.getElementById("packet-number").classList.remove("is-invalid"),socket.send(JSON.stringify({type:"set-packet-numbers",packetNumbers:a})))}),document.getElementById("pause").addEventListener("click",function(){this.blur();const a=parseFloat(document.querySelector(".timer .face").innerText),b=parseFloat(document.querySelector(".timer .fraction").innerText);socket.send(JSON.stringify({type:"pause",pausedTime:10*(a+b)}))}),document.getElementById("reading-speed").addEventListener("change",function(){socket.send(JSON.stringify({type:"set-reading-speed",readingSpeed:this.value}))}),document.getElementById("reading-speed").addEventListener("input",function(){document.getElementById("reading-speed-display").textContent=this.value}),document.getElementById("report-question-submit").addEventListener("click",function(){api.reportQuestion(document.getElementById("report-question-id").value,document.getElementById("report-question-reason").value,document.getElementById("report-question-description").value)}),document.getElementById("set-name").addEventListener("change",async function(){api.getSetList().includes(this.value)||0===this.value.length?this.classList.remove("is-invalid"):this.classList.add("is-invalid"),maxPacketNumber=await api.getNumPackets(this.value),document.getElementById("packet-number").value=""===this.value||0===maxPacketNumber?"":`1-${maxPacketNumber}`,socket.send(JSON.stringify({type:"set-set-name",setName:this.value,packetNumbers:rangeToArray(document.getElementById("packet-number").value)}))}),document.getElementById("toggle-lock").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-lock",lock:this.checked}))}),document.getElementById("toggle-login-required").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-login-required",loginRequired:this.checked}))}),document.getElementById("toggle-powermark-only").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-powermark-only",powermarkOnly:this.checked}))}),document.getElementById("toggle-rebuzz").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-rebuzz",rebuzz:this.checked}))}),document.getElementById("toggle-skip").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-skip",skip:this.checked}))}),document.getElementById("toggle-select-by-set-name").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-select-by-set-name",setName:document.getElementById("set-name").value,selectBySetName:this.checked}))}),document.getElementById("toggle-settings").addEventListener("click",function(){this.blur(),document.getElementById("buttons").classList.toggle("col-lg-9"),document.getElementById("buttons").classList.toggle("col-lg-12"),document.getElementById("content").classList.toggle("col-lg-9"),document.getElementById("content").classList.toggle("col-lg-12"),document.getElementById("settings").classList.toggle("d-none"),document.getElementById("settings").classList.toggle("d-lg-none")}),document.getElementById("toggle-standard-only").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-standard-only",standardOnly:this.checked}))}),document.getElementById("toggle-timer").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-timer",timer:this.checked}))}),document.getElementById("toggle-public").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-public",public:this.checked}))}),document.getElementById("username").addEventListener("change",function(){socket.send(JSON.stringify({type:"set-username",userId:USER_ID,username:this.value})),username=this.value,window.localStorage.setItem("multiplayer-username",username)}),document.getElementById("year-range-a").onchange=function(){const[a,b]=$("#slider").slider("values");if(b{oldCategories!==JSON.stringify(categoryManager.export())&&socket.send(JSON.stringify({type:"set-categories",...categoryManager.export()})),oldCategories=JSON.stringify(categoryManager.export())}})),ReactDOM.createRoot(document.getElementById("difficulty-dropdown-root")).render(/*#__PURE__*/React.createElement(DifficultyDropdown,{onChange:()=>socket.send(JSON.stringify({type:"set-difficulties",difficulties:getDropdownValues("difficulties")}))})); \ No newline at end of file + `),document.getElementById("player-list-group").appendChild(k),new bootstrap.Popover(k)}function setYearRange({minYear:a,maxYear:b,username:c}){c&&logEvent(c,`changed the year range to ${a}-${b}`),$("#slider").slider("values",0,a),$("#slider").slider("values",1,b),document.getElementById("year-range-a").textContent=a,document.getElementById("year-range-b").textContent=b}document.getElementById("answer-form").addEventListener("submit",function(a){a.preventDefault(),a.stopPropagation();const b=document.getElementById("answer-input").value;socket.send(JSON.stringify({type:"give-answer",givenAnswer:b}))}),document.getElementById("answer-input").addEventListener("input",function(){socket.send(JSON.stringify({type:"give-answer-live-update",message:this.value}))}),document.getElementById("buzz").addEventListener("click",function(){this.blur(),audio.soundEffects&&audio.buzz.play(),socket.send(JSON.stringify({type:"buzz"})),socket.send(JSON.stringify({type:"give-answer-live-update",message:""}))}),document.getElementById("chat").addEventListener("click",function(){this.blur(),document.getElementById("chat-input-group").classList.remove("d-none"),document.getElementById("chat-input").focus(),socket.send(JSON.stringify({type:"chat-live-update",message:""}))}),document.getElementById("chat-form").addEventListener("submit",function(a){a.preventDefault(),a.stopPropagation();const b=document.getElementById("chat-input").value;document.getElementById("chat-input").value="",document.getElementById("chat-input-group").classList.add("d-none"),document.getElementById("chat-input").blur(),socket.send(JSON.stringify({type:"chat",message:b}))}),document.getElementById("chat-input").addEventListener("input",function(){socket.send(JSON.stringify({type:"chat-live-update",message:this.value}))}),document.getElementById("clear-stats").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"clear-stats"}))}),document.getElementById("next").addEventListener("click",function(){switch(this.blur(),this.innerHTML){case"Start":socket.send(JSON.stringify({type:"start"}));break;case"Next":socket.send(JSON.stringify({type:"next"}))}}),document.getElementById("skip").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"skip"}))}),document.getElementById("packet-number").addEventListener("change",function(){const a=rangeToArray(this.value,maxPacketNumber);return a.some(a=>1>a||a>maxPacketNumber)?void document.getElementById("packet-number").classList.add("is-invalid"):void(document.getElementById("packet-number").classList.remove("is-invalid"),socket.send(JSON.stringify({type:"set-packet-numbers",packetNumbers:a})))}),document.getElementById("pause").addEventListener("click",function(){this.blur();const a=parseFloat(document.querySelector(".timer .face").innerText),b=parseFloat(document.querySelector(".timer .fraction").innerText);socket.send(JSON.stringify({type:"pause",pausedTime:10*(a+b)}))}),document.getElementById("reading-speed").addEventListener("change",function(){socket.send(JSON.stringify({type:"set-reading-speed",readingSpeed:this.value}))}),document.getElementById("reading-speed").addEventListener("input",function(){document.getElementById("reading-speed-display").textContent=this.value}),document.getElementById("report-question-submit").addEventListener("click",function(){api.reportQuestion(document.getElementById("report-question-id").value,document.getElementById("report-question-reason").value,document.getElementById("report-question-description").value)}),document.getElementById("set-name").addEventListener("change",async function(){api.getSetList().includes(this.value)||0===this.value.length?this.classList.remove("is-invalid"):this.classList.add("is-invalid"),maxPacketNumber=await api.getNumPackets(this.value),document.getElementById("packet-number").value=""===this.value||0===maxPacketNumber?"":`1-${maxPacketNumber}`,socket.send(JSON.stringify({type:"set-set-name",setName:this.value,packetNumbers:rangeToArray(document.getElementById("packet-number").value)}))}),document.getElementById("strictness").addEventListener("change",function(){this.blur(),socket.send(JSON.stringify({type:"set-strictness",strictness:this.value}))}),document.getElementById("strictness").addEventListener("input",function(){document.getElementById("strictness-display").textContent=this.value}),document.getElementById("toggle-lock").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-lock",lock:this.checked}))}),document.getElementById("toggle-login-required").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-login-required",loginRequired:this.checked}))}),document.getElementById("toggle-powermark-only").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-powermark-only",powermarkOnly:this.checked}))}),document.getElementById("toggle-rebuzz").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-rebuzz",rebuzz:this.checked}))}),document.getElementById("toggle-skip").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-skip",skip:this.checked}))}),document.getElementById("toggle-select-by-set-name").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-select-by-set-name",setName:document.getElementById("set-name").value,selectBySetName:this.checked}))}),document.getElementById("toggle-settings").addEventListener("click",function(){this.blur(),document.getElementById("buttons").classList.toggle("col-lg-9"),document.getElementById("buttons").classList.toggle("col-lg-12"),document.getElementById("content").classList.toggle("col-lg-9"),document.getElementById("content").classList.toggle("col-lg-12"),document.getElementById("settings").classList.toggle("d-none"),document.getElementById("settings").classList.toggle("d-lg-none")}),document.getElementById("toggle-standard-only").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-standard-only",standardOnly:this.checked}))}),document.getElementById("toggle-timer").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-timer",timer:this.checked}))}),document.getElementById("toggle-public").addEventListener("click",function(){this.blur(),socket.send(JSON.stringify({type:"toggle-public",public:this.checked}))}),document.getElementById("username").addEventListener("change",function(){socket.send(JSON.stringify({type:"set-username",userId:USER_ID,username:this.value})),username=this.value,window.localStorage.setItem("multiplayer-username",username)}),document.getElementById("year-range-a").onchange=function(){const[a,b]=$("#slider").slider("values");if(b{oldCategories!==JSON.stringify(categoryManager.export())&&socket.send(JSON.stringify({type:"set-categories",...categoryManager.export()})),oldCategories=JSON.stringify(categoryManager.export())}})),ReactDOM.createRoot(document.getElementById("difficulty-dropdown-root")).render(/*#__PURE__*/React.createElement(DifficultyDropdown,{onChange:()=>socket.send(JSON.stringify({type:"set-difficulties",difficulties:getDropdownValues("difficulties")}))})); \ No newline at end of file diff --git a/client/scripts/api/index.js b/client/scripts/api/index.js index f3282a94..abb9d92d 100644 --- a/client/scripts/api/index.js +++ b/client/scripts/api/index.js @@ -11,12 +11,12 @@ export default class api { * directedPrompt: String | null * }>} */ - static async checkAnswer (answerline, givenAnswer) { + static async checkAnswer (answerline, givenAnswer, strictness = 7) { if (givenAnswer === '') { return { directive: 'reject', directedPrompt: null }; } - return await fetch('/api/check-answer?' + new URLSearchParams({ answerline, givenAnswer })) + return await fetch('/api/check-answer?' + new URLSearchParams({ answerline, givenAnswer, strictness })) .then(response => response.json()); } diff --git a/client/singleplayer/tossups/index.html b/client/singleplayer/tossups/index.html index 1023b801..85aceaa0 100644 --- a/client/singleplayer/tossups/index.html +++ b/client/singleplayer/tossups/index.html @@ -143,6 +143,8 @@

+ +
View more settings here.
diff --git a/client/singleplayer/tossups/index.jsx b/client/singleplayer/tossups/index.jsx index 1a293faf..5475dc40 100644 --- a/client/singleplayer/tossups/index.jsx +++ b/client/singleplayer/tossups/index.jsx @@ -2,7 +2,6 @@ import account from '../../scripts/accounts.js'; import api from '../../scripts/api/index.js'; import questionStats from '../../scripts/auth/question-stats.js'; import audio from '../../audio/index.js'; -// import Player from '../../../quizbowl/Player.js'; import Player from '../../../quizbowl/Player.js'; import ClientTossupRoom from '../ClientTossupRoom.js'; import CategoryManager from '../../../quizbowl/category-manager.js'; @@ -15,7 +14,7 @@ let maxPacketNumber = 24; const categoryManager = new CategoryManager(); const queryVersion = '2024-10-11'; -const settingsVersion = '2024-10-11'; +const settingsVersion = '2024-10-16'; const USER_ID = 'user'; const room = new ClientTossupRoom(); @@ -40,6 +39,7 @@ function onmessage (message) { case 'reveal-answer': return revealAnswer(data); case 'set-categories': return setCategories(data); case 'set-difficulties': return setDifficulties(data); + case 'set-strictness': return setStrictness(data); case 'set-reading-speed': return setReadingSpeed(data); case 'set-packet-numbers': return setPacketNumbers(data); case 'set-set-name': return setSetName(data); @@ -183,6 +183,12 @@ function setDifficulties ({ difficulties }) { window.localStorage.setItem('singleplayer-tossup-query', JSON.stringify({ ...room.query, version: queryVersion })); } +function setStrictness ({ strictness }) { + document.getElementById('strictness').value = strictness; + document.getElementById('strictness-display').textContent = strictness; + window.localStorage.setItem('singleplayer-tossup-settings', JSON.stringify({ ...room.settings, version: settingsVersion })); +} + function setPacketNumbers ({ packetNumbers }) { document.getElementById('packet-number').value = arrayToRange(packetNumbers); window.localStorage.setItem('singleplayer-tossup-query', JSON.stringify({ ...room.query, version: queryVersion })); @@ -351,6 +357,15 @@ document.getElementById('start').addEventListener('click', function () { socket.sendToServer({ type: 'start' }); }); +document.getElementById('strictness').addEventListener('change', function () { + this.blur(); + socket.sendToServer({ type: 'set-strictness', strictness: this.value }); +}); + +document.getElementById('strictness').addEventListener('input', function () { + document.getElementById('strictness-display').textContent = this.value; +}); + document.getElementById('toggle-correct').addEventListener('click', function () { this.blur(); socket.sendToServer({ type: 'toggle-correct', correct: this.textContent === 'I was right' }); @@ -459,6 +474,7 @@ if (window.localStorage.getItem('singleplayer-tossup-settings')) { try { const savedSettings = JSON.parse(window.localStorage.getItem('singleplayer-tossup-settings')); if (savedSettings.version !== settingsVersion) { throw new Error(); } + socket.sendToServer({ type: 'set-strictness', ...savedSettings }); socket.sendToServer({ type: 'set-reading-speed', ...savedSettings }); socket.sendToServer({ type: 'toggle-rebuzz', ...savedSettings }); socket.sendToServer({ type: 'toggle-show-history', ...savedSettings }); diff --git a/client/singleplayer/tossups/index.min.js b/client/singleplayer/tossups/index.min.js index 59b3b745..b59c42d1 100644 --- a/client/singleplayer/tossups/index.min.js +++ b/client/singleplayer/tossups/index.min.js @@ -1,6 +1,5 @@ -import account from"../../scripts/accounts.js";import api from"../../scripts/api/index.js";import questionStats from"../../scripts/auth/question-stats.js";import audio from"../../audio/index.js";// import Player from '../../../quizbowl/Player.js'; -import Player from"../../../quizbowl/Player.js";import ClientTossupRoom from"../ClientTossupRoom.js";import CategoryManager from"../../../quizbowl/category-manager.js";import{arrayToRange,createTossupCard,rangeToArray}from"../../scripts/utilities/index.js";import{getDropdownValues}from"../../scripts/utilities/dropdown-checklist.js";import CategoryModal from"../../scripts/components/CategoryModal.min.js";import DifficultyDropdown from"../../scripts/components/DifficultyDropdown.min.js";let maxPacketNumber=24;const categoryManager=new CategoryManager,queryVersion="2024-10-11",settingsVersion="2024-10-11",USER_ID="user",room=new ClientTossupRoom;room.players[USER_ID]=new Player(USER_ID);const socket={send:onmessage,sendToServer:a=>room.message(USER_ID,a)};room.sockets[USER_ID]=socket;function onmessage(a){const b=JSON.parse(a);switch(b.type){case"buzz":return buzz(b);case"clear-stats":return clearStats(b);case"end-of-set":return endOfSet(b);case"give-answer":return giveAnswer(b);case"next":return next(b);case"no-questions-found":return noQuestionsFound(b);case"pause":return pause(b);case"reveal-answer":return revealAnswer(b);case"set-categories":return setCategories(b);case"set-difficulties":return setDifficulties(b);case"set-reading-speed":return setReadingSpeed(b);case"set-packet-numbers":return setPacketNumbers(b);case"set-set-name":return setSetName(b);case"set-year-range":return setYearRange(b);case"skip":return next(b);case"start":return next(b);case"timer-update":return updateTimerDisplay(b.timeRemaining);case"toggle-correct":return toggleCorrect(b);case"toggle-powermark-only":return togglePowermarkOnly(b);case"toggle-rebuzz":return toggleRebuzz(b);case"toggle-select-by-set-name":return toggleSelectBySetName(b);case"toggle-show-history":return toggleShowHistory(b);case"toggle-standard-only":return toggleStandardOnly(b);case"toggle-timer":return toggleTimer(b);case"toggle-type-to-answer":return toggleTypeToAnswer(b);case"update-question":return updateQuestion(b)}}function buzz({timer:a,userId:b,username:c}){audio.soundEffects&&audio.buzz.play();const d=document.getElementById("type-to-answer").checked;d&&(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus(),document.getElementById("buzz").disabled=!0)}function clearStats({userId:a}){updateStatDisplay(room.players[a])}function endOfSet(){window.alert("No more questions left"),document.getElementById("buzz").disabled=!0,document.getElementById("pause").disabled=!0,document.getElementById("next").disabled=!0}async function giveAnswer({directive:a,directedPrompt:b,perQuestionCelerity:c,score:d,tossup:e,userId:f}){return"prompt"===a?(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus(),void(document.getElementById("answer-input").placeholder=b?`Prompt: "${b}"`:"Prompt")):void(document.getElementById("answer-input").value="",document.getElementById("answer-input").blur(),document.getElementById("answer-input").placeholder="Enter answer",document.getElementById("answer-input-group").classList.add("d-none"),document.getElementById("next").disabled=!1,document.getElementById("pause").disabled=!1,room.settings.rebuzz&&(document.getElementById("buzz").disabled=!1,document.getElementById("buzz").textContent="Buzz"),updateStatDisplay(room.players[USER_ID]),audio.soundEffects&&f===USER_ID&&("accept"===a&&10room.message(USER_ID,a)};room.sockets[USER_ID]=socket;function onmessage(a){const b=JSON.parse(a);switch(b.type){case"buzz":return buzz(b);case"clear-stats":return clearStats(b);case"end-of-set":return endOfSet(b);case"give-answer":return giveAnswer(b);case"next":return next(b);case"no-questions-found":return noQuestionsFound(b);case"pause":return pause(b);case"reveal-answer":return revealAnswer(b);case"set-categories":return setCategories(b);case"set-difficulties":return setDifficulties(b);case"set-strictness":return setStrictness(b);case"set-reading-speed":return setReadingSpeed(b);case"set-packet-numbers":return setPacketNumbers(b);case"set-set-name":return setSetName(b);case"set-year-range":return setYearRange(b);case"skip":return next(b);case"start":return next(b);case"timer-update":return updateTimerDisplay(b.timeRemaining);case"toggle-correct":return toggleCorrect(b);case"toggle-powermark-only":return togglePowermarkOnly(b);case"toggle-rebuzz":return toggleRebuzz(b);case"toggle-select-by-set-name":return toggleSelectBySetName(b);case"toggle-show-history":return toggleShowHistory(b);case"toggle-standard-only":return toggleStandardOnly(b);case"toggle-timer":return toggleTimer(b);case"toggle-type-to-answer":return toggleTypeToAnswer(b);case"update-question":return updateQuestion(b)}}function buzz({timer:a,userId:b,username:c}){audio.soundEffects&&audio.buzz.play();const d=document.getElementById("type-to-answer").checked;d&&(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus(),document.getElementById("buzz").disabled=!0)}function clearStats({userId:a}){updateStatDisplay(room.players[a])}function endOfSet(){window.alert("No more questions left"),document.getElementById("buzz").disabled=!0,document.getElementById("pause").disabled=!0,document.getElementById("next").disabled=!0}async function giveAnswer({directive:a,directedPrompt:b,perQuestionCelerity:c,score:d,tossup:e,userId:f}){return"prompt"===a?(document.getElementById("answer-input-group").classList.remove("d-none"),document.getElementById("answer-input").focus(),void(document.getElementById("answer-input").placeholder=b?`Prompt: "${b}"`:"Prompt")):void(document.getElementById("answer-input").value="",document.getElementById("answer-input").blur(),document.getElementById("answer-input").placeholder="Enter answer",document.getElementById("answer-input-group").classList.add("d-none"),document.getElementById("next").disabled=!1,document.getElementById("pause").disabled=!1,room.settings.rebuzz&&(document.getElementById("buzz").disabled=!1,document.getElementById("buzz").textContent="Buzz"),updateStatDisplay(room.players[USER_ID]),audio.soundEffects&&f===USER_ID&&("accept"===a&&101>a||a>maxPacketNumber);return b?void document.getElementById("packet-number").classList.add("is-invalid"):void(document.getElementById("packet-number").classList.remove("is-invalid"),socket.sendToServer({type:"set-packet-numbers",packetNumbers:a}))}),document.getElementById("pause").addEventListener("click",function(){this.blur();const a=parseFloat(document.querySelector(".timer .face").innerText),b=parseFloat(document.querySelector(".timer .fraction").innerText);socket.sendToServer({type:"pause",pausedTime:10*(a+b)})}),document.getElementById("reading-speed").addEventListener("change",function(){socket.sendToServer({type:"set-reading-speed",readingSpeed:this.value})}),document.getElementById("report-question-submit").addEventListener("click",function(){api.reportQuestion(document.getElementById("report-question-id").value,document.getElementById("report-question-reason").value,document.getElementById("report-question-description").value)}),document.getElementById("set-name").addEventListener("change",async function(){socket.sendToServer({type:"set-set-name",setName:this.value.trim(),packetNumbers:rangeToArray(document.getElementById("packet-number").value)})}),document.getElementById("start").addEventListener("click",function(){socket.sendToServer({type:"start"})}),document.getElementById("toggle-correct").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-correct",correct:"I was right"===this.textContent})}),document.getElementById("toggle-powermark-only").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-powermark-only",powermarkOnly:this.checked})}),document.getElementById("toggle-rebuzz").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-rebuzz",rebuzz:this.checked})}),document.getElementById("toggle-select-by-set-name").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-select-by-set-name",selectBySetName:this.checked})}),document.getElementById("toggle-settings").addEventListener("click",function(){this.blur(),document.getElementById("buttons").classList.toggle("col-lg-9"),document.getElementById("buttons").classList.toggle("col-lg-12"),document.getElementById("content").classList.toggle("col-lg-9"),document.getElementById("content").classList.toggle("col-lg-12"),document.getElementById("settings").classList.toggle("d-none"),document.getElementById("settings").classList.toggle("d-lg-none")}),document.getElementById("toggle-show-history").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-show-history",showHistory:this.checked})}),document.getElementById("toggle-standard-only").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-standard-only",standardOnly:this.checked})}),document.getElementById("toggle-timer").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-timer",timer:this.checked})}),document.getElementById("type-to-answer").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-type-to-answer",typeToAnswer:this.checked})}),document.getElementById("year-range-a").onchange=function(){const a=$("#slider").slider("values",0),b=$("#slider").slider("values",1);socket.sendToServer({type:"set-year-range",minYear:a,maxYear:b})},document.getElementById("year-range-b").onchange=function(){const a=$("#slider").slider("values",0),b=$("#slider").slider("values",1);socket.sendToServer({type:"set-year-range",minYear:a,maxYear:b})},document.addEventListener("keydown",a=>{if(!["INPUT","TEXTAREA","SELECT"].includes(document.activeElement.tagName))switch(a.key){case" ":document.getElementById("buzz").click(),a.target===document.body&&a.preventDefault();break;case"e":return document.getElementById("toggle-settings").click();case"k":return document.getElementsByClassName("card-header-clickable")[0].click();case"n":return document.getElementById("next").click();case"p":return document.getElementById("pause").click();case"s":return document.getElementById("start").click();case"t":return document.getElementsByClassName("star-tossup")[0].click();case"y":return navigator.clipboard.writeText(room.tossup._id??"")}});let startingDifficulties=[];if(window.localStorage.getItem("singleplayer-tossup-query"))try{const a=JSON.parse(window.localStorage.getItem("singleplayer-tossup-query"));if(a.version!==queryVersion)throw new Error;categoryManager.import(a.categories,a.subcategories,a.alternateSubcategories),socket.sendToServer({type:"set-packet-numbers",...a}),socket.sendToServer({type:"set-set-name",...a}),socket.sendToServer({type:"set-year-range",...a}),socket.sendToServer({type:"toggle-powermark-only",...a}),socket.sendToServer({type:"toggle-select-by-set-name",...a}),socket.sendToServer({type:"toggle-standard-only",...a}),startingDifficulties=a.difficulties}catch{window.localStorage.removeItem("singleplayer-tossup-query")}if(window.localStorage.getItem("singleplayer-tossup-settings"))try{const a=JSON.parse(window.localStorage.getItem("singleplayer-tossup-settings"));if(a.version!==settingsVersion)throw new Error;socket.sendToServer({type:"set-reading-speed",...a}),socket.sendToServer({type:"toggle-rebuzz",...a}),socket.sendToServer({type:"toggle-show-history",...a}),socket.sendToServer({type:"toggle-timer",...a}),socket.sendToServer({type:"toggle-type-to-answer",...a})}catch{window.localStorage.removeItem("singleplayer-tossup-settings")}ReactDOM.createRoot(document.getElementById("category-modal-root")).render(/*#__PURE__*/React.createElement(CategoryModal,{categoryManager:categoryManager,onClose:()=>socket.sendToServer({type:"set-categories",...categoryManager.export()})})),ReactDOM.createRoot(document.getElementById("difficulty-dropdown-root")).render(/*#__PURE__*/React.createElement(DifficultyDropdown,{startingDifficulties:startingDifficulties??[],onChange:()=>socket.sendToServer({type:"set-difficulties",difficulties:getDropdownValues("difficulties")})})); \ No newline at end of file +document.getElementById("statline").innerHTML=`${a}/${b}/${c} with ${d} tossup${h} seen (${e} pts, celerity: ${g})`,document.getElementById("clear-stats").disabled=0===d}function updateTimerDisplay(a){const b=Math.floor(a/10);document.querySelector(".timer .face").innerText=b,document.querySelector(".timer .fraction").innerText="."+a%10}document.getElementById("answer-form").addEventListener("submit",function(a){a.preventDefault(),a.stopPropagation();const b=document.getElementById("answer-input").value;socket.sendToServer({type:"give-answer",givenAnswer:b})}),document.getElementById("buzz").addEventListener("click",function(){this.blur(),audio.soundEffects&&audio.buzz.play(),socket.sendToServer({type:"buzz"})}),document.getElementById("clear-stats").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"clear-stats"})}),document.getElementById("next").addEventListener("click",function(){this.blur(),"Skip"===this.innerHTML?socket.sendToServer({type:"skip"}):socket.sendToServer({type:"next"})}),document.getElementById("packet-number").addEventListener("change",function(){const a=rangeToArray(this.value.trim(),maxPacketNumber),b=a.some(a=>1>a||a>maxPacketNumber);return b?void document.getElementById("packet-number").classList.add("is-invalid"):void(document.getElementById("packet-number").classList.remove("is-invalid"),socket.sendToServer({type:"set-packet-numbers",packetNumbers:a}))}),document.getElementById("pause").addEventListener("click",function(){this.blur();const a=parseFloat(document.querySelector(".timer .face").innerText),b=parseFloat(document.querySelector(".timer .fraction").innerText);socket.sendToServer({type:"pause",pausedTime:10*(a+b)})}),document.getElementById("reading-speed").addEventListener("change",function(){socket.sendToServer({type:"set-reading-speed",readingSpeed:this.value})}),document.getElementById("report-question-submit").addEventListener("click",function(){api.reportQuestion(document.getElementById("report-question-id").value,document.getElementById("report-question-reason").value,document.getElementById("report-question-description").value)}),document.getElementById("set-name").addEventListener("change",async function(){socket.sendToServer({type:"set-set-name",setName:this.value.trim(),packetNumbers:rangeToArray(document.getElementById("packet-number").value)})}),document.getElementById("start").addEventListener("click",function(){socket.sendToServer({type:"start"})}),document.getElementById("strictness").addEventListener("change",function(){this.blur(),socket.sendToServer({type:"set-strictness",strictness:this.value})}),document.getElementById("strictness").addEventListener("input",function(){document.getElementById("strictness-display").textContent=this.value}),document.getElementById("toggle-correct").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-correct",correct:"I was right"===this.textContent})}),document.getElementById("toggle-powermark-only").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-powermark-only",powermarkOnly:this.checked})}),document.getElementById("toggle-rebuzz").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-rebuzz",rebuzz:this.checked})}),document.getElementById("toggle-select-by-set-name").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-select-by-set-name",selectBySetName:this.checked})}),document.getElementById("toggle-settings").addEventListener("click",function(){this.blur(),document.getElementById("buttons").classList.toggle("col-lg-9"),document.getElementById("buttons").classList.toggle("col-lg-12"),document.getElementById("content").classList.toggle("col-lg-9"),document.getElementById("content").classList.toggle("col-lg-12"),document.getElementById("settings").classList.toggle("d-none"),document.getElementById("settings").classList.toggle("d-lg-none")}),document.getElementById("toggle-show-history").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-show-history",showHistory:this.checked})}),document.getElementById("toggle-standard-only").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-standard-only",standardOnly:this.checked})}),document.getElementById("toggle-timer").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-timer",timer:this.checked})}),document.getElementById("type-to-answer").addEventListener("click",function(){this.blur(),socket.sendToServer({type:"toggle-type-to-answer",typeToAnswer:this.checked})}),document.getElementById("year-range-a").onchange=function(){const a=$("#slider").slider("values",0),b=$("#slider").slider("values",1);socket.sendToServer({type:"set-year-range",minYear:a,maxYear:b})},document.getElementById("year-range-b").onchange=function(){const a=$("#slider").slider("values",0),b=$("#slider").slider("values",1);socket.sendToServer({type:"set-year-range",minYear:a,maxYear:b})},document.addEventListener("keydown",a=>{if(!["INPUT","TEXTAREA","SELECT"].includes(document.activeElement.tagName))switch(a.key){case" ":document.getElementById("buzz").click(),a.target===document.body&&a.preventDefault();break;case"e":return document.getElementById("toggle-settings").click();case"k":return document.getElementsByClassName("card-header-clickable")[0].click();case"n":return document.getElementById("next").click();case"p":return document.getElementById("pause").click();case"s":return document.getElementById("start").click();case"t":return document.getElementsByClassName("star-tossup")[0].click();case"y":return navigator.clipboard.writeText(room.tossup._id??"")}});let startingDifficulties=[];if(window.localStorage.getItem("singleplayer-tossup-query"))try{const a=JSON.parse(window.localStorage.getItem("singleplayer-tossup-query"));if(a.version!==queryVersion)throw new Error;categoryManager.import(a.categories,a.subcategories,a.alternateSubcategories),socket.sendToServer({type:"set-packet-numbers",...a}),socket.sendToServer({type:"set-set-name",...a}),socket.sendToServer({type:"set-year-range",...a}),socket.sendToServer({type:"toggle-powermark-only",...a}),socket.sendToServer({type:"toggle-select-by-set-name",...a}),socket.sendToServer({type:"toggle-standard-only",...a}),startingDifficulties=a.difficulties}catch{window.localStorage.removeItem("singleplayer-tossup-query")}if(window.localStorage.getItem("singleplayer-tossup-settings"))try{const a=JSON.parse(window.localStorage.getItem("singleplayer-tossup-settings"));if(a.version!==settingsVersion)throw new Error;socket.sendToServer({type:"set-strictness",...a}),socket.sendToServer({type:"set-reading-speed",...a}),socket.sendToServer({type:"toggle-rebuzz",...a}),socket.sendToServer({type:"toggle-show-history",...a}),socket.sendToServer({type:"toggle-timer",...a}),socket.sendToServer({type:"toggle-type-to-answer",...a})}catch{window.localStorage.removeItem("singleplayer-tossup-settings")}ReactDOM.createRoot(document.getElementById("category-modal-root")).render(/*#__PURE__*/React.createElement(CategoryModal,{categoryManager:categoryManager,onClose:()=>socket.sendToServer({type:"set-categories",...categoryManager.export()})})),ReactDOM.createRoot(document.getElementById("difficulty-dropdown-root")).render(/*#__PURE__*/React.createElement(DifficultyDropdown,{startingDifficulties:startingDifficulties??[],onChange:()=>socket.sendToServer({type:"set-difficulties",difficulties:getDropdownValues("difficulties")})})); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 4e76f985..05f0c476 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "morgan": "^1.10.0", "nodemailer": "^6.9.13", "number-to-words": "^1.2.4", - "qb-answer-checker": "^1.0.4", + "qb-answer-checker": "^1.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", "roman-numerals": "^0.3.2", @@ -7424,9 +7424,9 @@ } }, "node_modules/qb-answer-checker": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/qb-answer-checker/-/qb-answer-checker-1.0.4.tgz", - "integrity": "sha512-Yv1roviP8QwdLeDGQjSOf4y6I6YplvDqD/Q9ovmA8wG01TZW1mND2prc76H/7cdrfgXVfhhcDOK5Q3kxSh86SA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/qb-answer-checker/-/qb-answer-checker-1.0.6.tgz", + "integrity": "sha512-ywKwOoBvFL0m1OPhBXjEmhKgkj8DsUbbnX1NC68BW9GnhYoe6U/WCXtg+trxjCZ4DorXKoGdp/bvtZTqBxHPKg==", "dependencies": { "damerau-levenshtein-js": "^1.1.8", "number-to-words": "^1.2.4", @@ -14437,9 +14437,9 @@ "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "qb-answer-checker": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/qb-answer-checker/-/qb-answer-checker-1.0.4.tgz", - "integrity": "sha512-Yv1roviP8QwdLeDGQjSOf4y6I6YplvDqD/Q9ovmA8wG01TZW1mND2prc76H/7cdrfgXVfhhcDOK5Q3kxSh86SA==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/qb-answer-checker/-/qb-answer-checker-1.0.6.tgz", + "integrity": "sha512-ywKwOoBvFL0m1OPhBXjEmhKgkj8DsUbbnX1NC68BW9GnhYoe6U/WCXtg+trxjCZ4DorXKoGdp/bvtZTqBxHPKg==", "requires": { "damerau-levenshtein-js": "^1.1.8", "number-to-words": "^1.2.4", diff --git a/package.json b/package.json index aa6d32f9..0075059c 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "morgan": "^1.10.0", "nodemailer": "^6.9.13", "number-to-words": "^1.2.4", - "qb-answer-checker": "^1.0.4", + "qb-answer-checker": "^1.0.6", "react": "^18.2.0", "react-dom": "^18.2.0", "roman-numerals": "^0.3.2", diff --git a/quizbowl/TossupRoom.js b/quizbowl/TossupRoom.js index 08dec466..fe46cee0 100644 --- a/quizbowl/TossupRoom.js +++ b/quizbowl/TossupRoom.js @@ -16,7 +16,7 @@ export default class TossupRoom extends Room { constructor (name, categories = [], subcategories = [], alternateSubcategories = []) { super(name); - this.checkAnswer = async function checkAnswer (answerline, givenAnswer) { throw new Error('Not implemented'); }; + this.checkAnswer = async function checkAnswer (answerline, givenAnswer, strictness = 7) { throw new Error('Not implemented'); }; this.getRandomTossups = async function getRandomTossups (args) { throw new Error('Not implemented'); }; this.getSet = async function getSet (args) { throw new Error('Not implemented'); }; this.getSetList = async function getSetList (args) { throw new Error('Not implemented'); }; @@ -65,6 +65,7 @@ export default class TossupRoom extends Room { }; this.settings = { + strictness: 7, rebuzz: false, readingSpeed: 50, skip: false, @@ -89,6 +90,7 @@ export default class TossupRoom extends Room { case 'pause': return this.pause(userId, message); case 'set-categories': return this.setCategories(userId, message); case 'set-difficulties': return this.setDifficulties(userId, message); + case 'set-strictness': return this.setStrictness(userId, message); case 'set-packet-numbers': return this.setPacketNumbers(userId, message); case 'set-reading-speed': return this.setReadingSpeed(userId, message); case 'set-set-name': return this.setSetName(userId, message); @@ -313,11 +315,17 @@ export default class TossupRoom extends Room { const celerity = this.questionSplit.slice(this.wordIndex).join(' ').length / this.tossup.question.length; const endOfQuestion = (this.wordIndex === this.questionSplit.length); const inPower = this.questionSplit.indexOf('(*)') >= this.wordIndex; - const { directive, directedPrompt } = await this.checkAnswer(this.tossup.answer, givenAnswer); + const { directive, directedPrompt } = await this.checkAnswer(this.tossup.answer, givenAnswer, this.settings.strictness); const points = scoreTossup({ isCorrect: directive === 'accept', inPower, endOfQuestion }); return { celerity, directive, directedPrompt, endOfQuestion, inPower, points }; } + setStrictness (userId, { strictness }) { + this.settings.strictness = strictness; + const username = this.players[userId].username; + this.emitMessage({ type: 'set-strictness', username, strictness }); + } + async setPacketNumbers (userId, { packetNumbers }) { if (!Array.isArray(packetNumbers)) { return false; } const allowedPacketNumbers = await this.getNumPackets(this.query.setName); diff --git a/routes/api/check-answer.js b/routes/api/check-answer.js index 74dec158..17eadefa 100644 --- a/routes/api/check-answer.js +++ b/routes/api/check-answer.js @@ -4,8 +4,8 @@ import checkAnswer from 'qb-answer-checker'; const router = Router(); router.get('/', (req, res) => { - const { answerline, givenAnswer } = req.query; - const { directive, directedPrompt } = checkAnswer(answerline, givenAnswer); + const { answerline, givenAnswer, strictness } = req.query; + const { directive, directedPrompt } = checkAnswer(answerline, givenAnswer, strictness); res.json({ directive, directedPrompt }); }); diff --git a/types.js b/types.js index 5fe691e0..221937d3 100644 --- a/types.js +++ b/types.js @@ -7,7 +7,7 @@ import { ObjectId } from 'mongodb'; * @typedef {object} Question * @property {ObjectId} _id * @property {string} category - * @property {number} difficulty + * @property {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10} difficulty * @property {string} subcategory * @property {number} number * @@ -61,5 +61,5 @@ import { ObjectId } from 'mongodb'; * @property {ObjectId} _id * @property {string} name * @property {number} year - * @property {number} difficulty + * @property {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10} difficulty */