Calculating Total And Average

Section overview

This lesson will focus on adding calculations to work out the total distance ran, along with the average distance per run. You'll learn how to use the reduce() method to total all array values, perform division for averages, and update the UI with calculated stats.

By the end of this lesson, your running tracker will automatically calculate and display the total miles run and the average distance per run whenever a new entry is added.

Required calculations

Before we dive into the code, let's understand what we need to calculate:

  1. Total distance: The total of all running entries
  2. Average distance: The total distance divided by the number of entries

These calculations will happen every time the user adds a new entry.

The reducer function

The reduce() method needs a function that combines values. Let's create a simple reducer function:

function reducer(total, currentValue) {
  return total + currentValue;
}
  • function reducer(total, currentValue) creates a function that takes two parameters.
  • total is the accumulated value (starts at 0 or the first value).
  • currentValue is the current array element being processed.
  • return total + currentValue adds the current value to the running total.
  • This function will be called once for each element in the array, adding to the previous total.

Understanding reduce() in detail

The reduce() method is powerful for calculations. Run the following example to see the result for each array value:

const entries = [2.5, 3.0, 1.5];

function reducer(total, currentValue) {
  const newTotal = total + currentValue;
  console.log(`Total: ${total}, Current: ${currentValue}, New Total: ${newTotal}`);
  return newTotal;
}

const result = entries.reduce(reducer, 0);
console.log('Final result:', result);

Loading code...

const entries = [2.5, 3.0, 1.5];

function reducer(total, currentValue) {
  const newTotal = total + currentValue;
  console.log(`Total: ${total}, Current: ${currentValue}, New Total: ${newTotal}`);
  return newTotal;
}

const result = entries.reduce(reducer, 0);
console.log('Final result:', result);

The reducer function is called for each element, building up the total step by step. Run the code above to see each iteration logged to the console.

Calculating the total

Now let's create a function to calculate and display the total:

function calcTotal() {
  const totalValue = entries.reduce(reducer);
  document.getElementById('total').innerText = totalValue;
  document.getElementById('progressTotal').innerText = totalValue;
}
  • function calcTotal() creates a function to calculate the total distance.
  • entries.reduce(reducer) uses the reduce() method to add together all values in the entries array.
  • document.getElementById('total') selects the span element displaying the total.
  • .innerText = totalValue updates the displayed text with the calculated total.
  • We also update progressTotal which will be used for the progress circle later.

Calculating the average

The next function will calculate and display the average distance ran:

function calcAverage() {
  const average = (entries.reduce(reducer) / entries.length).toFixed(1);
  document.getElementById('average').innerText = average;
}
  • function calcAverage() creates a function to calculate the average distance.
  • entries.reduce(reducer) gets the total combined value of all entries.
  • / entries.length divides the total by the number of entries to get the average.
  • .toFixed(1) formats the result to 1 decimal place and converts it to a string.
  • document.getElementById('average') selects the span element for the average.
  • .innerText = average updates the displayed value.

Note: If the array is empty, entries.length would be 0, causing division by zero. In a production app, you'd want to add a check like if (entries.length === 0) return. For now, we'll assume there's at least one entry.

Updating the handleSubmit function

Now we need to call these calculation functions whenever a new entry is added. Update your handleSubmit function:

function handleSubmit(event) {
  event.preventDefault();
  const entry = Number(document.querySelector('#entry').value);
  console.log(entry);

  if (!entry) return;
  entries.push(entry);
  document.querySelector('form').reset();
  addNewEntry(entry);
  // call our 2 new functions
  calcTotal();
  calcAverage();
}

These functions run every time a new entry is added, keeping the stats up to date.

Complete updated JavaScript code

Here's the complete script.js file with all the calculation functions:

let entries = [];
const entriesWrapper = document.querySelector('#entries');

function addNewEntry(newEntry) {
  entriesWrapper.removeChild(entriesWrapper.firstElementChild);
  const listItem = document.createElement('li');
  const listValue = document.createTextNode(newEntry.toFixed(1));
  listItem.appendChild(listValue);
  entriesWrapper.appendChild(listItem);
}

function reducer(total, currentValue) {
  return total + currentValue;
}

function calcTotal() {
  const totalValue = entries.reduce(reducer);
  document.getElementById('total').innerText = totalValue;
  document.getElementById('progressTotal').innerText = totalValue;
}

function calcAverage() {
  const average = (entries.reduce(reducer) / entries.length).toFixed(1);
  document.getElementById('average').innerText = average;
}

function handleSubmit(event) {
  event.preventDefault();
  const entry = Number(document.querySelector('#entry').value);
  console.log(entry);

  if (!entry) return;
  entries.push(entry);
  document.querySelector('form').reset();
  addNewEntry(entry);
  calcTotal();
  calcAverage();
}

const form = document
  .querySelector('form')
  .addEventListener('submit', handleSubmit);

Testing the calculations

  1. Open your running tracker in the browser.
  2. Add an entry: 2.5 miles
    • Total should show: 2.5
    • Average should show: 2.5
  3. Add another entry: 3.0 miles
    • Total should show: 5.5
    • Average should show: 2.8 (5.5 / 2 = 2.75, rounded to 2.8)
  4. Add a third entry: 1.5 miles
    • Total should show: 7.0
    • Average should show: 2.3 (7.0 / 3 = 2.33, rounded to 2.3)

The calculations should update automatically each time you add a new entry!

Summary

In this lesson, you've learned how to:

  • Use reduce(): Total all values in an array with the reduce() method.
  • Calculate averages: Divide the total by the count to get the average distance.
  • Update the DOM: Use getElementById and innerText to display calculated values.
  • Format numbers: Use toFixed() to control decimal places in displayed values.
  • Call functions in sequence: Execute multiple functions after adding an entry to keep everything up to date.

Your running tracker now displays real-time stats! In the next lesson, we'll add functionality to track weekly highs and set goals.