Skip to content

Refactor - Read Description #46

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

Conversation

Jsoto22
Copy link

@Jsoto22 Jsoto22 commented Mar 5, 2024

Minor Overhaul and Refactor

This pull request adds quite a bit complexity to the code base but enables greater flexibility for adding additional game modes. As is, the boilerplate addresses some open and closed issues, and implements a robust state management system. In some regards, how game modes are built has become simpler and follows a straightforward pattern of usage that's reminiscent to the original branch, while adding many UI/UX enhancements.

That being said, some features have been dropped, making this a breaking revision. I do not intend to keep it that way and would like to reimplement those features with some help. Hopefully the lack of comments and increased complexity doesn't scare contributors away. I apologize in advance for that, which is why this description is so long winded. I will greatly appreciate any feedback, suggestions, and overall insight anyone can give.

Breaking Changes (Dropped Features)

  1. Emoji Results
  2. Copy results to clipboard

I fully intend to bring back text-based results that can be copied to the clipboard. I'd like to do so in a way that's simply structured, intuitive, easily digestible, and accessible. The goal is to address the known issue of the emoji results.

Possible Solutions

I looked into ways to convert HTML into images that could be copied to clipboard or downloaded. For now, I only have two ideas that would keep this repo dependency free.

  • Dynamically build the DOM and convert it into an SVG, encoding it to a blob, then painting to Canvas
  • Using Canvas directly to draw the results using some involved math, but simple draw operations

New Class Features

Warning

Due to browser CORS policies, module imports must be server via a development server. I recommend using an IDE that can serve pages on localhost.

Note

All the duplicated feature code was consolidated into 3 classes: WordGen, Prompts, and Keyboard.

WordGen

Behavior

The word list generator's behavior remains relatively unchanged. Most changes removed duplication by adding options to the main feature methods.

Constructor

Important

The WordGen class now accepts an optional Seed parameter passed through the constructor. The current Date.toLocalString() is used by default.

Instance Method
WordGen WordGen( )
WordGen WordGen( Seed: string )

Properties

Type Property Access Description
string WordGen( ).seed get Gets seed value from instance
string WordGen( ).seed set Sets seed, reinitializing P-RNG generator
Date WordGen( ).date get Gets Date.toLocalString() of today
number WordGen.EPOC STATIC Gets milliseconds from site creation. Used to calculate Daily Puzzle #

Methods

Tip

difficulty parameter can be of type 'easy', 'medium', or 'hard'. Default is 'medium'

Caution

amount parameter can be any number. Default is 5
Please be aware of out-of-range amounts. I'll address this in a future update.

Return Method Description
string[] chooseWords( ) Creates a list of 'medium' words with a length of 5
string[] chooseWords(difficulty: string) Creates a list of words with given difficulty setting
string[] chooseWords(difficulty: string, amount: number) Creates a list of words with given difficulty setting and specified length
string[] shuffle( ) Creates a shuffled list of words with 'medium' difficulty setting
string[] shuffle(difficulty: string) Creates a shuffled list of words with given difficulty setting

Keyboard

Behavior

Letter inputs and backspace are captured on mousedown and keydown events, while submit or enter, is captured on mouseup and keyup events. All events captured call preventDefault() to block expected browser behaviors. Input events from the keyboard are matched by ReGex, as before, to block any non-character inputs, with the exception of backspace and enter. Letter inputs insert the character to an output string, raising a change event. Backspace removes the last character of the output string, also raising a change event. Submit or enter raises an submit event. (More information on events below).

Constructor

Important

The Keyboard class accepts an empty DOM Element which it will populate.

Instance Method
Keyboard Keyboard ( keyboard: HTMLDivElement )

Events

Note

Deleting all characters will return an empty string.

Name Method Event Description
'change' on('change', callback(event)) output: string Returns the current output string
'submit' on('submit', callback(event)) output: string Returns the submitted output string

Methods

Note

All onscreen keys exhibit a combination of states defined by the default CSS behavior or defined classes, DOM attributes, and styles pragmatically toggled. Different states are used to remedy user pain points and mitigate potential user error.

Return Method Description
void enableInput( ) Enables input event capture
void clear( ) Clears the output string and resets all states

Prompts

Behavior

The new behavior of the Prompts class is fairly complex, but it uses the previous implementation's ideas as a base line. Most of the changes made ensure proper state management, enhanced UI/UX, and a better-defined data model for evaluation results.

I'll refrain from explaining all nuanced behaviors, but I will list some technical and functional highlights.

  • Dynamically built allowing for variable number of prompts and diverse use cases
  • Uses DOM Hierarchy to store, traverse, and manage prompt buttons and audio players
  • Difficulty string is used to assign the proper file paths for the audio and to add context to results
  • Prompts now use tab key to cycle through the prompt buttons, selecting in valid order
  • Space bar triggers play and stop for the selected prompt button
  • Enhanced feedback for active, selected, and disabled button states

