Street Dice Pt9

Today I worked on the UIController and moved all the console.log calls.

let UIController = (function() {
  const DOMSTRINGS = {};
  return {
    //Object full of functions that will become methods of the UI Controller

    displayShooter: function(currentShooter) { 
      console.log(`Player ${currentShooter+1} is shooter.`);
    },
    displayDiceResult: function(diceResult) {
      console.log("Roll Result: ", diceResult);
    },
    displayDiceTotal: function(diceTotal) {
      console.log('Dice Total: ', diceTotal);
    },
    displayPoint: function(point) {
      console.log('Point is: ', point);
    },
    displayGameResult: function(result) {
      console.log('Game Result: ', result);
    },
    displayBet: function(bet) {
      console.log('Current Bet:', bet);
    },
    displayError: function(err) {
      console.log(err);
    },
    displayBank: function(bankArray) {
      console.log(bankArray);
    },
    displayMessage: function(message) {
      console.log(message);
    }

  }
})();

I am hoping this will make it easy when I transition to the browser. But first we need to create a real game controller to try to play several round until one player goes broke.

Here is today’s coding session on youTube:

Create StreetDice Game Pt8

Sometimes you gotta show off what you are working on to a friend, and today after playing a (losing) game of League of Legends, I showed TooTallE what I have been up to lately.

I was able to start the UIController as planned, and I built a try catch block into the bet process so it makes sure that you have a currentShooter set.

Most of it was testing and debugging what I had done in Pt7:

//determine when to declare a variable and when to import?
// when you import it is just a code block
// when you declare a variable and require you bring in an object
//const { resolve } = require('path');
const readline = require('readline');

// simplified
//https://altcodeunicode.com/alt-codes-die-checkers-shogi-symbols/
// Players must first identify the player who will be shooting dice – the shooter. 

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let game = {
  roundNumber: 0,
  players: [0,1],
  playersBanks: [20,20],
  bet: 0,
  point: undefined,
  currentShooter: undefined,
  currentDiceResult: undefined,
  currentGameResult: undefined, 
  getBet: function() {
    return this.bet;
  },
  setBet: function(player, amount) {
    // TODO: Need to add check to make sure player has enough in the bank, if not enough try a different bet also perhaps update to display bank for the shooter when making the bet.
    //console.log(`Player ${currentShooter+1}'s Bank Balance: `, game.playersBanks[currentShooter]);
    // TODO: Also need to check that the other player has enough to cover the bet.
    if (game.playersBanks[player] >= amount) {
      this.bet = amount;
      return this.bet;
    }

    return console.log(`Current bank balance: $${game.playersBanks[currentShooter]}. Not enough in bank. Please enter a bet you can cover.`);
    
  },
  getPlayerBank: function(player) {
    return this.playersBanks[player];
  },
  // Turn a number negative with:  -Math.abs(num); 
  // TODO: Rename as adjustPlayerBank
  setPlayerBank: function(player, amount) {
    this.playersBanks[player] += amount;
    return this.playersBanks[player]; //amount can be negative for a losing bet
  },
  rollDice: function(numDice, sides) {
    let diceArray = [];
    for (let i = 0; i < numDice; i++) {
      let dice = Math.floor(Math.random() * sides) + 1; // should be 1 - 6
      diceArray.push(dice);
    }
    return diceArray;
  },
  sumDice: function (diceArray) {
    let diceTotal = 0;
    for (let i = 0; i < diceArray.length;i++) {
      diceTotal += diceArray[i]
    }
    return diceTotal;
  },
  setPoint: function() {
    //this need to set a players point parameter (value) PROPERTY!
    this.point = this.currentDiceResult;
    //console.log(`Point is ${this.point}`);
    return this.point;
  },
  setShooter: function() {
    let shooterDetermined = false;
    let player0;
    let player1;
    //loop roll until see who goes first
    while (!shooterDetermined) {
      player0 = this.rollDice(1,6)[0];
      //console.log("Player 1: ", player0);
      player1 = this.rollDice(1,6)[0];
      //console.log("Player 2: ", player1);
      if ( player0 > player1) {
        // NOTE: UI Human Interface to allow player to click to roll
        //console.log('Player 1 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 0;
        return this.currentShooter;
      } else if (player1 > player0) {
        // Computer rolls till outcome
        // console.log('Player 2 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 1 
        return this.currentShooter;
      } 
    }
  }, 
  displayGameObject: function () {
    console.log("Game Object: ", this);
  }
}

// Part of Controller
function resolveBet(game) {
  console.log("Did the player win? ", (game.currentGameResult=='win'));
  //currentShooter, currentGameResult, bet
  if (game.currentGameResult == 'win') {
    // Define loser as opposite of winner if winner = currentShooter
    let loser = +!game.currentShooter;
    console.log("Loser: ", loser);
    // subtract money from loser bank v = +!v;
    console.log(game.setPlayerBank(loser, -game.bet)); 
    // add money to currentShooter bank
    console.log(game.setPlayerBank(game.currentShooter, game.bet));
  } else {
    // subtract money from currentShooter bank
    game.setPlayerBank(game.currentShooter, -game.bet);
    // add money to winner bank
    let winner = +!game.currentShooter;
    game.setPlayerBank(winner, game.bet); 
  }
  
  return console.log(game.playersBanks);
}


function resolveDice(game) {
  // this function needs to return whether it is a win a loss or a roll again
  // this function will take a dice total and the point if point is undefined the it is the first roll otherwise it is not the first roll
  // The come out roll comes next. 
  let roll = game.currentDiceResult;
  //let rollCount;
  let point = game.point;
  //roll = sumDice(rollDice(2,6));
  //rollCount++;
  // This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
  //  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
  if (point == undefined) { //isFirstRoll = true
    if (roll == 7 || roll == 11) {
      game.currentGameResult = 'win';
      return console.log('Game Result: ', game.currentGameResult);
    }
  //  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
    if (roll == 2  || roll == 3  || roll == 12 ) { 
      game.currentGameResult = 'lose';
      return console.log('Game Result: ', game.currentGameResult);  
    }
    else {
      // A Point number, which is a number other than those mentioned above, must be set up. 
      game.setPoint();
    } 
} else {
  // So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
  if (roll == 7 || roll == 11) {
    //  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
    game.currentGameResult = 'lose';
    return console.log('Game Result: ', game.currentGameResult);  
    // The shooter loses if the 7 comes up and wins if the Point is rolled. 
  } else if (roll == point) {
    // The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
    game.currentGameResult = 'win';
    return console.log('Game Result: ', game.currentGameResult);
  } 
}
return console.log('Roll again...');
}

// TODO: Add all console logs to this section to display different pieces of info to the screen.
// UI.CONTROLLER
let UIController = (function() {
  const DOMSTRINGS = {};
  return {
    //Object full of functions that will become methods of the UI Controller

    displayShooter: function(currentShooter) { 
      console.log(`Player ${currentShooter+1} is shooter.`);
    },

  }
})();
//console.log('SHooter Test', UIController.displayShooter(0));
// TODO: Create Game Controller
// Game CONTROLLER
let GameController = (function(game, UIController) {
 
  return {
   gameLoop: function(){
    // Roll against other player 
    // Set the Bet
    // Make sure that the "bet" is a number with number and return NaN if NaN
    // Roll the Dice
    // Display the Dice Roll
    // Resolve Roll
    // Resolve Bet or Re-Roll
    // if player wins keep rolling if lose other player is shooter
    // play continues until a player's bank goes to 0. 
   }
  }
})();

