var num_stars_løn = 0
var num_stars_team = 0
var num_stars_trivsel = 0
function add_rating(num_rating, section) {
if (section == "løn"){
num_stars_løn = num_rating;
document.getElementById("num_stars_løn").value = num_rating;
}
else if (section == "teambuilding"){
num_stars_team = num_rating;
document.getElementById("num_stars_team").value = num_rating;
}
else if (section == "trivsel") {
num_stars_trivsel = num_rating;
document.getElementById("num_stars_trivsel").value = num_rating;
}
for(var i = 1; i < num_rating + 1; i++) {
var section_id = section + " " + i
document.getElementById(section_id).innerHTML = "★"
}
if (num_rating < 5){
for(var i = 5; i > num_rating; i--) {
var section_id = section + " " + i
document.getElementById(section_id).innerHTML = "☆"
}
}
if (num_stars_team > 0 && num_stars_løn > 0 && num_stars_trivsel > 0){
show_mean_rating();
}
}
function show_mean_rating() {
var mean = document.getElementById("num_stars_løn").value +
document.getElementById("num_stars_team").value +
document.getElementById("num_stars_trivsel").value;
document.getElementById("mean_rating").innerText = "Gennemsnitlig rating: " + (mean/3).toFixed(2);
}
HTML
I have made a star rating system for some topics (3 in total) using JavaScript and HTML. Do one of you know how to calculate the average/mean of how many stars each topic received? So not the three topics all together, but the mean per topic of clicks/stars.
Right now it finds the mean of all 15 stars in total. (each topic has 5 stars) But it is supposed to calculate the mean for each individual topic. I’m thinking maybe something with a counter for each meeting every time a user clicks on the stars, but I am not sure. And then maybe divide the stars with amount of votes/stars given
To get the mean of each section, you would need to capture each vote with a counter (can be stored in state or in plain text with # of votes) and divide the sum of all of the votes by the number of votes.
This can be done with an array of votes with each vote being added to an array every time a user clicks a rating, adding all the values in the array together, and dividing it by array.length.
Related
The script would count the number of times all VIN numbers are repeated & if all parts have arrived for that VIN Number (Car).
In example, if the VIN number is repeated 5 times then that means there are five parts going to arrive, so then the next step would be to check the arrived column for such VIN if there are 5 "Yes" values then
(VIN number repeated) 5/5 (Number of "Yes" values)
would trigger it to change the [Master] tab Parts Order column to "Yes" for that particular VIN number.
User would manually update the [Parts] tab, arrived column with either "Yes" or leave blank. (If blank then part has not arrived.)
See link for google sheet Template:
https://docs.google.com/spreadsheets/d/1wlGV_QCWpRwmI5FWiOli6lXuzRATy_Goygp3lhtm-Ek/edit?usp=sharing
My attempt:
Special function to get the last value of a column:
function getLastRowSpecial(range){
var rowNum = 0;
var blank = false;
for(var row = 0; row < range.length; row++){
if(range[row][0] === "" && !blank){
rowNum = row;
blank = true;
}else if(range[row][0] !== ""){
blank = false;
};
};
return rowNum;
};
Here I was able to count the number of times each VIN Number appears, but I was unable to count the number of "Yes" values for each unique VIN number. This needs to be dynamic. My approach at the end was not dynamic. Regarding in particular the, var number
Main Script:
/** ---------------------- SPREAD SHEETS ---------------------- **/
var masterS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master");
var partS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Parts");
/** ----------------- Selecting Range of Cells ----------------- **/
/** ----- Parts Spread Sheet ----- **/
/** VIN to Match */
var vinPartOrderRangeP = partS.getRange("C5:C");
var vinPartValuesP = vinPartOrderRangeP.getValues();
var columnCheckPartVINP = getLastRowSpecial(vinPartValuesP);
var partVINDataRangeP = partS.getRange(5, 3, columnCheckPartVINP, 1);
var partsVinSetP = partVINDataRangeP.getValues();
/** Part Arrived */
var partOrderedRangeP = partS.getRange("N5:N");
var partOrderedValuesP = partOrderedRangeP.getValues();
var partOrderedValuesCorrectLengthP = partOrderedValuesP.splice(0,partsVinSetP.length);
/** Combining VINs with Parts Arrived */
var vinPartsArrivedP = [];
vinPartsArrivedP.push(partsVinSetP,partOrderedValuesCorrectLengthP);
/** ----- Master Spread Sheet ----- **/
/** VIN to Match */
var vinPartOrderRangeM = masterS.getRange("B5:B");
var vinPartValuesM = vinPartOrderRangeM.getValues();
var columnCheckPartVINM = getLastRowSpecial(vinPartValuesM);
var partVINDataRangeM = masterS.getRange(5, 2, columnCheckPartVINM, 1);
var partsVinSetM = partVINDataRangeM.getValues();
/** Part Arrived */
var partPastRangeM = masterS.getRange("I5:I");
var partPastValuesM = partPastRangeM.getValues();
/** ---- For-Loop getting Number of Parts that need to Arrive ---- **/
var vinNumber = [], arrivalPartsRequired = [], prev;
for (var i = 0; i < vinPartsArrivedP[0].length; i++) {
if (vinPartsArrivedP[0][i][0] !== prev) {
vinNumber.push(vinPartsArrivedP[0][i][0]);
arrivalPartsRequired.push(1);
} else {
arrivalPartsRequired[arrivalPartsRequired.length - 1]++;
}
prev = vinPartsArrivedP[0][i][0];
}
console.log('[' + vinNumber[0] + ']','[' + arrivalPartsRequired[0] + ']')
/**
* Now we can say arrivalPartsRequired has the number of Yes's we need
* per each VIN number.
**/
console.log(vinPartsArrivedP[0][3][0])
var number = 0;
var number2 = 0;
var number3 = 0;
var number4 = 0;
var number5 = 0;
for (var j = 0; j < partsVinSetM.length; j++) {
};
for (var k=0; k<vinPartsArrivedP[0].length; k++){
if(vinNumber[0] == vinPartsArrivedP[0][k][0]){
number++
for (var i=0; i<partOrderedValuesP[0].length; i++){
for (var j = 0; j < partOrderedValuesP[0].length; j++) {
if (partOrderedValuesP[i][j] == 'Yes') {
console.log(i);
return i+1;
}
}
return -1;
}
}
if(vinNumber[1] == vinPartsArrivedP[0][k][0]){
number2++
}
if(vinNumber[2] == vinPartsArrivedP[0][k][0]){
number3++
}
if(vinNumber[3] == vinPartsArrivedP[0][k][0]){
number4++
}
if(vinNumber[4] == vinPartsArrivedP[0][k][0]){
number5++
}
};
console.log(number);
console.log(number2);
console.log(number3);
console.log(number4);
console.log(number5);
I believe your goal as follows.
You want to retrieve the values from the columns "C" and "N" from "Parts" sheet, and want to check whether the number of same VIN # at the column "C" and the number of yes at the column "N".
When both numbers are the same, you want to put yes to the column "I" of "Master" sheet.
You want to achieve this using Google Apps Script.
In this case, in order to achieve your goal, how about the following flow?
Retrieve values from "Parts" sheet.
Create an object for checking the number of VIN # and yes.
Create an array for putting to the "Master" sheet.
Put the values to the "Master" sheet.
When this flow is reflected to a sample script, it becomes as follows.
Sample script:
function sample() {
// 1. Retrieve values from "Master" sheet.
var masterS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Master");
var valuesOfParts = partS.getRange("C5:N" + partS.getLastRow()).getValues();
// 2. Create an object for checking the number of `VIN #` and `yes`.
var obj = valuesOfParts.reduce((o, [c,,,,,,,,,,,n]) => {
if (o[c]) {
o[c].c += 1;
if (n == "yes") o[c].yes += 1;
} else {
o[c] = {c: 1, yes: n == "yes" ? 1 : 0};
}
return o;
}, {});
// 3. Create an array for putting to the "Master" sheet.
var partS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Parts");
var rangeOfMaster = masterS.getRange("B5:B" + masterS.getLastRow());
var valuesOfMaster = rangeOfMaster.getValues().map(([b]) => [obj[b] && obj[b].c == obj[b].yes ? "yes" : ""]);
// 4. Put the values to the "Master" sheet.
rangeOfMaster.offset(0, 7).setValues(valuesOfMaster);
}
References:
reduce()
map()
I want to write a code that automate the late days calculation. Here is how it should work
If the score of date after (ex: date 10) - score of day before (date 9)> 0 => the score of date after (120) will be assigned "late for 3 days"
On the other hand, that date after will keep looking and substracting from the next date before until it gets "> 0" result.
The example is illustrated in attached image.
Here is the code that I currently have and it didnt work:
function myFunction() {
var app = SpreadsheetApp;
var activeSheet = app.geActiveSpreadsheet().getActiveSheet();
for (var i=2; i <= 8; i++){
var scoreafterCell = activeSheet.getRange(i;2).getValue();
var scorebeforeCell= activeSheet.getRange(i++;2).getValue();
scoreDiff= scoreafterCell- scorebeforeCell;
if(scoreDiff > 0) {
activeSheet.getRange(i,3).setValue(3);
} else for (var k=0; k++) {
do {
lateDays= k+=3;
activeSheet.getRange(i,3).setValue(lateDays);
}
while (scoreDiff = 0);
}
}
}
Hope to have some inputs soon since this is very important for my work!!! Thank you.
Since there is no clear pattern above, I did a hack to achieve what you want. This only checks the scores and doesn't check the dates as lateDays won't be dependent on that.
Please see the code below.
function generateLateDays() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var lastRow = activeSheet.getLastRow();
var scores = activeSheet.getRange('B2:B' + lastRow).getValues().flat();
var output = activeSheet.getRange('C2:C' + lastRow);
var lateDays = [];
while(scores.length > 0) {
// get how many occurences does the first element have
occurence = scores.filter(value => value === scores[0]).length;
// remove current item in advance, we will only be checking number of occurences
// exact value will not be checked, so scores should be in descending order
scores = scores.filter(score => score !== scores[0]);
// contains per score late days
var temp = [];
for(var j = 0; j < occurence; j++) {
if(scores.length > 0) {
// e.g. 3 duplicates will make temp 3, 4, 5
temp.push(j + 3);
}
else {
// when last element is up, push 0
temp.push(0);
}
}
// e.g. temp reverse will be 5, 4, 3
temp.reverse();
// add to final output
lateDays.push(temp);
}
// convert 2d array to 1d array
lateDays = lateDays.flat();
for(var i = 0; i < lateDays.length; i++) {
// convert all elements into an array for setValues
lateDays[i] = [].concat(lateDays[i]);
}
output.setValues(lateDays);
}
Note that this will work only on the order your sample sheet works. I haven't tried doing it ascending. Since your sheet score descending, I made this to work that way.
If you have any questions, feel free to ask below.
Below is my suggested answer. Check it out:
function getLateDates() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var scores = activeSheet.getRange('B2:B10').getValues().flat();
var output = activeSheet.getRange('D2:D10');
/**
* Set LateDates[_] as array of 3,
* except the last value = 0 ( at t = 0 )
*
*/
let LateDates = [
...Array.from({ length: scores.length - 1 }).map((x) => 3),
0,
];
/** Check the diff of current score with each of the next score,
* if diff > 0 --> break --> LateDates[current] = 3
* if diff = 0 --> +1 to LateDates[current], and continue w the next score
*
*/
for (var current = 0; current < scores.length; current++) {
for (var next = current + 1; next < scores.length; next++) {
let d = scores[current] - scores[next];
if (d > 0) {
break;
} else {
LateDates[current]++;
}
}
}
/**
* Reduce the LateDates to fit setValues format
*/
let result = LateDates.reduce((a,c)=> ([...a,[c]]),[])
output.setValues(result)
//console.log('result', result);
}
Notice I'm using your date order (descending).
If it's ascending, switch 0 to top of LateDates[] instead:
let LateDates = [
0,
...Array.from({ length: scores.length - 1 }).map((x) => 3),
];
Someone showed me the following code which generates 3 random numbers between 1 and 10:
var limit = 10,
amount = 3,
lower_bound = 1,
upper_bound = 10,
unique_random_numbers = [];
if (amount > limit) limit = amount; //Infinite loop if you want more unique
//Natural numbers than exist in a
// given range
while (unique_random_numbers.length < limit) {
var random_number = Math.floor(Math.random()*(upper_bound - lower_bound) + lower_bound);
if (unique_random_numbers.indexOf(random_number) == -1) {
// Yay! new random number
unique_random_numbers.push( random_number );
}
}
//
How could I make these numbers appear in place of elements with a corresponding class? The code below is clearly wrong, but hopefully it illustrates what I'm trying to achieve:
<script type='text/javascript'>
var random_number1 = random_number1();
$('.random_number1').html(random_number1);
var random_number2 = random_number2();
$('.random_number2').html(random_number2);
</script>
<span class="random_number1"></span> <span class = "random_number2"></span>
assuming you had a div with id of numbers and the array unique_random_numbers, you'd populate it this way, assuming you have jquery reference:
for ( i = 0; i < unique_random_numbers.length; i++)
{
$("#Numbers").html($("#Numbers").html() +"<span>" + unique_random_numbers[i] + "</span><br/>");
}
Im trying to get a counter to register the least number of rolls it took to get a double and then when they play the 'game' again if they got an even lower number of doubles it replaces the first answer with the newer one.
count=0, doubles=0, lowest=10000000;
function Roll()
// Assumes: die images are in http://dave-reed.com/book/Images
// Results: displays a randomly selected image of a 6-sided die
{
var roll1, roll2;
roll1 = RandomInt(1, 6);
roll2 = RandomInt(1, 6);
document.getElementById('die1').src =
"http://dave-reed.com/book/Images/die" + roll1 + ".gif";
document.getElementById('die2').src =
"http://dave-reed.com/book/Images/die" + roll2 + ".gif";
count += 1;
if (roll1==roll2) {
doubles += 1;
}
if (doubles==3) {
alert("You got three pairs of doubles!!! It only took you " +count+ " rolls to get it! Now, go directly to jail, do not pass go, and do not collect $200");
doubles=0;
count=0;
}
if (doubles==3 && lowest>count){
lowest=count
document.getElementById('lowestLine').innerHTML = count;
}
document.getElementById('countLine').innerHTML = count;
document.getElementById('doublesLine').innerHTML = doubles;
}
You set doubles to 0 once it becomes 3 and then you check if doubles equals 3 which is never true.
It looks like you should put
if (lowest > count) {
lowest = count
document.getElementById('lowestLine').innerHTML = count;
}
inside first doubles === 3 check, but before you setting globals to 0.
Like this:
if (doubles === 3) {
alert("You got three pairs of doubles!!! It only took you " +count+ " rolls to get it! Now, go directly to jail, do not pass go, and do not collect $200");
if (lowest > count){
lowest = count
document.getElementById('lowestLine').innerHTML = count;
}
doubles = 0;
count = 0;
}
I want to be able to have a user enter multiple grades and then have the Javascript to average those grades that are entered. When the user is done entering grades, they can click cancel and close the Propmt Box, and if they don't enter any grades at all (defaults at 0), then the program displays that there were no grades entered.
I'm pretty new at this! I'm taking a javascript course at my College, and it's a bit confusing because the teacher doesn't teach! All we have to reference to is W3schools, which this stuff isn't listed at all!
Here's another explanation:
"Develop a program to allow a teacher to enter an arbitrary number of grades, perform an average calculation and then display the result in a grammatical sentence. The program must also tell the user if no grades were entered. You are required to use a loop and an “if else” statement. Be sure to declare all variables and test for the possibility of division by zero."
<script type = "text/javascript">
var gradeCounter = 0,
gradeValue = 0,
total = 0,
average, grade;
var sum = 0;
var i = 0;
while (gradeValue != -1 && gradeValue <= 100) {
//Prompt the user
grade = prompt("Enter Grades, -1 to Quit:", "0");
//Parse the prompt result to a int
sum += parseInt(grade);
i++;
if (i >= 0 && grade != null) {
document.getElementById("average").innerHTML = "The average of the grades you've entered are " + sum / i + ".";
} else {
document.getElementById("error").innerHTML = "There were no grades entered";
}
} </script>
Thanks again!
this does ok
updated
updated again
JSFIDDLE
// note: the dom must be ready before execution
var btn = document.querySelector('button'),
res = document.getElementById('average');
btn.addEventListener('click', function(e) {
var val = prompt('Enter comma delimited grades to average');
val = val.length ? val.replace(/\s/g, '').split(',') : '';
var count = val.length || 0; // no 0 division
if (!count) {
res.innerHTML = 'you must enter comma delimited numbers to average';
return;
} else {
var average = val.reduce(function(a, b) { // is a loop
return +a + +b;
});
res.innerHTML = (average /= count).toFixed(1);
}
});
html
<button id="avgBtn">Prompt</button>
<p>Average: <span id="average"></span></p>
var grades = [];
// initialize the array that will store the entries
var sum = 0;
// initialize the variable that will add the array values together
var average;
// initialize the variable that will contain the final result
var invalid = [];
// initialize the variable that will be used to make sure the user inserts something
for (i = 0; i < 5; i++) {
// repeat the following code 5 times
grades[i] = prompt("Please enter a grade. (You will be asked for 5 grades)", "");
// ask the user for a grade and store it to the array
}
for (i = 0; i < grades.length; i++) {
if (grades[i] === "" || grades[i] === null) {
invalid[invalid.length] = grades[i];
}
}
if (invalid.length !== 5) {
for (i = 0; i < grades.length; i++) {
// repeat this code the same amount of times as there are entries in the array (5)
sum += Number(grades[i]);
// add the entries together. make sure they are numbers using the Number() function
}
var average = sum / grades.length;
// divide the added entries by the number of entries (again, 5)
alert("The average of all of your numbers is: " + average);
// alert the user of the completed average
} else {
alert('You need to enter grades for this to work! Please reload the page to try again.');
}