Constructor

Important

The Prompts class accepts an empty DOM Element which it will populate.

Instance Method
Prompts Prompts( Prompts: HTMLDivElement )

Events

Name Method Event Description
'load' onLoad( callback(event)) difficulty: string Returns the set difficulty once all prompts are added to the DOM
'ready' onReady(callback()) void Raises an event when ready to evaluate a submission. No information is passed to the callback
'select' on('select', callback(event)) selectedPlayer: PromptButton, selectedWord: string When a prompt is seleted, either through user interaction or pragmatically, the current button with audio player, and its matching word is returned
'play' on('play', callback(event)) activePlayer: PromptButton, activeWord: string When a prompt is triggered and the audio begins to play, the current button with audio player, and its matching word is returned
'stopped' on('stopped', callback(event)) stoppedPlayer: PromptButton, activeWord: string When a prompt is forcefully interrupted and the audio stops, the current button with audio player, and its matching word is returned
'ended' on('ended', callback(event)) ctivePlayer: PromptButton, activeWord: string When a prompts audio plays through its full duration, the current button with audio player, and its matching word is returned
'evaluate' on('evaluate', callback(event)) result : prompt result When a user submits their spelling attempt, it gets evaluated, returning the result for the active prompt
'complete' on('complete', callback(event)) results: prompts results When all prompts in the queue are submitted and evaluate, the full results with extra information is returned

Methods

Return Method Description
void addWords(level:string, ...words: string[] ) Accepts difficulty and word list, then generates the prompts, raising an load event when done. Param level should be hanged to difficulty for consistency and clarity
void evaluatePrompt( submission: string ) Takes the attempt string and evaluates it against the current active word
void clear( ) Clears the prompts and resets all states

Other Changes

Changes to results page look

Still a work in progress, which is why there's dropped features.

image

Changes to results data model

Results are now formatted in JSON. It's stringified when saved to session storage and then parsed when accessed on the results page.

{
  "Daily #52: EASY": [
    {
      "word": "razz",
      "submission": "razz",
      "isCorrect": true
    },
    {
      "word": "forever",
      "submission": "forever",
      "isCorrect": true
    },
    {
      "word": "imagined",
      "submission": "imagined",
      "isCorrect": true
    },
    {
      "word": "behold",
      "submission": "behold",
      "isCorrect": true
    },
    {
      "word": "frankly",
      "submission": "frankly",
      "isCorrect": true
    }
  ],
  "Daily #52: MEDIUM": [
    {
      "word": "relentlessly",
      "submission": "relentlessly",
      "isCorrect": true
    },
    {
      "word": "wattage",
      "submission": "wattage",
      "isCorrect": true
    },
    {
      "word": "anabolic",
      "submission": "anabolic",
      "isCorrect": true
    },
    {
      "word": "elicitation",
      "submission": "illicitation",
      "isCorrect": false
    },
    {
      "word": "severely",
      "submission": "serverely",
      "isCorrect": false
    }
  ],
  "Daily #52: HARD": [
    {
      "word": "massacres",
      "submission": "masecres",
      "isCorrect": false
    },
    {
      "word": "dexterity",
      "submission": "dexterity",
      "isCorrect": true
    },
    {
      "word": "heirloom",
      "submission": "aerloom",
      "isCorrect": false
    },
    {
      "word": "verisimilitude",
      "submission": "ver",
      "isCorrect": false
    },
    {
      "word": "scallion",
      "submission": "scallion",
      "isCorrect": true
    }
  ]
}
Project structure modifications

Due to renaming the audio folders, it may result with being unable to view the changes made. Bellow I'll list most of the changes in detail.

Folder Changes

  • Removed original audio folders and files
  • Renamed audio folders from /levelOneNew, /levelTwoNew, and /levelThreeNew to /easy, /medium, and /hard, respectively.
  • Added /core folder in /assets/scripts
  • Added /dictionary folder in /assets/scripts/core

File Structure Changes

  • /scripts
    • /core
      • /dictionary
        • easy.js - Exports const array of all easy words
        • medium.js - Exports const array of all medium words
        • hard.js - Exports const array of all hard words
      • keyboard.js - Exports Keyboard class
      • prompts.js - Exports Prompts class
      • utils.js - Exports cyrb128 and sfc32 const functions
      • word-gen.js - Exports WordGen class
      • word-list.js - Re-exports word const arrays
    • daily_challange.js
    • practice.js
    • results.js
    • spelloff.js
    • youtube.js

@Jsoto22 Jsoto22 mentioned this pull request Jul 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant