diff --git a/movement/watch_faces/complication/wordle_face.c b/movement/watch_faces/complication/wordle_face.c index 3cf4722..1d40252 100644 --- a/movement/watch_faces/complication/wordle_face.c +++ b/movement/watch_faces/complication/wordle_face.c @@ -29,33 +29,8 @@ #include "watch_utility.h" #endif -#define FREQ 2 - -/* -TODO: -* Add a way to recount previous attempts -*/ - // From: https://gist.github.com/shmookey/b28e342e1b1756c4700f42f17102c2ff - -/* -Letter | Usage -_______|______ -E | 1519 -S | 1490 -A | 1213 -R | 1026 -O | 852 -L | 850 -I | 843 -T | 819 But looks bad across all positions -N | 681 -D | 619 lowercase d looks like a in certain positions -C | 525 -U | 514 P has more words with the other letters here (281 vs 198) -P | 448 -*/ static const char _valid_letters[] = {'A', 'C', 'E', 'I', 'L', 'N', 'O', 'P', 'R', 'S'}; // Number of words found: 281 @@ -253,7 +228,10 @@ static void display_streak(wordle_state_t *state) { char buf[12]; state->curr_screen = SCREEN_STREAK; #if USE_DAILY_STREAK - sprintf(buf, "WO St%2ddy", state->streak); + if (state->streak > 99) + sprintf(buf, "WO St--dy"); + else + sprintf(buf, "WO St%2ddy", state->streak); #else sprintf(buf, "WO St%4d", state->streak); #endif @@ -392,7 +370,8 @@ static void get_result(wordle_state_t *state) { if (exact_match) { state->playing = false; state->curr_screen = SCREEN_WIN; - state->streak++; + if (state->streak < 0x7F) + state->streak++; #if USE_DAILY_STREAK state->prev_day = get_day_unix_time(); #endif @@ -428,7 +407,7 @@ void wordle_face_activate(movement_settings_t *settings, void *context) { if (state->prev_day <= (now + (60 *60 * 24))) state->streak = 0; if (state->curr_day != now) state->playing = false; #endif - movement_request_tick_frequency(FREQ); + movement_request_tick_frequency(2); display_title(state); } @@ -485,7 +464,10 @@ bool wordle_face_loop(movement_event_t event, movement_settings_t *settings, voi break; case EVENT_LIGHT_BUTTON_DOWN: case EVENT_ACTIVATE: + break; case EVENT_TIMEOUT: + if (state->curr_screen >= SCREEN_WIN) + display_title(state); break; case EVENT_LOW_ENERGY_UPDATE: if (state->curr_screen == SCREEN_TITLE) diff --git a/movement/watch_faces/complication/wordle_face.h b/movement/watch_faces/complication/wordle_face.h index 9117334..b137512 100644 --- a/movement/watch_faces/complication/wordle_face.h +++ b/movement/watch_faces/complication/wordle_face.h @@ -1,7 +1,7 @@ /* * MIT License * - * Copyright (c) 2024 <#author_name#> + * Copyright (c) 2024 * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,15 +28,37 @@ #include "movement.h" /* - * A DESCRIPTION OF YOUR WATCH FACE - * - * and a description of how use it + * Wordle Face + * A port of NY Times' Wordle game (https://www.nytimes.com/games/wordle/index.html) + * A random 5 letter word is chosen and you have WORDLE_MAX_ATTEMPTS attempts to guess it. + * Each guess must be a valid 5-letter word found in _legal_words in the C file. + * The only letters used are _valid_letters, also found in the C file. + * After a guess, the letters in the correct spot will remain, + * and the letters found in the word, but in the incorrect spot will blink. + * The screen after the title screen if a new game is started shows the streak of games won in a row. + * + * If USE_DAILY_STREAK is set to True, then the game can only be played once per day, + * and the streak resets to 0 if a day goes by without playing the game. + * + * Controls: + * Light Press + * If Playing: Next letter + * Else: Next screen + * Light Hold + * If Playing: Previous letter + * Else: None * + * Alarm Press + * If Playing: Next position + * Else: Next screen + * Alarm Hold + * If Playing: Previous position + * Else: None */ #define WORDLE_LENGTH 5 #define WORDLE_MAX_ATTEMPTS 6 -#define USE_DAILY_STREAK true +#define USE_DAILY_STREAK false typedef enum { WORDLE_LETTER_WRONG = 0, diff --git a/utils/wordle_list.py b/utils/wordle_face/wordle_list.py similarity index 88% rename from utils/wordle_list.py rename to utils/wordle_face/wordle_list.py index 1b5baf0..f0c894b 100644 --- a/utils/wordle_list.py +++ b/utils/wordle_face/wordle_list.py @@ -1,4 +1,4 @@ -import random +import random, itertools, time, ast # From: https://gist.github.com/shmookey/b28e342e1b1756c4700f42f17102c2ff words = [ @@ -315,9 +315,12 @@ words = [ "YOUTH", "ZEBRA", "ZONES", ] -alphabet = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'] +alphabet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'] def most_used_letters(): + ''' + Outputs how many times each letter is used in the words array. + ''' dicto = {} for i in alphabet: count = 0 @@ -334,12 +337,13 @@ def most_used_letters(): print(f"{k.upper()} | {dicto[k]}") -def list_of_valid_words(): - letters = ['e', 's', 'a', 'r', 'o', 'l', 'i', 'n', 'c', 'p'] +def list_of_valid_words(letters): + ''' + Outputs the array of valid words that can be made with the combination of letters. + ''' letters = sorted(letters) for i, letter in enumerate(letters): # Force all letters to be capitalized letters[i] = letter.upper() - legal_words = [] for word in words: valid_word = True @@ -349,7 +353,14 @@ def list_of_valid_words(): break if valid_word and word not in legal_words: legal_words.append(word) + return legal_words + +def print_valid_words(letters): + ''' + Prints the array of valid words that the wordle_face.c can use + ''' + legal_words = list_of_valid_words(letters) for i,word in enumerate(legal_words): legal_words[i] = word.upper().replace("D","d") random.shuffle(legal_words) @@ -373,7 +384,71 @@ def list_of_valid_words(): print('') print("};") + +def get_sec_val_and_units(seconds): + if seconds < 1: + return f"{round(seconds * 1000)} ms" + hours = int(seconds // 3600) + minutes = int((seconds % 3600) // 60) + secs = int(seconds % 60) + if hours > 0: + return f"{hours} hr {minutes} min {secs} sec" + elif minutes > 0: + return f"{minutes} min {secs} sec" + else: + return f"{secs} sec" + + +def txt_of_all_letter_combos(num_letters_in_set): + ''' + Creates a txt file that shows every combination of letters and how many words + their combo can make. + num_letters_in_set - How many letters should be in each combination + ''' + num_status_prints = 100 + dict_combos_counts = {} + print_iter = 0 + prev = time.time() + start = prev + letters_to_ignore = ['D','T'] # Don't diplay well on the watch + legal_letters = [item for item in alphabet if item not in letters_to_ignore] + print(f"Finding all {num_letters_in_set} letter combinations with the following letters: {legal_letters}") + all_combos = list(itertools.combinations(legal_letters, num_letters_in_set)) + len_all_combos = len(all_combos) + to_print = max(1, int(len_all_combos/ num_status_prints)) + print(f"Amount of Combos: {len_all_combos}") + estimated_prints = round(len_all_combos / to_print) + for i, letters in enumerate(all_combos): + letters = sorted(letters) + dict_combos_counts[repr(letters)] = len(list_of_valid_words(letters)) + print_iter+=1 + if print_iter >= to_print: + curr = time.time() + delta = curr - prev + time_passed = curr - start + total_time_estimate = delta * estimated_prints + time_left_estimate = (delta * estimated_prints) - time_passed + output = f"Time Passed: {get_sec_val_and_units(time_passed)} | " + output+= f"Amount of time for {to_print} items: {get_sec_val_and_units(delta)} | " + output+= f"Estimate for total: {get_sec_val_and_units(total_time_estimate)} | " + output+= f"items Left {len_all_combos - i} | " + output+= f"Percent Complete {round((100 * i) / len_all_combos)}% | " + output+= f"Estimated Time Left : {get_sec_val_and_units(time_left_estimate)}" + print(output) + prev = curr + print_iter = 0 + dict_combos_counts = dict(sorted(dict_combos_counts.items(), key=lambda item: item[1], reverse=True)) + + most_common_key = next(iter(dict_combos_counts)) + print(f"The Most Common Combo is: {most_common_key}") + print_valid_words(ast.literal_eval(most_common_key)) + + with open('output.txt', 'w') as file: + for key, value in dict_combos_counts.items(): + file.write(f'{key}: {value}\n') + + if __name__ == "__main__": most_used_letters() - list_of_valid_words() - + print_valid_words(['A', 'C', 'E', 'I', 'L', 'N', 'O', 'P', 'R', 'S']) + #txt_of_all_letter_combos(10) \ No newline at end of file