var players = [];
var totalplayers = 0
var team1 = [];
var team2 = [];
var commands = {
"teams.join": {
name: "Join random team.",
description: "Anybody who joins will be put to a team",
process: function(bot, msg, suffix) {
players.push(msg.sender);
bot.sendMessage(msg.channel, players);
bot.sendMessage(msg.channel, msg.sender + " has been added to the random team selection.");
totalplayers += 1;
bot.sendMessage(msg.channel, totalplayers)
},
},
"teams.random": {
name: "Random team selection.",
desciption: "Displays all players in random team selection in a random team.",
process: function(bot, msg, suffix) {
var playcount = 0;
bot.sendMessage(msg.channel, "tp: " + totalplayers); // Check
bot.sendMessage(msg.channel, "i: " + playcount); // Check
for (playcount = 0; playcount < totalplayers; playcount++) {
//bot.sendMessage(msg.channel, "Looping?") // Check
var Rteam = players[Math.floor(Math.random() * players.length)];
//bot.sendMessage(msg.channel, Rteam); // Check
if (playcount = 0 || 2 || 4 || 6 || 8) {
team1.push(Rteam);
bot.sendMessage(msg.channel, "isEven = true"); // Check
playcount + 1;
} else if (playcount = 1 || 3 || 5 || 7 || 9) {
team2.push(Rteam);
bot.sendMessage(msg.channel, "isEven = false"); // Check
playcount + 1;
}
playcount + 1;
var roll = players.splice(Rteam, 1);
var yourNumber = roll[totalplayers];
//i += 1;
}
bot.sendMessage(msg.channel, "Team 1: " + team1);
bot.sendMessage(msg.channel, "Team 2: " + team2);
},
}
teams.join works fine, but I included to show the whole section of the teams. teams.random should take the players array, randomise the players (users) locations in the array, then distribute them so that players[0] is on Team 1, players[1] is on Team 2 (etc.) until there are no more users left. Essentially it is taking a list and splitting it up into two groups randomly. The main thing I realized while testing this is that playcount doesn't increment (I've tried For, While and Do-Until loops to no avail.
This is not correct:
if (playcount = 0 || 2 || 4 || 6 || 8) {
There are two problems: First, you're using =, which is assignment, when it should be == for comparison. Second, you can't use || that way to compare against multiple elements, you need to do the comparisons separately for each item. So it should be:
if (playcount == 0 || playcount == 2 || playcount == 4 || playcount == 6 || playcount == 8) {
But if you want to know if playcount is even, you can just do:
if (playcount % 2 == 0)
You don't need to use else if for the other test, just use else, since there are just two possibilities.
The lines that contain:
playcount + 1;
don't do anything. You don't need this at all, since you're incrementing playcount in the for() header.
By the way, there's nothing in your code that prevents you from selecting the same player multiple times, and adding them to different teams.
I agree with barmar on his comments about the OP original code.
But for completeness sake, here's a sample code to split the teams in half and randomly place players in each team.
var players = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
team1 = [],
team2 = [],
i;
while (players.length > 0) {
i = Math.floor(Math.random() * players.length);
if (players.length % 2 === 0) {
team1.push(players[i]);
} else {
team2.push(players[i]);
}
players.splice(i, 1);
}
console.log(team1, team2);
Output:
[10, 4, 1, 6, 5] [3, 8, 2, 9, 7]
Run the code in browser console a few times, you'll get different random numbers in each array.
Related
As the topic states what is the best way to make it so that when you pass an array of emotions/values, to show the closest value based on a numeric mapping in javascript?.
Assume that 'Glad' is the same thing as 'Happy', and 'Down' is the same thing as 'Sad'. Ithe code I've tried seems incredibly lengthy and gets bloated if I add more emotions/states (i.e. Angry). Aside from the emotions array, any new functions and data structures and variables can be changed/introduced.
for example, I can get a list of emotions:
let emotions = ['Happy','Happy','Sad','Glad','Angry'];
Now I want to return a string that reflects what the 'closest' emotion based on these 5 emotions.
For a better example, let's assume the values correspondent to each emotion is:
Angry = 1, Happy = 2, Sad = 3
I was trying something like:
var numb = 0;
for (var i = 0; i < emotions.length; i++) {
if (numb == 'Angry')
numb += 1;
if (numb == 'Happy' || numb == 'Glad')
numb += 2;
if (numb == 'Sad' || numb == 'Down')
numb += 3;
}
var average = numb / emotions.length;
// check which number is closer to
if (average < 1.5)
return 'Angry';
if (average >= 1.5 && < 2.5)
return 'Happy';
if (average > 2.5)
return 'Sad';
if (average == 1.5)
return 'Angry or Happy';
if (average == 2.5)
return 'Happy or Sad';
My expected result based on this list of emotions is:
2(*Happy*) + 2(*Happy*) + 3(*Sad*) + 2(*Happy|Glad*) + 1(*Angry*) = 10
Then divide by 5 (the emotions array length), resulting in 2.
So the result that should be returned, as string, is "Happy".
Let's say I added a fourth type of emotion/feeling... I would be adding more and more of these conditions, and it gets more complicated in the logic checking for the ranges of the numbers.
I am looking at the list of emotions as a whole, and trying to come up with an overall emotion that represents the whole list.
What is the best way to do this so that the code looks clean and I can support more states without having the lines of code become too long?
What about something like this:
Having two object constants:
emotionsValues: Here you assing a value to each emotion you want, like a score to each.
emotionsRank: Here is the final result of each value, based on average you'll get the result from here.
Now:
Receive the emotions array by parameter.
reduce it based on the value of each mapped emotion (using emotionsValues).
Get the average
See if the floor value + ceil value divided by 2 is equal to the number itself (it means its exactly the half), so use the "emotion or emotion".
OR, if not the half, then round to the nearest and get the correct emotion. Don't forget to check if average is below 1 or bigger the the last rank (3 in this case)
const emotionsValues = {
"Angry": 1,
"Happy": 2,
"Glad": 2,
"Sad": 3,
"Down": 3,
}
const emotionsRank = {
1: "Angry",
2: "Happy",
3: "Sad",
}
function getEmotion(arrayEmot) {
let numb = arrayEmot.reduce((acc, v) => Number(emotionsValues[v]) + acc, 0);
let avg = numb / arrayEmot.length;
let min = Math.floor(avg)
let max = Math.ceil(avg)
if ((min + max) / 2 == avg && min != max) {
return emotionsRank[min] + " or " + emotionsRank[max]
} else {
let rounded = avg < 1 ? 1 : avg > 3 ? 3 : Math.round(avg);
return emotionsRank[rounded];
}
}
let emotionsTest = ['Happy', 'Happy', 'Sad', 'Glad', 'Angry'];
console.log(getEmotion(emotionsTest))
let emotionsTest2 = ['Happy', 'Happy', 'Sad', 'Sad'];
console.log(getEmotion(emotionsTest2))
You may create the function emo to value and its reciprocal one: value to emotionS:
Then you map every emotions found in array to its value
do your standard mathematical stuff
and get back to emotions via the reciprocal function
const emoToValue = {
Glad: 1,
Happy: 1,
Sad: 2
}
const valueToEmos = Object.entries(emoToValue).reduce((acc, [emo, val]) => {
acc[val] = acc[val] || []
acc[val].push(emo)
return acc
}, {})
//compute the average:
function avgEmotion (emotions) {
if (emotions.length == 0) return ''
const avg = emotions.reduce((s, em) => s + emoToValue[em], 0) / emotions.length
return valueToEmos[Math.round(avg)].join(' or ')
}
console.log('str', avgEmotion(['Happy', 'Happy', 'Sad', 'Happy'])) //Glad or Happy
console.log('str', avgEmotion(['Happy', 'Happy', 'Sad', 'Sad'])) //Sad
This function explicitly checks for the "mid" case and also for out of range values (since it's based on indices):
function getEmotion(emotions, value) {
// Out of range
if ( value > emotions.length ) return emotions[emotions.length - 1];
if ( value < 1 ) return emotions[0];
// Determine if decimal is .5
let mid = value % 1 === .5;
// Round the value to the nearest integer
let rounded = Math.round(value);
return mid ? `${emotions[rounded - 2]} or ${emotions[rounded - 1]}` : emotions[rounded - 1];
}
Output:
let emotions = ['Happy', 'Happy', 'Sad', 'Glad', 'Angry'];
console.log(getEmotion(emotions, -23)); // Happy
console.log(getEmotion(emotions, 0)); // Happy
console.log(getEmotion(emotions, 1)); // Happy
console.log(getEmotion(emotions, 2.43)); // Happy
console.log(getEmotion(emotions, 2.5)); // Happy or Sad
console.log(getEmotion(emotions, 3.1)); // Sad
console.log(getEmotion(emotions, 155.65)); // Angry
You could create a set of indices and get the values by filtering with the index.
function getEmotion(emotions, value) {
var values = new Set([value + 0.5, value - 0.5, Math.round(value)]);
return emotions.filter((e, i) => values.has(i + 1)).join(' and ');
}
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1));
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1.5));
console.log(getEmotion(['Happy', 'Sad', 'Glad', "Angry"], 1.7));
I've been practicing javascript, and made a suduko game. I push() some numbers inside an array.
var sudukoNmb = [1,2,3,3,2,1,2,1,3]
and I have this condition to read the numbers by rows and by columns, but I think its not the proper way.
if(sudukoNmb[0] === sudukoNmb[1] || sudukoNmb[0] === sudukoNmb[2] || sudukoNmb[1] === sudukoNmb[2] ||
sudukoNmb[0] === sudukoNmb[3] || sudukoNmb[0] === sudukoNmb[6] || sudukoNmb[3] === sudukoNmb[6] ||
sudukoNmb[1] === sudukoNmb[4] || sudukoNmb[1] === sudukoNmb[7] || sudukoNmb[4] === sudukoNmb[7] ||
sudukoNmb[3] === sudukoNmb[4] || sudukoNmb[3] === sudukoNmb[5] || sudukoNmb[4] === sudukoNmb[5] ||
sudukoNmb[6] === sudukoNmb[7] || sudukoNmb[6] === sudukoNmb[8] || sudukoNmb[7] === sudukoNmb[8] ||
sudukoNmb[2] === sudukoNmb[5] || sudukoNmb[2] === sudukoNmb[8] || sudukoNmb[5] === sudukoNmb[8]) {
console.log('error')
} else {
console.log('correct')
}
Is there any other way to minimize this condition?
Note: these numbers are actually come from rows and columns indices of a 2D array (3x3) mapped in a 1D array. (sudukoNmb[3] is for first cell of second row and so on...)
Its relatively hard to understand the logic behind your condition, but i found that it is comparing rows and columns of a 2D array (3x3) stored in a 1D array (total 9 elements).
So the array contains following elements:
0 1 2
3 4 5
6 7 8
and we must check every row or column such that they don't have same values in each horizontal or vertical line. For example:
the first row is: 0,1,2 => we shall check: 0,1 / 0,2 / 1,2
the second row is: 3,4,5 => we shall check: 3,4 / 3,5 / 4,5
the third row is: 6,7,8 => we shall check: 6,7 / 6,8 / 7,8
so the formula for rows is: check i,(i+1) / i,(i+2) / (i+1),(i+2)
and
the first column is: 0, 3, 6 => we shall check: 0,3 / 0,6 / 3,6
the second column is: 1, 4, 7 => we shall check: 1,4 / 1,7 / 4,7
the third column is: 2, 5, 8 => we shall check: 2,5 / 2,8 / 5,8
so the formula for rows is: check i,(i+3) / i,(i+2*3) / (i+3),(i+2*3)
we can merge both formulas to one more general:
check i,(i+n) / i,(i+2*n) / (i+n),(i+2*n)
where n is 1 for rows and is 3 for columns.
the following code can check the values in every column or row:
var sudukoNmb = [1,2,3, 4,5,6, 7,5,9];
function checkLine(a, i, n) //a:array, i: first cell index, n: offset to get next cell in row or column
{
return (a[i]===a[i+n] || a[i]===a[i+2*n] || a[i+n]===a[i+2*n]);
}
var msg = "OK";
for(var j=0; j<2; j++)
{
//if (checkLine(sudukoNmb, j, 3)) {msg="Error"; break;} //to check columns
//if (checkLine(sudukoNmb, j*3, 1)) {msg="Error"; break;} //to check rows
if (checkLine(sudukoNmb, j, 3) || checkLine(sudukoNmb, j*3, 1))
{msg = "Error"; break;}
}
console.log("Check result is: " + msg);
The nine values of a "sudoku box" are supposed to be unique, so it could be possible to take advantage of the Set class of ES6, it stores unique values.
var sudukoNmb = [1,2,3,3,2,1,2,1,3]
if (new Set(sudukoNmb).size === 9) { // Set instance has [1,2,3] only
console.log('correct')
} else {
console.log('error')
}
Try This
var sudukoNmb = [1,2,3,3,2,1,2,1,3],
allow = [[1,2,3,6], [2,4,7], [5,8], [6,4,5], [7,5], [8], [7,8], [8]];
var f = 0;
allow.forEach(function(v,i){
v.forEach(function(vv){
if(sudukoNmb[i] == sudukoNmb[vv]) f=1;
})
})
if(f) console.log('error')
else console.log('correct')
I have the following requirements:
A function to create a "list" container to hold a
group of data with numValues data, and the range,
median, and interquartile ranges assigned. Pass TRUE if
you want the data elements to be arranged in ascending
order. Pass –1 for either extreme, either quartile, or the
median if you do not require them to be specific values.
For example:
makelist(3, 5, -1, 8, -1, 9, TRUE) will return "5, 8, 9"
Both quartile values must be supplied to the makelist()
function. If either one is not, they are both ignored.
I have the beginnings of the function below (In JavaScript). I'm looking for some help in figuring out the quartile part of this (how to create the spread of numbers to satisfy the quartile requirements).
makelist = function(numValues, lowerExtreme, lowerQuartile, median, upperQuartile, upperExtreme, sortData) {
if (lowerExtreme == -1) lowerExtreme = 0;
if (upperExtreme == -1) upperExtreme = lowerExtreme + 100;
var magnitude = upperExtreme - lowerExtreme, // 9 - 5 = 4
quarter = magnitude * .25,
midway = magnitude * .5,
threeQuarters = magnitude * .75;
quarter = lowerExtreme + quarter;
midway = lowerExtreme + midway;
threeQuarters = lowerExtreme + threeQuarters;
if (lowerQuartile == -1) upperQuartile = quarter;
if (upperQuartile == -1) lowerQuartile = threeQuarters
if (median == -1) median = midway;
var step = magnitude / (numValues - 1); // 4 / 3 =
var quartet = {
lowerExtreme: lowerExtreme,
lower: [],
lowerMid: [],
upperMid: [],
upper: []
}
var fill = function(list, lowerExtreme, upperExtreme) {
var lastPush = null,
step = (upperExtreme - lowerExtreme) / ((numValues) * .25);
for (var i = lowerExtreme; i <= upperExtreme; i += step) {
list.push(Math.round(i));
lastPush = i;
}
return lastPush;
}
quartet.lowerExtreme = fill(quartet.lower, quartet.lowerExtreme, lowerQuartile, step) || quartet.lowerExtreme;
console.info("quartet.lower: " + quartet.lower + " quartet.lowerExtreme: " + quartet.lowerExtreme);
quartet.lowerExtreme = fill(quartet.lowerMid, quartet.lowerExtreme, median, step) || quartet.lowerExtreme; // lowerQuartile
console.info("quartet.lowerMid: " + quartet.lowerMid);
quartet.lowerExtreme = fill(quartet.upperMid, quartet.lowerExtreme, upperQuartile, step) || quartet.lowerExtreme; // median
console.info("quartet.upperMid: " + quartet.upperMid);
quartet.lowerExtreme = fill(quartet.upper, quartet.lowerExtreme, upperExtreme, step) || quartet.lowerExtreme;
console.info("quartet.upper: " + quartet.upper);
var list = [];
list = list.concat(quartet.lower);
list = list.concat(quartet.lowerMid);
list = list.concat(quartet.upperMid);
list = list.concat(quartet.upper);
if (sortData) {
return list;
} else {
return list; // assume this is shuffled
}
}
alert(makelist(3, 5, -1, 8, -1, 9, true))
Note: Don't have to worry about the sortData part.
These are for generating test questions. So the numbers will be used to then ask: "What is the lower quartile?", etc. So just looking to create a set of numbers with known properties of extremes, median and quartile.
Here is the function that checks the quartiles:
quartile: function(array, percent){ /** #param percent - pass 25 for lower quartile, 75 for upper, 50 for mean. Defaults to 50 */
if (!percent) percent = 50;
array = array.sort(function(a, b){return a-b});
var n = Math.round(array.length * percent / 100);
return array[n];
}
I hope this will provide enough of a skeleton that you can tweak to suit your work. As a matter of fact you already had almost all the parts.
// make quartiles
makelist = function(numValues, extrema, quartiles, sortData) {
var milestone_V = [extrema[0]];
var milestone_N = [0];
var q_size = numValues / (quartiles.length + 1); // because the givens do not include the extremes
var accounted = 0;
for ( var i = 0; i < quartiles.length; ++i ) { // easier to do with a filter!
accounted = (i+1) * q_size;
if ( quartiles[i] !== -1 ) {
milestone_V.push( quartiles[i] );
milestone_N.push( Math.floor(accounted) );
}
}
// tweak ranges for the last value
milestone_N.push( numValues - 1 );
milestone_V.push( extrema[1] );
console.log("inputs:", "numValues=", numValues, "range=", extrema, "quartiles=", quartiles);
/*
console.log("..", "milestone_V", milestone_V);
console.log("..", "milestone_N", milestone_N);
*/
function myfill (N, fillrange) {
var count = Math.floor(N);
if (count <= 0) return [];
// fills [lower, upper)
var res = [];
var step = (fillrange[1] - fillrange[0]) / count;
var v0 = fillrange[0];
for (var i = 0; i < N; ++i) {
var tmp = v0 + i * step;
res.push(Math.round(tmp*1e3)/1000); // prints 3 dec digits, most of the time
}
//console.log("....fill range=", fillrange, "count=", count, "N=", N, "results=", res);
return res;
}
// driver
var outcome = [];
for ( var qno = 1; qno < milestone_V.length; ++qno ) {
var qrange = [ milestone_V[qno-1], milestone_V[qno] ];
var howmany = milestone_N[qno] - milestone_N[qno-1];
var tmp = myfill(howmany, qrange);
outcome = outcome.concat(tmp);
}
outcome.push( extrema[1] );
return outcome;
}
console.log( "=================")
var x = makelist(3, [5, 9], [-1, 8, -1], true);
console.log( "len=",x.length, "...", x.join(","));
console.log( "=================")
var x = makelist(22, [5, 9], [6, 8, 8.5], true);
console.log( "len=",x.length, "...", x.join(","));
console.log( "=================")
var x = makelist(21, [5, 9], [-1, 8, 8.5], true);
console.log( "len=",x.length, "...", x.join(","));
And the output looks like:
inputs: numValues= 3 range= [ 5, 9 ] quartiles= [ -1, 8, -1 ]
len= 3 ... 5,8,9
=================
inputs: numValues= 22 range= [ 5, 9 ] quartiles= [ 6, 8, 8.5 ]
len= 22 ... 5,5.2,5.4,5.6,5.8,6,6.333,6.667,7,7.333,7.667,8,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9,9
=================
inputs: numValues= 21 range= [ 5, 9 ] quartiles= [ -1, 8, 8.5 ]
len= 21 ... 5,5.3,5.6,5.9,6.2,6.5,6.8,7.1,7.4,7.7,8,8.1,8.2,8.3,8.4,8.5,8.6,8.7,8.8,8.9,9
First, we know that we need the median, the upper extreme, and the lower extreme in the list. There is no generally accepted definition of quartile for discrete distributions. I will assume that the following definition is used:
Use the median to divide the ordered data set into two halves. Do not include the median in either half. The lower quartile value is the median of the lower half of the data. The upper quartile value is the median of the upper half of the data.
We will put both the upper quartile and the lower quartile into the list twice. Finally, we fill the list with copies of the median. If any of the values are not explicitly given, we can select a valid number arbitrarily.
i want the user to enter a few marks and at the end i want to display the highest lowest average how many got a make of "A","B","C","D","F"
var highestMark=0;
var gradeAwarded;
var StudentArr= [Student];
var markArr = [mark];
var Student = prompt("Enter Student Name: ", "Name");
var mark = prompt("Enter Student Mark: ", 50);
var max = Math.max.apply(markArr); /* This about equal to Math.max(numbers[0], ...) or Math.max(5, 6, ..) */
var min = Math.min.apply(markArr);
if (mark < 0 || mark > 100) {
alert("Grate out of bounds");
} else if (mark >= 83) {
gradeAwarded = "A";
} else if (mark >= 70) {
gradeAwarded = "B";
} else if (mark >= 50) {
gradeAwarded = "C";
} else if (mark >= 0) {
gradeAwarded = "F";
}
document.write(min);
You can just sort the array and take the first and last value. For example:
arr = [3, 5, 2, 14];
arr.sort(function(x, y){return x-y});
min = arr[0]; // 2
max = arr[arr.length - 1]; // 14
Note that a custom comparison function is necessary since you want numerical sorting instead of lexical sorting of the string representation of the numbers. (Otherwise, "14" would be 'smaller' than "2", which is obviously not the way you want it.)
For the record, I agree with Mike Samuel on the other issues with your code.
Array.prototype.reduce allows you to fold over an array.
var min = markArr.reduce(
function (a,b) { return Math.min(a, b); },
Infinity);
var max = markArr.reduce(
function (a,b) { return Math.max(a, b); },
-Infinity);
var mean = markArr.reduce(function (a, b) { return a + b; }, 0)
/ markArr.length;
You've got a number of issues with your code though.
var markArr = [mark];
var Student = prompt("Enter Student Name: ", "Name");
var mark = prompt("Enter Student Mark: ", 50);
You're using mark to initialize markArr before reading mark.
Also, mark is read as a string.
You should reorder your statements so that you initialize variables before using them, and you
should make sure mark ends up as a numeric value.
var mark = +prompt("Enter Student Mark: ", 50);
The + before prompt coerces the string returned by prompt to a number.
Is there any maximum limit of conditions for If in Javascript? I am using following method to detect bombs in division "b". But it skips more than 3 or 4 conditions and hence less bombcount than the actual count.
The following function triggers as soon as I click on div b where b = some number . It has a Kwhere I check for bomb in every cell and if the cell with the bomb satisfies the position criterion it increases bombcount by 1.
var i = 1;
var p1 = b-1;
var p2 = b+1;
var p3 = b+6;
var p4 = b-6;
var p5 = b-5;
var p6 = b+5;
var p7 = b-7;
var p8 = b+7;
var bombcount = 0;
while(i<37)
{
var check = document.getElementById(i).value;
if (check == "explode" && b>6 && b<31) {
if(i==p1 || i==p2 || i==p3 || i==p4 ||
i==p5 || i==p6 || i==p7 || i==p8) {
bombcount++
};
}
i++;
}
Use array for p and indexOf to check is i in array:
var p = [b - 1, b + 1, b + 6, b - 6, b + 5, b - 5, b + 7, b - 7];
if (p.indexOf(i) !== -1) {
bombcount++;
}
No, there is no limit to number of if-else statements, be it one after another or nested if-else loops. Also, there is as such no limit to number of condition you can have under a if statement.
But, it is better to use switch in those cases. It improves readability and performance.
For switch syntax see this
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/switch
For using switch over a range of values see this previous post
Switch statement for greater-than/less-than
There is no limit. And as a tip, you maybe better off using switch and falling through for these conditions:
switch (i) {
case p1:
case p2:
case p3:
// your logic
break;
}
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Statements/switch