Skip to content
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

Inconsistency on No Score and how it effects averages and checkout percentage #53

Open
richercs opened this issue Oct 9, 2017 · 0 comments
Labels

Comments

@richercs
Copy link
Collaborator

richercs commented Oct 9, 2017

The solution to this topic is to resolve the inconsistency by defining how we think No Score should be counted in averages.
After checking out a few forums online I couldn't find an exact solution yet.

The inconsistency is as follows:

  • What is "No Score" in darts:
  1. The player thrown 3 darts into the black side area of the board where the dart is considered not scoring (equivalent of scoring 0 points with each dart)
  2. The player has reached the possibility to checkout, now it is possible to throw 1, 2 or 3 darts. If any of these darts would put the players score in the current turn over the required points to checkout the player scores 0 points and it is a No Score.
  • The problem now is that these two are handled differently in turn average and checkout percentage.
  • What Turn Average is doing:
  1. Turn average is counted after every single throw. The average is the average of 3 darts so if there are more than 3 darts thrown the average is recalculated (multiplied by 3).
    This is the code for it:
    this.roundAvg = ko.computed(function () {
      var avg = this.history().reduce(
        function (total, num) {
          return total + num;
        }, 0)
        / this.history().length;

      if (this.history().length >= 3) {
        return Math.round(((avg * 3) + 0.00001) * 100) / 100;
      }

      return 0;
    }, this);

  1. Turn Average uses the history array. The history array however is not consistent considering No Score. It will allow a turn to have 0 score by scoring 0,0,0 with each dart but it won't allow No Score by going over the requirement point during checkout attempts. As soon as any of the 3 darts thrown at attempting a checkout puts the score above the requirement the history array gets reduced and the current turn gets removed from it.
    this is in Bust:
    this.handleThrow = function (score) {
      var pointsScored = parseInt(score.scoreOfThrow);
      var sectorId = score.scoreId;
      var currentPlayer = self.getCurrentPlayer();

      if (self.gameShotDetectorService.isGameShotAttempt(self.getCurrentPlayer().require(), self.thrown(), self.isDoubleOut())) {
        currentPlayer.gameShotAttempnts(currentPlayer.gameShotAttempnts() + 1);
      }

      currentPlayer.history.push(pointsScored);

      // Too much..
      if (currentPlayer.require() < 0) {
        self.handleBust(currentPlayer);
        return;
      }
...
    };
    this.handleBust = function (currentPlayer) {
      self.thrown(self.thrown() + 1);
      currentPlayer.history.splice((0 - self.thrown()), self.thrown());
      self.jumpToNextPlayer(currentPlayer);
    };

So handleBust removes the last thrown darts form history array if the requirement went under 0 with the last throw.

So this is one inconsistency, where while the turn average comes from the history array the history array will not have records of Busted turns but it will have records of turns when the score of each dart was 0,0,0. Also there is another array called turnHistory which shows the score of each turn. BUT it won't have records of turns when the score was 0, although the history array does have it.
This is the code for populating turnHistory:

    this.turnScore = function (currentPlayer) {
      var countDarts = self.thrown() + 1;
      var turnThrows = currentPlayer.history.slice(-countDarts);
      var turnSum = 0;
      for (var i = 0; i < countDarts; i++) {
        turnSum += turnThrows[i];
      }
      if (turnSum !== 0) {
        currentPlayer.turnHistory.push(turnSum);
        currentPlayer.allTurnHistory.push(turnSum);
      }
      if (turnSum >= 100) {
        currentPlayer.hundredPlusCount((currentPlayer.hundredPlusCount() + 1));
      }
    };

So whenever the throws in a turn sum up to 0, the turnHistory won't be updated. But the history array does have the records of the 0 scoring No Score.

Here is an example:
d_ave_issue1

On this picture Gary Anderson has thrown 2 turns (20,20,20 and 5,20,20), now lets make him throw 3 zeros.

d_ave_issue2

As we can see the history array has the 3 zeros but the turnHistory doesn't. Also the average is updated and now it is considering the 3 zero throws as a turn with 0 points scored with 3 darts.

But what happens when a Bust is thrown. So the required points to checkout are overstepped.
d_ave_issue3

On this picture Gary has thrown 2 turns so far and he is at the last throw of his 3rd turn, now if I make him throw a 60 he will throw a Bust and will have a requirement of -9. Therefore he will have No Score in this turn and his point will reset to the end of the previous turn.

d_ave_issue4

The two fives are gone from history array and he again has 61 points.

  1. So to sum up the Turn Average is currently using the history array to calculate turn averages during games, but the history array is not consistent on which turns it records and which not when a turn ends in No Score.
  • What Checkout Percentage is doing:
    Checkout Percentage (in the code it is called gameShotAttempnts - so it also has a typo) is however simply considers every throw that was thrown as a checkout attempt. Even if that throw is not in the history array. It is just a ko.observable model property which updates every time a throw is handled and the throw is considered a checkout attempt.
    this.handleThrow = function (score) {
      var pointsScored = parseInt(score.scoreOfThrow);
      var sectorId = score.scoreId;
      var currentPlayer = self.getCurrentPlayer();

      if (self.gameShotDetectorService.isGameShotAttempt(self.getCurrentPlayer().require(), self.thrown(), self.isDoubleOut())) {
        currentPlayer.gameShotAttempnts(currentPlayer.gameShotAttempnts() + 1);
      }
...
    };
/* global define */
define(function () {
  /**
   * A module that is responsible for detecting whether game shot attempt was thrown.
   *
   * @exports GameShotDetectorService
   */
  var GameShotDetectorService = {
    /**
     * Return whether game shot attempt was thrown.
     *
     * @return {boolean}
     */
    isGameShotAttempt: function (currentPlayerScore, dartsThrown, isDoubleOut) {
      // If double out, then a game shot was thrown if:
      if (isDoubleOut) {
        // player has equal or under the score 40 with even numbers,
        return (currentPlayerScore <= 40 && currentPlayerScore % 2 === 0) ||
          // or has 50 with all darts thrown (if not last shot, maybe rounding).
          (currentPlayerScore === 50 && dartsThrown === 2);
      }

      // If simple out, then a game shot was thrown if:
      // player has equal or under the score 40 with even numbers,
      return (currentPlayerScore <= 40 && currentPlayerScore % 2 === 0) ||
        // or has 50 with all darts thrown (if not last shot, maybe rounding)
        (currentPlayerScore === 50 && dartsThrown === 2) ||
        // or has equal or under 60 throwable with a tripple
        (currentPlayerScore <= 60 && currentPlayerScore % 3 === 0) ||
        // player is under 20 (simple sector)
        (currentPlayerScore <= 20) ||
        // player has 25 after, and had 2 darts.
        (currentPlayerScore === 25 && dartsThrown === 1);
    }
  };

  return GameShotDetectorService;
});
@rbalazs rbalazs added the bug label Oct 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants