389 lines
13 KiB
JavaScript
389 lines
13 KiB
JavaScript
//
|
|
// trivia.js
|
|
//
|
|
// Created by Rebecca Stankus on 06/11/18
|
|
// 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
|
|
|
|
/* global EventBridge */
|
|
|
|
(function() {
|
|
var TRIVIA_CHANNEL = "TriviaChannel";
|
|
var TABLET_BUTTON_IMAGE = Script.resolvePath('assets/icons/questionMark-i.png?1234');
|
|
var TABLET_BUTTON_PRESSED = Script.resolvePath('assets/icons/questionMark-a.png?1234');
|
|
var CORRECT_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/correct.wav'));
|
|
var WRONG_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/audio1.wav'));
|
|
var TIMER_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/timer.wav'));
|
|
var GAME_BEGIN_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/welcome.wav'));
|
|
var NEXT_ROUND_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/ding.wav'));
|
|
var GAME_OVER_SOUND = SoundCache.getSound(Script.resolvePath('assets/sounds/oohAah.wav?3425'));
|
|
var SEARCH_RADIUS = 100;
|
|
var ONE_HUNDRED = 100;
|
|
var TEN_SECONDS_MS = 10000;
|
|
|
|
var audioVolume = 0.7;
|
|
var tablet = Tablet.getTablet('com.highfidelity.interface.tablet.system');
|
|
var appPage = Script.resolvePath('trivia.html?009');
|
|
var button = tablet.addButton({
|
|
text: 'TRIVIA',
|
|
icon: TABLET_BUTTON_IMAGE,
|
|
activeIcon: TABLET_BUTTON_PRESSED
|
|
});
|
|
var open = false;
|
|
var injector;
|
|
var questionText;
|
|
var choiceTexts = [];
|
|
var answerText;
|
|
var triviaData;
|
|
var request = Script.require('./modules/request.js').request;
|
|
var type = null;
|
|
var category = null;
|
|
var difficulty = null;
|
|
var currentChoices = [];
|
|
var podiumQuestions = [];
|
|
var podiumReveals = [];
|
|
|
|
var htmlEnDeCode = (function() {
|
|
var charToEntityRegex,
|
|
entityToCharRegex,
|
|
charToEntity,
|
|
entityToChar;
|
|
|
|
function resetCharacterEntities() {
|
|
charToEntity = {};
|
|
entityToChar = {};
|
|
// add the default set
|
|
addCharacterEntities({
|
|
'&': '&',
|
|
'>': '>',
|
|
'<': '<',
|
|
'"': '"',
|
|
''': "'",
|
|
'‘': '"',
|
|
'’': '"',
|
|
'“': '"',
|
|
'”': '"',
|
|
'é': 'e',
|
|
'′': '\'',
|
|
'&Prime': '"'
|
|
});
|
|
}
|
|
|
|
function addCharacterEntities(newEntities) {
|
|
var charKeys = [],
|
|
entityKeys = [],
|
|
key, echar;
|
|
for (key in newEntities) {
|
|
echar = newEntities[key];
|
|
entityToChar[key] = echar;
|
|
charToEntity[echar] = key;
|
|
charKeys.push(echar);
|
|
entityKeys.push(key);
|
|
}
|
|
charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
|
|
entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
|
|
}
|
|
|
|
function htmlEncode(value) {
|
|
var htmlEncodeReplaceFn = function(match, capture) {
|
|
return charToEntity[capture];
|
|
};
|
|
|
|
return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
|
|
}
|
|
|
|
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() {
|
|
playSound(GAME_BEGIN_SOUND);
|
|
findTargets();
|
|
clearGame();
|
|
}
|
|
|
|
function findTargets() {
|
|
podiumQuestions = [];
|
|
podiumReveals = [];
|
|
Entities.findEntities(MyAvatar.position, SEARCH_RADIUS).forEach(function(element) {
|
|
var name = Entities.getEntityProperties(element, ['name']).name;
|
|
switch (name) {
|
|
case "Trivia Question":
|
|
questionText = element;
|
|
break;
|
|
case "Trivia Answer":
|
|
answerText = element;
|
|
break;
|
|
case "Trivia Choice Text 1":
|
|
choiceTexts[0] = element;
|
|
break;
|
|
case "Trivia Choice Text 2":
|
|
choiceTexts[1] = element;
|
|
break;
|
|
case "Trivia Choice Text 3":
|
|
choiceTexts[2] = element;
|
|
break;
|
|
case "Trivia Choice Text 4":
|
|
choiceTexts[3] = element;
|
|
break;
|
|
case "Trivia Podium Question":
|
|
podiumQuestions.push(element);
|
|
break;
|
|
case "Trivia Podium Reveal":
|
|
podiumReveals.push(element);
|
|
break;
|
|
}
|
|
});
|
|
print("number of podium questions: ", podiumQuestions.length);
|
|
}
|
|
|
|
function onClicked() {
|
|
if (open) {
|
|
tablet.gotoHomeScreen();
|
|
} else {
|
|
tablet.gotoWebScreen(appPage);
|
|
}
|
|
}
|
|
|
|
function getQuestion() {
|
|
try {
|
|
var 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) {
|
|
tablet.emitScriptEvent(JSON.stringify(data.results[0]));
|
|
triviaData = data.results;
|
|
}
|
|
});
|
|
} 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() {
|
|
var formattedQuestion = htmlEnDeCode.htmlDecode(triviaData[0].question);
|
|
Entities.editEntity(questionText, { text: formattedQuestion });
|
|
Entities.editEntity(answerText, {
|
|
text: "",
|
|
visible: false
|
|
});
|
|
if (triviaData[0].type === "boolean") {
|
|
Entities.editEntity(choiceTexts[0], {
|
|
text: "",
|
|
visible: false
|
|
});
|
|
Entities.editEntity(choiceTexts[1], {
|
|
text: "True",
|
|
visible: true
|
|
});
|
|
Entities.editEntity(choiceTexts[2], {
|
|
text: "False",
|
|
visible: true
|
|
});
|
|
Entities.editEntity(choiceTexts[3], {
|
|
text: "",
|
|
visible: false
|
|
});
|
|
currentChoices = [];
|
|
currentChoices.push("True");
|
|
currentChoices.push("False");
|
|
} else {
|
|
currentChoices = [];
|
|
currentChoices.push(htmlEnDeCode.htmlDecode(triviaData[0].correct_answer));
|
|
triviaData[0].incorrect_answers.forEach(function(choice) {
|
|
currentChoices.push(htmlEnDeCode.htmlDecode(choice));
|
|
});
|
|
shuffle(currentChoices);
|
|
currentChoices.forEach(function(choice, index) {
|
|
Entities.editEntity(choiceTexts[index], {
|
|
text: choice,
|
|
visible: true
|
|
});
|
|
});
|
|
}
|
|
Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({
|
|
type: "newQuestion",
|
|
question: formattedQuestion,
|
|
choices: currentChoices
|
|
}));
|
|
startTimer();
|
|
Script.setTimeout(function() {
|
|
Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({type: "reveal"}));
|
|
}, TEN_SECONDS_MS);
|
|
}
|
|
|
|
function clearGame() {
|
|
podiumQuestions.forEach(function(textEntity) {
|
|
print("clearing podium question: ", textEntity);
|
|
Entities.editEntity(textEntity, {
|
|
text: "Questions will appear here"
|
|
});
|
|
});
|
|
podiumReveals.forEach(function(textEntity) {
|
|
print("clearing podium reveal: ", textEntity);
|
|
Entities.editEntity(textEntity, {
|
|
text: "?",
|
|
backgroundColor: { red: 131, blue: 252, green: 238 }
|
|
});
|
|
});
|
|
Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({type: "clearPodium"}));
|
|
Entities.editEntity(questionText, { text: "Questions will appear here" });
|
|
choiceTexts.forEach(function(choice) {
|
|
Entities.editEntity(choice, {
|
|
text: "Answers appear here",
|
|
visible: true
|
|
});
|
|
});
|
|
Entities.editEntity(answerText, {
|
|
text: "",
|
|
visible: false
|
|
});
|
|
}
|
|
|
|
function startTimer() {
|
|
playSound(TIMER_SOUND);
|
|
}
|
|
|
|
function showCorrect() {
|
|
var formattedAnswer = htmlEnDeCode.htmlDecode(triviaData[0].correct_answer);
|
|
Messages.sendMessage(TRIVIA_CHANNEL, JSON.stringify({
|
|
type: "check",
|
|
correct: formattedAnswer
|
|
}));
|
|
Entities.editEntity(answerText, {
|
|
text: formattedAnswer,
|
|
visible: true
|
|
});
|
|
}
|
|
|
|
function onWebEventReceived(event) {
|
|
if (typeof event === 'string') {
|
|
event = JSON.parse(event);
|
|
switch (event.type) {
|
|
case 'begin':
|
|
begin();
|
|
break;
|
|
case 'type':
|
|
if (event.selectedIndex === 0) {
|
|
category = null;
|
|
} else {
|
|
type = event.value;
|
|
}
|
|
break;
|
|
case 'difficulty':
|
|
if (event.selectedIndex === 0) {
|
|
category = null;
|
|
} else {
|
|
difficulty = event.value;
|
|
}
|
|
break;
|
|
case 'category':
|
|
if (event.selectedIndex === 0) {
|
|
category = null;
|
|
} else {
|
|
category = event.value;
|
|
}
|
|
break;
|
|
case 'newQuestion':
|
|
getQuestion();
|
|
break;
|
|
case 'showQuestion':
|
|
showQuestion();
|
|
break;
|
|
case 'showCorrect':
|
|
showCorrect();
|
|
break;
|
|
case 'correctAnswer':
|
|
playSound(CORRECT_SOUND);
|
|
break;
|
|
case 'wrongAnswer':
|
|
playSound(WRONG_SOUND);
|
|
break;
|
|
case 'gameBegin':
|
|
playSound(GAME_BEGIN_SOUND);
|
|
break;
|
|
case 'nextRound':
|
|
playSound(NEXT_ROUND_SOUND);
|
|
break;
|
|
case 'gameEnd':
|
|
playSound(GAME_OVER_SOUND);
|
|
break;
|
|
case 'volumeSlider':
|
|
if (injector) {
|
|
injector.setOptions( { volume: event.volume / ONE_HUNDRED } );
|
|
}
|
|
break;
|
|
default:
|
|
print("error in detecting event.type");
|
|
}
|
|
}
|
|
}
|
|
|
|
function onScreenChanged(type, url) {
|
|
open = (url === appPage);
|
|
button.editProperties({isActive: open});
|
|
}
|
|
|
|
function appEnding() {
|
|
Messages.unsubscribe(TRIVIA_CHANNEL);
|
|
clearGame();
|
|
button.clicked.disconnect(onClicked);
|
|
tablet.removeButton(button);
|
|
tablet.screenChanged.disconnect(onScreenChanged);
|
|
tablet.webEventReceived.disconnect(onWebEventReceived);
|
|
}
|
|
|
|
function playSound(sound) {
|
|
if (sound.downloaded) {
|
|
if (injector) {
|
|
injector.stop();
|
|
}
|
|
injector = Audio.playSound(sound, {
|
|
position: MyAvatar.position,
|
|
volume: audioVolume
|
|
});
|
|
}
|
|
}
|
|
|
|
Messages.subscribe(TRIVIA_CHANNEL);
|
|
button.clicked.connect(onClicked);
|
|
tablet.screenChanged.connect(onScreenChanged);
|
|
tablet.webEventReceived.connect(onWebEventReceived);
|
|
|
|
Script.scriptEnding.connect(appEnding);
|
|
}());
|