// Pass the UI Controller (VIEW) in to the GameController (CONTROLLER)
// This is the DEBUG CONTROLLER
var recursiveAsyncReadLine = function (game, UIController) {
  rl.question('MENU: \n 1. Set shooter \n 2. Roll Dice \n 3. Set Point \n 4. Resolve dice(game logic) \n 5. Set Bet \n 6. Resolve Bet\n 7. Display Game Object\n 8. Init Game Object \n**XX. Run Game** (NOT ACTIVE!) \nEnter an option =>', function (entry) {
    if (entry == 'exit' || entry == 'quit') //we need some base case, for recursion
      return rl.close(); //closing RL and returning from function.
    // Create switch to run functions
    switch(entry) {
      case ('1'):
        game.currentShooter = game.setShooter();
        UIController.displayShooter(game.currentShooter);
        break;
      case ('2'):
        let diceResult = game.rollDice(2, 6);
        console.log("Roll Result: ", diceResult);
        game.currentDiceResult = game.sumDice(diceResult);
        console.log('Dice Total: ', game.currentDiceResult);
        break;
      case ('3'):
        game.setPoint();
        break;
      case ('4'):
        resolveDice(game);
        break;
      case ('5'):
        rl.question('Please enter Bet: ', function (bet) {
          // TODO: Make sure that the "bet" is a number with number and return NaN if NaN
          try {
          console.log(game.setBet(game.currentShooter, Number(bet)));
          } catch (err) {
            console.log(err);
            console.log("Make Sure to set shooter!");
          }
          recursiveAsyncReadLine(game, UIController);
        });
        break;
      case ('6'):
        resolveBet(game);
        console.log('Resolve the bet...');
        break;
      case ('7'):
        game.displayGameObject();
        break;
      case ('8'):
        console.log('Init Game Object!');
        break;
      default:
        // code block
        console.log('Invalid Response: ');
        break;
    }
    //displayGameObject(game);
    //console.log('Entry: ', entry);
    recursiveAsyncReadLine(game, UIController); //Calling this function again to ask new question
  });
};

recursiveAsyncReadLine(game,UIController); //we have to actually start our recursion somehow

rl.on("close", function() {
  console.log("\n Exiting Program... \n");
  process.exit(0);
});
Check out the conversation. NSFW...

Create a StreetDice Game Pt7

Today my goal was to start moving what code we have into an MVC architecture or pattern. We needed to move several functions into the game object. I also reviewed an several year old game RPG Dice Battle for clues on how to create closures to control scope and started to clean up the current code a bit.

Here is the final code at the end of the coding session:

//determine when to declare a variable and when to import?
// when you import it is just a code block
// when you declare a variable and require you bring in an object
//const { resolve } = require('path');
const readline = require('readline');

// simplified
//https://altcodeunicode.com/alt-codes-die-checkers-shogi-symbols/
// Players must first identify the player who will be shooting dice – the shooter. 

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let game = {
  roundNumber: 0,
  players: [0,1],
  playersBanks: [20,20],
  bet: 0,
  point: undefined,
  currentShooter: undefined,
  currentDiceResult: undefined,
  currentGameResult: undefined, 
  getBet: function() {
    return this.bet;
  },
  setBet: function(player, amount) {
    // TODO: Need to add check to make sure player has enough in the bank, if not enough try a different bet also perhaps update to display bank for the shooter when making the bet.
    //console.log(`Player ${currentShooter+1}'s Bank Balance: `, game.playersBanks[currentShooter]);
    // TODO: Also need to check that the other player has enough to cover the bet.
    if (game.playersBanks[player] >= amount) {
      this.bet = amount;
      return this.bet;
    }

    return console.log(`Current bank balance: $${game.playersBanks[currentShooter]}. Not enough in bank. Please enter a bet you can cover.`);
    
  },
  getPlayerBank: function(player) {
    return this.playersBanks[player];
  },
  // Turn a number negative with:  -Math.abs(num); 
  // TODO: Rename as adjustPlayerBank
  setPlayerBank: function(player, amount) {
    this.playersBanks[player] += amount;
    return this.playersBanks[player]; //amount can be negative for a losing bet
  },
  rollDice: function(numDice, sides) {
    let diceArray = [];
    for (let i = 0; i < numDice; i++) {
      let dice = Math.floor(Math.random() * sides) + 1; // should be 1 - 6
      diceArray.push(dice);
    }
    return diceArray;
  },
  sumDice: function (diceArray) {
    let diceTotal = 0;
    for (let i = 0; i < diceArray.length;i++) {
      diceTotal += diceArray[i]
    }
    return diceTotal;
  },
  setPoint: function() {
    //this need to set a players point parameter (value) PROPERTY!
    this.point = this.currentDiceResult;
    //console.log(`Point is ${this.point}`);
    return this.point;
  },
  setShooter: function() {
    let shooterDetermined = false;
    let player0;
    let player1;
    //loop roll until see who goes first
    while (!shooterDetermined) {
      player0 = this.rollDice(1,6)[0];
      //console.log("Player 1: ", player0);
      player1 = this.rollDice(1,6)[0];
      //console.log("Player 2: ", player1);
      if ( player0 > player1) {
        // NOTE: UI Human Interface to allow player to click to roll
        //console.log('Player 1 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 0;
        return this.currentShooter;
      } else if (player1 > player0) {
        // Computer rolls till outcome
        // console.log('Player 2 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 1 
        return this.currentShooter;
      } 
    }
  }, 
  initGame: function() {
  console.log('Reset Game Values');
  },
  displayGameObject: function () {
    console.log("Game Object: ", this);
  }
}

