Skip to content

Latest commit

 

History

History
423 lines (335 loc) · 13.3 KB

11_stats.md

File metadata and controls

423 lines (335 loc) · 13.3 KB

Stats

In the last section we learned how to update the Last 10 values section so that older values get pushed down everytime new values come in.

In this section we will work on calculating the Avg, Max and Min and displaying those calculations in the Stats on the last 10 values section.


All we need to do here is create helper functions that can calculate the Avg, Max and Min then display the calculations.

// Calculates the Average
function calculate_avg() {
  // Holds sum
  let hum_sum  = 0;
  let temp_sum = 0;

  // Holds averages
  let hum_avg  = 0;
  let temp_avg = 0;

  // Holds string representation of the average
  let s_hum_avg  = "";
  let s_temp_avg = "";

  // Calculates sum
  for (let i = 0; i < value_count; i++) {
    hum_sum += Number(app_elements.latest_values_section.Hum[i].innerHTML);
    temp_sum += Number(app_elements.latest_values_section.Temp[i].innerHTML);
  }

  // Calculates average and rounds to the nearest hundreth
  hum_avg = two_decimals(hum_sum / value_count);
  temp_avg = two_decimals(temp_sum / value_count);

  // Covert number to string to string
  s_hum_avg = hum_avg.toString();
  s_temp_avg = temp_avg.toString();

  // Display the calculated averages
  app_elements.statistics_section.Avg.Hum.innerHTML = s_hum_avg;
  app_elements.statistics_section.Avg.Temp.innerHTML = s_temp_avg;
}

// Finds the Maximum
function get_max() {
  // Holds the max values, temp holding Number.NEGATIVE_INFINITY so that we can 
  // gurantee that the next number we compare it too will be greater
  let hum_max = Number.NEGATIVE_INFINITY;
  let temp_max = Number.NEGATIVE_INFINITY;

  // Loop through each displayed value
  for (let i = 0; i < value_count; i++) {
    // Get the displayed value
    let hum_value = Number(app_elements.latest_values_section.Hum[i].innerHTML)
    let temp_value = Number(app_elements.latest_values_section.Temp[i].innerHTML)

    // Compare the displayed value to the temporary max
    if (hum_value > hum_max) {
      // Sets the current value to the max
      hum_max = hum_value;
    }
    // Compare the displayed value to the temporary max
    if (temp_value > temp_max) {
      // Sets the current value to the max
      temp_max = temp_value;
    }
  }

  // Display the Max values
  app_elements.statistics_section.Max.Hum.innerHTML = hum_max.toString()
  app_elements.statistics_section.Max.Temp.innerHTML = temp_max.toString()
}

// Finds the Minimum
function get_min() {
  // Holds the min values, temp holding Number.POSITIVE_INFINITY so that we can 
  // gurantee that the next number we compare it too will be smaller
  let hum_min = Number.POSITIVE_INFINITY;
  let temp_min = Number.POSITIVE_INFINITY;

  // Loop through each displayed value
  for (let i = 0; i < value_count; i++) {
    // Get the displayed value
    let hum_value = Number(app_elements.latest_values_section.Hum[i].innerHTML)
    let temp_value = Number(app_elements.latest_values_section.Temp[i].innerHTML)

    // Compare the displayed value to the temporary min
    if (hum_value < hum_min) {
      // Sets the current value to the min
      hum_min = hum_value;
    }
    // Compare the displayed value to the temporary min
    if (temp_value < temp_min) {
      // Sets the current value to the min
      temp_min = temp_value;
    }
  }

  // Display the Min values
  app_elements.statistics_section.Min.Hum.innerHTML = hum_min.toString()
  app_elements.statistics_section.Min.Temp.innerHTML = temp_min.toString()
}

Average

For the average we have created the calculate_avg function.

