This is a function for a simple shopping app (kinda) thing that I coded to work on my JS skills, considering my elementary experience in it. But everything works except for one thing:
The applyStaffDiscount function doesn't seem to work. Everytime I try to apply an employee discount, the program just returns the same original value that was present before trying to apply the discount. Please help and also let me know how I can improve this program.
function StaffMember(name, discountPercent) {
this.name = name;
this.discountPercent = discountPercent;
}
var sally = new StaffMember("sally", 5);
var bob = new StaffMember("bob", 10);
var arhum = new StaffMember("arhum", 20);
var cashRegister = {
total: 0,
lastTransactionAmount: 0,
add: function(itemCost) {
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
scan: function(item, quantity) {
switch (item) {
case "eggs": this.add(0.98 * quantity); break;
case "milk": this.add(1.23 * quantity); break;
case "magazine": this.add(4.99 * quantity); break;
case "chocolate": this.add(0.45 * quantity); break;
}
return true;
},
voidLastTransaction: function() {
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
applyStaffDiscount: function(employee) {
this.total -= (this.total * (employee.discountPercent/100))
}
};
var cont = confirm("Are you ready to shop?")
while (cont) {
var user = ("Choose your function: A to Add Item, ED for Employee Discount, VT to Void Transaction or just X to Close")
var askUser = prompt(user).toUpperCase()
if (askUser === "A") {
var itemName = prompt("What item would you like?", "Eggs, Milk, Magazine, Chocolate").toLowerCase()
var itemNum = prompt("How many?")
cashRegister.scan(itemName, itemNum)
var cont = confirm("Your total bill is $" + cashRegister.total.toFixed(2) + ". Would you like anything else?")
}
else if (askUser === "ED") {
var name1 = prompt("Please enter you name").toLowerCase()
cashRegister.applyStaffDiscount[name1]
alert("Your total bill is $" + cashRegister.total.toFixed(2) + ".")
}
else if (askUser === "VT") {
cashRegister.voidLastTransaction()
alert("Your previous transaction has been voided. Your total bill is $" + cashRegister.total.toFixed(2) + " now.")
}
else if (askUser === "X") {
cont = false
}
if (cont === false) {
alert("We hope you had a good time. have a nice day!")
}
}
calling applyStaffDiscount should be done as shown below
cashRegister.applyStaffDiscount(name1);
Then inside applyStaffDiscount function, it should be accessed as below
this.total -= (this.total * (window[employee].discountPercent/100))
You didn't call the function in here:
cashRegister.applyStaffDiscount[name1]
Try it with something like this:
cashRegister.applyStaffDiscount(name1);
Related
I've created a simple higher or lower card guessing game, it works but once it completes once it then loops through the game logic n^2 times and I cant explain why. I'm really new to coding and JavaScript and I cant figure out what's happening. The issue I currently have is while I'm able to look up concepts in isolation I don't understand enough about the bigger picture to know what interaction is causing the looping.
less useful further info:
Currently the whole script is really a proof of concept, ultimately I will replace the deck building function and just use the random number generator to find images of cards, record all of the previous game events and remove cards from the deck as the game progresses but I cant have it looping by the square of the number of times its been through the game cycle.
Here is the code, please feel free to talk to me like I'm 5, I currently feel like a monkey with a gun.
console.log(">>>>>>>>>>>>>>>>>>>>>>> SCRIPT START");
console.log("variables are defined");
var suitClubs = [];
var suitDiamonds = [];
var suitHearts = [];
var suitSpade = [];
var history = [];
var userGuess;
var activeCard;
var nextCard;
var randomSuitOne;
var randomCardOne;
var randomSuitTwo;
var randomCardTwo;
var activeCardValue;
var nextCardValue;
var gameCycle = 0;
const card = document.querySelector(".card");
const title = document.querySelector(".title");
const historyP = document.querySelector(".history-p");
console.log("buildDeck() is called")
buildDeck();
function buildDeck() {
console.log("Deck is built");
for (i = 1; i <= 13; i++) {
suitDiamonds.push(i + " Diamond");
}
for (i = 1; i <= 13; i++) {
suitHearts.push(i + " Heart");
}
for (i = 1; i <= 13; i++) {
suitClubs.push(i + " Club");
}
for (i = 1; i <= 13; i++) {
suitSpade.push(i + " Spade");
}
var deck = suitClubs.concat(suitDiamonds, suitHearts, suitSpade);
console.log("cardChoice is called");
cardChoice();
};
function cardChoice() {
gameCycle = gameCycle + 1;
console.log(">>>>>>>>>>>>>>>>>>>>>>> GAME CYCLE START");
title.innerHTML = "Higher or Lower!"
activeSequenceCard();
// console.log("activeSequenceCard is called to randomize the active card");
function activeSequenceCard() {
randomSuitOne = Math.floor((Math.random() * 4) + 1);
randomCardOne = Math.floor((Math.random() * 13));
switch (randomSuitOne) {
case 1:
activeCard = suitClubs[randomCardOne];
break;
case 2:
activeCard = suitDiamonds[randomCardOne];
break;
case 3:
activeCard = suitSpade[randomCardOne];
break;
case 4:
activeCard = suitHearts[randomCardOne];
break;
}
card.innerHTML = activeCard;
nextSequenceCard();
// console.group("nextSequenceCard is called to randomize the next card in the deck")
}
function nextSequenceCard() {
randomSuitTwo = Math.floor((Math.random() * 4) + 1);
randomCardTwo = Math.floor((Math.random() * 13));
switch (randomSuitTwo) {
case 1:
nextCard = suitClubs[randomCardTwo];
break;
case 2:
nextCard = suitDiamonds[randomCardTwo];
break;
case 3:
nextCard = suitSpade[randomCardTwo];
break;
case 4:
nextCard = suitHearts[randomCardTwo];
break;
}
historyP.innerHTML = ("The next card will be: " + nextCard);
console.log("randomSuitOne is: " + randomSuitOne + " randomCardOne is: " + randomCardOne);
console.log("randomSuitTwo is: " + randomSuitTwo + " randomCardTwo is: " + randomCardTwo);
gamePlay();
}
}
function gamePlay() {
for (let i = 0; i < 2; i++) {
document.getElementsByClassName("game-button")[i].addEventListener("click", function () {
userGuess = parseInt(this.value);
console.log("The users guess was button (" + this.value + ") " + this.innerHTML + " and is a: " + typeof this.value);
switch (userGuess) {
case 1: console.log("User clicked HIGHER");
if (activeCardValue <= nextCardValue) {
console.log("Case 1: TRUE fired");
title.innerHTML = "CORRECT!"
setTimeout(cardChoice, 2000);
break;
} else {
console.log("Case 1: FALSE fired");
title.innerHTML = "GAME OVER!"
}
break;
case 2: console.log("User clicked LOWER");
if (activeCardValue >= nextCardValue) {
console.log("Case 2: TRUE fired");
title.innerHTML = "CORRECT!"
setTimeout(cardChoice, 2000);
break;
} else {
console.log("Case 2: FALSE fired");
title.innerHTML = "GAME OVER!"
}
break;
} console.log(">>>>>>>>>>>>>>>>>>>>>>> GAME CYCLE ENDS, this is cycle: " + gameCycle);
})
}
activeCardValue = activeCard.split(" ");
activeCardValue = parseInt(activeCardValue.splice(0, 1));
console.log("activeCardValue is: " + activeCardValue);
nextCardValue = nextCard.split(" ");
nextCardValue = parseInt(nextCardValue.splice(0, 1));
console.log("nextCardValue is: " + nextCardValue);
}
I am trying to make a game when you have to guess a number that is generated by the Math.random() function in JavaScript. But I realized that when I do that I have to rerun the function if they get the number wrong. Then the number regenerates when it reruns the function. Is there a way that I can make the variable stay until I want to change it. I was going to change it using the const function but I realized it would do the same thing. Here is my full code:
var tries = 5;
var howMany = 0;
var wrong = 0;
var player1 = 0;
var player2 = 0;
var triesmulti = 10;
var turn = 'player 1';
var number;
function start() {
var min = document.getElementById('min').value;
var max = document.getElementById('max').value;
number = Math.floor(Math.random() * (+max - +min)) + +min;
if (tries < 1) {
alert('You \don\'t have any more tries left. The number was \n' + number);
tries = 5;
wrong += 1;
document.getElementById('wrong').innerHTML = 'You have got the number wrong ' + wrong + ' times';
} else {
var guess = prompt();
if (guess == number) {
alert('You got the number right!\n' + number);
howMany += 1;
tries = 5;
document.getElementById('howMany').innerHTML = 'You have guessed the number ' + howMany + ' times';
document.getElementById('tries').innerHTML = 'You have 5 tries left';
} else {
alert('You got the number wrong.');
tries -= 1;
document.getElementById('tries').innerHTML = 'You have ' + tries + ' tries left';
setTimeout(start, 1000);
}
}
}
function multiplayer() {
var min = document.getElementById('minm').value;
var max = document.getElementById('maxm').value;
number = Math.floor(Math.random() * (+max - +min)) + +min;
if (triesmulti < 1) {
alert('You \don\'t have any more tries left\n' + number);
triesmulti = 10;
document.getElementById('triesmulti').innerHTML = 'You have 5 tries for each player';
} else {
var guess = prompt(turn);
if (turn == 'player 1') {
if (guess == number) {
alert('You got the number right!\n' + number);
player1 += 1;
triesmulti = 10;
document.getElementById('triesmulti').innerHTML = 'You have 5 tries for each player';
} else {
alert('You got the number wrong!');
turn = 'player 2';
setTimeout(multiplayer, 1000);
}
} else if (turn == 'player 2') {
if (guess == number) {
alert('You got the number right!\n' + number);
player2 += 1;
triesmulti = 10;
document.getElementById('triesmulti').innerHTML = 'You have 5 tries for each player';
} else {
alert('You got the number wrong!');
turn = 'player1';
setTimeout(multiplayer, 1000);
}
}
}
}
If you see there, in the setTimeout() it reruns the function.
You can create a stateful random number generator quite easily with an object or closure:
const rndRng = (lo, hi) => ~~(Math.random() * (hi - lo) + lo);
const intRng = (lo, hi) => {
let n = rndRng(lo, hi);
return {
next: () => (n = rndRng(lo, hi)),
get: () => n
};
};
const rng = intRng(10, 20);
console.log(rng.get());
console.log(rng.get());
rng.next();
console.log(rng.get());
console.log(rng.get());
But having to do this shouldn't really be necessary for your application. Currently, the application uses non-idempotent functions that rely on global state, repeated/duplicate logic and deeply nested conditionals, so it's become too encumbered to easily work with.
I'd start by storing state in an object. A game like this can be modeled well by a finite state machine.
The below code is a naive implementation of this with plenty of room for improvement, but hopefully demonstrates the idea. It works for any number of players and it's fairly easy to add features to.
However, string messages are baked into business logic so the class is overburdened. A good next step would be creating a separate view class to abstract business logic from display. However, although the message strings are baked into the game logic, the DOM is decoupled. This makes it fairly easy for the caller to use the class in other UIs such as substituting the DOM for alert/prompt.
The below solution is far from the only way to approach this design problem.
class GuessingGame {
constructor(players=1, guesses=5, lo=0, hi=10) {
this.players = Array(players).fill().map(() => ({
guesses: guesses, score: 0
}));
this.guesses = guesses;
this.lowerBound = lo;
this.upperBound = hi;
this.state = this.initialize;
}
initialize() {
const {lowerBound: lo, upperBound: hi} = this;
this.players = this.players.map(({score}) => ({
guesses: this.guesses,
score: score
}));
this.target = ~~(Math.random() * (hi - lo) + lo);
this.currentPlayer = ~~(Math.random() * this.players.length);
this.state = this.guess;
this.message = `guess a number between ${lo} and ${hi - 1} ` +
`(inclusive), player ${this.currentPlayer}:`;
}
handleCorrectGuess() {
this.state = this.initialize;
this.players[this.currentPlayer].score++;
this.message = `player ${this.currentPlayer} guessed ` +
`${this.target} correctly! press 'enter' to continue.`;
}
handleNoGuessesLeft(guess) {
this.state = this.initialize;
this.players[this.currentPlayer].score--;
this.flash = `${guess} was not the number, player ` +
`${this.currentPlayer}.`;
this.message = `player ${this.currentPlayer} ran out of ` +
`guesses. the secret number was ${this.target}. press ` +
`'enter' to continue.`;
}
handleIncorrectGuess(guess) {
this.flash = `${guess} was not the number, player ` +
`${this.currentPlayer}.`;
this.currentPlayer = (this.currentPlayer + 1) % this.players.length;
const {lowerBound: lo, upperBound: hi} = this;
this.message = `guess a number between ${lo} and ${hi - 1} ` +
`(inclusive), player ${this.currentPlayer}:`;
}
guess(guess) {
if (String(+guess) !== String(guess)) {
this.flash = `sorry, ${guess || "that"} ` +
`isn't a valid number. try something else.`;
return;
}
if (this.target === +guess) {
this.handleCorrectGuess();
}
else if (!--this.players[this.currentPlayer].guesses) {
this.handleNoGuessesLeft(+guess);
}
else {
this.handleIncorrectGuess(+guess);
}
}
nextState(...args) {
this.flash = "";
return this.state(...args);
}
scoreBoard() {
return game.players.map((e, i) =>
`player ${i}: {score: ${e.score}, guesses remaining: ` +
`${e.guesses}} ${game.currentPlayer === i ? "<--" : ""}`
).join("\n");
}
}
const msgElem = document.getElementById("message");
const responseElem = document.getElementById("response");
const scoresElem = document.getElementById("scoreboard");
const game = new GuessingGame(3);
game.nextState();
msgElem.innerText = game.message;
scoresElem.innerText = game.scoreBoard();
let timeout;
responseElem.addEventListener("keydown", e => {
if (timeout || e.code !== "Enter") {
return;
}
game.nextState(e.target.value);
e.target.value = "";
e.target.disabled = true;
msgElem.innerText = game.flash;
clearTimeout(timeout);
timeout = setTimeout(() => {
msgElem.innerText = game.message;
scoresElem.innerText = game.scoreBoard();
timeout = null;
e.target.disabled = false;
e.target.focus();
}, game.flash ? 1300 : 0);
});
* {
background: white;
font-family: monospace;
font-size: 1.03em;
}
input {
margin-bottom: 1em;
margin-top: 1em;
}
<div id="message"></div>
<input id="response">
<div id="scoreboard"></div>
Well, your code is not organised, have lot of duplicates, you could devide it into functions anyway, you can add a boolean variable to check against when you should change the number, I don't know about your HTML code or css but I just added those elements according to you selectors, you can change the multiplayer function too.
var tries = 5;
var howMany = 0;
var wrong = 0;
var player1 = 0;
var player2 = 0;
var triesmulti = 10;
var turn = 'player 1';
var number;
var isAlreadyPlaying = false;
function start() {
var min = document.getElementById('min').value;
var max = document.getElementById('max').value;
if(!isAlreadyPlaying) {
isAlreadyPlaying = true;
number = Math.floor(Math.random() * (+max - +min)) + +min;
}
if (tries < 1) {
alert('You \don\'t have any more tries left. The number was \n' + number);
tries = 5;
wrong += 1;
document.getElementById('wrong').innerHTML = 'You have got the number wrong ' + wrong + ' times';
isAlreadyPlaying = false;
} else {
var guess = prompt();
if (guess == number) {
alert('You got the number right!\n' + number);
howMany += 1;
tries = 5;
document.getElementById('howMany').innerHTML = 'You have guessed the number ' + howMany + ' times';
document.getElementById('tries').innerHTML = 'You have 5 tries left';
isAlreadyPlaying = false;
} else {
alert('You got the number wrong.');
tries -= 1;
document.getElementById('tries').innerHTML = 'You have ' + tries + ' tries left';
setTimeout(start, 1000);
}
}
}
Min <input type="number" id="min" value="1"><br>
Max<input type="number" id="max" value="10"><br>
<button onclick="start()">Play</button>
<p id="wrong"></p>
<p id="howMany"></p>
<p id="tries"></p>
My code seems to log the if statement as false, even though if I console.log the conditions it returns as true. Why is it doing that? (the code , that is not working is indicated by error not bypassing.)
function StaffMember(name,discountPercent){
this.name = name;
this.discountPercent = discountPercent;
}
function Stock(item){
this.item = item;
}
//Global Variables
var staffMembers = {};
var sally = new StaffMember("Sally",0.05);
staffMembers['sally'] = sally;
var bob = new StaffMember("Bob",0.10);
staffMembers['bob'] = bob;
var me = new StaffMember("Aaron",0.20);
staffMembers['me'] = me;
//item variables
var eggs = new Stock("Eggs");
var milk = new Stock("Milk");
var magazine = new Stock("Magazine");
var chocolate = new Stock("Chocolate");
//item Objects
var Stock = {};
Stock['eggs'] = eggs;
Stock['milk'] = milk;
Stock['magazine'] = magazine;
Stock ['chocolate'] = chocolate;**
var cashRegister = {
total:0,
lastTransactionAmount: 0,
add: function(itemCost){
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
scan: function(item,quantity){
switch (item){
case "eggs": this.add(0.98 * quantity); break;
case "milk": this.add(1.23 * quantity); break;
case "magazine": this.add(4.99 * quantity); break;
case "chocolate": this.add(0.45 * quantity); break;
}
return true;
},
voidLastTransaction : function(){
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
// Create a new method applyStaffDiscount here
applyStaffDiscount : function(employee){
this.total -= this.total*(employee.discountPercent);
}
};
$(document).ready(function(){
$('#target2').hide();
$('#check').on('click', function(e){
e.preventDefault();
var item = $('#item').val();
var quantity = $('#quantity').val();
var staff = $('#staff').val();
cashRegister.scan(item, quantity);
//ERROR IN CODE NOT BYPASSING
if(item === Stock['item'] && quantity > 0) {
cashRegister.scan(item, quantity);
}
///
else {
alert("This Item Does Not Exist!");
}
if(staff.length > 0 && typeof staffMembers[staff] !='undefined'){
cashRegister.applyStaffDiscount(staffMembers[staff]);
}
var output = document.getElementById("result");
result.innerHTML = 'Your bill is ' + cashRegister.total.toFixed(2);
$('#target2').fadeIn(5000)
// .animate({opacity: 0.5}, 3000)
.fadeOut(5000);
});
$('#target').submit(function(){
var info = $(this).serializeJSON();
console.log(info);
var data = JSON.parse('[info]');
console.log(data);
return false;
});
});
Stock['item'] is going to return undefined because Stock['item'] is not declared. You declare Stock['milk'], Stock['magazine'],Stock['eggs'], and Stock['chocolate'], but not Stock['item']. If you were trying to use it as a variable, you should remove the quotes.
You are also overwriting your "Stock" function with a "Stock" object, which is not causing trouble right now but it could cause issues later down the line. You should rename those to be different if possible.
Try using Stock[item] !== undefined && quantity > 0 in place of your current if expression
You did not post your HTML or a working fiddle, but my guess is your if statement should be:
if(item === Stock[item] && quantity > 0) {
cashRegister.scan(item, quantity);
}
Stock['item'] returns undefined as you're not calling it either with an object context like obj.Stock() or after using bind or call, so this is undefined. It's not returning anything either, so no assignment is made. I'm assuming $('#item').val() also. $('#item') is most likely null, triggering a runtime error and stopping your if sentence.
I'm guessing the onload function is not properly implemented. Entering numbers or letters do not get the appropriate error or calculation response.
This is my code as of now:
http://jsfiddle.net/907yn57r/
var $ = function (id) {
return document.getElementById(id);
}
var calculateTaxAndTotals = function () {
var taxRate = parseFloat($("taxRate").value); //The tax rate, as a percentage (e.g. 8.5)
var subTotal = parseFloat($("itemPrice").value); //An item price ex $5.95
$("salesTax").value = "";
$("totalItemCost").value = "";
if (isNaN(taxRate) || taxRate <= 0) {
document.taxCalc.taxRate.focus();
document.$("taxRateMessage").firstChild.nodeValue = "Please enter a valid value.";
} else if (isNaN(itemPrice) || itemPrice <= 0) {
document.$("priceMessage").firstChild.nodeValue = "Please enter a valid value.";
} else {
var salesTax = subTotal * (taxRate / 100);
var totalItemCost = salesTax + itemPrice;
$("orderTotal").focus();
alert(totalItemCost);
}
}
window.onload = function () {
calculateTaxAndTotals();
}
There are a couple of problems.
First of all, JSFiddle deals with the main html structure itself, so you don't need new body tags and the like.
Secondly, the Javascript here needs to be loaded in the head or the body (on the top left in JSFiddle you can choose different places for it to be loaded).
Finally, there's a few errors in the definition for CalculateTaxAndTotals, it should say
if (isNaN(taxRate) || taxRate <= 0) {
document.taxCalc.taxRate.focus();
$("taxRateMessage").firstChild.nodeValue = "Please enter a valid value.";
} else if (isNaN(subTotal) || itemPrice <= 0) {
$("priceMessage").firstChild.nodeValue = "Please enter a valid value.";
} else {
var salesTax = subTotal * (taxRate / 100);
var totalItemCost = salesTax + itemPrice;
$("orderTotal").focus();
alert(totalItemCost);
}
Really Fixed Fiddle
The final issue was that you were calling isNaN on itemPrice, but the variable itemPrice didn't exist.
<!DOCTYPE html>
<html>
<body>
<script language="javascript" type="text/javascript">
//Definition of staff members (class)
function StaffMember(name,discountPercent){
this.name = name;
this.discountPercent = discountPercent;
}
//Creation of staff members (object)
var s121 = new StaffMember("Sally",5);
var b122 = new StaffMember("Bob",10);
var d123 = new StaffMember("Dave",20);
staffMembers = [s121,b122,d123];
//Creation of cash register (object)
var cashRegister = {
total:0,
lastTransactionAmount: 0,
//Add to the total (method)
add: function(itemCost){
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
//Retreive the value of an item (method)
scan: function(item,quantity){
switch (item){
case "eggs": this.add(0.98 * quantity); break;
case "milk": this.add(1.23 * quantity); break;
case "magazine": this.add(4.99 * quantity); break;
case "chocolate": this.add(0.45 * quantity); break;
}
return true;
},
//Void the last item (method)
voidLastTransaction : function(){
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
//Apply a staff discount to the total (method)
applyStaffDiscount: function(employee) {
this.total -= this.total * (employee.discountPercent / 100);
}
};
//Ask for number of items
do {
var numOfItems = prompt("How many items do you have?");
document.body.innerHTML = numOfItems;
if (isNaN(numOfItems)) {
i=0;
} else {
i=1;
}
} while (i===0);
//Ask for item and qty of item
var items = [];
var qtys = [];
for(var i=0;i<numOfItems;i++) {
var j=0;
do {
items[i] = prompt("What are you buying? (eggs, milk, magazine, chocolate)");
switch (items[i]) {
case "eggs" :;
case "milk" :;
case "magazine" :;
case "chocolate" : j=1; document.body.innerHTML = items[i]; break;
default : document.body.innerHTML = 'Item not reconized, please re-enter...'
; break;}
} while (j===0);
do {
qtys[i] = prompt("How many " + items[i] + " are you buying?");
document.body.innerHTML = qtys[i];
if (isNaN(qtys[i])) {
j=1;
} else {
j=0;
}
} while (j===1);
//Add to the sub-total
cashRegister.scan(items[i],qtys[i])
}
//Find out if it's a staff member & if so apply a discount
var customer;
var staffNo;
do {
customer = prompt("Please enter customer name or type 'staff'.");
document.body.innerHTML = customer;
if (customer === 'staff') {
staffNo = prompt("Please enter your staff number");
for (i in staffMembers) {
if (staffMembers[i] === staffNo) {
cashRegister.applyStaffDiscount(staffNo);
} else {
document.body.innerHTML = "Staff number not found";
};
}
}
i=1;
} while (i=0);
// Show the total bill
if (customer !== 'staff') {
document.body.innerHTML = 'Your bill is £'+cashRegister.total.toFixed(2)
+' Thank you for visiting ' +customer;
} else {
document.body.innerHTML = 'Your bill is £'+cashRegister.total.toFixed(2)
+' Thank you for visiting ' +staffNo;
};
</script>
</body>
</html>
What seems to be wrong with my code, it works but does not apply the staff discount, I feel the error is around;
for (i in staffMembers) {
if (staffMembers[i] === staffNo) {
cashRegister.applyStaffDiscount(staffNo);
} else {
document.body.innerHTML = "Staff number not found";
};
}
Can anybody help spot the error, I've been learning on CodeAcademy but have taken the final example further with checks on data entered. But I can't seem to see why this section is not working as it should when checked via 'http://www.compileonline.com/try_javascript_online.php'.
It turns out there is quite a lot wrong with your code. The key things you need to fix to get it "working" are the following:
First - you are asking for a "staff number", but your employee structure doesn't have space for that. You could modify the StaffMember as follows:
//Definition of staff members (class)
function StaffMember(name, number, discountPercent){
this.name = name;
this.number = number;
this.discountPercent = discountPercent;
}
//Creation of staff members (object)
var s121 = new StaffMember("Sally","s121",5);
var b122 = new StaffMember("Bob","b122",10);
var d123 = new StaffMember("Dave","d123",20);
staffMembers = [s121,b122,d123];
Now you have a "unique identifier" - I decided to give the employee the same number as the variable name, but that is not necessary.
Next, let's look at the loop you had: change it to
do {
customer = prompt("Please enter customer name or type 'staff'.");
document.body.innerHTML = customer;
if (customer === 'staff') {
staffNo = prompt("Please enter your staff number:");
for (i in staffMembers) {
if (staffMembers[i].number === staffNo) { // <<<<< change the comparison
cashRegister.applyStaffDiscount(staffMembers[i]); // <<<<< call applyStaffDiscount with the right parameter: the object, not the staff number
} else {
document.body.innerHTML = "Staff number not found";
};
}
}
i=1; // <<<<< I really don't understand why you have this do loop at all.
} while (i == 0); // <<<<< presumably you meant "while(i == 0)"? You had "while (i=0)"
There are many, many things you could do to make this better - but at least this will get you started. Complete "working" code (I may have made other edits that I forgot to point out - but the below is copied straight from my working space, and "works" - albeit rather flaky):
<!DOCTYPE html>
<html>
<body>
<script language="javascript" type="text/javascript">
//Definition of staff members (class)
function StaffMember(name, number, discountPercent){
this.name = name;
this.number = number;
this.discountPercent = discountPercent;
}
//Creation of staff members (object)
var s121 = new StaffMember("Sally","s121",5);
var b122 = new StaffMember("Bob","b122",10);
var d123 = new StaffMember("Dave","d123",20);
staffMembers = [s121,b122,d123];
//Creation of cash register (object)
var cashRegister = {
total:0,
lastTransactionAmount: 0,
//Add to the total (method)
add: function(itemCost){
this.total += (itemCost || 0);
this.lastTransactionAmount = itemCost;
},
//Retreive the value of an item (method)
scan: function(item,quantity){
switch (item){
case "eggs": this.add(0.98 * quantity); break;
case "milk": this.add(1.23 * quantity); break;
case "magazine": this.add(4.99 * quantity); break;
case "chocolate": this.add(0.45 * quantity); break;
}
return true;
},
//Void the last item (method)
voidLastTransaction : function(){
this.total -= this.lastTransactionAmount;
this.lastTransactionAmount = 0;
},
//Apply a staff discount to the total (method)
applyStaffDiscount: function(employee) {
this.total -= this.total * (employee.discountPercent / 100);
}
};
//Ask for number of items
do {
var numOfItems = prompt("How many items do you have?");
document.body.innerHTML = numOfItems;
if (isNaN(numOfItems)) {
i=0;
} else {
i=1;
}
} while (i===0);
//Ask for item and qty of item
var items = [];
var qtys = [];
for(var i=0;i<numOfItems;i++) {
var j=0;
do {
items[i] = prompt("What are you buying? (eggs, milk, magazine, chocolate)");
switch (items[i]) {
case "eggs" :;
case "milk" :;
case "magazine" :;
case "chocolate" : j=1; document.body.innerHTML = items[i]; break;
default : document.body.innerHTML = 'Item not reconized, please re-enter...'
; break;}
} while (j===0);
do {
qtys[i] = prompt("How many " + items[i] + " are you buying?");
document.body.innerHTML = qtys[i];
if (isNaN(qtys[i])) {
j=1;
} else {
j=0;
}
} while (j===1);
//Add to the sub-total
cashRegister.scan(items[i],qtys[i])
}
//Find out if it's a staff member & if so apply a discount
var customer;
var staffNo;
do {
customer = prompt("Please enter customer name or type 'staff'.");
document.body.innerHTML = customer;
if (customer === 'staff') {
staffNo = prompt("Please enter your number:");
for (i in staffMembers) {
if (staffMembers[i].number === staffNo) {
cashRegister.applyStaffDiscount(staffMembers[i]);
} else {
document.body.innerHTML = "Staff number not found";
};
}
}
i=1;
} while (i=0);
// Show the total bill
if (customer !== 'staff') {
document.body.innerHTML = 'Your bill is £'+cashRegister.total.toFixed(2)
+'<br> Thank you for visiting ' + customer;
} else {
document.body.innerHTML = 'Your bill is £'+cashRegister.total.toFixed(2)
+'<br> Thank you for visiting staff member ' +staffNo;
};
</script>
</body>
</html>
In every singe loop there is an element from stattMembers in i, not its position. So you don't get 0, 1, 2 in it but staffMembers[0], staffMembers[1], staffMembers[2]. You should think about this, maybe a simple for-loop is better in your case?
The problem lies in these lines
if (staffMembers[i] === staffNo) {
cashRegister.applyStaffDiscount(staffNo);
}
it should have been
if (i === staffNo) {
cashRegister.applyStaffDiscount(staffMembers[i]);
}
Since you are first validating for the existence of the index(no) of a staff, then i == staffNo should be the right condition.
cashRegister.applyStaffDiscount() expects an instance of a StaffMember so passing on to the staffMembers[i] object does the trick.