// Part of Controller
function resolveBet(game) {
  console.log("Did the player win? ", (game.currentGameResult=='win'));
  //currentShooter, currentGameResult, bet
  if (game.currentGameResult == 'win') {
    // Define loser as opposite of winner if winner = currentShooter
    let loser = +!game.currentShooter;
    console.log("Loser: ", loser);
    // subtract money from loser bank v = +!v;
    console.log(game.setPlayerBank(loser, -game.bet)); 
    // add money to currentShooter bank
    console.log(game.setPlayerBank(game.currentShooter, game.bet));
  } else {
    // subtract money from currentShooter bank
    game.setPlayerBank(game.currentShooter, -game.bet);
    // add money to winner bank
    let winner = +!game.currentShooter;
    game.setPlayerBank(winner, game.bet); 
  }
  
  return console.log(game.playersBanks);
}


function resolveDice(game) {
  // this function needs to return whether it is a win a loss or a roll again
  // this function will take a dice total and the point if point is undefined the it is the first roll otherwise it is not the first roll
  // The come out roll comes next. 
  let roll = game.currentDiceResult;
  //let rollCount;
  let point = game.point;
  //roll = sumDice(rollDice(2,6));
  //rollCount++;
  // This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
  //  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
  if (point == undefined) { //isFirstRoll = true
    if (roll == 7 || roll == 11) {
      game.currentGameResult = 'win';
      return console.log('Game Result: ', game.currentGameResult);
    }
  //  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
    if (roll == 2  || roll == 3  || roll == 12 ) { 
      game.currentGameResult = 'lose';
      return console.log('Game Result: ', game.currentGameResult);  
    }
    else {
      // A Point number, which is a number other than those mentioned above, must be set up. 
      setPoint(game);
    } 
} else {
  // So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
  if (roll == 7) {
    //  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
    game.currentGameResult = 'lose';
    return console.log('Game Result: ', game.currentGameResult);  
    // The shooter loses if the 7 comes up and wins if the Point is rolled. 
  } else if (roll == point) {
    // The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
    game.currentGameResult = 'win';
    return console.log('Game Result: ', game.currentGameResult);
  } 
}
return console.log('Roll again...');
}

// TODO: Add all console logs to this section to display different pieces of info to the screen.
// UI.CONTROLLER
let UIController = (function() {
  const DOMSTRINGS = {};
  return {
    //Object full of functions that will become methods of the UI Controller
  }
})();
// TODO: Create Game Controller
// Game CONTROLLER
let GameController = (function() {
 return {
   gameLoop: function(){
    // Roll against other player 
    // Set the Bet
    // Make sure that the "bet" is a number with number and return NaN if NaN
    // Roll the Dice
    // Display the Dice Roll
    // Resolve Roll
    // Resolve Bet or Re-Roll
    // if player wins keep rolling if lose other player is shooter
    // play continues until a player's bank goes to 0. 
   }
  }
})();

// Pass the UI Controller (VIEW) in to the GameController (CONTROLLER)
// This is the DEBUG CONTROLLER
var recursiveAsyncReadLine = function (game) {
  rl.question('MENU: \n 1. Set shooter \n 2. Roll Dice \n 3. Set Point \n 4. Resolve dice(game logic) \n 5. Set Bet \n 6. Resolve Bet\n 7. Display Game Object 8. Run Game \nEnter an option =>', function (entry) {
    if (entry == 'exit' || entry == 'quit') //we need some base case, for recursion
      return rl.close(); //closing RL and returning from function.
    // Create switch to run functions
    switch(entry) {
      case ('1'):
        game.currentShooter = game.setShooter();
        console.log(`Player ${game.currentShooter+1} is shooter.`);
        break;
      case ('2'):
        let diceResult = game.rollDice(2, 6);
        console.log("Roll Result: ", diceResult);
        game.currentDiceResult = game.sumDice(diceResult);
        console.log('Dice Total: ', game.currentDiceResult);
        break;
      case ('3'):
        game.setPoint();
        break;
      case ('4'):
        resolveDice(game);
        break;
      case ('5'):
        rl.question('Please enter Bet: ', function (bet) {
          // TODO: Make sure that the "bet" is a number with number and return NaN if NaN
          console.log(game.setBet(game.currentShooter, Number(bet)));
          recursiveAsyncReadLine(game);
        });
        break;
      case ('6'):
        resolveBet(game);
        console.log('Resolve the bet...');
        break;
      case ('7'):
        game.displayGameObject();
        break;
      default:
        // code block
        console.log('Invalid Response: ');
        break;
    }
    //displayGameObject(game);
    //console.log('Entry: ', entry);
    recursiveAsyncReadLine(game); //Calling this function again to ask new question
  });
};

recursiveAsyncReadLine(game); //we have to actually start our recursion somehow

rl.on("close", function() {
  console.log("\n Exiting Program... \n");
  process.exit(0);
});

Tomorrow the goal is to start building the UIController and also create the GameController which will take the game model and the UI controller.

No video today, I forgot to switch screens and recorded my face the whole time. Oof!

Street Dice Pt 6

Today our goal is to update the function for the final value in our game debug menu which is resolveBet(). Last video we ran into an issue where we tried to nest a question in our debug interface. So what happened was when we selected to set the bet, we needed to then input a bet value to use to set the bet. When we added our question, it would take our bet but wouldn’t loop so we would just hang on the input stream. We needed to add a call to our recursive menu function after taking that value.

With the bet set. Today’s task will be to resolve the bet. We need to know the current player, the game result, and the bet amount. The other challenge was to get the opposite value of the current player. so if it was 0 then we needed 1 for the other player because we needed to add or subtract from the other player’s bank depending on the result.

We found a neat solution on stack overflow that operates like a button being on or off and gives the desired result.

v = +!v;

The final code for our resolveBet() function was:

function resolveBet(game) {
  console.log("Did the player win? ", (game.currentGameResult=='win'));
  //currentShooter, currentGameResult, bet
  if (game.currentGameResult == 'win') {
    // Define loser as opposite of winner if winner = currentShooter
    let loser = +!game.currentShooter;
    console.log("Loser: ", loser);
    // subtract money from loser bank v = +!v;
    console.log(game.setPlayerBank(loser, -game.bet)); 
    // add money to currentShooter bank
    console.log(game.setPlayerBank(game.currentShooter, game.bet));
  } else {
    // subtract money from currentShooter bank
    game.setPlayerBank(game.currentShooter, -game.bet);
    // add money to winner bank
    let winner = +!game.currentShooter;
    game.setPlayerBank(winner, game.bet); 
  }
  return console.log(game.playersBanks);
}

Please watch the coding session on youTube to follow along.

Create Dice Game pt 5

Now that we have a game object we need to update all of our existing functions and modify our resolveDice() function so that it doesn’t loop. Here is the new resolveDice() function.

function resolveDice(game) {
  // this function needs to return whether it is a win a loss or a roll again
  // this function will take a dice total and the point if point is undefined the it is the first roll otherwise it is not the first roll
  // The come out roll comes next. 
  let roll = game.currentDiceResult;
  //let rollCount;
  let point = game.point;
  //roll = sumDice(rollDice(2,6));
  //rollCount++;
  //console.log(roll);
  //console.log(rollCount);
  // This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
  //  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
  if (point == undefined) { //isFirstRoll = true
    if (roll == 7 || roll == 11) {return console.log('win');}
  //  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
    if (roll == 2  || roll == 3  || roll == 12 ) { return console.log('lose');}
    else {
      // A Point number, which is a number other than those mentioned above, must be set up. 
      setPoint(game);
    } 
} else {
  // So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
  if (roll == 7) {
    //  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
    return console.log('lose');
    // The shooter loses if the 7 comes up and wins if the Point is rolled. 
  } else if (roll == point) {
    // The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
    return console.log('win');
  } 
}

Next I need to handle setting the bet and resolving the bet, then work on a game controller. And finally create a web UI.

Here is the recording of this coding session:

Create a Steet Dice Game Pt 4

Today we created a game object so we could use the result of the functions we were testing with the other functions. We created some methods to get and set object properties and we added a displayGameObject menu item. And we are now using the gameObject with the set shooter function and it appears to be working properly. Here is the game Object:

let game = {
  roundNumber: 0,
  players: [0,1],
  playersBanks: [20,20],
  bet: 0,
  currentShooter: undefined,
  getBet: function() {
    return this.bet;
  },
  setBet: function(amount) {
    this.bet = amount;
    return this.bet;
  },
  getPlayerBank: function(player) {
    return this.playersBanks[player];
  },
  // Turn a number negative with:  -Math.abs(num); 
  setPlayerBank: function(player, amount) {
    return this.getPlayerBank[player] + amount; //amount can be negative for a losing bet
  }
}

In the next part we will use the game object in each menu item and then we will start working on the game logic.

Please watch the video of today’s coding session and like and subscribe so you don’t miss any content from Dead Set on Success Coding.

Creating a Street Dice Game Pt3

Today I want to finish the functions on the interface and we need to determine how to pass data. I think we need to create a game object to pass into the functions for now until I understand more about scope.

Here is what we have left to implement for the first set of functions:

4. Resolve dice (game logic)
5. Set Bet
6. Resolve Bet

I think the game logic will be a bit tedious but should be relatively straight forward and simple. My first thought is to just use if then else if then statements to handle each outcome.

I did end up using some nested if statements. the idea is that if the point is not defined the the win / lose conditions are different than if the point is set. so we check to see if point is defined and if it is we check to see if it is a lose condition and then if it is a win and if not then we roll again (loop restarts)

Also thank you to Nicolas Marcora https://blog.usejournal.com/mastering-javascripts-and-logical-operators-fd619b905c8f for the help with the Logical Operators.

See resolveDice() function code below:

function resolveDice() {
  // The come out roll comes next. 
  let roll;
  let rollCount;
  let point;

  while(true) {
    roll = sumDice(rollDice(2,6));
    //rollCount++;
    console.log(roll);
    //console.log(rollCount);
    // This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
    //  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
    if (point == undefined) {
      if (roll == 7 || roll == 11) {return console.log('win');}
    //  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
      if (roll == 2  || roll == 3  || roll == 3 ) { return console.log('lose');}
      else {
        // A Point number, which is a number other than those mentioned above, must be set up. 
        point = roll;
      } 
  } else {
    // So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
    if (roll == 7) {
      //  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
      return console.log('lose');
      // The shooter loses if the 7 comes up and wins if the Point is rolled. 
    } else if (roll == point) {
      // The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
      return console.log('win');
    }
  }
}
}

Creating a Street Dice Game Pt2

Ok, since Creating a Street Dice Game Pt1 I realize I needed a testing interface, and I thought back to DOS batch files. When I was young and everything was run from command line, sometimes you wanted to boot a disk and run a program or you wanted a simple menu on boot and you had to create a .bat file. So what I set out to do today was to create a simple menu for testing function that I will use in the Street Dice game and this gave me a chance to practice the switch syntax and also to again use the readline library in this project.

Here is my final code for the night:

//determine when to declare a variable and when to import?
// when you import it is just a code block
// when you declare a variable and require you bring in an object
const readline = require('readline');

// simplified
//https://altcodeunicode.com/alt-codes-die-checkers-shogi-symbols/
// Players must first identify the player who will be shooting dice – the shooter. 

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});


function rollDice(numDice, sides) {
  let diceArray = [];
  for (let i = 0; i < numDice; i++) {
    let dice = Math.floor(Math.random() * sides) + 1; // should be 1 - 6
    diceArray.push(dice);
  }
  return diceArray;
}