// Calculates the Average
function calculate_avg() {
  // Holds sum
  let hum_sum  = 0;
  let temp_sum = 0;

  // Holds averages
  let hum_avg  = 0;
  let temp_avg = 0;

  // Holds string representation of the average
  let s_hum_avg  = "";
  let s_temp_avg = "";

  // Calculates sum
  for (let i = 0; i < value_count; i++) {
    hum_sum += Number(app_elements.latest_values_section.Hum[i].innerHTML);
    temp_sum += Number(app_elements.latest_values_section.Temp[i].innerHTML);
  }

  // Calculates average and rounds to the nearest hundreth
  hum_avg = two_decimals(hum_sum / value_count);
  temp_avg = two_decimals(temp_sum / value_count);

  // Covert number to string to string
  s_hum_avg = hum_avg.toString();
  s_temp_avg = temp_avg.toString();

  // Display the calculated averages
  app_elements.statistics_section.Avg.Hum.innerHTML = s_hum_avg;
  app_elements.statistics_section.Avg.Temp.innerHTML = s_temp_avg;
}

Essentially the way the function works is that it creates a couple of temporary variables. Calculates the sum of all of the currently displayed values, calculates the average and lastly, displays the result.

First temporary variables for the sum:

// Holds sum
let hum_sum  = 0;
let temp_sum = 0;

Temporary variables for numberical representation of the averages:

// Holds averages
let hum_avg  = 0;
let temp_avg = 0;

Lastly, temporary variables for the string representation of the averages:

// Holds string representation of the average
let s_hum_avg  = "";
let s_temp_avg = "";

After setting up the variables that we will use, we then calculate the sum for the humidity and the temperature. In the loop we essentially grab the values being displayed for the humidity and temperature, convert those values to their numerical representation and then add them the current sum:

// Calculates sum
for (let i = 0; i < value_count; i++) {
  hum_sum += Number(app_elements.latest_values_section.Hum[i].innerHTML);
  temp_sum += Number(app_elements.latest_values_section.Temp[i].innerHTML);
}

Next, we calculate the average values for the humidity and the temperature:

// Calculates average and rounds to the nearest hundreth
hum_avg = two_decimals(hum_sum / value_count);
temp_avg = two_decimals(temp_sum / value_count);

In the code above you can probably notice two things here. We are using a variable here called value_count. This is a new variable that we will need to create, the point of the variable is to provide a count of how many values are currently being displayed. I created this variable below the app_elements sctructure near the top.

let value_count = 0;

The next thing you probably notice it that we are using the two_decimals function again. This is because when calculating the average we have the potential of getting really long numbers again so here we are going to round them again.

The last thing we do in the function is convert the numerical averages to strings so that we can then display them.

// Covert number to string
s_hum_avg = hum_avg.toString();
s_temp_avg = temp_avg.toString();

// Display the calculated averages
app_elements.statistics_section.Avg.Hum.innerHTML = s_hum_avg;
app_elements.statistics_section.Avg.Temp.innerHTML = s_temp_avg;

Maximum

For the maximum we created the get_max function:

// Finds the Maximum
function get_max() {
  // Holds the max values, temp holding Number.NEGATIVE_INFINITY so that we can 
  // gurantee that the next number we compare it too will be greater
  let hum_max = Number.NEGATIVE_INFINITY;
  let temp_max = Number.NEGATIVE_INFINITY;

  // Loop through each displayed value
  for (let i = 0; i < value_count; i++) {
    // Get the displayed value
    let hum_value = Number(app_elements.latest_values_section.Hum[i].innerHTML)
    let temp_value = Number(app_elements.latest_values_section.Temp[i].innerHTML)

    // Compare the displayed value to the temporary max
    if (hum_value > hum_max) {
      // Sets the current value to the max
      hum_max = hum_value;
    }
    // Compare the displayed value to the temporary max
    if (temp_value > temp_max) {
      // Sets the current value to the max
      temp_max = temp_value;
    }
  }

  // Display the Max values
  app_elements.statistics_section.Max.Hum.innerHTML = hum_max.toString()
  app_elements.statistics_section.Max.Temp.innerHTML = temp_max.toString()
}

The way that this function works is, it first creates temporary max variables with negative infinity so that any number we compare it too would be larger than it, we then loop through each displayed value and compare it to the current temporary max variable, we then compare each value to the temporary max variable, if it is larger, we replace the current temporary max with the value we saw was larger. Lastly, once we have looped through all of the displayed values, we display the max value variable.

Temporary max variables:

// Holds the max values, temp holding Number.NEGATIVE_INFINITY so that we can 
// gurantee that the next number we compare it too will be greater
let hum_max = Number.NEGATIVE_INFINITY;
let temp_max = Number.NEGATIVE_INFINITY;

Loop where the logic to check which is the largest displayed value:

// Loop through each displayed value
for (let i = 0; i < value_count; i++) {
  // Get the displayed value
  let hum_value = Number(app_elements.latest_values_section.Hum[i].innerHTML)
  let temp_value = Number(app_elements.latest_values_section.Temp[i].innerHTML)

  // Compare the displayed value to the temporary max
  if (hum_value > hum_max) {
    // Sets the current value to the max
    hum_max = hum_value;
  }
  // Compare the displayed value to the temporary max
  if (temp_value > temp_max) {
    // Sets the current value to the max
    temp_max = temp_value;
  }
}

Displaying the max value

// Display the Max values
app_elements.statistics_section.Max.Hum.innerHTML = hum_max.toString()
app_elements.statistics_section.Max.Temp.innerHTML = temp_max.toString()

Minimum

For the minimum we created the get_min functions:

// Finds the Minimum
function get_min() {
  // Holds the min values, temp holding Number.POSITIVE_INFINITY so that we can 
  // gurantee that the next number we compare it too will be smaller
  let hum_min = Number.POSITIVE_INFINITY;
  let temp_min = Number.POSITIVE_INFINITY;

  // Loop through each displayed value
  for (let i = 0; i < value_count; i++) {
    // Get the displayed value
    let hum_value = Number(app_elements.latest_values_section.Hum[i].innerHTML)
    let temp_value = Number(app_elements.latest_values_section.Temp[i].innerHTML)

    // Compare the displayed value to the temporary min
    if (hum_value < hum_min) {
      // Sets the current value to the min
      hum_min = hum_value;
    }
    // Compare the displayed value to the temporary min
    if (temp_value < temp_min) {
      // Sets the current value to the min
      temp_min = temp_value;
    }
  }

  // Display the Min values
  app_elements.statistics_section.Min.Hum.innerHTML = hum_min.toString()
  app_elements.statistics_section.Min.Temp.innerHTML = temp_min.toString()
}

I won't explain this one since it is pretty much the same as the get_max just checking for the values to be smaller not larger.

Lastly, to make use of these new functions we need to call them in the onmessage function so that they run everytime a new value is generated and we also need to increment the value_count variable so that we can accurately calculate the average. Below is how the onmessage function should look like:

// === Defines what happens when a message is recieved ===
ws.onmessage = function (event) {
  // Save the data that was received
  let received = event.data;

  // Logs the received message
  console.log(`Message from Server: ${received}`);

  // de-stringify the packet received 
  let received_obj = JSON.parse(received);

  // Extract the humidity and temperature values from the packet
  let long_hum_value = received_obj.data[0];
  let long_temp_value = received_obj.data[1];

  // Round to the nearest hundreth
  let short_hum_value = two_decimals(long_hum_value);
  let short_temp_value = two_decimals(long_temp_value);

  // Pushes the previous values down 
  for (let i = app_elements.latest_values_section.Hum.length - 1; i > 0; i--){
    app_elements.latest_values_section.Hum[i].innerHTML = app_elements.latest_values_section.Hum[i-1].innerHTML;
    app_elements.latest_values_section.Temp[i].innerHTML = app_elements.latest_values_section.Temp[i-1].innerHTML;
  }

  // Display the humidity and temperature values in the first entry
  app_elements.latest_values_section.Hum[0].innerHTML = short_hum_value;
  app_elements.latest_values_section.Temp[0].innerHTML = short_temp_value;

  // Count of how many generated values are being displayed, used to calculate 
  // the average
  if (value_count < app_elements.latest_values_section.Hum.length) {
    value_count++;
  }

  // Calculate Statistics
  calculate_avg();
  get_max();
  get_min();
}

Once all this is added, run the server and this is how it should run:

image

You can see how immediately after generating a new value we calculate the statistics.


In this section we learned how to calculate the average, get the maximum and minimum and then displaying the results.

Currently we can set alarm thresholds but we aren't checking to see if the alarm should trigger or not. In the next section we will change the status if the alarm threshold is passed when a new value is generated.


Back to Beginning | Prev: Queue Like List | Next: Working Alarm