// triviaMasterClientStandard.js // // Created by Rebecca Stankus on 06/11/18 // Modified by Mark Brosche on 10/16/18 // Updated 3/13/19 by Mark Brosche // Copyright 2018 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // // This is the standard version of "Last Avatar Standing" Trivia // that draws from a third-party database of thousands of questions. /* global EventBridge Users AccountServices */ (function() { var SECRETS = Script.require(Script.resolvePath('triviaInfo.json')), TRIVIA_CHANNEL = SECRETS.TRIVIA_CHANNEL, GOOGLE_URL = SECRETS.GOOGLE_URL, TABLET_BUTTON_IMAGE = Script.resolvePath('../entities/icons/questionMark-i.png'), TABLET_BUTTON_PRESSED = Script.resolvePath('../entities/icons/questionMark-a.png'), SEARCH_RADIUS = 1000, ONE_SECOND_MS = 1000; var FIVE_SECONDS = 5 * ONE_SECOND_MS, TEN_SECONDS_MS = 10 * ONE_SECOND_MS, ZONE_COLOR_INDEX = 19, HALF_MULTIPLIER = 0.5, FIRST_WAIT_TO_COUNT_AVATARS = ONE_SECOND_MS, WAIT_TO_SHOW_QUESTION = 0.5 * ONE_SECOND_MS, MIN_PLAYERS = 3, HFC_INCREMENT = 100, HFC_HALVER = 0.5, MIN_PRIZE = 300, HOST_PERCENTAGE = 0.1; var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system'), appPage = Script.resolvePath('trivia.html?v100'), button = tablet.addButton({ text: 'TRIVIA', icon: TABLET_BUTTON_IMAGE, activeIcon: TABLET_BUTTON_PRESSED }); var open = false, gSheetTabName = "Halloween", intervalBoard, questionText, triviaURL = "", choiceTexts = [], answerText, triviaData, request = Script.require('../entities/modules/request.js').request, type = null, category = null, difficulty = null, currentChoices = [], letter = [], lights = [], correctHighlights = [], timer, gameZone, gameZoneProperties, avatarCounter, formattedQuestion = null, intervalTimer, bubble, bubbleState = false, introPlayed = false, correctCount = null, prizeDisplay, useGoogle = false, prizeMoney, winnerID = null, correctColor = null; var formattedAnswer = null; // The following function from https://stackoverflow.com/questions/3700326/decode-amp-back-to-in-javascript var htmlEnDeCode = (function() { var charToEntityRegex, entityToCharRegex, charToEntity, entityToChar; function resetCharacterEntities() { charToEntity = {}; entityToChar = {}; // add the default set addCharacterEntities({ '&': '&', '>': '>', '<': '<', '"': '"', ''': "'", ''': "'", '‘': '"', '’': '"', '“': '"', 'Ü': 'U', 'ü': 'u', '”': '"', 'é': 'e', '′': '\'', '&Prime': '"' }); } function addCharacterEntities(newEntities) { var charKeys = [], entityKeys = [], key, encodedChar; for (key in newEntities) { encodedChar = newEntities[key]; entityToChar[key] = encodedChar; charToEntity[encodedChar] = key; charKeys.push(encodedChar); entityKeys.push(key); } charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g'); entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g'); } function htmlEncode(value) { var htmlEncodeReplace = function(match, capture) { return charToEntity[capture]; }; return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplace); } function htmlDecode(value) { var htmlDecodeReplaceFn = function(match, capture) { return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10)); }; return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn); } resetCharacterEntities(); return { htmlEncode: htmlEncode, htmlDecode: htmlDecode }; })(); function begin() { if (Entities.serversExist()) { try { if (findTargets()){ bubbleOn(); prizeCalculator("new game"); if (!introPlayed) { Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['GAME_INTRO']); introPlayed = true; } else { Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['NEW_GAME_SFX']); } Entities.callEntityServerMethod(gameZoneProperties.id, "stopConfetti"); lights.forEach(function(light) { Entities.callEntityServerMethod(light, "lightsOn"); }); } else { var data = {"error message": "found no targets"}; data.application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data)); } } catch (e) { console.log(e, "error finding targets"); var data = {"error message": e}; data.application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data)); } } else { Script.setTimeout(function(){ try { findTargets(); bubbleOn(); prizeCalculator("new game"); if (!introPlayed) { Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['GAME_INTRO']); introPlayed = true; } else { Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['NEW_GAME_SFX']); } Entities.callEntityServerMethod(gameZoneProperties.id, "stopConfetti"); lights.forEach(function(light) { Entities.callEntityServerMethod(light, "lightsOn"); }); } catch (e) { console.log(e, "error finding targets"); var data = {"error message": e}; data.application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data)); } }, FIVE_SECONDS); } } function bubbleOn() { bubbleState = true; Entities.callEntityServerMethod(bubble, "bubbleOn"); Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({ type: "game on" })); usersInZone(gameZoneProperties, "begin"); if (!intervalBoard) { intervalBoard = Script.setInterval(function(){ updateAvatarCounter(false); Entities.callEntityServerMethod(prizeDisplay, "textUpdate", [prizeMoney, true]); }, ONE_SECOND_MS); } else { Script.clearInterval(intervalBoard); intervalBoard = false; intervalBoard = Script.setInterval(function(){ updateAvatarCounter(false); Entities.callEntityServerMethod(prizeDisplay, "textUpdate", [prizeMoney, true]); }, ONE_SECOND_MS); } } function bubbleOff() { bubbleState = false; Entities.callEntityServerMethod(bubble, "bubbleOff"); usersInZone(gameZoneProperties, "end"); Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({ type: "game off" })); if (intervalBoard) { Script.clearInterval(intervalBoard); intervalBoard = false; } type = null; category = null; difficulty = null; } function findTargets() { Entities.findEntities(MyAvatar.position, SEARCH_RADIUS).forEach(function(element) { var name = Entities.getEntityProperties(element, ['name']).name; if (name.indexOf("Trivia") !== -1) { var serverScriptURL = Entities.getEntityProperties(element, ['serverScripts']).serverScripts; if (serverScriptURL !== "") { Entities.getServerScriptStatus(element, (function() { return function(success, isRunning, status, errorInfo) { if (!success || !isRunning) { console.log("Script not running:", element, success, isRunning, status, errorInfo, JSON.stringify(serverScriptURL)); Entities.reloadServerScripts(element); } }; })()); } if (name.indexOf("Light") !== -1) { lights.push(element); } else if (name.indexOf("Correct") !== -1) { correctHighlights.push(element); } else { switch (name) { case "Trivia Question": questionText = element; break; case "Trivia Answer": answerText = element; break; case "Trivia Choice Text Green": choiceTexts[0] = element; break; case "Trivia Choice Text Yellow": choiceTexts[1] = element; break; case "Trivia Choice Text Red": choiceTexts[2] = element; break; case "Trivia Choice Text Blue": choiceTexts[3] = element; break; case "Trivia Timer Countdown": timer = element; break; case "Trivia Avatar Counter Total": avatarCounter = element; break; case "Trivia Player Game Zone": gameZone = element; gameZoneProperties = Entities.getEntityProperties(gameZone, ["id", "position", "dimensions", "rotation", "userData"]); break; case "Trivia Prize Amount": prizeDisplay = element; break; case "Trivia Bubble": bubble = element; break; case "Trivia Choice Letter Blue Board": letter[0] = element; break; case "Trivia Choice Letter Green Board": letter[1] = element; break; } } } }); return true; } function onClicked() { if (open) { tablet.gotoHomeScreen(); tablet.webEventReceived.disconnect(onWebEventReceived); } else { tablet.gotoWebScreen(appPage); Script.setTimeout(function(){ if (triviaData) { if (triviaData.length !== 0 && !useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("gameInProgress"); } else if (bubbleState === true && !useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("noQuestionPosted"); } else if (triviaData.length !== 0 && useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("gameInProgressCustom"); } else if (bubbleState === true && useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("noQuestionPostedCustom"); } } }, 500); } } function getQuestion() { if (intervalTimer) { Script.clearInterval(intervalTimer); intervalTimer = false; } Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['NEXT_QUESTION_SFX']); if (useGoogle){ try { if (triviaURL === "") { triviaURL = SECRETS.trivia_URL; } else if (triviaURL.indexOf("category=") === -1) { triviaURL = triviaURL + "category=" + gSheetTabName; } var expression = /[-a-zA-Z0-9@:%_\+.~#?&\/=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9@:%_\+.~#?&\/=]*)?/gi; var regex = new RegExp(expression); if (triviaURL.match(regex)) { request(triviaURL, function (error, data) { if (error || data.status !== "success") { data.application = "trivia"; tablet.emitScriptEvent("nothingEntered"); useGoogle = false; } else { data.application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data)); triviaData = data; } }); } else { tablet.emitScriptEvent("nothingEntered"); } } catch (err) { print("Could not get domain data using userData domainAPIURL"); } } else { try { triviaURL = "https://opentdb.com/api.php?amount=1"; if (type) { triviaURL = triviaURL + "&type=" + type; } if (difficulty) { triviaURL = triviaURL + "&difficulty=" + difficulty; } if (category) { triviaURL = triviaURL + "&category=" + category; } request(triviaURL, function (error, data) { if (!error) { data.results[0].application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data.results[0])); triviaData = data.results; } else { data.response_code.application = "trivia"; tablet.emitScriptEvent(JSON.stringify(data.response_code)); } }); } catch (err) { print("Could not get domain data using userData domainAPIURL"); } } } function shuffle(array) { var currentIndex = array.length, temporaryValue, randomIndex; while (currentIndex !== 0) { randomIndex = Math.floor(Math.random() * currentIndex); currentIndex -= 1; temporaryValue = array[currentIndex]; array[currentIndex] = array[randomIndex]; array[randomIndex] = temporaryValue; } return array; } function showQuestion() { clearBoard(); formattedQuestion = null; Script.setTimeout(function() { choiceTexts.forEach(function(choice) { Entities.callEntityServerMethod(choice, "textUpdate", ["", true]); }); Entities.callEntityServerMethod(letter[0], "textUpdate", ["C", true]); Entities.callEntityServerMethod(letter[1], "textUpdate", ["B", true]); if (useGoogle) { formattedQuestion = triviaData.question; } else { formattedQuestion = htmlEnDeCode.htmlDecode(triviaData[0].question); } Entities.callEntityServerMethod(questionText, "textUpdate", [formattedQuestion, true]); Entities.callEntityServerMethod(answerText, "textUpdate", ["", false]); }, WAIT_TO_SHOW_QUESTION); } function showAnswers() { if (useGoogle) { if (triviaData.type === "boolean") { Entities.callEntityServerMethod(choiceTexts[0], "textUpdate", ["",false]); Entities.callEntityServerMethod(choiceTexts[1], "textUpdate", ["True", true]); Entities.callEntityServerMethod(choiceTexts[2], "textUpdate", ["False", true]); Entities.callEntityServerMethod(choiceTexts[3], "textUpdate", ["", false]); Entities.callEntityServerMethod(letter[0], "textUpdate", ["C", false]); Entities.callEntityServerMethod(letter[1], "textUpdate", ["B", false]); currentChoices = []; currentChoices.push("True"); currentChoices.push("False"); lights.forEach(function(light) { var lightName = Entities.getEntityProperties(light, 'name').name; if ((lightName.indexOf("Green") !== -1) || (lightName.indexOf("Blue") !== -1)) { Entities.callEntityServerMethod(light, "lightsOff"); } }); } else { currentChoices = []; currentChoices.push({"text": triviaData.correct_answer, "correct": true}); triviaData.incorrect_answers.forEach(function(choice) { currentChoices.push({"text": choice, "correct": false}); }); shuffle(currentChoices); currentChoices.forEach(function(choice, index) { Entities.callEntityServerMethod(choiceTexts[index], "textUpdate", [choice.text, true]); }); } } else { if (triviaData[0].type === "boolean") { Entities.callEntityServerMethod(choiceTexts[0], "textUpdate", ["",false]); Entities.callEntityServerMethod(choiceTexts[1], "textUpdate", ["True", true]); Entities.callEntityServerMethod(choiceTexts[2], "textUpdate", ["False", true]); Entities.callEntityServerMethod(choiceTexts[3], "textUpdate", ["", false]); Entities.callEntityServerMethod(letter[0], "textUpdate", ["C", false]); Entities.callEntityServerMethod(letter[1], "textUpdate", ["B", false]); currentChoices = []; currentChoices.push("True"); currentChoices.push("False"); lights.forEach(function(light) { var lightName = Entities.getEntityProperties(light, 'name').name; if ((lightName.indexOf("Green") !== -1) || (lightName.indexOf("Blue") !== -1)) { Entities.callEntityServerMethod(light, "lightsOff"); } }); } else { currentChoices = []; currentChoices.push({"text": triviaData[0].correct_answer, "correct": true}); triviaData[0].incorrect_answers.forEach(function(choice) { currentChoices.push({"text": choice, "correct": false}); }); shuffle(currentChoices); currentChoices.forEach(function(choice, index) { Entities.callEntityServerMethod(choiceTexts[index], "textUpdate", [choice.text, true]); }); } } } function clearGame(userTriggered) { correctCount = null; prizeMoney = 0; winnerID = null; triviaData = []; if (intervalTimer){ Script.clearTimeout(intervalTimer); intervalTimer = false; } if (userTriggered) { Entities.callEntityServerMethod(gameZoneProperties.id, "stopSound"); } bubbleOff(); lights.forEach(function(light) { Entities.callEntityServerMethod(light, "lightsOff"); }); correctHighlights.forEach(function(highlight) { Entities.callEntityServerMethod(highlight, "lightsOff"); }); Entities.callEntityServerMethod(questionText, "textUpdate", ["Questions will appear here.", true]); choiceTexts.forEach(function(choice) { Entities.callEntityServerMethod(choice, "textUpdate", ["Answers will appear here.", true]); }); Entities.callEntityServerMethod(timer, "textUpdate", ["0", true]); Entities.callEntityServerMethod(letter[0], "textUpdate", ["C", true]); Entities.callEntityServerMethod(letter[1], "textUpdate", ["B", true]); Entities.callEntityServerMethod(answerText, "textUpdate", ["", true]); Entities.callEntityServerMethod(avatarCounter, "textUpdate", [0, true]); Entities.callEntityServerMethod(prizeDisplay, "textUpdate", [0, true]); } function isPositionInsideBox(position, gameZoneProperties) { var localPosition = Vec3.multiplyQbyV(Quat.inverse(gameZoneProperties.rotation), Vec3.subtract(position, gameZoneProperties.position)); var halfDimensions = Vec3.multiply(gameZoneProperties.dimensions, HALF_MULTIPLIER); return -halfDimensions.x <= localPosition.x && halfDimensions.x >= localPosition.x && -halfDimensions.y <= localPosition.y && halfDimensions.y >= localPosition.y && -halfDimensions.z <= localPosition.z && halfDimensions.z >= localPosition.z; } function usersInZone(gameZoneProperties, state) { var count = 0; if (state === undefined) { AvatarManager.getAvatarIdentifiers().forEach(function(avatarID) { var avatar = AvatarManager.getAvatar(avatarID); if (avatar.sessionUUID && isPositionInsideBox(avatar.position, gameZoneProperties)) { count++; } }); return count; } else if (state === "begin") { AvatarManager.getAvatarIdentifiers().forEach(function(avatarID) { var avatar = AvatarManager.getAvatar(avatarID); if (avatar.sessionUUID && isPositionInsideBox(avatar.position, gameZoneProperties)) { console.log("created validator", avatar.sessionUUID); Entities.callEntityServerMethod(gameZone, "rezValidator", [avatar.sessionUUID]); } }); } else { AvatarManager.getAvatarIdentifiers().forEach(function(avatarID) { var avatar = AvatarManager.getAvatar(avatarID); if (avatar.sessionUUID && isPositionInsideBox(avatar.position, gameZoneProperties)) { Entities.callEntityServerMethod(gameZone, "deleteValidator", [avatar.sessionUUID]); } }); } } function updateAvatarCounter(roundOver) { var count = usersInZone(gameZoneProperties); if (roundOver) { Script.setTimeout(function(){ if (correctCount === 1) { prizeCalculator("game over"); } else { prizeCalculator("increase pot"); } }, 1500); } Entities.callEntityServerMethod(avatarCounter, "textUpdate", [count, true]); } function prizeCalculator(gameState) { var count = usersInZone(gameZoneProperties); switch (gameState) { case "new game": if (count <= MIN_PLAYERS) { prizeMoney = MIN_PRIZE; } else { prizeMoney = count * HFC_INCREMENT; } break; case "everyone wrong": prizeMoney *= HFC_HALVER; if (prizeMoney <= MIN_PRIZE) { prizeMoney = MIN_PRIZE; } Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['POT_DECREASE_SFX']); // Entities.callEntityServerMethod(gameZoneProperties.id, "loseCoins"); Entities.callEntityServerMethod(gameZoneProperties.id, "halfHFC"); break; case "increase pot": prizeMoney += HFC_INCREMENT; Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['POT_INCREASE_SFX']); // Entities.callEntityServerMethod(gameZoneProperties.id, "winCoins"); Entities.callEntityServerMethod(gameZoneProperties.id, "plusHFC"); break; case "game over": prizeMoney += HFC_INCREMENT; Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['WINNER_MUSIC']); Entities.callEntityServerMethod(gameZoneProperties.id, "startConfetti"); if (prizeMoney >= 300 && winnerID !== MyAvatar.sessionUUID) { var pot = prizeMoney; var winnerBanner = AvatarManager.getAvatar(winnerID).sessionDisplayName + " wins " + pot + "HFC!"; Entities.callEntityServerMethod(questionText, "textUpdate", [winnerBanner, true]); Users.requestUsernameFromID(winnerID); Script.setTimeout(function(){ clearGame(false); Entities.callEntityServerMethod(questionText, "textUpdate", [winnerBanner, true]); }, 2 * ONE_SECOND_MS); tablet.emitScriptEvent("newGame"); } break; } } function sendInput(winningUserName) { if (prizeMoney >= 300 && winnerID !== MyAvatar.sessionUUID && winningUserName !== AccountServices.username) { var hostPayout = prizeMoney * HOST_PERCENTAGE; var paramString = encodeURLParams({ date: new Date(), triviaMasterUserName: AccountServices.username, triviaMasterPayout: hostPayout, winnerUserName: winningUserName, winnings: prizeMoney, senderID: AccountServices.username }); var request = new XMLHttpRequest(); request.open('GET', GOOGLE_URL + "?" + paramString); request.timeout = 10000; request.send(); } } function encodeURLParams(params) { var paramPairs = []; for (var key in params) { paramPairs.push(key + "=" + params[key]); } return paramPairs.join("&"); } function setUserName(uuid, userName) { sendInput(userName); } function clearBoard() { if (intervalTimer) { Script.clearInterval(intervalTimer); intervalTimer = false; } lights.forEach(function(light) { Entities.callEntityServerMethod(light,"lightsOn"); }); correctHighlights.forEach(function(highlight) { Entities.callEntityServerMethod(highlight, "lightsOff"); }); Entities.callEntityServerMethod(letter[0], "textUpdate", ["C", true]); Entities.callEntityServerMethod(letter[1], "textUpdate", ["B", true]); Entities.callEntityServerMethod(questionText, "textUpdate", ["", true]); choiceTexts.forEach(function(choice) { Entities.callEntityServerMethod(choice, "textUpdate", ["", true]); }); Entities.callEntityServerMethod(answerText, "textUpdate", ["", false]); } function startTimer() { if (intervalTimer) { Script.clearInterval(intervalTimer); intervalTimer = false; } Entities.callEntityServerMethod(gameZoneProperties.id, "playSound", ['TIMER_SOUND']); var seconds = 10; Entities.callEntityServerMethod(timer, "textUpdate", [seconds, true]); intervalTimer = Script.setInterval(function() { seconds--; Entities.callEntityServerMethod(timer, "textUpdate", [seconds, true]); if (seconds <= 0) { Script.clearInterval(intervalTimer); intervalTimer = false; seconds = 0; } }, ONE_SECOND_MS); } function isAnyAvatarCorrect(correctColor) { var result = null; var correctZoneColorID = null; switch (correctColor){ case "Red": correctZoneColorID = Entities.findEntitiesByName("Trivia Zone Red", MyAvatar.position, SEARCH_RADIUS)[0]; break; case "Green": correctZoneColorID = Entities.findEntitiesByName("Trivia Zone Green", MyAvatar.position, SEARCH_RADIUS)[0]; break; case "Yellow": correctZoneColorID = Entities.findEntitiesByName("Trivia Zone Yellow", MyAvatar.position, SEARCH_RADIUS)[0]; break; case "Blue": correctZoneColorID = Entities.findEntitiesByName("Trivia Zone Blue", MyAvatar.position, SEARCH_RADIUS)[0]; break; } var correctColorZoneProperties = Entities.getEntityProperties( correctZoneColorID, ["position", "dimensions", "rotation"]); result = usersInZone(correctColorZoneProperties); if (result === 1) { AvatarManager.getAvatarIdentifiers().forEach(function(avatarID) { var avatar = AvatarManager.getAvatar(avatarID); if (avatar.sessionUUID !== MyAvatar.sessionUUID) { if (isPositionInsideBox(avatar.position, correctColorZoneProperties)) { winnerID = avatar.sessionUUID; } } }); } return result; } function showCorrect() { if (useGoogle){ formattedAnswer = triviaData.correct_answer; correctColor = null; var correctIndex = currentChoices[currentChoices.map(function(e) { return e.correct; }).indexOf(true)]; var properties = Entities.getEntityProperties(choiceTexts[currentChoices.indexOf(correctIndex)], ['name']); correctColor = properties.name.substr(ZONE_COLOR_INDEX); lights.forEach(function(light) { var lightName = Entities.getEntityProperties(light, 'name').name; if (lightName.indexOf(correctColor) === -1) { Entities.callEntityServerMethod(light, "lightsOff"); } }); correctHighlights.forEach(function(highlight) { var highlightName = Entities.getEntityProperties(highlight, 'name').name; if (highlightName.indexOf(correctColor) !== -1) { Entities.callEntityServerMethod(highlight, "lightsOn"); } }); var anyCorrect = isAnyAvatarCorrect(correctColor); if (anyCorrect === 0) { Script.setTimeout(function() { prizeCalculator("everyone wrong"); }, FIRST_WAIT_TO_COUNT_AVATARS); } else { Script.setTimeout(function() { Entities.callEntityServerMethod(bubble, "checkAnswer", [correctColor]); correctCount = isAnyAvatarCorrect(correctColor); updateAvatarCounter(true); }, FIRST_WAIT_TO_COUNT_AVATARS); } Entities.callEntityServerMethod(answerText, "textUpdate", [formattedAnswer, true]); } else { formattedAnswer = htmlEnDeCode.htmlDecode(triviaData[0].correct_answer); correctColor = null; var correctIndex = currentChoices[currentChoices.map(function(e) { return e.correct; }).indexOf(true)]; var properties = Entities.getEntityProperties(choiceTexts[currentChoices.indexOf(correctIndex)], ['name']); correctColor = properties.name.substr(ZONE_COLOR_INDEX); lights.forEach(function(light) { var lightName = Entities.getEntityProperties(light, 'name').name; if (lightName.indexOf(correctColor) === -1) { Entities.callEntityServerMethod(light, "lightsOff"); } }); correctHighlights.forEach(function(highlight) { var highlightName = Entities.getEntityProperties(highlight, 'name').name; if (highlightName.indexOf(correctColor) !== -1) { Entities.callEntityServerMethod(highlight, "lightsOn"); } }); anyCorrect = isAnyAvatarCorrect(correctColor); if (anyCorrect === 0) { Script.setTimeout(function() { prizeCalculator("everyone wrong"); }, FIRST_WAIT_TO_COUNT_AVATARS); } else { Script.setTimeout(function() { Entities.callEntityServerMethod(bubble, "checkAnswer", [correctColor]); correctCount = isAnyAvatarCorrect(correctColor); console.log("loading the check answer script for ", correctColor, "and how many are right: ", correctCount); updateAvatarCounter(true); }, FIRST_WAIT_TO_COUNT_AVATARS); } Entities.callEntityServerMethod(answerText, "textUpdate", [formattedAnswer, true]); } } function onWebEventReceived(event) { if (typeof event === 'string') { try { event = JSON.parse(event); } catch (e) { console.log("error parsing web event", e); return; } if (event.app === 'trivia') { switch (event.type) { case 'listening': if (triviaData) { if (triviaData.length !== 0 && !useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("gameInProgress"); } else if (bubbleState === true && !useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData[0])); tablet.emitScriptEvent("noQuestionPosted"); } else if (triviaData.length !== 0 && useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData)); tablet.emitScriptEvent("gameInProgressCustom"); } else if (bubbleState === true && useGoogle) { tablet.emitScriptEvent(JSON.stringify(triviaData)); tablet.emitScriptEvent("noQuestionPostedCustom"); } else { tablet.emitScriptEvent("newGame"); } } else { tablet.emitScriptEvent("newGame"); } break; case 'catalog': switch (event.value) { case "Default Catalog": useGoogle = false; break; case "Custom Catalog": useGoogle = true; triviaURL = SECRETS.trivia_URL; answer = Window.prompt("What is the tab name of the sheet to use?", ""); if (answer === null) { tablet.emitScriptEvent("nothingEntered"); useGoogle = false; } else { gSheetTabName = answer; } break; case "Misc. Catalog": var answer = Window.prompt("URL of your GSheets script?", ""); if (answer === null) { tablet.emitScriptEvent("nothingEntered"); useGoogle = false; } else { triviaURL = answer; answer = Window.prompt("What is the tab name of the sheet to use?", ""); if (answer === null) { tablet.emitScriptEvent("nothingEntered"); useGoogle = false; } else { useGoogle = true; gSheetTabName = answer; } } break; } break; case 'begin': begin(); break; case 'end': clearGame(true); break; case 'type': switch (event.value) { case "Any Type": type = null; break; case "Multiple Choice": type = "multiple"; break; case "True or False": type = "boolean"; break; } break; case 'difficulty': switch (event.value) { case "Any Difficulty": difficulty = null; break; case "Easy": difficulty = "easy"; break; case "Medium": difficulty = "medium"; break; case "Hard": difficulty = "hard"; break; } break; case 'category': switch (event.value) { case "Any Category": category = null; break; case "General Knowledge": category = "9"; break; case "Books": category = "10"; break; case "Film": category = "11"; break; case "Music": category = "12"; break; case "Musicals and Theatres": category = "13"; break; case "Television": category = "14"; break; case "Video Games": category = "15"; break; case "Board Games": category = "16"; break; case "Comics": category = "29"; break; case "Japanese Anime and Manga": category = "31"; break; case "Cartoon and Animations": category = "32"; break; case "Computers": category = "18"; break; case "Mathematics": category = "19"; break; case "Gadgets": category = "30"; break; case "Art": category = "25"; break; case "Celebrities": category = "26"; break; case "Animals": category = "27"; break; case "Vehicles": category = "28"; break; case "Mythology": category = "20"; break; case "Sports": category = "21"; break; case "History": category = "23"; break; case "Geography": category = "22"; break; case "Politics": category = "24"; break; } break; case 'newQuestion': getQuestion(); break; case 'showQuestion': showQuestion(); break; case 'showAnswers': showAnswers(); startTimer(); Script.setTimeout(function() { showCorrect(); if (useGoogle) { tablet.emitScriptEvent("re-enableCustom"); } else { tablet.emitScriptEvent("re-enable"); } }, TEN_SECONDS_MS); break; default: print(JSON.stringify(event)); print("error in detecting event.type"); } } } } function onScreenChanged(type, url) { open = (url === appPage); button.editProperties({isActive: open}); if (open) { tablet.webEventReceived.connect(onWebEventReceived); } } function appEnding() { if (intervalBoard) { Script.clearInterval(intervalBoard); intervalBoard = false; } Messages.unsubscribe(TRIVIA_CHANNEL); clearGame(true); button.clicked.disconnect(onClicked); tablet.removeButton(button); AvatarManager.avatarRemovedEvent.disconnect(updateCountOnAvatarRemoved); tablet.screenChanged.disconnect(onScreenChanged); if (open) { tablet.webEventReceived.disconnect(onWebEventReceived); } Users.usernameFromIDReply.disconnect(setUserName); } function updateCountOnAvatarRemoved(){ updateAvatarCounter(false); } this.unload = function() { clearGame(true); introPlayed = false; }; findTargets(); Messages.subscribe(TRIVIA_CHANNEL); AvatarManager.avatarRemovedEvent.connect(updateCountOnAvatarRemoved); Users.usernameFromIDReply.connect(setUserName); button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); Script.scriptEnding.connect(appEnding); }());