Files
NodeCames/src/main/resources/static/js/grid.js
T

336 lines
9.6 KiB
JavaScript

var socket = null
var player = '_'
var wsHeaders = {}
var cards = []
var gc = {}
var currentHint = null
var currentHintCount = -1
var currentGuessCount = -1
var phase = {}
// This variable is here to check for updates to availableHintWordCount, as updating it is a bit expensive
var registeredAvailableHintWordCountInvalid = true
/*
* Update html to match state
* This is idempotent
*/
function updatePhase() {
$('#hint-counter-num').text(currentHintCount)
$('#hint-counter-den').text(gc["max-hint"])
if(currentHint) {
$('#hint-text').text(currentHint['word']+" in "+currentHint['word-count'])
$('#guess-counter-num').text(currentGuessCount)
if(gc['one-more-guess']) {
$('#guess-counter-den').text(currentHint['word-count'] + "(+1)")
} else {
$('#guess-counter-den').text(currentHint['word-count'])
}
}
if(registeredAvailableHintWordCountInvalid) {
$('#submit-hint-wordcount').empty()
for (let i = 0; i < gc['available-hint-word-count'].length; i++) {
const e = gc['available-hint-word-count'][i];
$('#submit-hint-wordcount').append($(`<option value="${e}">${e}</option>`))
}
registeredAvailableHintWordCountInvalid = false
}
$('#submit-hint-text').attr('maxlength', gc['hint-max-length'])
p = player.toLowerCase()
o = (player=='A')?'b':'a'
if(phase[p+'-guessing']) {
$('.card-button').css('visibility', 'visible')
$('.card-button.untouchable').css('visibility', 'hidden')
} else {
$('.card-button').css('visibility', 'hidden')
$('#end-guessing-button').hide()
}
if(phase['name'] == 'need_more_hints_a' || phase['name'] == 'need_more_hints_b') {
$('#enter-sudden-death-button').show()
} else {
$('#enter-sudden-death-button').hide()
}
if((phase['name'] == 'waiting_for_one_more_'+p) ||
(phase[p+'-guessing'] &&
(gc['end-guessing'] || (currentHint && currentGuessCount >= currentHint['word-count'])))) {
$('#end-guessing-button').show()
} else {
$('#end-guessing-button').hide()
}
if(phase[p+'-guessing'] || phase[o+'-guessing']) {
$('#hint-text').show()
$('#guess-counter').show()
} else {
$('#hint-text').hide()
$('#guess-counter').hide()
}
if(phase[p+'-hinting']) {
$('#submit-hint').show()
} else {
$('#submit-hint').hide()
}
if(!phase[p+'-guessing'] && !phase[p+'-hinting']) {
$('#other-playing').show()
} else {
$('#other-playing').hide()
}
}
function createCard(i) {
html = `
<li class="card ${cards[i].color}" id="card-${i}">
<span class="card-word">${cards[i].word}</span><br/>
<div class="card-bottom-bar">
<div id="card-${i}-a-public">A</div>
<button class="card-button" id="card-${i}-button">Toucher</button>
<div id="card-${i}-b-public">B</div>
</div>
</li>
`
$('#cards-list').append($(html))
$(`#card-${i}-button`).on('click', pointCard)
}
function updateCard(i) {
card = cards[i]
if(card['revealed-a']) {
$(`#card-${i}-b-public`).addClass((player=='A')?card.otherColor:card.color)
$(`#card-${i}-b-public`).css('visibility', 'visible')
} else {
$(`#card-${i}-b-public`).css('visibility', 'hidden')
}
if(card['revealed-b']) {
$(`#card-${i}-a-public`).addClass((player=='B')?card.otherColor:card.color)
$(`#card-${i}-a-public`).css('visibility', 'visible')
} else {
$(`#card-${i}-a-public`).css('visibility', 'hidden')
}
cardDone = (
gc["only-one-green-green"] &&
((card['revealed-a'] && ((player=='A')?card.otherColor:card.color == "green")) ||
(card['revealed-b'] && ((player=='B')?card.otherColor:card.color == "green")))) ||
(card['revealed-a'] && card['revealed-b']);
if(cardDone) $(`#card-${i}`).addClass('card-done')
cantTouch = cardDone ||
(player=='A' && card['revealed-a']) ||
(player=='B' && card['revealed-b']);
if(cantTouch) {
$(`#card-${i}-button`).addClass('untouchable')
$(`#card-${i}-button`).css('visibility', 'hidden')
}
}
function addHintEvent(issuer, hint, hintWordCount) {
$("#event-log").append($(`
<li>
${issuer} proposed "${hint}" in ${hintWordCount} word(s)
</li>
`))
}
function addPointEvent(issuer, cardIndex, color) {
$("#event-log").append($(`
<li>
${issuer} pointed card ${cards[cardIndex].word} (${color})
</li>
`))
}
function addEndGuessingEvent(issuer, manual) {
if(manual) {
$("#event-log").append($(`
<li>
${issuer} ended guessing
</li>
`))
} else {
$("#event-log").append($(`
<li>
${issuer} can't guess anymore
</li>
`))
}
}
function addSuddenDeathEvent() {
$("#event-log").append($(`
<li>
Starting sudden death
</li>
`))
}
function addEndGameEvent(issuer, won) {
if(won) {
$("#event-log").append($(`
<li>
You won the game !
</li>
`))
} else {
$("#event-log").append($(`
<li>
You lost the game !
</li>
`))
}
}
function addEvent(e) {
switch(e.type) {
case "HintEvent":
addHintEvent(e.issuer, e.word, e['word-count'])
currentHint = {word: e.word, 'word-count': e['word-count']}
currentHintCount += 1
currentGuessCount = 0
updatePhase()
break
case "GuessEvent":
addPointEvent(e.issuer, e['card-index'], e.color)
currentGuessCount += 1
break
case "EndGuessingEvent":
addEndGuessingEvent(e.issuer, e.manual)
currentHint = null
currentGuessCount = 0
break
case "GameEndEvent":
addEndGameEvent(e.issuer, e.win)
currentHint = null
currentGuessCount = 0
break
case "EnterSuddenDeathEvent":
addSuddenDeathEvent()
currentHint = null
currentGuessCount = 0
break
}
}
/*
* Listeners
*/
function initGame(data) {
gc = data.config
cards = data.cards
$('#cards-list').empty()
for(var i = 0; i<cards.length; i++) {
createCard(i)
updateCard(i)
}
phase = data['phase']
events = data.events
for(var i = 0; i<events.length; i++) {
e = events[i]
addEvent(e)
}
if(data['current-hint']) {
currentHint = data['current-hint']
}
currentGuessCount = data['current-guess-count']
currentHintCount = data['used-hints']
updatePhase()
}
function selectPlayer(player) {
wsHeaders = {
"room": roomId,
"player": player
}
$('#player-name').text(player)
$('#player-selector').hide()
$('#game-panel').show()
$('#side-panel').show()
$.ajax({
contentType: 'application/json',
type: "GET",
url: "/room/"+roomId+"/game/player-"+player.toLowerCase(),
success: initGame
})
socket = Stomp.over(new SockJS('/socket'));
socket.connect({}, function (frame) {
socket.subscribe('/topic/'+roomId+'/new-phase', onNewPhase);
socket.subscribe('/topic/'+roomId+'/new-event', onNewEvent);
socket.subscribe('/topic/'+roomId+'/update-card/' + player.toLowerCase(), onUpdateCard);
socket.subscribe('/topic/'+roomId+'/config-change', onConfigChange)
});
}
function submitHint(e) {
hint = $('#submit-hint-text').val()
hintWordCount = Number($('#submit-hint-wordcount option:selected').val())
socket.send('/app/submit-hint', wsHeaders, JSON.stringify({
'hint': hint,
'hintWordCount': hintWordCount
}))
}
function pointCard(e) {
cardIndex = Number(/card-([0-9]+)-button/.exec(e.target.id)[1])
socket.send('/app/point-card', wsHeaders, JSON.stringify({
'cardIndex': cardIndex,
}))
}
function endGuessing(e) {
socket.send('/app/end-guessing', wsHeaders, "")
}
function enterSuddenDeath(e) {
socket.send('/app/enter-sudden-death', wsHeaders, "")
}
function onNewPhase(m) {
phase = JSON.parse(m.body)
updatePhase()
}
function onNewEvent(m) {
e = JSON.parse(m.body)
addEvent(e)
}
function onUpdateCard(m) {
data = JSON.parse(m.body)
i = Number(m.headers['cardIndex'])
cards[i] = data
updateCard(i)
}
function onConfigChange(m) {
data = JSON.parse(m.body)
for(const [key, value] of Object.entries(data)) {
console.log("New config option : ", key, "=", value)
gc[key] = value
switch(key) {
case "available-hint-word-count":
registeredAvailableHintWordCountInvalid = true
updatePhase()
break
case "only-one-green-green":
for(var i = 0; i < cards.length; i++)
updateCard(i)
case "max-hint":
case "one-more-guess":
case "hint-max-length":
case "end-guessing":
case "sudden-death":
updatePhase()
break
case "hints-in-a-row":
// All the changes are made with phases
break;
}
}
}
function initialize() {
$('#submit-hint button').on('click', submitHint)
$('#end-guessing-button').on('click', endGuessing)
$('#enter-sudden-death-button').on('click', enterSuddenDeath)
$('#game-panel').hide()
$('#side-panel').hide()
}