Averaged variables giving NaN?? Plz help

Can anyone help me understand why avg1,avg2,avg3,avg4 from each section when averaged
at the bottom of the code produces a NaN?? Instead of a numeric value?

Here is my code, thanks!!
*each section gives an averaged score I’m trying to average each section now to produce over-all score.

var avg1, avg2, avg3, avg4;
$w.onReady( function () {
const section1 = [$w(“#radioGroup1”), $w(“#radioGroup2”), $w(“#radioGroup3”), $w(“#radioGroup4”)];
let s1totalCount = 0;
section1.forEach(e => {
e.onChange((event) => {
let selected = section1.filter(o => o.valid);
s1totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg1 = Math.round(s1totalCount / section1.length);
$w(“#text57”).text = avg1.toString();
})
})
const section2 = [$w(“#radioGroup5”), $w(“#radioGroup6”), $w(“#radioGroup7”), $w(“#radioGroup8”)];
let s2totalCount = 0; section2.forEach(e => {
e.onChange((event) => {
let selected = section2.filter(o => o.valid);
s2totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg2 = Math.round(s2totalCount / section2.length);
$w(“#text153”).text = avg2.toString();
})
})
const section3 = [$w(“#radioGroup9”), $w(“#radioGroup10”), $w(“#radioGroup11”), $w(“#radioGroup12”)];
let s3totalCount = 0; section3.forEach(e => {
e.onChange((event) => {
let selected = section3.filter(o => o.valid);
s3totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg3 = Math.round(s3totalCount / section3.length);
$w(“#text121”).text = avg3.toString();
})
})
const section4 = [$w(“#radioGroup13”), $w(“#radioGroup14”), $w(“#radioGroup15”), $w(“#radioGroup16”)];
var s4totalCount = 0; section4.forEach(e => {
e.onChange((event) => {
var selected = section4.filter(o => o.valid);
s4totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg4 = Math.round(s4totalCount / section4.length);
$w(“#text156”).text = avg4.toString();
})
})
var finaltotal = (avg1 + avg2 + avg3 + avg4);
var finalavg = Math.round(finaltotal / 4);
$w(“#text150”).text = finalavg.toString();
})

NaN means not a number, basically you are trying to use a number that is not acceptable, not a legal number.

Thanks @sailorcihan any suggestions on how I can get the average without it returning NaN? Thanks heaps!!

as of now, you calculate avg1-4 on change, but you calculate the final average once the page is ready which occurs before any change is made, so no wonder it gives you NaN.
You need to run the final average after you retrieve the 4 averages.

@jonatandor35 Thank you for pointing that out! I’m not great with Javascript so I hope you don’t mind explaining in code how I can calculate the final average after I retrieve the averages? Thank you so much!

@danrbraine

//top of the code
let avg1, avg2, avg3, avg4;
let finalAvg;
let allAverages = [avg1, avg2, avg3, avg4];
function calculateFinalAvg(){
    if (allAverages.every(e => typeof e === "number")){
    finalAvg = allAverages.reduce((a, c) => a + c)/allAverages.length;
    }
}
//then inside each of the onChange() functions after calculation the specific average (such as avg1, avg2):
 calculateFinalAvg(); 

[updated]

2 Likes

Thanks @jonatandor35 so what you’re saying is in the rest of my code, for each section I’m supposed place the variable in the function? Like I have below in bold?

const section1 = [$w(“#radioGroup1”), $w(“#radioGroup2”), $w(“#radioGroup3”), $w(“#radioGroup4”)];
let s1totalCount = 0;
section1.forEach(e => {
e.onChange((event) => {
let selected = section1.filter(o => o.valid);
s1totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg1 = Math.round(s1totalCount / section1.length);
$w(“#text57”).text = avg1.toString();
calculateFinalAvg(avg1);
})
})

@danrbraine since avg1 is a global variable no need to pass it with the function call. You can leave the parenthesis empty.
anyway in the calculateFinalAvg function itself (that I wrote in the previous commen) add (after the final avg calculation):
$w("#text150”).text = finalAvg.toString();

@jonatandor35 Just want to confirm is this what you had in mind? It’s not returning the average in the ‘$w’ field unfortunately. Is it because it’s calculating the average ‘w.onReady’ Before it can calculate the averages somehow? Thanks!!!

$w.onReady ( function () {
let avg1, avg2, avg3, avg4;
let finalAvg;
let allAverages = [avg1, avg2, avg3, avg4];
function calculateFinalAvg(){
if (allAverages.every(e => typeof e === “number”)){
finalAvg = allAverages.reduce((a, c) => a + c)/allAverages.length;
calculateFinalAvg($w(“#text150”).text = finalAvg.toString());
}
}

@danrbraine just:

let avg1, avg2, avg3, avg4;
let finalAvg;
let allAverages = [avg1, avg2, avg3, avg4];
function calculateFinalAvg(){
    if (allAverages.every(e => typeof e === "number")){
    finalAvg = allAverages.reduce((a, c) => a + c)/allAverages.length;
    $w("#text150").text = finalAvg.toString();
    }
}
//and in your onChange() function after avg1 = .... :
calculateFinalAvg();

@jonatandor35 Thank you so much for your patience! For some reason, nothing is turning up in the “text150” variable? Does it have something to do with the onReady function?


$w.onReady ( function () {
let avg1, avg2, avg3, avg4;
let finalAvg;
let allAverages = [avg1, avg2, avg3, avg4];
function calculateFinalAvg(){
if (allAverages.every(e => typeof e === “number”)){
finalAvg = allAverages.reduce((a, c) => a + c)/allAverages.length;
$w(“#text150”).text = finalAvg.toString()
}
}
calculateFinalAvg();

const section1 = [$w(“#radioGroup1”), $w(“#radioGroup2”), $w(“#radioGroup3”), $w(“#radioGroup4”)];
let s1totalCount = 0;
section1.forEach(e => {
e.onChange((event) => {
let selected = section1.filter(o => o.valid);
s1totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg1 = Math.round(s1totalCount / section1.length);
calculateFinalAvg();
$w(“#text57”).text = avg1.toString();
})
})
const section2 = [$w(“#radioGroup5”), $w(“#radioGroup6”), $w(“#radioGroup7”), $w(“#radioGroup8”)];
let s2totalCount = 0; section2.forEach(e => {
e.onChange((event) => {
let selected = section2.filter(o => o.valid);
s2totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg2 = Math.round(s2totalCount / section2.length);
calculateFinalAvg();
$w(“#text153”).text = avg2.toString();
})
})
const section3 = [$w(“#radioGroup9”), $w(“#radioGroup10”), $w(“#radioGroup11”), $w(“#radioGroup12”)];
let s3totalCount = 0; section3.forEach(e => {
e.onChange((event) => {
let selected = section3.filter(o => o.valid);
s3totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg3 = Math.round(s3totalCount / section3.length);
calculateFinalAvg();
$w(“#text121”).text = avg3.toString();
})
})
const section4 = [$w(“#radioGroup13”), $w(“#radioGroup14”), $w(“#radioGroup15”), $w(“#radioGroup16”)];
var s4totalCount = 0; section4.forEach(e => {
e.onChange((event) => {
var selected = section4.filter(o => o.valid);
s4totalCount = selected.reduce((a, c) => a + Number(c.value), 0);
avg4 = Math.round(s4totalCount / section4.length);
calculateFinalAvg();
$w(“#text156”).text = avg4.toString();
})
})
})

@danrbraine yes. My mistake, put the array declaration inside the function like this:

let avg1, avg2, avg3, avg4;
let finalAvg;
//remove the array declaration from here and move it down
function calculateFinalAvg(){
    let allAverages = [avg1, avg2, avg3, avg4];
    if (allAverages.every(e => typeof e === "number")){
    finalAvg = allAverages.reduce((a, c) => a + c)/allAverages.length;
    $w("#text150").text = finalAvg.toString();
    }
}
//and continue from here.
1 Like

@jonatandor35 Yes! It works! Can’t thank you enough.

@danrbraine you’re welcome :slight_smile: