Wordle data at high fidelity isn’t stored beyond the current day. Once the calendar turns over to tomorrow, only an aggregated summary is available in the game itself.
The current day’s data has a wealth of detail:
{
"boardState": [
"track",
"spice",
"<the actual solution - redacted>",
"",
"",
""
],
"evaluations": [
[
"absent",
"absent",
"absent",
"correct",
"absent"
],
[
"absent",
"absent",
"correct",
"correct",
"correct"
],
[
"correct",
"correct",
"correct",
"correct",
"correct"
],
null,
null,
null
],
"rowIndex": 3,
"solution": "<the actual solution - redacted>",
"gameStatus": "WIN",
"lastPlayedTs": 1657288128419,
"lastCompletedTs": 1657288128419,
"restoringFromLocalStorage": null,
"hardMode": true
}
The historical data gives you a basic overview of your play results but no granularity whatsoever:
{
"currentStreak": 61,
"maxStreak": 61,
"guesses": {
"1": 0,
"2": 7,
"3": 22,
"4": 38,
"5": 23,
"6": 6,
"fail": 0
},
"winPercentage": 100,
"gamesPlayed": 96,
"gamesWon": 96,
"averageGuesses": 4
}
As you can see, the historical gives you a nice overview of your career totals but not much more than that. With the level of detail in the current day numbers, if preserved, you can do more advanced analysis than what is in the app itself.
I originally started with a desktop browser bookmarklet but was inspired by Katy DeCorah’s iOS shortcut.
main
main
merge, GitHub auto-triggers a Hugo build and deploy on Cloudflare Workers SitesView a video demo to see the solution in action.
const stats = JSON.parse(window.localStorage.getItem("nyt-wordle-statistics"));
const state = JSON.parse(window.localStorage.getItem("nyt-wordle-state"));
const epoch = new Date("2021-06-19T00:00:00");
const solutionCount = 2309;
function getDaysBetween(start, end) {
let startDate = new Date(start);
let daysBetween = new Date(end).setHours(0, 0, 0, 0) - startDate.setHours(0, 0, 0, 0);
return Math.floor(daysBetween / 864e5)
}
function getPuzzleNumber(today) {
let puzzleNumber = getDaysBetween(epoch, today) % solutionCount
return puzzleNumber
}
// from: https://usefulangle.com/post/30/javascript-get-date-time-with-offset-hours-minutes
function getLocalTimeZone () {
var timezone_offset_min = new Date().getTimezoneOffset(),
offset_hrs = parseInt(Math.abs(timezone_offset_min/60), 10),
offset_min = Math.abs(timezone_offset_min%60),
timezone_standard;
if(offset_hrs < 10)
offset_hrs = '0' + offset_hrs;
if(offset_min < 10)
offset_min = '0' + offset_min;
if(timezone_offset_min < 0)
timezone_standard = '+' + offset_hrs + ':' + offset_min;
else if(timezone_offset_min > 0)
timezone_standard = '-' + offset_hrs + ':' + offset_min;
else if(timezone_offset_min == 0)
timezone_standard = 'Z';
return timezone_standard
}
function getDateTime (dateStr) {
var dt = new Date(dateStr),
current_date = dt.getDate(),
current_month = dt.getMonth() + 1,
current_year = dt.getFullYear(),
current_hrs = dt.getHours(),
current_mins = dt.getMinutes(),
current_secs = dt.getSeconds(),
current_datetime;
current_date = current_date < 10 ? '0' + current_date : current_date;
current_month = current_month < 10 ? '0' + current_month : current_month;
current_hrs = current_hrs < 10 ? '0' + current_hrs : current_hrs;
current_mins = current_mins < 10 ? '0' + current_mins : current_mins;
current_secs = current_secs < 10 ? '0' + current_secs : current_secs;
current_datetime = current_year + '-' + current_month + '-' + current_date + 'T' + current_hrs + ':' + current_mins + ':' + current_secs;
return current_datetime
}
let puzzleNumber = getPuzzleNumber(new Date)
let puzzleDate = getDateTime(state.lastCompletedTs).substring(0,10)
const fileText = `---
title: "${puzzleNumber}: ${puzzleDate}"
date: ${getDateTime(state.lastCompletedTs)+getLocalTimeZone()}
tags: []
words: ${JSON.stringify(state.boardState.filter(w => w !== ''))}
puzzles: [${puzzleNumber}]
state: ${JSON.stringify(state, null, 2)}
stats: ${JSON.stringify(stats, null, 2)}
---
<!-- more -->
`;
const encodedFileText = encodeURIComponent(fileText);
const filename = `${puzzleDate}.md`;
const githubQueryLink = "https://github.com/tphummel/wordle/new/main/content/w/new?quick_pull=1&labels=puzzle&value=" + encodedFileText +"&filename=" + filename;
// Call completion to finish
completion(githubQueryLink);
It may not be an obvious choice, but the Go/Hugo templating system and other capabilities make it a place you can do data analysis.
{{ $found := slice }}
{{ range . }}
{{ $wordleDate := .Date }}
{{ $wordle := . }}
{{ $presentLetters := 0}}
{{ range $guess := .Params.state.evaluations }}
{{ range $e := $guess }}
{{ if eq "present" $e }}
{{ $presentLetters = add $presentLetters 1 }}
{{ end }}
{{ end }}
{{ end }}
{{ if (eq $presentLetters 0) }}
{{ $found = $found | append (slice (dict "date" $wordleDate "puzzle" $wordle)) }}
{{ end }}
{{ end }}
{{ return $found }}
{{ $missedFirstGuesses := 0 }}
{{ $found := slice }}
{{ range . }}
{{ $wordleDate := .Date }}
{{ $wordle := . }}
{{ $firstGuess := index .Params.state.evaluations 0 }}
{{ $absentLetters := 0}}
{{ range $char := (seq 0 4) }}
{{ if (eq "absent" (index $firstGuess $char)) }}
{{ $absentLetters = add $absentLetters 1 }}
{{ end }}
{{ end }}
{{ if (eq $absentLetters 5) }}
{{ $missedFirstGuesses = add 1 $missedFirstGuesses }}
{{ $found = $found | append (slice (dict "date" $wordleDate "puzzle" $wordle)) }}
{{ end }}
{{ end }}
{{ return $found }}
Streak ends if you miss a calendar day. Source
{{ $wordles := . }}
{{ $thisW := dict }}
{{ $lastW := dict }}
{{ $active := slice }}
{{ $streaks := slice }}
{{ range $i, $wordle := $wordles.ByDate }}
{{ $thisW = $wordle }}
{{ if (and $thisW.Date $lastW.Date) }}
{{ $thisDay := time ($thisW.Date.Format "2006-01-02") }}
{{ $lastDay := time ($lastW.Date.Format "2006-01-02") }}
{{ $isConsecDays := eq $thisDay ($lastDay.AddDate 0 0 1) }}
{{ $isSameDay := eq $thisDay $lastDay }}
{{ if $isConsecDays }}
{{ $active = $active | append (slice $thisW) }}
{{ else if $isSameDay }}
{{ else }}
{{ $start := (index (first 1 $active) 0) }}
{{ $end := (index (last 1 $active) 0) }}
{{ $streak := dict "length" (len $active) "start" $start "end" $end }}
{{ $streaks = $streaks | append (slice $streak) }}
{{ $active = slice }}
{{ $active = $active | append (slice $thisW )}}
{{ end }}
{{ else }}
{{ $active = $active | append (slice $thisW )}}
{{ end }}
{{ $lastW = $thisW }}
{{ end }}
{{ if gt (len $active) 0 }}
{{ $streak := dict "length" (len $active) "start" (index (first 1 $active) 0) "end" (index (last 1 $active) 0) "note" "Active 🚧" }}
{{ $streaks = $streaks | append (slice $streak) }}
{{ end }}
{{ return $streaks }}
Get your Wordle data out today before it is lost. You can get Hugo to do interesting analysis and it is optimized for publishing and the operational simplicity of a static website. You might quit wordle, but your data website won’t quit on you.
📝 1098 Words
📆 2022-09-10 08:00 -0800