Last active
November 23, 2017 21:02
-
-
Save jakwuh/f56047dfb0dc3a375a59178417a246d5 to your computer and use it in GitHub Desktop.
Akinator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<title>Akinator</title> | |
</head> | |
<body> | |
<span id="question"></span> | |
<br> | |
<button id="firstButton" type="button" name="button"></button> | |
<button id="secondButton" type="button" name="button"></button> | |
<script src="./index.js" charset="utf-8"></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let $$question = document.querySelector('#question'); | |
let $$firstButton = document.querySelector('#firstButton'); | |
let $$secondButton = document.querySelector('#secondButton'); | |
function ask(question, [first, second]) { | |
$$question.innerHTML = question; | |
$$firstButton.innerHTML = first; | |
$$secondButton.innerHTML = second; | |
return new Promise((resolve) => { | |
$$firstButton.onclick = () => resolve(first); | |
$$secondButton.onclick = () => resolve(second); | |
}); | |
} | |
let parseFeatures = lines => { | |
return lines.split('\n').map(line => { | |
let [name, question, ...options] = line.split(';'); | |
return {name, question, options}; | |
}).reduce((memo, current) => { | |
return Object.assign(memo, {[current.name]: current}); | |
}, {}) | |
} | |
let splitConditions = conditions => conditions.split(';').reduce((memo, current) => { | |
let [name, answer] = current.split(' '); | |
return Object.assign(memo, {[name]: answer}); | |
}, {}) | |
let parseRules = lines => lines.split('\n').map(line => { | |
let [conditions, conclusion] = line.split('!'); | |
return { | |
ifs: splitConditions(conditions), | |
thens: splitConditions(conclusion) | |
} | |
}) | |
let featuresLines = `студент;;Андрей;Кун;Влад;Дима;Антон;Ира;Наташа;Вика;Оля;Маша | |
балл;Средний балл больше 7?;да;нет | |
работа;Человек работает?;да;нет | |
общага;Человек живёт в общаге?;да;нет | |
пол;Человек - девочка?;да;нет | |
стажировка;Человек уезжал на стажировку?;да;нет | |
успех;;да;нет`; | |
let rulesLines = `балл да;работа да!успех да | |
балл нет!успех нет | |
работа нет!успех нет | |
общага да;пол да;стажировка нет;успех да!студент Наташа | |
общага нет;пол да;стажировка нет;успех да!студент Маша | |
общага да;пол да;стажировка нет;успех нет!студент Оля | |
общага нет;пол да;стажировка нет;успех нет!студент Вика | |
общага нет;пол да;стажировка да;успех нет!студент Ира | |
общага да;пол нет;стажировка да;успех да!студент Дима | |
общага нет;пол нет;стажировка нет;успех да!студент Антон | |
общага нет;пол нет;стажировка да;успех да!студент Влад | |
общага нет;пол нет;стажировка нет;успех нет!студент Кун | |
общага да;пол нет;стажировка нет;успех нет!студент Андрей`; | |
let rules = parseRules(rulesLines); | |
let features = parseFeatures(featuresLines); | |
function log(object) { | |
for (let key of Object.getOwnPropertyNames(object)) { | |
console.log(`${key}: `, object[key]); | |
} | |
} | |
async function solve() { | |
let target = await ask('Выберите цель', ['успех', 'студент']); | |
let targets = [target]; | |
let context = {}; | |
while (targets.length) { | |
let currentTarget = targets[targets.length - 1]; | |
log({targets, currentTarget, context}); | |
if (currentTarget in context) { | |
targets.pop(); | |
continue; | |
} | |
let currentRuleIndex = rules.length - 1 - rules.slice().reverse().findIndex(rule => currentTarget in rule.thens); | |
let currentRule = rules[currentRuleIndex]; | |
log({currentRule}); | |
if (!currentRule) { | |
let feature = features[currentTarget]; | |
if (feature.question) { | |
log({feature}); | |
context[currentTarget] = await ask(feature.question, feature.options); | |
} else { | |
break; | |
} | |
} else { | |
let nextTarget, isValid = true; | |
for (let key of Object.keys(currentRule.ifs).sort()) { | |
if (key in context) { | |
if (context[key] !== currentRule.ifs[key]) { | |
isValid = false; | |
break; | |
} | |
} else { | |
nextTarget = nextTarget || key; | |
} | |
} | |
rules.splice(currentRuleIndex, 1); | |
log({isValid}); | |
if (isValid) { | |
if (nextTarget) { | |
log({nextTarget}); | |
targets.push(nextTarget); | |
rules.push(currentRule); | |
} else { | |
context = Object.assign(context, currentRule.thens); | |
} | |
} | |
} | |
} | |
if (target in context) { | |
alert(`${target}: ${context[target]}`); | |
} else { | |
alert(`Couldn't find solution :(`); | |
} | |
} | |
solve().catch(console.error); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
python -m SimpleHTTPServer 8000 | |
# Now open localhost:8000 in a browser |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment