Hit a roadblock on my project help

Hi, I am trying to make a speed typing game where a user has to type the random word on the screen before the timer runs out. I have a time tracker class that keeps track of the time value and a countdown method that returns a promise while the countdown is running using a set interval method in it.

I am having trouble in implementing a way to keep track if the user has typed the word displayed on the screen correctly while the contdown function is running any help is appreciated


/**
 * Use to keep track of the timer and display it to the user
 *
 */
class timerTracker(){
    constructor(time){
        this._time = time;
    }

    /**
     * Starts the countdown timer and display the time on the html element
     * @element the dom element to display the timer to
     * @match callback function to check if the wordinput entered by the user matches the random word
     */
    startCountDown(element,match){
        const temp = this._time; // temp variable to store initial time
        const promise = new Promise((resolve,reject)=>{
            setInterval(()=> {
                if(this._time <=0){
                    clearInterval(timer);
                    this._time = 0;
                    resolve(this._time);
                }

               //TODO check function that ensures the word input are equal before resolving

                if(match){
                    this._time = temp;
                    resolve();
                }

                this._time--;
                let res = this._time > 0 ? this._time/100 : 0;
                element.textContent = `${res.toPrecision(this._time.toString().length)}`
            },10)
        })
    }



}    
    
    
1 Like

Logically, treat them as two separate pieces.

  • The timer should simply count down to zero, and at zero trigger a “oops!” state or message.

  • The input where the user is typing should check on keyup if the current text of the input matches the given word – and if it does, it should notify the timer to stop.

It may make sense to have a gameManager type component. At the start of the round:

  1. the gameManager sets and starts the timer.
  2. It also sets the input with the current word.
  3. If the word has been input correctly, notify the gameManager, which stops the timer.
  4. If the timer runs out, notify the gameManager, which disables the input.

Just tossing about ideas. It seems to me that these are all separate areas of concern. The timer shouldn’t be aware of the input, and the input shouldn’t be aware of the timer, so something should be managing them both, and allowing communication.

thanks so much for your input @snowmonkey ! your explanation helped me resolved the issue. You are right the timer shouldn’t be aware about the input and when you mention notify it hit me what to do. I used a boolean to notify the timer to stop this time and it became alot simpler :smiley:


/**
 * Use to keep track of the timer and display it to the user
 *
 */
class TimerTracker{
    constructor(time){
        this._time = time; // time in miliseconds 
        this._clear = false; // use to notify the timer to stop while the game resets 
        this._initial = time; // resets the timer when the timer resets
    }

    /**
     * Starts the countdown timer and display the time on the html element
     * @param element the dom element to display the timer to
     * 
     */
    startCountDown(element){
        const promise = new Promise((resolve,reject)=>{
        const timer= setInterval(()=> {
                if(this._time <=0){
                    clearInterval(timer);
                    this._time = 0;
                    resolve(this._time);
                }
          
                if(this._clear){ // if anytime clear is set to true , stop the time and reset the initial values
                    clearInterval(timer)
                    this._clear = false;
                    this._time = this._initial;
                    resolve(this._time);
                }
     

                this._time--;
                let res = this._time > 0 ? this._time/100 : 0;
                element.textContent = `${res.toPrecision(this._time.toString().length)}`;
            },10)
        })
        return promise;
    }

    /**
     * Stops the timer while the timer is counting down
     */
    clearTimer(){
      this._clear = true;
      console.log(this._clear);
    }


}     
    
    
    
1 Like

Very nicely done! By abstracting the communication like this, each piece becomes decoupled from the other, making far less brittle code. “Brittle code” means, if something small changes, everything breaks. By making the pieces separate and requiring they communicate, you’re building a more mature codebase!

I actually started tinkering, for my own fun and amusement, with building some ES6 component classes. Started playing about a year ago, got a few decent components in my personal lib, and one of my favorites? A Timer class. I can instantiate it with an object:

let myTimer = new Timer({
  time: 10,  /* Time in seconds */
  onTick: function(){
   /* I can have a function that fires every second */ 
  },
  onComplete: function(){ 
    /* And, in this one, I could notify the function that created myTimer
     *    that the time has elapsed, and cause, for example, a customTextInput
     *    to be disabled. For example. 
     */
  }
});
myTimer.start();

The class is completely encapsulated, I can call myTimer.stop() at any point to pause the timer, I can call myTimer.time to get the remaining seconds (custom getter), I can call myTimer.time = 10 to update the time (custom setter).

And it goes further – I can get a DOM node to insert onto the page (to display a timer), and listen to custom events on that, or I can use the timer without the DOM node, and simply provide the custom onTick and onComplete events.

The reason I am excited about it is, as I update this thing (make it use webWorkers, for example, or use the system dateTime rather than a simple setInterval), I can change it without affecting any other part of the system! Updating this won’t break the customTextInput, or the manager component.

You see, I created an interface to my Timer: a start() and stop(), functions to get and set properties and behaviors, and all neatly hidden within the component. You don’t have to know how it works, or what mechanism I’m using, it simply provides an interface (rather than requiring a certain implementation).

Not to toot my own horn, but it’s a pretty sweet bit of code. If you’d like to check it out, it’s on my github. :wink: