Browse Source

5.12: working Game.

Frederic G. MARAND 5 years ago
parent
commit
e73ba9dc8b
8 changed files with 130 additions and 54 deletions
  1. 1 0
      .gitignore
  2. 7 0
      Makefile
  3. 14 53
      app/app.ts
  4. 75 0
      app/game.ts
  5. 25 0
      app/scoreboard.ts
  6. 6 0
      app/utility.ts
  7. 1 1
      index.html
  8. 1 0
      package.json

+ 1 - 0
.gitignore

@@ -4,4 +4,5 @@
 /yarn.lock
 
 # Built output.
+/app/*.js
 /js/*

+ 7 - 0
Makefile

@@ -0,0 +1,7 @@
+all: js/app.js
+
+js/app.js: app/*.ts
+	yarn compile
+
+clean:
+	yarn clean

+ 14 - 53
app/app.ts

@@ -1,59 +1,20 @@
 /// <reference path="player.ts" />
+/// <reference path="game.ts" />
 
-function startGame() {
-  // Starting a new game.
-  let playerName: string | undefined = getInputValue('playername');
-  logPlayer(playerName);
+let newGame: Game;
 
-  postScore(100, playerName);
-}
+document.getElementById('startGame')!.addEventListener('click', () => {
+  let player: Player = new Player();
+  player.name = Utility.getInputValue('playername');
 
-function getInputValue(elementId: string): string | undefined {
-  // Type assertions applies to the whole document.get...., not to document.
-  // We know that we're only going to pass valid IDs, so will never get a null,
-  // so we can assert the result will always be an input element.
-  const inputElement: HTMLInputElement = <HTMLInputElement>document.getElementById(elementId);
-  if (inputElement.value === '') {
-    return undefined;
-  }
-  else {
-    return inputElement.value;
-  }
-}
+  let problemCount: number = Number(Utility.getInputValue('problemCount'));
+  let factor: number = Number(Utility.getInputValue('factor'));
 
-function postScore(score: number, playerName: string = 'MultiMath player'): void {
-  let logger: (value: string) => void;
+  newGame = new Game(player, problemCount, factor);
+  newGame.displayGame();
+});
 
-  if (score < 0) {
-    logger = logError;
-  }
-  else {
-    logger = logMessage;
-  }
-
-  let scoreElement: HTMLElement | null = document.getElementById('postedScores');
-  scoreElement!.innerText = `${score} - ${playerName}`;
-  logger(`Score: ${score}`);
-}
-
-function logPlayer(name: string = 'MultiMath player'): void {
-  console.log(`New game starting for player: ${name}.`);
-}
-
-function arm(doc: HTMLDocument) {
-  // We know getElementById() cannot be null because we control the markup, so
-  // we can use a non-null type assertion on the function call result.
-  doc.getElementById('startGame')!.addEventListener('click', startGame);
-}
-
-arm(document);
-
-const logMessage = (message: string) => console.log(message);
-
-function logError(message: string): void {
-  console.error(message);
-}
-
-let firstPlayer: Player = new Player();
-firstPlayer.name = 'Laney';
-console.log(firstPlayer.formatName());
+// Add click handler to the calculate score button.
+document.getElementById('calculate')!.addEventListener('click', () => {
+  newGame.calculateScore();
+});

+ 75 - 0
app/game.ts

@@ -0,0 +1,75 @@
+/// <reference path="utility.ts" />
+/// <reference path="result.ts" />
+/// <reference path="player.ts" />
+/// <reference path="scoreboard.ts" />
+
+class Game {
+  private scoreboard: Scoreboard = new Scoreboard();
+
+  /**
+   * Passing "public" parameters to constructor() automatically creates
+   * properties of the same name and initializes them to the value of the passed
+   * argument. Same with "protected", "private", and "readonly".
+   *
+   * The name for this is "parameter properties".
+   *
+   * @param player
+   * @param problemCount
+   * @param factor
+   */
+  constructor(
+    public player: Player,
+    public problemCount: number,
+    public factor: number) {
+  }
+
+  displayGame(): void {
+    // Create the HTML for the current game.
+    let gameForm: string = '';
+
+    for (let i = 1; i <= this.problemCount; i++) {
+      gameForm += '<div class="form-group">';
+      gameForm += '<label for="answer' + i + '" class="col-sm-2 control-label">';
+      // Note use of the String constructor vs a type assertion: they do not
+      // fulfill the same purpose.
+      gameForm += String(this.factor) + ' x ' + i + ' = </label>';
+      gameForm += '<div class="col-sm-1"><input type="text" class="form-control" id="answer' + i + '"></div>';
+      gameForm += '</div>';
+    }
+
+    // Add the game to the page.
+    let gameElement: HTMLElement = document.getElementById('game')!;
+    gameElement.innerHTML = gameForm;
+
+    // Enable the calculate score button.
+    document.getElementById('calculate')!.removeAttribute('disabled');
+  }
+
+  calculateScore(): void {
+    let score: number = 0;
+
+    // Loop through the text boxes and calculate the number that are correct.
+    for (let i = 1; i < this.problemCount; i++) {
+      let answer: number = Number(Utility.getInputValue('answer' + i));
+      if (i * this.factor === answer) {
+        score++;
+      }
+    }
+
+    // Create a new result object to pass to the scoreboard.
+    let result: Result = {
+      playerName: this.player.name,
+      score,
+      problemCount: this.problemCount,
+      factor: this.factor,
+    };
+
+    this.scoreboard.addResult(result);
+    this.scoreboard.updateScoreboard();
+
+    // Disable the calculate score button.
+    document.getElementById('calculate')!.setAttribute('disabled', 'true');
+
+  }
+
+}

+ 25 - 0
app/scoreboard.ts

@@ -0,0 +1,25 @@
+/// <reference path="result.ts" />
+
+class Scoreboard {
+  private results: Result[] = [];
+
+  addResult(newResult: Result): void {
+    this.results.push(newResult);
+  }
+
+  updateScoreboard(): void {
+    let output: string = '<h2>Scoreboard</h2>';
+
+    // Loop over results and create HTML for the scoreboard.
+    for (let index = 0; index < this.results.length; index++) {
+      let result: Result = this.results[index];
+      output += '<h4>';
+      output += result.playerName + ': ' + result.score + '/' + result.problemCount + ' for ' + result.factor;
+      output += '</h4>';
+    }
+
+    // Add the updated scoreboard to the page.
+    let scoresElement: HTMLElement = document.getElementById('scores')!;
+    scoresElement.innerHTML = output;
+  }
+}

+ 6 - 0
app/utility.ts

@@ -0,0 +1,6 @@
+class Utility {
+  static getInputValue(elementId: string): string {
+    const inputElement: HTMLInputElement = <HTMLInputElement>document.getElementById(elementId);
+    return inputElement.value;
+  }
+}

+ 1 - 1
index.html

@@ -46,7 +46,7 @@
 
         <div class="form-horizontal" id="game"></div>
 
-        <div class="col-sm-offset-2 col-sm-10" id="score">
+        <div class="col-sm-offset-2 col-sm-10" id="scores">
             <h2>Scoreboard</h2>
             <h4 id="postedScores">No scores yet</h4>
         </div>

+ 1 - 0
package.json

@@ -10,6 +10,7 @@
   "main": "index.js",
   "name": "Pluralsight-GettingStartedWithTypeScript",
   "scripts": {
+    "clean": "rm -fr js/* all/*.js",
     "compile": "rm -fr js/* && cd app && npx tsc",
     "start": "http-server"
   },