Skip to content
Snippets Groups Projects
Commit f43a3ff7 authored by Eric Oulashin's avatar Eric Oulashin Committed by Rob Swindell
Browse files

Good Time Trivia 1.03: Fixes to score reading & parsing. Q&A files can have...

Good Time Trivia 1.03: Fixes to score reading & parsing. Q&A files can have more flexible metadata. Added more questions.
parent e8944f5b
No related branches found
No related tags found
2 merge requests!463MRC mods by Codefenix (2024-10-20),!241Good Time Trivia 1.03: Fixes to score reading & parsing. Q&A files can have more flexible metadata. Added more questions.
......@@ -27,6 +27,7 @@ scoreSoFarText=C
clueHdr=RH
clue=GH
answerAfterIncorrect=G
answerFact=G
[CATEGORY_ARS]
dirty_minds=AGE 18
......
......@@ -14,10 +14,25 @@ Date Author Description
2022-12-08 Eric Oulashin Version 1.02
The game can now post scores in (networked) message sub-boards as
a backup to using a JSON DB server in case the server can't be
contacted.
contacted.
2023-01-03 Eric Oulashin Version 1.03 beta
Started working on allowing Q&A files to have a section of JSON
metadata, and also for its answers to possibly be a section of
JSON containing multiple possible answers. JSON metadata in
a QA file may have the following properties (all optional):
category_name: The name of the category
ARS: An ARS string that can restrict usage of the category
"-- Answer metadata begin"/"-- Answer metadata end" sections
need to have an "answers" property, which is an array of
acceptable answers (as strings). It can also optionally have an
"answerFact" property, to specify an interesting fact about
the answer.
Fixed a bug in reading local scores and parsing them, which
affected saving local scores and showing local scores.
2023-01-14 Eric Oulashin Version 1.03
Releasing this version
*/
"use strict";
......@@ -41,8 +56,8 @@ if (system.version_num < 31500)
}
// Version information
var GAME_VERSION = "1.02";
var GAME_VER_DATE = "2022-12-08";
var GAME_VERSION = "1.03";
var GAME_VER_DATE = "2023-01-14";
// Determine the location of this script (its startup directory).
// The code for figuring this out is a trick that was created by Deuce,
......@@ -259,7 +274,7 @@ while (continueOn)
console.print("\x01n\x01cReturning to \x01y\x01h" + system.name + "\x01n\x01c...\x01n");
mswait(1000);
mswait(500);
// End of script execution.
......@@ -320,15 +335,15 @@ function playTrivia()
console.crlf();
// Load and parse the section filename into questions, answers, and points
var QAArray = parseQAFilename(qaFilenameInfo[chosenSectionIdx].filename);
var QAArray = parseQAFile(qaFilenameInfo[chosenSectionIdx].filename);
shuffle(QAArray);
console.print("There are " + QAArray.length + " questions in total.");
console.print("There are " + add_commas(QAArray.length, 0) + " questions in total.");
console.crlf();
// Each element in QAArray is an object with the following properties:
// question
// answer
// numPoints
console.print("\x01n\x01gWill ask \x01h" + gSettings.behavior.numQuestionsPerPlay + "\x01n\x01g questions.\x01n");
console.print("\x01n\x01gWill ask up to \x01h" + gSettings.behavior.numQuestionsPerPlay + "\x01n\x01g questions.\x01n");
console.crlf();
console.print("\x01n\x01gYou can answer \x01hQ\x01n\x01g at any time to quit.\x01n");
console.crlf();
......@@ -368,7 +383,12 @@ function playTrivia()
console.print("Clue:");
console.crlf();
console.attributes = "N" + gSettings.colors.clue;
console.print(partiallyHiddenStr(QAArray[i].answer, tryI-1) + "\x01n");
var clueAnswer = "";
if (typeof(QAArray[i].answer) === "string")
clueAnswer = QAArray[i].answer;
else if (Array.isArray(QAArray[i].answer))
clueAnswer = QAArray[i].answer[0];
console.print(partiallyHiddenStr(clueAnswer, tryI-1) + "\x01n");
console.crlf();
}
// Prompt for an answer
......@@ -410,9 +430,23 @@ function playTrivia()
console.print("The answer was:");
console.crlf();
console.attributes = "N";
printWithWordWrap(answerWhenIncorrectColor, QAArray[i].answer);
var theCorrectAnswer = "";
if (typeof(QAArray[i].answer) === "string")
theCorrectAnswer = QAArray[i].answer;
else if (Array.isArray(QAArray[i].answer))
theCorrectAnswer = QAArray[i].answer[0];
printWithWordWrap(answerWhenIncorrectColor, theCorrectAnswer);
console.attributes = "N";
}
if (QAArray[i].hasOwnProperty("answerFact") && typeof(QAArray[i].answerFact) === "string" && QAArray[i].answerFact.length > 0)
{
console.crlf();
console.attributes = "N" + gSettings.colors.questionHdr;
console.print("Fact:");
console.crlf();
printWithWordWrap(attrCodeStr("N" + gSettings.colors.answerFact), QAArray[i].answerFact, true);
console.crlf();
}
// Print the user's score so far
console.crlf();
......@@ -733,15 +767,75 @@ function getQACategoriesAndFilenames()
{
// Get the section name - Start by removing the .qa filename extension
var filenameExtension = file_getext(QAFilenames[i]);
// sectionName is the filename without the extension, but the section name can also be specified by
// JSON metadata in the Q&A file
var sectionName = file_getname(QAFilenames[i]);
var charIdx = sectionName.lastIndexOf(".");
if (charIdx > -1)
sectionName = sectionName.substring(0, charIdx);
// Currently, sectionName is the filename without the extension.
// Open the file to see if it has a JSON metadata section specifying a section name, etc.
// Note: If its metadata has an "ars" setting, then we'll use that instead of
// any ARS setting that may be in gttrivia.ini for this section.
var sectionARS = null;
var QAFile = new File(QAFilenames[i]);
if (QAFile.open("r"))
{
var fileMetadataStr = "";
var readingFileMetadata = false;
var haveSeenAllFileMetadata = false;
while (!QAFile.eof && !haveSeenAllFileMetadata)
{
var fileLine = QAFile.readln(2048);
// I've seen some cases where readln() doesn't return a string
if (typeof(fileLine) !== "string")
continue;
fileLine = fileLine.trim();
if (fileLine.length == 0)
continue;
//-- QA metadata begin" and "-- QA metadata end"
if (fileLine === "-- QA metadata begin")
{
fileMetadataStr = "";
readingFileMetadata = true;
continue;
}
else if (fileLine === "-- QA metadata end")
{
readingFileMetadata = false;
haveSeenAllFileMetadata = true;
continue;
}
else if (readingFileMetadata)
fileMetadataStr += fileLine + " ";
}
QAFile.close();
// If we've read all the file metadata lines, then parse it & use the metadata.
if (haveSeenAllFileMetadata && fileMetadataStr.length > 0)
{
try
{
var fileMetadataObj = JSON.parse(fileMetadataStr);
if (typeof(fileMetadataObj) === "object")
{
if (fileMetadataObj.hasOwnProperty("category_name") && typeof(fileMetadataObj.category_name) === "string")
sectionName = fileMetadataObj.category_name;
if (fileMetadataObj.hasOwnProperty("ARS") && typeof(fileMetadataObj.ARS) === "string")
sectionARS = fileMetadataObj.ARS;
}
}
catch (error) {}
}
}
// See if there is an ARS string for this in the configuration, and if so,
// only add it if the ARS string passes for the user.
var addThisSection = true;
if (gSettings.category_ars.hasOwnProperty(sectionName))
if (typeof(sectionARS) === "string")
addThisSection = bbs.compare_ars(sectionARS);
else if (gSettings.category_ars.hasOwnProperty(sectionName))
addThisSection = bbs.compare_ars(gSettings.category_ars[sectionName]);
// Add this section/category, if allowed
if (addThisSection)
......@@ -760,13 +854,16 @@ function getQACategoriesAndFilenames()
return sectionsAndFilenames;
}
// Parses a Q&A filename
// Parses a Q&A file with questions and answers
//
// Parameters:
// pQAFilenameFullPath: The full path & filename of the trivia Q&A file to read
//
// Return value: An array of objects containing the following properties:
// question: The trivia question
// answer: The answer to the trivia question
// numPoints: The number of points to award for the correct answer
function parseQAFilename(pQAFilenameFullPath)
function parseQAFile(pQAFilenameFullPath)
{
if (!file_exists(pQAFilenameFullPath))
return [];
......@@ -777,9 +874,14 @@ function parseQAFilename(pQAFilenameFullPath)
var QAFile = new File(pQAFilenameFullPath);
if (QAFile.open("r"))
{
var inFileMetadata = false; // Whether or not we're in the file metadata question (we'll skip all of this for the questions & answers)
var theQuestion = "";
var theAnswer = "";
var theNumPoints = -1;
var readingAnswerMetadata = false;
var doneReadintAnswerMetadata = false; // For immediately after done reading answer JSON
var answerIsJSON = false;
var component = "Q"; // Q/A/P for question, answer, points
while (!QAFile.eof)
{
var fileLine = QAFile.readln(2048);
......@@ -790,23 +892,69 @@ function parseQAFilename(pQAFilenameFullPath)
if (fileLine.length == 0)
continue;
// Skip any file metadata lines (those are read in getQACategoriesAndFilenames())
if (fileLine === "-- QA metadata begin")
{
inFileMetadata = true;
continue;
}
else if (fileLine === "-- QA metadata end")
{
inFileMetadata = false;
continue;
}
if (inFileMetadata)
continue;
if (theQuestion.length > 0 && theAnswer.length > 0 && theNumPoints > -1)
{
QA_Array.push(new QA(theQuestion, theAnswer, +theNumPoints));
addQAToArray(QA_Array, theQuestion, theAnswer, theNumPoints, answerIsJSON);
theQuestion = "";
theAnswer = "";
theNumPoints = -1;
readingAnswerMetadata = false;
doneReadintAnswerMetadata = false;
answerIsJSON = false;
component = "Q";
}
if (theQuestion.length == 0)
if (component === "Q")
{
theQuestion = fileLine;
else if (theAnswer.length == 0)
theAnswer = fileLine;
else if (theNumPoints < 1)
component = "A"; // Next, set answer
}
else if (component === "A")
{
// Possible JSON for multiple answers
if (fileLine === "-- Answer metadata begin")
{
readingAnswerMetadata = true;
answerIsJSON = true;
theAnswer = "";
continue;
}
else if (fileLine === "-- Answer metadata end")
{
readingAnswerMetadata = false;
doneReadintAnswerMetadata = true;
}
if (readingAnswerMetadata)
theAnswer += fileLine + " ";
else
{
if (doneReadintAnswerMetadata)
doneReadintAnswerMetadata = false;
else
theAnswer = fileLine;
component = "P"; // Next, set points
}
}
else if (component === "P")
{
theNumPoints = +(fileLine);
if (theNumPoints < 1)
theNumPoints = 10;
component = "Q"; // Next, set question
}
// Older: Each line in the format question,answer,numPoints
......@@ -829,18 +977,71 @@ function parseQAFilename(pQAFilenameFullPath)
QAFile.close();
// Ensure we've added the last question & answer, if there is one
if (theQuestion.length > 0 && theAnswer.length > 0 && theNumPoints > -1)
QA_Array.push(new QA(theQuestion, theAnswer, +theNumPoints));
addQAToArray(QA_Array, theQuestion, theAnswer, theNumPoints, answerIsJSON);
}
return QA_Array;
}
// QA object constructor
function QA(pQuestion, pAnswer, pNumPoints)
function QA(pQuestion, pAnswer, pNumPoints, pAnswerFact)
{
this.question = pQuestion;
this.answer = pAnswer;
this.numPoints = pNumPoints;
if (this.numPoints < 1)
this.numPoints = 10;
if (typeof(pAnswerFact) === "string" && pAnswerFact.length > 0)
this.answerFact = pAnswerFact;
}
// Helper for parseQAFile(): Adds a question, answer, and # points to the Q&A array
//
// Parameters:
// QA_Array (INOUT): The array to add the Q/A/Point sets to
// theQuestion: The question (string)
// theAnswer: The answer (string)
// theNumPoints: The number of points to award (number)
// answerIsJSON: Boolean - Whether or not theAnswer is in JSON format or not (if JSON, it contains
// multiple possible answers)
function addQAToArray(QA_Array, theQuestion, theAnswer, theNumPoints, answerIsJSON)
{
// If the answer is a JSON object, then there may be multiple acceptable answers specified
var addAnswer = true;
var answerFact = null;
if (answerIsJSON)
{
try
{
var answerObj = JSON.parse(theAnswer);
if (typeof(answerObj) === "object")
{
if (answerObj.hasOwnProperty("answers") && Array.isArray(answerObj.answers) && answerObj.answers.length > 0)
{
// Make sure all answers in the array are non-zero length
theAnswer = [];
for (var i = 0; i < answerObj.answers.length; ++i)
{
if (answerObj.answers[i].length > 0)
theAnswer.push(answerObj.answers[i]);
}
// theAnswer is an array
addAnswer = (theAnswer.length > 0);
}
else if (answerObj.hasOwnProperty("answer") && typeof(answerObj.answer) === "string" && answerObj.answer.length > 0)
theAnswer = answerObj.answer;
else
addAnswer = false;
if (answerObj.hasOwnProperty("answerFact") && answerObj.answerFact.length > 0)
answerFact = answerObj.answerFact;
}
else
addAnswer = false;
}
catch (error)
{
addAnswer = false;
}
}
if (addAnswer) // Note: theAnswer is converted to an object if it's JSON
QA_Array.push(new QA(theQuestion, theAnswer, +theNumPoints, answerFact));
}
// Shuffles an array
......@@ -871,6 +1072,11 @@ function shuffle(pArray)
// Match is case-insensitive. If it's a 1-word answer, then it should match exactly. Otherwise,
// a Levenshtein distance is used.
//
// Properties:
// pAnswer: The answer to the question. This can either be a string (for a single answer) or an array of
// strings (if multiple answers are acceptable)
// pUserInput: The user's response to the question (string)
//
// Return value: An object with the following properties:
// userChoseQuit: Boolean: Whether or not the user chose to quit
// userInputMatchedAnswer: Boolean: Whether or not the user's answer matches the given answer to the question
......@@ -881,14 +1087,13 @@ function checkUserResponse(pAnswer, pUserInput)
userInputMatchedAnswer: false
};
if (typeof(pAnswer) !== "string" || typeof(pUserInput) !== "string")
// pAnswer should be a string or an array, and pUserInput should be a string
if (!(typeof(pAnswer) === "string" || Array.isArray(pAnswer))|| typeof(pUserInput) !== "string")
return retObj;
if (pUserInput.length == 0)
return retObj;
// Convert both to uppercase for case-insensitive matching
var answerUpper = pAnswer.toUpperCase();
var userInputUpper = pUserInput.toUpperCase();
var userInputUpper = pUserInput.toUpperCase(); // For case-insensitive matching
if (userInputUpper == "Q")
{
......@@ -896,24 +1101,42 @@ function checkUserResponse(pAnswer, pUserInput)
return retObj;
}
// If there are spaces in the answer, then do a Levenshtein comparison. Otherwise,
// do an exact match.
if (answerUpper.indexOf(" ") > -1)
// In case there are multiple acceptable answers, make an array (or copy it) so
// we can check the user's response against all acceptable answers
var acceptableAnswers = null;
if (typeof(pAnswer) === "string")
acceptableAnswers = [ pAnswer.toUpperCase() ];
else if (Array.isArray(pAnswer))
{
var levDist = levenshteinDistance(answerUpper, userInputUpper);
retObj.userInputMatchedAnswer = (levDist <= MAX_LEVENSHTEIN_DISTANCE);
acceptableAnswers = [];
for (var i = 0; i < pAnswer.length; ++i)
acceptableAnswers.push(pAnswer[i].toUpperCase());
}
else
return retObj; // pAnswer isn't valid here, so just return with a 'false' response
// Check the user's response against the acceptable answers
for (var i = 0; i < acceptableAnswers.length && !retObj.userInputMatchedAnswer; ++i)
{
// There are no spaces in the answer. If the answer is 12 or shorter, use an exact match;
// otherwise, use a Levenshtein distance.
if (answerUpper.length <= 12)
retObj.userInputMatchedAnswer = (userInputUpper == answerUpper);
else
var answerUpper = acceptableAnswers[i].toUpperCase();
// If there are spaces in the answer, then do a Levenshtein comparison. Otherwise,
// do an exact match.
if (answerUpper.indexOf(" ") > -1)
{
var levDist = levenshteinDistance(answerUpper, userInputUpper);
retObj.userInputMatchedAnswer = (levDist <= MAX_LEVENSHTEIN_DISTANCE);
}
else
{
// There are no spaces in the answer. If the answer is 12 or shorter, use an exact match;
// otherwise, use a Levenshtein distance.
if (answerUpper.length <= 12)
retObj.userInputMatchedAnswer = (userInputUpper == answerUpper);
else
{
var levDist = levenshteinDistance(answerUpper, userInputUpper);
retObj.userInputMatchedAnswer = (levDist <= MAX_LEVENSHTEIN_DISTANCE);
}
}
}
return retObj;
......@@ -998,11 +1221,8 @@ function updateScoresFile(pUserCurrentGameScore, pLastSectionName)
{
if (scoresFile.open("r"))
{
var scoreFileArray = scoresFile.readAll();
var scoreFileContents = scoresFile.read(scoresFile.length);
scoresFile.close();
var scoreFileContents = "";
for (var i = 0; i < scoreFileArray.length; ++i)
scoreFileContents += (scoreFileArray[i] + "\n");
try
{
scoresObj = JSON.parse(scoreFileContents);
......@@ -1207,16 +1427,24 @@ function showLocalScores()
var scoresFile = new File(SCORES_FILENAME);
if (scoresFile.open("r"))
{
var scoreFileArray = scoresFile.readAll();
var scoreFileContents = scoresFile.read(scoresFile.length);
scoresFile.close();
var scoreFileContents = "";
for (var i = 0; i < scoreFileArray.length; ++i)
scoreFileContents += (scoreFileArray[i] + "\n");
var scoresObj = JSON.parse(scoreFileContents);
for (var prop in scoresObj)
try
{
sortedScores.push(new UserScoreObj(prop, scoresObj[prop].total_score, scoresObj[prop].last_score,
scoresObj[prop].last_trivia_category, scoresObj[prop].last_time));
var scoresObj = JSON.parse(scoreFileContents);
for (var prop in scoresObj)
{
sortedScores.push(new UserScoreObj(prop, scoresObj[prop].total_score, scoresObj[prop].last_score,
scoresObj[prop].last_trivia_category, scoresObj[prop].last_time));
}
}
catch (error)
{
log(LOG_ERR, GAME_NAME + " - Parsing local scores: Line " + error.lineNumber + ": " + error);
bbs.log_str(GAME_NAME + " - Parsing local scores scores: Line " + error.lineNumber + ": " + error);
console.attributes = "N" + gSettings.colors.error;
console.print("* Line: " + error.lineNumber + ": " + error);
console.crlf();
}
}
// Sort the array: High total score first
......@@ -1774,11 +2002,8 @@ function postGTTriviaScoresToSubBoard(pSubCode)
{
if (scoresFile.open("r"))
{
var scoreFileArray = scoresFile.readAll();
var scoreFileContents = scoresFile.read(scoresFile.length);
scoresFile.close();
var scoreFileContents = "";
for (var i = 0; i < scoreFileArray.length; ++i)
scoreFileContents += (scoreFileArray[i] + "\n");
try
{
scoresForThisBBS[BBS_ID].user_scores = JSON.parse(scoreFileContents);
......@@ -1990,6 +2215,17 @@ function readGTTriviaScoresFromSubBoard(pSubCode)
return scoreUpdateSucceeded;
}
function add_commas(val, pad)
{
var s = val.toString();
s = s.replace(/([0-9]+)([0-9]{3})$/,"$1,$2");
while (s.search(/[0-9]{4}/)!=-1)
s = s.replace(/([0-9]+)([0-9]{3}),/g,"$1,$2,");
while (s.length < pad)
s = " " + s;
return(s);
}
// Parses command-line arguments. Returns an object with settings/actions specified.
//
// Parameters:
......
-- QA metadata begin
{
"category_name": "Dirty Minds",
"ARS": "AGE 18"
}
-- QA metadata end
I can be used for stroking. You hold me by my hard end. If I'm too stiff, I can make you raw.
Hair brush
10
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
-- QA metadata begin
{
"category_name": "Star Trek (general)"
}
-- QA metadata end
In Gene Roddenberry's original treatment for Star Trek, what was the name of the Starship?
-- Answer metadata begin
{
"answers": ["Yorktown", "Starship Yorktown"]
}
-- Answer metadata end
10
Who was the first actor to play a member of all three of the major alien races in Star Trek?
Mark Lenard
10
What two stars of Star Trek: Deep Space Nine were married in real life in 1997?
-- Answer metadata begin
{
"answers": ["Alexander Siddig and Nana Visitor", "Nana Visitor and Alexander Siddig", "Alexander Siddig Nana Visitor", "Nana Visitor Alexander Siddig", "Alexander Siddig, Nana Visitor", "Nana Visitor, Alexander Siddig"]
}
-- Answer metadata end
10
What is Sulu's primary position on the U.S.S. Enterprise?
Helmsman
10
Which Star Trek captain has an artificial heart?
-- Answer metadata begin
{
"answers": ["Jean-Luc Picard", "Picard"]
}
-- Answer metadata end
10
Captain Picard has an artificial heart because a member of what species stabbed him?
Nausicaan
10
Who was the first real astronaut to appear in any Star Trek episode?
-- Answer metadata begin
{
"answers": ["Mae C Jemison", "Mae C. Jemison"]
}
-- Answer metadata end
10
NBC rejected the pilot for "Star Trek." What famous comedian got them to take another look?
Lucille Ball
10
What is Deanna Troi's favorite food?
Chocolate
10
What weapon did Kirk and Spock use when they fought for possession of T'Pring during Spock's Pon farr ritual in "Amok Time"?
A lirpa
10
Who was originally cast as Captain Janeway?
Genevieve Bujold
10
Which character serves as the head of security for the space station Deep Space Nine?
Odo
10
Who created the Bajoran wormhole?
-- Answer metadata begin
{
"answers": ["Prophets", "The Prophets"]
}
-- Answer metadata end
10
What type of weapons technology does a phaser use?
Particle-beam weapons
10
In which Star Trek series did writer Larry Niven introduce the cat-like alien race, the Kzinti, into the Star Trek universe?
-- Answer metadata begin
{
"answers": ["Animated Series", "The Animated Series", "Star Trek: The Animated Series", "TAS"]
}
-- Answer metadata end
10
What species, known to the Borg as "species 329", were deemed unworthy of assimilation?
-- Answer metadata begin
{
"answers": ["Kazon", "The Kazon"]
}
-- Answer metadata end
10
In the Mirror universe, what has replaced the United Federation of Planets?
Terran Empire
10
What was the name of Data's cat?
Spot
10
Even though Klingon is a real language you can speak now, what Trek actor help create it?
James Doohan
10
What is Lieutenant Uhura's first name?
Nyota
15
What was Seven of Nine's name before she was assimilated by the Borg?
Annika Hansen
10
Who was the first Vulcan science officer aboard the starship Enterprise?
T'Pol
10
Who was the first Star Trek actor to write a Star Trek story?
Walter Koenig
10
What future Starfleet captain survived the Battle of Wolf 359?
-- Answer metadata begin
{
"answers": ["Sisko", "Benjamin Sisko", "Ben Sisko"]
}
-- Answer metadata end
10
Who serves as the communications officer in the final episode of Star Trek: The Original Series?
-- Answer metadata begin
{
"answers": ["Lisa", "Lt. Lisa", "Lt Lisa", "Lieutenant Lisa"]
}
-- Answer metadata end
10
Which of the following was not a founding species of the United Federation of Planets? Andorians, Tellarites, Bajorans, or Vulcans?
-- Answer metadata begin
{
"answers": ["Bajorans", "The Bajorans"]
}
-- Answer metadata end
10
Which alien race did Ronald Reagan say reminded him of Congress?
Klingons
10
Who played Captain Pike's first officer in "The Cage?"
-- Answer metadata begin
{
"answers": ["Majel Barrett"],
"answerFact": "Majel Barrett was Star Trek creator Gene Roddenberry's wife in real life"
}
-- Answer metadata end
10
Whose voice was the voice of the computer in most of the Original Series and in The Animated Series, The Next Gneration, Deep Space 9, Voyager, and Enterprise?
-- Answer metadata begin
{
"answers": ["Majel Barrett"],
"answerFact": "Majel Barrett, Gene Roddenberry's wife, made phonetic recordings of her voice in 2016 so that her voice could continue to be used. Rod Roddenberry (her and Gene's son) made the recordings with her."
}
-- Answer metadata end
10
Before Kirk, who was Captain of the Enterprise in the pilot episode of the original Star Trek series?
-- Answer metadata begin
{
"answers": ["Christopher Pike", "Captain Pike", "Captain Christopher Pike"]
}
-- Answer metadata end
10
Which comedian had a role written for them in "Star Trek IV" that they ultimately turned down?
Eddie Murphy
10
Which Star Trek captain suffers from androgenic alopecia?
Captain Picard
10
What character dies in the series finale of Star Trek: Enterprise?
-- Answer metadata begin
{
"answers": ["Trip Tucker", "Charles Trip Tucker III", "Charles Trip Tucker the third", "Trip"]
}
-- Answer metadata end
10
Who is the youngest captain in Starfleet history?
-- Answer metadata begin
{
"answers": ["James Kirk", "James T Kirk", "James T. Kirk", "James Tiberius Kirk", "Jim Kirk", "Captain Kirk", "Kirk"]
}
-- Answer metadata end
10
What actress turned down the role of Seven of Nine four times?
Jeri Ryan
10
Who is captain Jonathan Archer (of the NX-01 in "Star Trek: Enterprise") played by?
Scott Bakula
10
What famous character was named after a pilot Gene Roddenberry had met during WWII?
-- Answer metadata begin
{
"answers": ["Khan", "Khan Noonien Singh"]
}
-- Answer metadata end
10
Which Trek movie featured the first entirely CG sequence in film history?
-- Answer metadata begin
{
"answers": ["Wrath of Khan", "The Wrath of Khan"]
}
-- Answer metadata end
10
What was Majel Barrett's first role on Star Trek?
-- Answer metadata begin
{
"answers": ["First officer", "1st officer", "Number One, Captain Pike's first officer", "Number One", "Number 1", "Captain Pike's first officer", "Pike's first officer", "Pike's 1st officer"]
}
-- Answer metadata end
10
What is the Klingon homeworld?
-- Answer metadata begin
{
"answers": ["Kronos", "Q'onoS", "Qo'noS"]
}
-- Answer metadata end
10
What type of fish does Captain Picard keep in his ready room?
Lionfish
10
Which Star Trek character was trapped in a transporter buffer for 75 years?
-- Answer metadata begin
{
"answers": ["Montgomery Scott", "Scotty"]
}
-- Answer metadata end
10
What is Mr. Chekhov's first name?
Pavel
10
What is Mr. Chekov's full name?
Pavel Andreievich Chekov
10
What is Captain Kirk's middle name?
Tiberius
5
Which Star Trek captain loves baseball?
-- Answer metadata begin
{
"answers": ["Sisko", "Benjamin Sisko", "Ben Sisko", "Captain Sisko"]
}
-- Answer metadata end
10
What medical condition did William Shatner and Leonard Nimoy both suffer as a result of standing too close to a special effect explosion?
Tinnitus
10
Who was Spock's mother?
Amanda Grayson
10
Which Star Trek series has a female Chief Engineer?
Voyager
10
Which Chief Medical Officer is a Denobulan?
Phlox
10
Which Star Trek captain was forced to impersonate a historical figure to preserve the timeline?
-- Answer metadata begin
{
"answers": ["Sisko", "Benjamin Sisko", "Ben Sisko", "Captain Sisko"]
}
-- Answer metadata end
10
What character asks Data if he is "fully functional"?
Tasha Yar
10
Who was the first Kelpien to enter Starfleet?
Saru
10
What were the last words of the last episode of Star Trek: The Original Series?
If only
10
Who was originally offered the role of Spock?
Martin Landau
10
Which species was the first to discover warp drive?
Vulcans
10
According to Klingon mythology, what is the place where all life began?
QI'tu'
10
Thanks to Trek fans, NASA named a space shuttle "Enterprise." What was it going to be called before?
Constitution
10
Which Trek actor was shot six times on D-Day?
-- Answer metadata begin
{
"answers": ["James Doohan"],
"answerFact": "James Doohan came up with the basic sounds of the Vulcan and Klingon languages for The Motion Picture"
}
-- Answer metadata end
10
Which Next Generation species was meant to be introduced as a replacement for Klingons as a major enemy?
Ferengi
10
What Star Trek character was labeled "unknown sample" when discovered by Bajoran scientists?
Odo
10
According to results from the 2013 Star Trek Convention, what was the 7th best "Star Trek " film ever?
Galaxy Quest
10
What was the first ship James T. Kirk served on?
-- Answer metadata begin
{
"answers": ["Farragut", "U.S.S. Farragut", "USS Farragut"]
}
-- Answer metadata end
10
What ship is Sulu assigned when he's promoted to captain?
-- Answer metadata begin
{
"answers": ["Excelsior", "U.S.S. Excelsior", "USS Excelsior"]
}
-- Answer metadata end
10
Which infamous episode of "The Next Generation" is considered the series' worst?
Shades of Grey
10
What type of pet does Captain Archer have on Enterprise?
Beagle
10
Which character has appeared in more episodes than any other in all of Trek history?
Worf
10
In what year was Star Trek: The Motion Picture released?
1979
10
What actor from Star Trek: The Original Series lost his right middle finger during World War II?
James Doohan
10
Which TNG actor was so convinced the show would fail they never bothered to unpack their bags for over a month?
Patrick Stewart
10
Trek famously reuses actors in many alien roles. Who was the first to play a Vulcan, a Romulan, and a Klingon?
Mark Lenard
10
Captain Picard played a flute in an episode of "The Next Generation" that went up for auction in 2006. How much money did it go for?
-- Answer metadata begin
{
"answers": ["48,000 dollars", "48000 dollars", "$48,000", "$48000", "48000"]
}
-- Answer metadata end
10
How many different characters has actor Jeffrey Combs played in the "Star Trek" universe?
-- Answer metadata begin
{
"answers": ["Eight", "8"]
}
-- Answer metadata end
10
What character was adopted by the Vulcan ambassador Sarek?
Michael Burnham
10
What is the name of the Klingon Commander who ordered the death of Kirk's son David?
Commander Kruge
10
What species' motto is 'Victory is life'?
-- Answer metadata begin
{
"answers": ["Jem'Hadar", "Jem Hadar"]
}
-- Answer metadata end
10
Chief O'Brien's wife, Keiko, is the station's schoolteacher, but what is her trained profession?
Botanist
10
What mentor to Benjamin Sisko was the host of the Dax symbiote before Jadzia?
Curzon
10
What ship was Picard on before the Enterprise?
-- Answer metadata begin
{
"answers": ["Stargazer", "The Stargazer"]
}
-- Answer metadata end
10
Ziyal is the daughter of which evil mastermind?
Gul Dukat
10
What does Deanna love almost as much as life itself?
-- Answer metadata begin
{
"answers": ["Chocolate", "Chocolates"]
}
-- Answer metadata end
10
What is the name of the first "Star Trek" movie?
-- Answer metadata begin
{
"answers": ["The Motion Picture", "Star Trek: The Motion Picture"]
}
-- Answer metadata end
10
What is the name of the vessel that makes first contact with the Vulcans in "Star Trek: First Contact"?
-- Answer metadata begin
{
"answers": ["Phoenix", "The Phoenix"]
}
-- Answer metadata end
10
Under the Treaty of Armens established between the Federation and the Sheliak Corporate, what planet does the Federation cede?
-- Answer metadata begin
{
"answers": ["Tau Cygna V", "Tau Cygna 5"]
}
-- Answer metadata end
10
What influential member of the Duras family does Mogh suspect has conspired with the Romulans to overthrow the Klingon emperor?
Ja'rod
10
Who was the first Starfleet captain to encounter the Borg after the events in "Star Trek: First Contact" slightly altered linear history?
-- Answer metadata begin
{
"answers": ["Archer", "Jonathan Archer", "Jon Archer"]
}
-- Answer metadata end
10
Which is the only crew member of the Enterprise-D ever to attempt suicide and succeed?
Dan Kwan
10
Which of the following is related to Guinan, the El-Aurian Enterprisde-D bartender?
Terkim
10
Which "Deep Space Nine" crew member goes MIA during the course of the series?
-- Answer metadata begin
{
"answers": ["Sisko", "Benjamin Sisko", "Ben Sisko", "Captain Sisko"]
}
-- Answer metadata end
10
What was the unusual property of the drink known as a Samarian sunset?
-- Answer metadata begin
{
"answers": ["Changed color", "It changed color", "Changes color", "It changes color"]
}
-- Answer metadata end
10
In "Star Trek: Voyager", Captain Janeway is well known for drinking coffee. She wasn't the only one though. Who had a two pot limit per day of a type of coffee called Landras blend?
-- Answer metadata begin
{
"answers": ["Torres", "Lt. Torres", "Lt Torres", "Lieutenant Torres", "B'Elanna Torres"]
}
-- Answer metadata end
10
Who is the engineer aboard the U.S.S Enterprise-E?
Geordi La Forge
10
Naomi Wildman appears aboard which starship?
Voyager
10
We all know Deanna's mother made several appearances and other mothers appeared from time to time. Whose mother did we never see played by an actress?
-- Answer metadata begin
{
"answers": ["Beverly's", "Beverly", "Beverly Crusher's", "Beverly Crusher"]
}
-- Answer metadata end
10
Worf hadn't always worn a gold uniform. What color did he wear in the first season?
Red
10
In what season of The Next Generation did Riker first appear with his beard?
-- Answer metadata begin
{
"answers": ["Second", "2nd", "2"]
}
-- Answer metadata end
10
Which crewmember was it implied that Data became intimate with?
-- Answer metadata begin
{
"answers": ["Tasha Yar", "Yar"]
}
-- Answer metadata end
10
Who did Data serve as 'father of the bride' for?
Keiko
10
In the episode where Data was having dreams, who did he dream was a cake?
-- Answer metadata begin
{
"answers": ["Troi", "Deanna Troi"]
}
-- Answer metadata end
10
Which famous mystery character does Data like to be in the holodeck?
Sherlock Holmes
10
Which of the following body parts is the oldest on Data's body?
-- Answer metadata begin
{
"answers": ["Head", "His head"]
}
-- Answer metadata end
10
Q was responsible for introducing the crew of the Enterprise D to which race?
-- Answer metadata begin
{
"answers": ["Borg", "The Borg"]
}
-- Answer metadata end
10
Where is the Borg's native territory?
-- Answer metadata begin
{
"answers": ["Delta Quadrant", "The Delta Quadrant"]
}
-- Answer metadata end
10
What gift did Chakotay present to the Captain in 'Year of Hell' as a birthday present?
Pocket watch
10
What is the given name of the Bajoran liaison officer of Deep Space Nine?
Nerys
10
What is the military rank of Doctor Julian Bashir?
Lieutenant
10
Who invented the duotronic computer system used on the USS Enterprise?
Richard Daystrom
10
What is the Vulcan marriage ritual called?
Koon-ut-kal-if-fee
15
What was the name of the wheat like grain in the episode 'The Trouble with Tribbles'?
Quadrotriticale
10
What was Max's nickname for B'Elanna in 'Equinox'?
BLT
15
What is the name of the race that the Kazon hate?
Trabe
10
In the episode 'Author, Author,' what is the name of the ship the Doc uses in his holonovel?
Vortex
10
What were the name for the people that inhabited the water world?
Monean
10
What was the name of the device used to circumvent the memories of the Voyager crew in the episode 'The Killing Game'?
Neural Interface
10
What name does the Q, who is granted asylum aboard 'Voyager', adopt once he becomes human in the episode 'Death Wish'?
Quinn
10
Who is the quote on 'Voyager's' registration plaque by?
Alfred Lord Tennyson
15
What was the name of Chakotay's father?
Kolopak
10
This diff is collapsed.
This diff is collapsed.
Good Time Trivia
Version 1.02
Release date: 2022-12-08
Version 1.03
Release date: 2023-01-05
by
......@@ -150,8 +150,33 @@ of the following files and directories:
The trivia category files (in the qa directory, with filenames ending in .qa)
are plain text files and contain questions, their answers, and their number of
points. For eqch question in a category file, there are 3 lines:
are plain text files.
Optionally, a QA file may have a section of metadata specified in JSON
(JavaScript Object Notation) format that can contain some information about the
question category. The information can have the following properties:
category_name: The name of the category (if different from simple parsing of
the filename)
ARS: Optional - An ARS security string to restrict access to the question set.
This overrides any setting for the question set in the [CATEGORY_ARS]
section in gttrivia.ini.
This JSON must be between two lines:
-- QA metadata begin
-- QA metadata end
For example, for a test category you might want to restrict to only the sysop:
-- QA metadata begin
{
"category_name": "Test category (not meant for use)",
"ARS": "SYSOP"
}
-- QA metadata end
The questions and answers inside the QA files contain questions, their answers,
and their number of points. For eqch question in a category file, the main
format is 3 lines:
Question
Answer
Number of points
......@@ -162,6 +187,40 @@ What color is the sky?
Blue
5
Alternately, the answer can be specified via JSON (JavaScript Object Notation)
with multiple acceptable answers, and optionally a fact about the answer. When
JSON is specified for the answer, there need to be two text lines to specify
that the answer is JSON:
-- Answer metadata begin
-- Answer metadata end
One example where this can be used is to specify an answer that is a number and
you want to allow both spelling out the number and the number itself. Also, in
some cases it can be good to specify the spelled-out version first (if it's
short) since that will be used for the clue. For example:
How many sides does a square have?
-- Answer metadata begin
{
"answers": ["Four", "4"]
}
-- Answer metadata end
5
An example of a question specifying an answer with a fact specified:
Who's picture is on the US $50 bill?
-- Answer metadata begin
{
"answers": ["Ulysses Grant", "Ulysses S. Grant", "Ulysses S Grant"],
"answerFact": "The US capitol building is on the other side of the $50 bill"
}
-- Answer metadata end
5
NOTE: The questions and answers must be specified in exactly either of the two
above formats, or else the questions and answers will not be read correctly.
Also, there is a script in the qa directory called converter.js. This is a
rough script that can be modified to convert a list of trivia questions into
the format that can be used by this door. It is not a generic script; if you
......@@ -304,6 +363,8 @@ scoreSoFarText "Your score so far" text
clueHdr Header text for clues
clue Clue text
answerAfterIncorrect The answer printed after incorrect response
answerFact Fact displayed after an answer (not all
questions will have one)
[CATEGORY_ARS] section
----------------------
......
......@@ -4,6 +4,17 @@ Revision History (change log)
=============================
Version Date Description
------- ---- -----------
1.03 2023-01-05 Question sets (in the .qa files) may now have a section
of JSON metadata to specify the name of the category (if
different from simple filename parsing) and optionally
an ARS security string (overrides gttrivia.ini). Also,
answers can be specified as a JSON section to specify
multiple acceptable answers, and optionally a fact about
the answer/question. A new color setting, answerFact,
specifies the color to use to output the answer fact.
1.02 2022-12-08 The game can now post scores in (networked) message sub-
boards as a backup to using a JSON DB server in case the
server can't be contacted.
1.01 2022-11-25 Added the ability to store & retrieve scores to/from a
server, so that scores from multiple BBSes can be
displayed. By default, it's configured to use Digital
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment