Last active
February 14, 2022 17:54
-
-
Save cyrillsemenov/ffc4e13e219c1fe76eceecf92107ede0 to your computer and use it in GitHub Desktop.
Three guesses
This file contains 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 regex = /(?<=Ma=\[).+(?=\]\,Oa)/gm, | |
alphabet = {}, | |
wordsList = [], | |
weights = {}; | |
// Каждый день у игры новый хэш, его легко достать из объекта window, | |
// затем в тексте файла нужно найти переменную со списком слов | |
// и превратить ее из текста в массив | |
fetch(`main.${window.wordle.hash}.js`) | |
.then(response => response.text()) | |
.then(data => wordsList = JSON.parse(`[${regex.exec(data)}]`)) | |
.then(_ => getWeights ()); | |
function getWeights () { | |
// Мы просто проходимся по каждой букве каждого слова | |
// и добавляем к счетчику в объекте alphabet | |
wordsList.forEach(w => { | |
w.split("").forEach( | |
l => {alphabet[l] = alphabet[l] ? alphabet[l]+1 : 1 | |
}) | |
}); | |
// Было бы неплохо его (объект alphabet) отсортировать | |
var sortable = []; | |
for (var letter in alphabet) { | |
sortable.push([letter, alphabet[letter]]); | |
} | |
sortable.sort(function(a, b) { | |
return a[1] - b[1]; | |
}); | |
// Заполняем "таблицу мер и весов" | |
sortable.forEach((l, i) => { | |
weights[l[0]] = i | |
}); | |
} | |
// Нам понадобятся само приложение, к которому можно обратиться | |
// через querySelector и переменные для подсказок | |
let app = document.querySelector("game-app"), | |
let firstBest = ["", 0], | |
secondBest = ["", 0], | |
thirdBest = ["", 0]; | |
function getFirstGuess () { | |
// Теперь считаем суммарный вес каждого слова | |
wordsList.forEach(w => { | |
weight = 0; | |
// Причем для этого мы убираем повторяющиеся буквы, | |
// чтобы например слова с двумя «l» не были слишком тяжелыми - | |
// они нам не интересны | |
[...new Set(w.split(""))].forEach(l => { | |
weight += weights[l]; | |
}); | |
if (weight > firstBest[1]) { | |
firstBest = [w, weight] | |
} | |
}); | |
// Выводим подсказку на табло | |
print(firstBest[0]) | |
} | |
function getSecondGuess () { | |
// Это я объясню позже | |
secondBest = ["", 0]; | |
// Здесь нам понадобятся результаты предыдущей попытки | |
let evaulations = app.letterEvaluations; | |
// Снова считаем вес | |
wordsList.forEach(w => { | |
weight = 0; | |
[...new Set(w.split(""))].forEach(l => { | |
weight += weights[l]; | |
}); | |
// Но теперь с условием: | |
// в самом "тяжелом" слове не должно быть букв | |
// из первой подсказки и тех, которые как игра нам сказала, | |
// отсутствуют в правильном решении | |
unique = !firstBest[0] | |
.split("").some(el => {return w.includes(el)}) | |
&& [...new Set(w.split(""))].every(el => | |
evaulations[el] != "absent" | |
); | |
if (weight > secondBest[1] && unique) { | |
secondBest = [w, weight] | |
} | |
}); | |
print(secondBest[0]) | |
} | |
function getThirdGuess () { | |
// К этому вернемся позже | |
thirdBest = ["", 0]; | |
evaulations = app.letterEvaluations; | |
// Ищем буквы, присутствующие в ответе, на своих и на чужих местах | |
let correct = [undefined, undefined, undefined, undefined, undefined], | |
wrongPlace = {}; | |
app.boardState.forEach((w, i) => { | |
if (app.evaluations[i] != null) { | |
app.evaluations[i].forEach( | |
(e,j) => { | |
if (e == "correct") { | |
correct[j] = w[j] | |
} else if (e == "present") { | |
if (wrongPlace[w[j]]) { | |
wrongPlace[w[j]].push(j) | |
} else { | |
wrongPlace[w[j]] = [j] | |
} | |
} | |
}) | |
} | |
}) // Ужас, но что поделать | |
// Тут я соберу все присутствующие и правильные буквы | |
// Начинается путаница с названиями переменных, прошу простить | |
let present = Object.entries(evaulations) | |
.filter(e => | |
e[1] == "present" || e[1] == "correct" | |
).map(e => e[0]); | |
// Снова считаем массы | |
wordsList.forEach(w => { | |
weight = 0; | |
let letters = [...new Set(w.split(""))]; | |
letters.forEach(l => { | |
weight += weights[l]; | |
}); | |
// Мама, не выгоняй меня из дома, я проверяю: | |
// 1. В слове нет отсутствующих в ответе букв | |
// 2. Каждая присутствующая буква есть в слове | |
// 3. Каждая правильная буква на правильной позиции | |
// 4. Все угаданные на не правильном месте буквы стоят | |
// в других местах | |
let passing = letters | |
.every(el => evaulations[el] != "absent") | |
&& present.every(el => w.includes(el)) | |
&& w.split("") | |
.every((el, i) => correct[i] == el || correct[i] == undefined) | |
&& w.split("") | |
.every((el, i) => ![...wrongPlace[el]||[]].includes(i)); | |
if (weight >= thirdBest[1] && passing) { | |
thirdBest = [w, weight] | |
} | |
}); | |
print(thirdBest[0]) | |
} | |
// Сперва нужно создать функцию print, | |
// чтобы выводить рехультат подсказок на табло | |
function print(w, enter=false) { | |
// Делается это с помощью KeyboardEvent'ов: | |
// именно так работает экранная клавиатура в игре | |
w.split("").forEach(l => | |
window.dispatchEvent( | |
new KeyboardEvent('keydown', {'key': l}) | |
)); | |
if (enter) { | |
window.dispatchEvent( | |
new KeyboardEvent('keydown', {'key': 'Enter'}) | |
); | |
} | |
} | |
// Еще одна помогайка, название говорит само за себя | |
function applyStyle(el, style){ | |
Object.entries(style).forEach(p => { | |
el.style[p[0]] = p[1]; | |
}) | |
} | |
// Создадим контейнер для кнопок, | |
// а так же найдем куда его поместить (для этого придется | |
// залезть в сумеречную зону) | |
let suggestions = document.createElement("div"), | |
header = document.querySelector("game-app").shadowRoot | |
.querySelector("game-theme-manager > header"); | |
// Накинем стиль на контейнер и кнопки | |
// Я делаю это здесь, а не в поле CSS потому что он находится | |
// в Shadow Root и CSS до него не доберется | |
applyStyle(suggestions, { | |
display: "grid", | |
gridTemplateColumns: "repeat(3, 1fr)", | |
gridGap: "5px", | |
justifyItems: "center", | |
padding: "10px", | |
margin: "auto", | |
boxSizing: "border-box", | |
maxWidth: "350px", | |
width: "100%", | |
fontSize: "1.5rem", | |
lineHeight: "2rem", | |
fontWeight: "bold", | |
verticalAlign: "middle", | |
color: "var(--tile-text-color)", | |
}); | |
let buttonStyle = { | |
textAlign: "center", | |
width: "100%", | |
background: "#a52a2a" | |
}; | |
// Чтобы не повторяться соорудил вот это | |
let buttons = [ | |
["First", getFirstGuess], | |
["Second", getSecondGuess], | |
["Third", getThirdGuess] | |
].forEach(b => { | |
let el = document.createElement("div"); | |
applyStyle(el, buttonStyle); | |
el.innerText = b[0]; | |
el.onclick = b[1]; | |
suggestions.appendChild(el); | |
}); | |
// Добавили кнопки в интерфейс | |
header.after(suggestions); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment