Skip to content

Custom Stats

Subscription Tier Required

This feature requires the Premier subscription tier or higher.

Although GS comes equipped with many statistics out of the box, you may want to view additional statistics specific to your own enterprise. GS allows customizing the Stats Grid in order to display custom statistics.

In this guide, you will display a custom Percent Giveaway (sometimes called Overpack) statistic in a Stats Grid. This statistic is often used in the food and beverage industry to indicate how much product is being given away.

Prerequisites

This guide assumes you have sufficient data collected in the past week to perform analysis across several Parts. It also assumes that the Characteristics on those Parts have a Target X set.

Information

For the sake of this guide, the Target X is being treated as the package weight. In the real world, you will typically set the Target to a value slightly higher than the listed package weight in order to avoid underpack. The correct package weight is more typically retrieved from a third party system or set on a different field on the Characteristic, like Lower Individual Limit.

This guide will use Parts named B-34KW, B-36W, and B-34M, and will measure the Weight Characteristic of each Part.

Creating the Dashboard

To begin, create a new Dashboard. The fastest way to create a new Dashboard is to navigate to the Quick Chart menu entry, which acts as a shortcut for a new Dashboard.

Adding a Retrieval

Next, add a Retrieval:

  1. Press the Add Retrieval button. An image showing the location of the Add Retrieval button on the Dashboard
  2. Fill in the Retrieval Name with Current Week. An image showing the Name and Script ID fields
  3. Modify the Date field to Current Week. An image showing the date field
  4. Select the Weight Characteristic in the Characteristics field for the Parts you wish to measure. An image showing the date field
  5. Press Confirm. An image showing the confirm button

Add a Stats Grid

We will now add the table which will be used to display the calculated Giveaway. In order to calculate Giveaway, we will need the Mean. To retrieve this information, we will add a hidden Mean column:

  1. Press the Stats Grid button. An image showing the stats grid button
  2. Change the Process Group Column to Part. An image showing the location of the group column edit
  3. Press Add Column in the Value Columns section. An image showing the location of the value column add
  4. Select Mean and set Hidden to Yes. An image showing the value column
  5. Press Confirm.
  6. Press Confirm on the next overlay.

Scripting

Now that the Dashboard has been set up, you can begin scripting. Create a new Dashboard Script and give it a memorable name. If this interface is unfamiliar, review the Dashboard Scripting Principles and Code Editor articles.

An image showing the location of the Dashboard Script action

An image showing the location of the add button in the Dashboard Script overlay

The tasks we will use scripting to accomplish are:

  1. Updating the Stats Grid to have an additional column for Giveaway.
  2. Updating the Stats Grid to fetch the data used to calculate stats.
  3. Calculating the Giveaway statistic in the onBeforeDraw event of the Stats Grid.

Add Custom Columns

In the newly created Dashboard scipt, add a handler for the onReady Dashboard event:

gsApi.dashboard.onReady(async () => {

});

This will allow us to execute a function when the dashboard has fully loaded. Next, create a reference to the Stats Grid API for use later, and update the properties to include a customColumn. This custom column will be used to render the Giveaway for each Part. The actual values will be calculated later.

const statsGrid = gsApi.dashboard.statsGrid('item 1');
gsApi.dashboard.onReady(async () => {
    await statsGrid.updateProperties({
        customColumns: [{
            id: 'giveaway',
            heading: 'Giveaway'
        }]
    });
});

Perform the Giveaway Calculation

Next, bind to the onBeforeDraw property of the Stats Grid. This will be called every time the Stats Grid is about to render its content.

statsGrid.onBeforeDraw(async (e) => {

});

Inspecting the e parameter that is passed into the function bound to onBeforeDraw reveals that it contains a data property, which has rows. Modifying the values or the customValues on a row allows you to update the value or change the background color of a particular cell. Modifying other properties will have no effect on how the Stats Grid appears.

To start, iterate over each row. This is done as a normal for loop instead of using the built-in Array.forEach so that we can utilize await:

statsGrid.onBeforeDraw(async (e) => {
    for (let i = 0; i < e.data.rows.length; i++) {
        const row = e.data.rows[i];
    }
});

Each row contains an array of values, which contains one item for each Retrieval / Data Type combination in the Stats Grid. For the purpose of this demo, values will only have one item in it (SPC Data for the Current Week Retrieval). However, if the Stats Grid was comparing across retrievals (for example, comparing this week with last week) or had multiple data types, the values array would contain multiple items. For simplicity, this example assumes that only one item is present.

Add a variable to retrieve the first value from the row, and ensure that it is for SPC data:

const row = e.data.rows[i];
const value = row.values[0];
if (value.dataType !== 'spc') {
   return;
} 

In order to calculate percent Giveaway, we require:

  • The listed package weight for each Part.
  • The average package weight of the Parts produced in this time range.

Because we are using the Target X of the Characteristic, we will need to get the Characteristic. Both the Characteristic and the Mean can be retrieved from the previous value:

const characteristic = value.characteristic;
const mean = value.stats.mean?.value;
const packageWeight = characteristic.targetX;

if (!packageWeight || typeof mean !== 'number') {
   continue;
}

The percent Giveaway will be calculated using the formula:

\[ \text{Giveaway} = \frac{\text{Average Package Weight} - \text{Expected Package Weight}}{\text{Expected Package Weight}} \times 100 \]

In Javascript, using the variables we established above, this translates to:

const giveaway = ((mean - packageWeight) / packageWeight) * 100;

Finally, set this value on the customColumns for this row, fixed to two decimal places and formatted as a percentage. Modifying the values or the customColumns on a row will update the values in the table. No other changes to the row will be reflected.

row.customValues.giveaway = {
   value: `${giveaway.toFixed(2)}%`,
};

Note that .giveaway must match the id property used when setting the customColumns during updateProperties.

Color the Cells

It is nice to be able to glance at a chart and see how things are performing. Adding color is a great way to monitor performance without needing to read every row. For this guide, we will use red to color any cells which have a negative Giveaway (indicative of underpack, which is requires expensive scrap and rework), as well as any cells which have more than 5% Giveaway. We will also color cells yellow when Giveaway is between 2% and 5%.

Note that this guide uses hexadecimal values to represent colors. Any valid HTML color will work.

Begin by calculating the color:

const giveaway = ((mean - packageWeight) / packageWeight) * 100;
let color = undefined;
if (giveaway < 0 || giveaway > 5) {
   // Red
   color = '#E30000';
} else if (giveaway > 2) {
   // Yellow
   color = '#E3E300'
}

Next, set the color on the value:

row.customValues.giveaway = {
   value: `${giveaway.toFixed(2)}%`,
   color: color
};

Exercise

On your own, add an additional columns which calculates how much this Giveaway costs. Doing this will require:

  • The total number of Parts produced in the time frame you're looking at.
  • The cost per weight.

If this is not data that you possess, add additional functions which perform a static lookup for each Part.

Testing the Dashboard

Save and View the Dashboard. If you have not previously saved the Dashboard, fill in the Name overlay with Giveaway. The Dashboard should load with a Stats Grid showing the overpack for each Part.

A Dashboard view with the current Stats Grid.

Final Code

const statsGrid = gsApi.dashboard.statsGrid('item 1');
gsApi.dashboard.onReady(async () => {
    await statsGrid.updateProperties({
        customColumns: [{
            id: 'giveaway',
            heading: 'Giveaway'
        }]
    });
});

statsGrid.onBeforeDraw(async (e) => {
    for (let i = 0; i < e.data.rows.length; i++) {
        const row = e.data.rows[i];
        const value = row.values[0];
        if (value.dataType !== 'spc') {
            return;
        }        

        const characteristic = value.characteristic;
        const mean = value.stats.mean?.value;
        const packageWeight = characteristic.targetX;

        if (!packageWeight || typeof mean !== 'number') {
            continue;
        }

        const giveaway = ((mean - packageWeight) / packageWeight) * 100;
        let color = undefined;
        if (giveaway < 0 || giveaway > 5) {
            // Red
            color = '#E30000';
        } else if (giveaway > 2) {
            color = '#E3E300'
        }
        row.customValues.giveaway = {
            value: `${giveaway.toFixed(2)}%`,
            color: color
        };
    }
});