function sumDice(diceArray) {
  let diceTotal = 0;
  for (let i = 0; i < diceArray.length;i++) {
    diceTotal += diceArray[i]
  }
  return diceTotal;
}

function setPoint(player, rollTotal) {
  //this need to set a players point parameter (value) PROPERTY!
  console.log(`${player+1}'s point is ${rollTotal}`);
}

function determineOutcome(throwTotal, timesRolled) {
  if (timesRolled === 0) {
  } 
  // win, lose or play again
  // true, false or undefined
}

let player0;
let player1;
// let player0Bank = 20;
// let player1Bank = 20;

// let timesRolled = 0;


function setShooter() {
  let shooterDetermined = false;
  //loop roll until see who goes first
  while (!shooterDetermined) {
    player0 = rollDice(1,6)[0];
    console.log("Player 1: ", player0);
    player1 = rollDice(1,6)[0];
    console.log("Player 2: ", player1);
    if ( player0 > player1) {
      // UI Human Interface to allow player to click to roll
      console.log('Player 1 goes first.')
      shooterDetermined = true;
      return 0;
    } else if (player1 > player0) {
      // Computer rolls till outcome
      console.log('Player 2 goes first.')
      shooterDetermined = true;
      return 1;
    } 
  }

}

// The shooter will then need to make a bet followed by the rest of the group in the clockwise direction.
// Each player can cover a portion of or all of the shooter’s bet.
// Betting continues until the shooter’s wager is matched.
let bet = 0;

// The come out roll comes next. 
// This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
//  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
//  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
// A Point number, which is a number other than those mentioned above, must be set up. 
// So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
// The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
//  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
// Rolling dice proceeds until a 7 or the Point is rolled. 
// The shooter loses if the 7 comes up and wins if the Point is rolled. 
// If other numbers are rolled the shooter continues rolling the dice. The round ends only after a 7 or the point is rolled.

//if we try to resolve the dice and there is now point value then set point

var recursiveAsyncReadLine = function () {
  rl.question('MENU: \n 1. Set shooter \n 2. Roll Dice \n 3. Set Point \n 4. Resolve dice(game logic) \n 5. Set Bet \n 6. Resolve Bet\nEnter an option =>', function (entry) {
    if (entry == 'exit' || entry == 'quit') //we need some base case, for recursion
      return rl.close(); //closing RL and returning from function.
    // Create switch to run functions
    switch(entry) {
      case ('1'):
        let startingPlayer = setShooter();
        console.log(`Player${startingPlayer+1} is shooter.`);
        // code block
        break;
      case ('2'):
        let diceResult = rollDice(2, 6);
        console.log("Roll Result: ", diceResult);
        console.log('Dice Total: ', sumDice(diceResult));
      
        // code block
        break;
      case ('3'):
        setPoint(startingPlayer, diceResult);
      default:
        // code block
        console.log('Invalid Response: ');
    }
    //console.log('Entry: ', entry);
    recursiveAsyncReadLine(); //Calling this function again to ask new question
  });
};

recursiveAsyncReadLine(); //we have to actually start our recursion somehow

rl.on("close", function() {
  console.log("\n Exiting Program... \n");
  process.exit(0);
});

Please check out the video below, where I walk through my thought process:

Creating a Street Dice Game Pt1

Today, I wanted to build a game and start a project from scratch. I decided on Street Dice. I decided on Street Dice because it has fixed rules and I think it is a perfect beginner project for my skill level.

About a year and a half ago I created an RPG Dice Battle Game but I stopped working in Javascript and I don’t have the confidence to build anything like it today, so I want to start with a small project to get back on a “roll”.

Here are the simplified rules I will be basing the game around:

simplified
Players must first identify the player who will be shooting dice – the shooter. 
The shooter will then need to make a bet followed by the rest of the group in the clockwise direction.
Each player can cover a portion of or all of the shooter’s bet.
Betting continues until the shooter’s wager is matched.
The come out roll comes next. 
This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
 The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
 If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
A Point number, which is a number other than those mentioned above, must be set up. 
So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
 The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
Rolling dice proceeds until a 7 or the Point is rolled. 
The shooter loses if the 7 comes up and wins if the Point is rolled. 
If other numbers are rolled the shooter continues rolling the dice. The round ends only after a 7 or the point is rolled.

First thing I do is start trying to determine who will go first. I create a couple of functions to get a dice roll and then set up an if statement to see which player wins the dice.

In testing I realized that I didn’t account for a tie, and had to create a while loop so we could roll off until a player was determined as the shooter.

Please watch the video below were I begin the project:

Trying to Understand MongoDB Data Modelling

I am currently taking a node.js, express, and mongoDB bootcamp on Udemy by Jonas Schmedtmann https://www.udemy.com/course/nodejs-express-mongodb-bootcamp/ and I am struggling a bit to understand data modeling so today I rewatched the two class videos that cover this in detail, and took the following notes:

Data Modeling

Real world scenario -> Unstructured Data -> Structured, logical data Model

  1. Steps to Model Data
    1. Identify Relationships between Data
      1. 1 to 1
        1. Movie -> Name
      2. 1 to Many 
        1. 1: Few
          1. Movie -> Award, Movie -> Award
        2. 1: Many
          1. Movie -> review (thousands)
        3. 1: TON
          1. App -> Log (millions)
      3. Many to Many
        1. Movie -> Actor
          1. A movie can have many actors and an actor can play in many movies
    2. Referencing/normalization vs. embedding/denormalization
      1. Referenced / Normalized
        1. Each Data Document is separate
        2. One document references the others by ID
        3. Performance increased when need to query each document on its own
        4. Con: Need 2 queries to get data from referenced document
      2. Embedded / Normalized
        1. Data Documents are combined into a single document
        2. Good on Performance
          1. Can get all data in one query 
        3. Impossible to query the embedded document on its own
    3. Embedding or referencing other documents
      1. Embedding
        1. Relationship Type 
          1. 1: Few
          2. 1: Many
        2. Data Access Patterns
          1. Data is mostly read
          2. Data does not change quickly
          3. (High read/write ratio
        3. Data Closeness
          1. Data really belongs together
      2. Referencing
        1. Relationship Type 
          1. 1: Many
          2. 1: Ton
          3. Many:Many
        2. Data Access Patterns
          1. Data is updated a lot
          2. (low read/write ratio)
        3. Data Closeness
          1. We frequently need to query both datasets on their own
    4. Types of Referencing
      1. Child Referencing
        1. The parent contains references to the ids of its children
        2. Uses
          1.  1: FEW
      2. Parent Referencing
        1. The child contains a reference to the id of its parent
        2. Uses
          1. 1:Many 
          2. 1:Ton
      3. Two-Way Referencing
        1. The parent references its children and the child references it’s parents
          1. Example movies and actors 
            1. Movie references the ids of all of the actors in the movie
            2. Actor references the ids of all of the movies that they have acted in
        2. Uses 
          1. Many:Many
    5. Important Principles to Consider when deciding
      1. Most Important: Structure your data to match the ways that your application queries and updates data
        1. Identify the questions that arise from your application’s use cases first, and then model your data so that the questions can get answered in the most efficient way
        2. Always favor embedding, unless there is a good reason not to embed. 
          1. Especially for 1:Few and 1:Many
      2. 1:Ton or Many:Many is usually a good reason to reference instead of embedding
      3. Favor referencing when data is updated a lot and if you need to frequently access a dataset on its own
      4. Use embedding when data is mostly read but rarely updated, and when two datasets belong intrinsically together
      5. Don’t allow arrays to grow indefinitely. Therefore, if you need to normalize, use child referencing for 1:Many relationships, and parent referencing for 1:Ton relationships
      6. Use Two-Way referencing for Many:Many relationships

Then I tried to model some data for a Poker Home Game Stats Tracking App that I plan to make as a portfolio project.

While modeling the data I realized I still wasn’t very clear on what data would belong in a new document. For example in the poker app there would be a document for users and a document for games. But If I wanted to display information on a leader board with stats in it would I need a leader board document? I believe so because I would not want to have to reference all of the users and games to build the stats each time a user accessed the page, I would likely have the stats compiled from the data and stored in a chart of some type.