Skip to content

Instantly share code, notes, and snippets.

@marko-knoebl
Created October 11, 2022 18:25
Show Gist options
  • Save marko-knoebl/be724c96331899caf89ac40765bc9b02 to your computer and use it in GitHub Desktop.
Save marko-knoebl/be724c96331899caf89ac40765bc9b02 to your computer and use it in GitHub Desktop.
Akinator project where two aspects have been extracted into separate functions
/*
* akinator.js
* Copyright (C) 2022 Martin Užák uzak+git@mailbox.org
*
* Distributed under terms of the MIT license.
*/
"use strict";
const prompt = require("prompt-sync")();
let positiveAttrs = [];
let negativeAttrs = [];
let objects = [
{
name: "donkey",
attrs: ["animal", "grey"],
},
{
name: "horse",
attrs: ["animal", "fast", "big"],
},
{
name: "wolf",
attrs: ["animal", "carnivoure", "grey"],
},
{
name: "elephant",
attrs: ["animal", "grey", "big"],
},
];
while (true) {
// main loop
// filter objects
let matches = [];
for (let obj of objects) {
let add = true;
for (let posAttr of positiveAttrs) {
if (!obj.attrs.includes(posAttr)) {
add = false;
break;
}
}
for (let negAttr of negativeAttrs) {
if (obj.attrs.includes(negAttr)) {
add = false;
break;
}
}
if (add) {
matches.push(obj);
}
}
console.log(matches);
// TODO: ignore attributes available for all objects
// handle matches
if (matches.length === 0) {
console.info("I'm sorry, I've no idea what you're thinking of");
} else if (matches.length === 1) {
console.info(`I think you were you thinking of ${matches[0].name}`);
break; // exit main loop
} else {
// ask another question
// first: find all available attributes for asking
let availableAttrs = [];
for (let match of matches) {
for (let attr of match.attrs) {
if (
!positiveAttrs.includes(attr) &&
!negativeAttrs.includes(attr) &&
!availableAttrs.includes(attr)
) {
availableAttrs.push(attr);
}
}
}
console.log(`availableAttrs: ${availableAttrs}`);
if (availableAttrs.length === 0) {
console.error("No avail attr. This should not happen");
}
// obtain answer
let attr = availableAttrs[0]; // choose attr. TODO randomly
let answer = promptIfInputIsValid(
`Is what you're thinking of '${attr}' [y/n/q-uit]: `
);
// process answer
processAnswer(answer, attr);
}
}
/**
* Prompt the user for an answer.
* Check if the answer is "y", "n", "q".
* If not, ask again.
* Return "y" / "n" / "q"
*/
function promptIfInputIsValid(question) {
let ans;
while (true) {
ans = prompt(question);
if (!["n", "y", "q"].includes(ans)) {
console.log("Please answer 'y' or 'n' or 'q'.");
continue;
}
break;
}
return ans;
}
function processAnswer(ans, attr) {
if (ans === "q") {
process.exit(0);
} else if (ans === "y") {
positiveAttrs.push(attr);
} else if (ans === "n") {
negativeAttrs.push(attr);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment