Can someone explain how to properly write this Javascript program? - javascript

I'm looking for someone to show me how this task should be done and where I went wrong. The instructions are as follows:
"Write your code for this exercise in this file beneath this long comment.
Please be certain to use only syntax and techniques covered in the assigned
freeCodeCamp courses.
(The material referenced here was the 110 lessons of FreeCodeCamp's basic Javascript, exploring Var and Let keywords and the 26 Object oriented programming lessons)
Write a function named createMovie that expects to receive three arguments:
title, duration, and quote. This function should return an object. The object
it returns should have properties that are also named title, duration, and
quote. The values assigned to these properties should be the values that are
passed to the function. Additionally, the object that createMovie returns
should have two methods:
isLongerThan - a function that accepts one movie object as a parameter and
returns true if the movie is longer than the one that is passed to it as
an argument and false otherwise.
logQuote - a function that logs the value of the movie object's quote
property to the console.
Create a variable named movies and assign to it an array. This array should
contain six objects that are created by calling the createMovie function. The
values you should pass to the createMovie function to create these objects are:
title | duration | line
----------------------------------------------------------------------------
Star Wars | 121 | If there's a bright center to the universe,
| | you're on the planet that it's farthest from.
| |
Pulp Fiction | 154 | Do you know what they call a Quarter Pounder
| | with Cheese in France?
| |
Dirty Dancing | 100 | Nobody puts Baby in a corner.
| |
Forrest Gump | 142 | Life is like a box of chocolates.
| |
The Wizard of Oz | 101 | Lions and tigers and bears, oh my!
| |
Cabaret | 124 | Life is a cabaret, old chum, so come to the
| | cabaret.
Write the following two functions, both of which use the movies array to
determine what to return.
getMovieByTitle - this function expects a string as a parameter and
returns the object in the movies array whose title property is equal to
the string that is passed to it (if there is one).
getAverageDuration - this function returns the average duration of all the
movies in the array.
You can test your code by opening index.html in Chrome and using the console
(see http://jsforcats.com/ for instructions on using the console). After you
correct any errors you see when you open the console, you can run commands such
as those below and verify the output.
var starWars = getMovieByTitle('Star Wars');
var pulpFiction = getMovieByTitle('Pulp Fiction');
pulpFiction.isLongerThan(starWars);
pulpFiction.logQuote();
getAverageDuration();
*/"
so the code I wrote was formed from some pseudo-code that was as best as I could get towards the answer.
I'm completely new to this and I've definitely bitten off more than I can chew. Any help would be appreciated.
Here is as far as I got:
var Movies = [];
function CreateMovie (id, title, duration, quote) {
let Films = {
title: title,
duration: duration,
quote: quote,
isLongerThan: function (Movies) {
for (var x = 0; x < Movies.length; x++) {
for (var y = 0; y < Movies[x].length; y++) {
if (This.duration > Movies[x][y].duration) {
return true;
} else {
return false;
}
}
}
},
logQuote: function (title){
for (var x = 0; x < Movies.length; x++) {
for (var y = 0; y < Movies[x].length; y++){
if (Movies[x][y].hasOwnProperty(title)){
console.log(Movies[x][y].quote)
}
}
}
}
};
Movies.push(Films);
return Films;
};
function getMovieByTitle (title) {
for (var x = 0; x < Movies.length; x++) {
for (var y = 0; y < Movies[x].length; y++) {
if (title === Movies[x][y].title) {
return Movies[x];
} else {
return undefined;
}
};
function getAverageDuration () {
var totalMovies = [];
for (var i = 0; i < Movies.length; i++) {
totalMovies.push[i];
}
var durationTotal = 0;
for (var x = 0; x < Movies.length; x++) {
durationTotal += (Movies[x][2]) ;
}
var totalAvg = (durationTotal / totalMovies.length);
return totalAvg;
};
I appreciate that this might all be completely garbage code, but I'm hoping if someone can show me the light, it might inspire me to keep progressing with coding instead of giving up and continue working in a bar forever

Sorry to hear about your setback. Here's the code, let me know if you have questions:
class Movie {
constructor(title, duration, quote) {
this.title = title;
this.duration = duration;
this.quote = quote;
}
isLongerThan(other) {
return this.duration > other.duration;
}
logQuote() {
console.log(this.quote);
}
}
function createMovie(title, duration, quote) {
return new Movie(title, duration, quote);
}
function getMovieByTitle(movies, title) {
for (let m of movies)
if (m.title === title)
return m;
}
function getAverageDuration(movies) {
let total = 0;
for (let m of movies)
total += m.duration;
return total / movies.length;
}

This is the simplest version without using any class, and functions that you are yet to familiarize. I have written a simple solution with loops. You can write the same thing using class and map functions as given in other answers.
let movies = [];
/**
* Creates a new movie object and adds the object to
* the movies array.
*
* Returns the newly created movies object.
*/
function createMovie(title, duration, quote) {
let movie = {
title: title,
duration: duration,
quote: quote,
isLongerThan: function (other_movie) {
return this.duration > other_movie.duration;
},
logQuote: function () {
console.log(this.quote);
}
}
movies.push(movie);
return movie;
}
/**
* Searches the movies array for matching title and returns
* the movie object if a match is found. Returns "undefined"
* if no atch is found.
*
* #param string title
*/
function getMovieByTitle(title) {
for (let i = 0; i < movies.length; i++) {
let movie = movies[i];
if (movie.title === title) {
return movie;
}
}
}
/**
* Gets the average duration of all the movies using a simple
* for loop.
*/
function getAverageDuration() {
let total_duration = 0;
let average_duration = 0;
if (movies.length > 0) {
// Iterate through the movies, if movies array
// is not empty. If we don't do this check, the average
// duration could result in an NaN result (division by 0).
for (let i = 0; i < movies.length; i++) {
let movie = movies[i];
total_duration += isNan(movie.duration) ? 0 : movie.duration;
}
// Rounds the average to two decimal places.
average_duration = (total_duration / movies.length).toFixed(2);
}
return average_duration;
}

It sucks to be stuck on a piece of code. We've all been there.
This is how I would execute your assignment.
And just like #georg. If you have any questions, please let us know.
class Movie {
constructor(title, duration, quote) {
this.title = title;
this.duration = duration;
this.quote = quote;
}
isLongerThan(movie) {
return this.movie.duration > movie.duration;
}
logQuote() {
console.log(this.quote);
}
}
const movies = [];
function createMovie(title, duration, quote) {
let movie = new Movie(title, duration, quote);
movies.push(movie);
}
function getMovieByTitle(title) {
return movies.find(movie => movie.title === title);
}
function getAverageDuration() {
return movies.reduce(accumulator, movie => {
return accumulator + movie.duration;
}, 0) / movies.length;
}

It sux spending money on education and not getting it approved :/. Hope you don't give up!
I tried to replicate your enviroment. It stands in your task you should not use other stuff you haven't learned yet. I used a more modern for-loop than you...
var movies = [];
// Task 1:
function createMovie(title, duration, quote) {
// Something missing
if (!title || !duration || !quote) {
console.error('Missing parameter.');
return null;
}
// Convert type
if (typeof duration === 'string') {
duration = Number(duration);
}
// Check type
if (typeof title !== 'string' || typeof duration !== 'number' || typeof quote !== 'string') {
console.error('Parameter type incorrect.');
return null;
}
return {
title,
duration,
quote,
methods: {
isLongerThan: (movie) => {
if (movie && typeof movie === 'object' && duration > movie.duration) { return true; }
return false;
},
logQuote: () => {
console.log('Quote:', quote);
}
}
};
}
// Task 2: Add movies
movies.push(createMovie('Star Wars', 121, 'If there\'s a bright center to the universe, you\'re on the planet that it\'s farthest from.'));
movies.push(createMovie('Pulp Fiction', 154, 'Do you know what they call a Quarter Pounder with Cheese in France?'));
movies.push(createMovie('Dirty Dancing', 100, 'Nobody puts Baby in a corner.'));
movies.push(createMovie('Forrest Gump', 142, 'Life is like a box of chocolates.'));
movies.push(createMovie('The Wizard of Oz', 101, 'Lions and tigers and bears, oh my!'));
movies.push(createMovie('Cabaret', 124, 'Life is a cabaret, old chum, so come to the cabaret.'));
// Task 3:
function getMovieByTitle(title) {
// Should maybe be async
if (title && typeof title === 'string') {
for (let movie of movies) {
if (movie.title.toLocaleLowerCase() === title.toLocaleLowerCase()) {
return movie;
}
}
}
return null;
}
function getAverageDuration() {
// Should maybe be async
let combinedDurations = 0;
for (let movie of movies) {
combinedDurations += movie.duration;
}
return (combinedDurations / movies.length);
}
//
// Display some results
var movie0 = document.getElementById('movie0');
var movie0Compared = document.getElementById('movie0-compared');
movie0.innerHTML = '<pre>' + JSON.stringify(movies[0], undefined, 2) + '</pre>';
movie0Compared.innerHTML = 'Is Movie 0 longer than Movie 1? <b>' + movies[0].methods.isLongerThan(movies[1]) + '</b>';
movies[0].methods.logQuote();
console.log('Pulp Fiction:', getMovieByTitle('pulp fiction').duration, 'min');
console.log('Average duration:', getAverageDuration().toFixed(0), 'min');
<h1>Results for: Movie0</h1>
<div id="movie0"></div>
<div id="movie0-compared"></div>
<br>
<br>
<br>
<br>
<br>

Related

I generate 2 arrays of equal length (15), with a choice of 4 possible letters at each position - why do they come back 53% to 87% similar?

This is inspired by a Codecadamey project, where I'm learning JavaScript.
The problem is meant to simulate a simple DNA strand. It has 15 positions in the array, and those elements are either an A, T, C, or G to represent DNA bases.
There are no limits to the amount of times a single letter (base) can show up in the array.
I create 30 arrays that are made up of at least 60% C and/or G in any of the positions, these are meant to represent strong DNA strands.
I compare the strands to each other to see what % match they are. I consider a 'match' being true when there is the same base at the same position thisDNA[i] === comparisonDNA[i]
When I test a batch of 30 of these 'strong' samples to see the best and worst match levels, I find the results very tightly grouped (I ran it 3,000 times and the highest was 87%, lowest 53%), yet it is very easy for me to concieve of two samples that will survive that are a 0% match:
const sample1 = AGACCGCGCGTGGAG
const sample2 = TCTGGCGCGCACCTC
(obviously I've cheated by building these to be a 0% match and not randomly generating them)
Here's the full code: https://gist.github.com/AidaP1/0770307979e00d4e8d3c83decc0f7771
My question is as follows: Why is the grouping of matches so tight? Why do I not see anything below a 53% match after running the test thousands of times?
Full code:
// Returns a random DNA base
const returnRandBase = () => {
const dnaBases = ['A', 'T', 'C', 'G']
return dnaBases[Math.floor(Math.random() * 4)]
}
// Returns a random single stand of DNA containing 15 bases
const mockUpStrand = () => {
const newStrand = []
for (let i = 0; i < 15; i++) {
newStrand.push(returnRandBase())
}
return newStrand
}
const pAequorFactory = (num, arr) => { //factory function for new strand specimen
return {
specimenNum: num,
dna: arr,
mutate() {
//console.log(`old dna: ${this.dna}`) //checking log
let randomBaseIndex = Math.floor(Math.random() * this.dna.length) /// chooses a location to exchange the base
let newBase = returnRandBase()
while (newBase === this.dna[randomBaseIndex]) { // Rolls a new base until newBase !== current base at that position
newBase = returnRandBase()
}
this.dna[randomBaseIndex] = newBase;
//console.log(`New dna: ${this.dna}`) //checking log
return this.dna;
},
compareDNA(pAequor) { // compare two strands and output to the console
let thisDNA = this.dna;
let compDNA = pAequor.dna;
let matchCount = 0
for (i = 0; i < this.dna.length; i++) { //cycles through each array and log position + base matches on matchCount
if (thisDNA[i] === compDNA[i]) {
matchCount += 1;
};
};
let percMatch = Math.round(matchCount / this.dna.length * 100) //multiply by 100 to make 0.25 display as 25 in console log
console.log(`specimen #${this.specimenNum} and specimen #${pAequor.specimenNum} are a ${percMatch}% DNA match.`)
return percMatch;
},
compareDNAbulk(pAequor) { //as above, but does not log to console. Used for large arrays in findMostRelated()
let thisDNA = this.dna;
let compDNA = pAequor.dna;
let matchCount = 0
for (i = 0; i < this.dna.length; i++) {
if (thisDNA[i] === compDNA[i]) {
matchCount += 1;
};
};
let percMatch = Math.round(matchCount / this.dna.length * 100) //multiply by 100 to make 0.25 display as 25 in console log
return percMatch;
},
willLikelySurvive() { // looks for >= 60% of bases as either G or C
let countCG = 0;
this.dna.forEach(base => {
if (base === 'C' || base === 'G') {
countCG += 1;
}
})
//console.log(countCG) // testing
//console.log(this.dna) // testing
return countCG / this.dna.length >= 0.6
},
complementStrand() {
return this.dna.map(base => {
switch (base) {
case 'A':
return 'T';
case 'T':
return 'A';
case 'C':
return 'G';
case 'G':
return 'C';
}
})
} //close method
} // close object
} // close factory function
function generatepAequorArray(num) { // Generatess 'num' pAequor that .willLikelySurvive() = true
let pAequorArray = []; //result array
for (i = 0; pAequorArray.length < num; i++) {
let newpAequor = pAequorFactory(i, mockUpStrand()); // runs factory until there are 30 items in the result array
if (newpAequor.willLikelySurvive() === true) {
pAequorArray.push(newpAequor)
}
}
return pAequorArray;
}
function findMostRelated(array) { // champion/challenger function to find the most related specimens
let winningScore = 0;
let winner1;
let winner2;
for (let i = 0; i < array.length; i++) {
for (let j = i; j < array.length; j++) // j = i to halve the number of loops. i = 0, j = 5 is the same as i = 5, j = 0
if (i !== j) { // Do not check specimen against itself
let currentScore = array[i].compareDNAbulk(array[j]);
if (currentScore > winningScore) { // Challenger becomes the champion if they are a closer match
winningScore = currentScore;
winner1 = array[i].specimenNum;
winner2 = array[j].specimenNum;
}
}
}
let resultArray = [winner1, winner2, winningScore] // stored together for easy return
//console.log(`The most related specimens are specimen #${winner1} and specimen #${winner2}, with a ${winningScore}% match.`)
return resultArray
}
function multiArray(loops) { //test by running finding the closest match in 30 random 'will survive' samples, repaeated 1000 times. Returns the highest and lowest match across the 1000 runs
let highScore = 0;
let lowScore = 100
for (let i = 0; i < loops; i++) {
let pAequorArray = generatepAequorArray(30);
let currentArray = findMostRelated(pAequorArray);
highScore = Math.max(highScore, currentArray[2])
lowScore = Math.min(lowScore, currentArray[2])
}
return results = {
'high score': highScore,
'low score': lowScore
}
}
console.log(multiArray(10000))

I was expecting I would get only one line of result, but I got three lines of results

Currently I am working on a practicing code, which is generating slot machine feature(very basic). And here is the code
function randMax(max) {
return Math.trunc(1E9 * Math.random()) % max;
}
var reel = {
symbols: ["X", "Y", "Z", "W", "$", "*", "<", "#"],
spin() {
if (this.position == null) {
this.position = randMax(this.symbols.length - 1);
}
this.position = (this.position + 100 + randMax(100)) % this.symbols.length;
},
display() {
if (this.position == null) {
this.position = randMax(this.symbols.length - 1);
}
return this.symbols[this.position];
}
}
var slotMachine = {
reels: [
Object.create(reel),
Object.create(reel),
Object.create(reel)
],
spin() {
this.reels.forEach(function spinReel(reel) {
reel.spin();
});
},
display() {
var lines = [];
for (
let linePos = -1; linePos <= 1; linePos++
) {
let line = this.reels.map(
function getSlot(reel) {
var slot = Object.create(reel);
slot.position = (reel.symbols.length + reel.position + linePos) % reel.symbols.length;
return reel.display.call(slot);
}
);
lines.push(line.join(" | "));
}
return lines.join("\n");
}
};
slotMachine.spin();
console.log(slotMachine.display());
The code is simple, var reel (line 4) generates random this.position (line 7) value by using randMax(max) (line 1) function. By using this.position it gets an element from symbols (line5).
So in var slotmachine I am using Object.create(reel) (line 17) feature to access var reel(as I know this is a way to get Prototypes so that I can access certain property features right?)
And in below var slotMachine is using for loop to generate three random elements from symbols array.
The question is, when I am seeing this part (from line 33~42) ,
...
for (
let linePos = -1; linePos <= 1; linePos++
) {
let line = this.reels.map(...
In this for loop, I was assuming it is going to get 3 elements from symbols array. Since there is only linePos in this for loop so I expected this loop will end after linePos got value of 1 (started in -1) , so only three numbers would be generated.
PS C:\Users\leePC\babel\public\src> node slotmachine.js
< | * | #
This is what I expected, but I got
PS C:\Users\leePC\babel\public\src> node slotmachine.js
< | * | #
# | < | X
X | # | Y
all three lines. This is a desired outcome but I am still not sure why it got all the three lines! I was thinking I should do loop three times but by doing one loop it generates 9 items. How could this happen? Did I miss something or any other stuff that I am using but still not noticing?

Javascript adding multiple arrays in a loop

I am trying to add multiple arrays in javascript.
Here are my arrays I have made, and are working.
function getAmountSpent(){
var amountSpent = ((Math.random() * 500) + 1);
return amountSpent.toFixed(2)
}
function getGift(){
var gift = ((Math.random()* 50) + 1);
return gift.toFixed(2)
}
var names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
var spent = [];
for (let i = 0; i < 5; i++) {
spent.push(getAmountSpent());
}
var gifts = [];
for (let i = 0; i<5; i++) {
gifts.push(getGift());
}
What I need help with is adding these arrays in a new function. I have began writing the code, and I am not sure what is wrong.
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals())
}
function getSumTotals(a){
totals= spent+(spent * gifts);
return totals.toFixed(2)
}
From what you can see, I am trying to add up the totals much like this:
totals[0] = spent[0] + (spent[0] * gifts[0]);
totals[1] = spent[1] + (spent[1] * gifts[1]);
totals[2] = spent[2] + (spent[2] * gifts[2]);
totals[3] = spent[3] + (spent[3] * gifts[3]);
totals[4] = spent[4] + (spent[4] * gifts[4]);
if it helps, the professor added guided instructions for function getSumTotals(a) stating:
This function will return the sum of the elements in array a.
You will be passing the array that holds your totals to
the parameter a. Be sure to treat the values in a as numbers.
I am not sure if this helps but here is the output to my document.
Current Total should equal (spent) + (spent * gifts). For instance, for Jeremy in this example, current total should equal:
$36.55 + ($36.55*0.0626) = $38.83. Since there are many variables involved, I am not 100% sure what I should write for function getSumTotals(a)
The parameter "a" is a placeholder because I am not sure how many parameter values I need, and the proper format I need to use.
As for the code...
You're both
not passing an index to getSumTotals
not using this parameter within getSumTotals to access your spent and gifts arrays
var totals =[];
for (let i=0; i<5; i++) {
totals.push(getSumTotals(i)) // you were missing i
}
function getSumTotals(idx) { // I took liberties to rename this
totals = spent[idx] + (spent[idx] * gifts[idx]);
return totals.toFixed(2);
}
Now for the Math...
All that said, this math of spent[i] + spent[i] * gifts[i] doesn't make much sense either. Was this specified in the problem?
you may use like this
defined gifts
gifts=[45,43,32];
defined spends
spends=[43,32,21];
this is the getSumTotal funtion
getSumTotal=(x)=>(x.a+x.b)
this is where added
totals=gifts.map((d1,i)=>{
return fu({a:gifts[i],b:spends[i]})
})
I understand this is your assignment, however - if the idea is to both generate arrays, and then add them together, it is a redundant step. Just use the name array to iterate once and do all your calculations within that single loop.
Here, I had some fun and took some liberties, but hopefully you see why multiple arrays are redundant.
function getSumTotals() {
const getAmountSpent = () => Math.random() * 500 + 1;
const getGift = () => Math.random() * 50 + 1;
const names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let totals = []
names.forEach((name, i) => {
let spent = getAmountSpent()
let gifts = getGift()
let $$$ = (spent + spent * gifts).toFixed(2);
totals[i] = $$$
console.log(`${name} cost me $${$$$}${'!'.repeat(($$$/1000) | 1)}`)
});
return totals;
}
getSumTotals()
Note, that toString returns a type of "String", but not "Number".
When you try to sum a number with string, you get a concatenated string "1" + 2 = "12"
To turn a string into Number, you must use a Number("str") function, or just a bunary + before the string:
console.log( "1" + 2 );
console.log( Number("1") + 2 );
console.log( +"1" + 2 );
Also, you use the same loop 3 times, but can use just one loop instead, and call all functions inside the one loop. And use your array.length instead of fixed number 5:
let names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"];
let spent = [];
let gifts = [];
let totals = [];
for (let i = 0; i < names.length; i++) {
spent.push( getAmountSpent() );
gifts.push( getGift() );
totals.push( getSumTotals(i) );
}
console.log( totals );
function getAmountSpent() {
return rand(1, 500, 2);
}
function getGift() {
return rand(1, 50, 2);
}
function getSumTotals(i) {
return +( spent[i] * ( 1 + gifts[i] ) ).toFixed(2);
}
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
P.s. Math.random() returns a number between 0 (included) and 1 (not included). If you need a random number between (example) 20 and 100, Math.random()*(100-20) will give a number between 0 and 80. After adding +20 to the result, you get a number from 20 to 100. That's what does this formula Math.random()*( to - from ) + from
P.P.s. Another way, to get the same thing:
var names = ["Jeremy", "Arun", "Alisa", "Rohan", "Dana"].reduce( (prev, elem) => {
let spent = rand(1, 500, 2);
let gift = rand(1, 50, 2);
prev[elem] = new UserData( spent, gift );
return prev;
}, {});
console.log( "Jeremy spent: " + names.Jeremy.spent );
console.log( names );
function rand(from, to, fixed = 0){
return +(Math.random()*( to - from ) + from).toFixed(fixed);
}
function UserData(spent, gift){
this.spent = spent;
this.gift = gift;
this.total = +(spent * ( 1 + gift )).toFixed(2);
}
/* Google → Array reduce, Constructor functions */
function getAmountSpent(){
let amountSpent = ((Math.random() * 500) + 1);
return Number(amountSpent.toFixed(2))
}
function getGift(){
let gift = ((Math.random()* 50) + 1);
return Number(gift.toFixed(2))
}
let names = ["Jeremy","Arun","Alisa","Rohan","Dana"];
let spent = [];
let gifts = [];
let totals =[];
for (let i = 0; i < names.length; i++) {
spent.push(getAmountSpent());
gifts.push(getGift());
totals[i] = (spent[i]+(spent[i] * gifts[i])).toFixed(2);
totals[i] = parseFloat(totals[i])
}
Hi there
I don't think you need a function to add the totals. you just need to loop through and assign totals[i] to spent[i] + (spent[i] * gifts[i]).
then you can use the parseFloat and toFixed function to change the string to a number. remember toFixed() function turns numbers to string. so you need to use the parseFloat to change it to number again as shown in the code above. or you can come up with an easy way of changing it to number. I hope this helps!

How to return the sum of objects-array properties instead of their double?

I was making an expense tracker basic code (without ui, only the initial script), but i had a problem while trying to console.log the sum of the total spent money by the user, my code only doubles the spent money for each bought item so i decided to ask here for help.
The code:
//initial code
const account = {
name: 'user',
expenses: [],
addExpense: function(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary: function() {
let expenses = account.expenses;
for (let i = 0; i < expenses.length; i++ ) {
let value = expenses[i].amount + expenses[i].amount;
console.log(value);
}
}
}
//output calls
account.addExpense('Milk', 8);
account.addExpense('Netflix', 30);
account.addExpense('Steam summer sale', 26);
account.addExpense('Coffee', 4);
console.log(account.getAccountSummary());
The code always logs this values below:
16
60
52
8
which are actually the double of the input values (8, 30, 26, 4).
The output i'm looking for is the sum of all of those value which is in this case:
68
Hope my question was clear.
When you want a value that is based on items in an array, then you should be looking at reduce
const account = {
name: 'user',
expenses: [],
addExpense: function(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary: function() {
return account.expenses.reduce((acc,{amount}) => acc+amount,0);
}
}
expenses[i].amount is been added 2 times at let value = expenses[i].amount + expenses[i].amount;, that's why is been doubled.
If you want to print the sum inside the getAccountSummary, you can do something like this:
getAccountSummary: function() {
const expenses = account.expenses;
let value = 0
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount;
}
console.log(value);
}
But if you want to return the sum on getAccountSummary so you can print it (which seems more reasonable), then you could do this:
getAccountSummary: function() {
const expenses = account.expenses;
let value = 0
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount;
}
return value;
}
And you should be able to call console.log(account.getAccountSummary());
You can use forEach() to iterate over expenses as well.
In your getAccountSummary
Use
let value = 0;
for (let i = 0; i < expenses.length; i++ ) {
value += expenses[i].amount ;
console.log(value);
}
Hope it will help you.
The main issue was that you were logging the values directly, instead of returning them for later logging.
Also, there's no need to use the "function" keyword in modern Javascript.
Here's my solution, gives the expected output.
const account = {
name: 'user',
expenses: [],
addExpense(description, amount) {
account.expenses.push({
description: description,
amount: amount
});
},
getAccountSummary() {
return account.expenses.reduce((result, expense) => result + expense.amount, 0)
}
}
//output calls
account.addExpense('Milk', 8);
account.addExpense('Netflix', 30);
account.addExpense('Steam summer sale', 26);
account.addExpense('Coffee', 4);
console.log(account.getAccountSummary()); // 68

Discord RPG Bot display ids for each player in array

I'm trying to learn javascript and how to use the developer api provided by discord.
I do believe everything I want so far is working except I wanted to create a system like how a database works. Where each player in the table has a unique id key. I'm not sure if this is possible without using a db.
[Index.js]
/* Discord API Information */
const Discord = require('discord.js');
const token = '';
const Game = require('./game.js');
const client = new Discord.Client();
let playersName = []; // tracks each player that joins
let currPlayers = 0; //tracker for total players online
let INIT_GAME;
let userJoined = false;
let inBattle = false;
client.on('message', (msg) => {
if(msg.content === '!join'){
// Prevents multiple instances of the same person from joining
for(var x = 0; x < playersName.length; x++){
if(playersName[x]===msg.author.username){
return playersName[x];
}
}
currPlayers++;
userJoined = true;
playersName.push(msg.author.username);
//My attempt at having the question im asking
function convertToID(arr, width) {
return arr.reduce(function (rows, key, index) {
return (index % width == 0 ? rows.push([key])
: rows[rows.length-1].push(key)) && rows;
}, []);
}
console.log(convertToID(playersName,1)); /* Tracks players by ID in developer tools */
INIT_GAME = new Game(playersName, client, 'bot-testing', currPlayers);
let myRet = INIT_GAME.startGame();
const embed = new Discord.RichEmbed()
.setTitle("Welcome To Era Online")
.setColor(0xFF0000)
.addField(`${msg.author.username} has Joined`, myRet);
msg.channel.send(embed);
msg.channel.send(`${msg.author} has joined the game.`);
return;
}
if(userJoined == true){
if(msg.content === '!fight' && (!inBattle)){
let grabCurrPlayer = msg.author.username;
msg.channel.send(`${INIT_GAME.initBattle(grabCurrPlayer)}`);
}
else if(msg.content === '!leave'){
let tempLeave = msg.author.username;
for(var y = 0; y < playersName.length; y++){
if(playersName[y] == msg.author.username){
playersName[y] = [`${playersName[y]} was previously ID: ` + [y]];
currPlayers--;
}
}
msg.channel.send([`${tempLeave} has left the server.`]);
userJoined = false;
}
else if(msg.content === '!newgame'){
msg.channel.send(INIT_GAME.newGame());
}
/* Simply checks the bonus damage. command for developer*/
else if(msg.content === '!bonus'){
msg.channel.send(INIT_GAME.bonusAttack());
}
}
/* checks whose currently online. command for developer*/
if(msg.content === '!online'){
msg.channel.send(INIT_GAME.getOnline());
}
});
client.on('ready', () => {
console.log('Bot is now connected');
});
client.login(token);
[game.js]
class Game {
constructor(player, client, channelName='bot-testing', playersOnline){
this.client = client;
this.channelName = channelName;
this.currentPlayer = player;
this.playersOnline = [];
this.hitpoints = 120;
this.damage = '';
this.chance = 3;
this.inBattle = false;
this.online = playersOnline;
this.monster = [{
hp: Math.floor(Math.random() * 200),
temphp: 0,
damage: 10
}];
};
/* main menu information, players online */
startGame(){
for(var x = 0; x < this.currentPlayer.length; x++){
this.playersOnline.push(this.currentPlayer[x]);
if(this.playersOnline[x] === this.currentPlayer[x]){
return [`Players Online: ${this.online}\n`];
}
}
}
/* Battle system */
initBattle(currPlayer){
this.inBattle = true;
let npcHP = this.monster[0].hp;
let numberOfAttacks = 0;
let totalDamage=0, totalBonusDamage=0;
while( this.monster[0].hp > 0 ){
let playerDamage = Math.floor(Math.random() * (npcHP / 4));
if(this.bonusAttack() === 2){
console.log(`Bonus Attack: ${this.bonusAttack()}`);
console.log(`Regular damage without bonus attack: ${playerDamage}`);
playerDamage = playerDamage + 2;
}
this.monster[0].hp -= playerDamage;
this.hitpoints -= this.monster[0].damage;
console.log('Monster: ' + this.monster[0].hp);
console.log('Player: ' + this.hitpoints);
console.log(`${currPlayer} has attacked for ${playerDamage}`);
console.log(`NPC health: ${this.monster[0].hp}`);
if(this.hitpoints <= 0){
return [`You lost the battle.`];
}
this.inBattle = false;
numberOfAttacks++;
totalDamage += playerDamage;
totalBonusDamage = playerDamage + this.bonusAttack();
}
if(this.monster[0].hp <= 0 && this.inBattle !== true){
let maxDamage = totalDamage + totalBonusDamage;
return [`${currPlayer} has attacked ${numberOfAttacks} times dealing ${totalDamage} + (${totalBonusDamage}) bonus damage for a total of ${maxDamage} damage. The monster is dead.\n
Your Health: ${this.hitpoints}`];
}
else{
this.newGame();
return [`You rejuvenated your hitpoints and are ready for battle. \nType !fight again to start a new battle!`];
}
}
/* bonus attack damage [ 1 in 3 chance ] */
bonusAttack(bonusDamage){
let chance = Math.floor(Math.random() * 3);
return chance === 2 ? bonusDamage = 2 : false;
}
/* displays players currently online */
getOnline(){
console.log(this.currentPlayer);
return this.currentPlayer;
}
/* refresh stats */
newGame(){
this.monster[0].hp = Math.floor(Math.random() * 50);
this.hitpoints = 150;
}
}
module.exports = Game;
[My Question]
The only real important part within those 2 files is in index.js at the line that speaks about when a player leaves. So !leave.
I had a problem where one player typed !leave, both people would leave. That is the solution I used to fix it.
I could not get it to empty the array for ONLY the person who typed the command.
Example:
Person A types !join
Players online = [PlayerA]
Person B types !join
Players online = [PlayerA, PlayerB]
Player A types !leave
Players online = [[], PlayerB]]
It would always insert a empty array in the spot. So what I did was just fill that spot with the users previous name and their array id.
What I want is so that it completely deletes the person from the array AND removes that empty spot.
I would also like to know if it's possible that every time someone types !join, I would be able to insert them into an new array that is multidimensional and has the id for each player so that when I type !online, it would display
[[0, PlayerA], [1, PlayerB]] . Like a database where I can always see their index if needed.
What I have so far:
https://i.imgur.com/lWrtEtB.png
It only tracks the last index after they leave. How do I make it display the current index of the players online?
Use findIndex() to find the position of the name in your array. Then use the splice() method to remove a value from your array. You don't need to use that for loop, as findIndex will run a similar loop.
var playerIndex = playersName.findIndex(function(index) {
return index === tempLeave
})
playersName.splice(playerIndex, 1)
After reading the second part of your question though, I think you should be creating objects inside of your array. An example would be:
[
{
playerName: "Foo",
id: indexNumber,
isOnline: true
},
{
playerName: "Bar",
id: indexNumber,
isOnline: true
}
]
When someone joins, you check if their name is already assigned to an object (you can use findIndex again here). If not you create a new player, else you will change the players isOnline attribute to true. I'm sure this is the best way to go about storing user info, but it might work for you.

Categories

Resources