'Dynamic position of progress bars based on results for multiple sections

I have a rather interesting question here that I've been stumped on for awhile. We're playing with dynamic results that we'd like to indicate on reports.

We'd like to display a "marker" (darker section) where the end users result ends up in. These are Pathology Results and an example would look like the following:

showing result..

For the above example, the details are as follows:

  • RESULT: 128
  • LOW RANGE: 115
  • HIGH RANGE: 165

As you can see above in the example graph there are 3 sections:

  • Yellow (LOW): indicates a result that is below normal/outside of the lower range.
  • Green (GOOD): to indicate a result that is good and within optimal ranges.
  • Red (HIGH): indicates a result that is above normal/outside of the upper range.

Another example of what we're trying to achieve would look like the following - however this is all done statically at current: enter image description here

Notes

  • We already now which "section" it'll be in, but we need to create functionality to indicate "where" in that section it would end up, preferably percentage based.

For the Low range we've come up with a simple (pseudo) solution as follows:

$result = 1.15;
$rangeLow = 2.0;

function getLowRangePercentile($result, $rangeLow) {
    // number format as we only want the percentile, i.e. 0.1, 0.5, 0.6, etc...
    // NOT: 0.45, 0.98, etc...
    return number_format($result / $rangeLow, 1);
}

For the High range we've used a similar solution:

$result = 364;
$rangeHigh = 360;

function getHighRangePercentile($result, $rangeHigh) {
    return number_format($rangeHigh / $result, 2);
}

There are inherent issues with this as some results and/or ranges could have larger numbers causing the percentiles to be highly specific, i.e. 99% in the above example...


We need to be able to generate HTML (Bootstrap) progress bar's as follows, with the "indicator" being 2% bar of the darker colour for the section it ends up in..

<div class="progress">
    <div class="progress-bar bg-light-warning" role="progressbar" style="width: 23%" aria-valuenow="23" aria-valuemin="0" aria-valuemax="100"></div>
    <!-- START "INDICATOR" marker -->
    <div class="progress-bar bg-warning" role="progressbar" style="width: 2%" aria-valuenow="2" aria-valuemin="0" aria-valuemax="100"></div>
     <!-- END "INDICATOR" marker -->
    <div class="progress-bar bg-light-success" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
    <div class="progress-bar bg-light-danger" role="progressbar" style="width: 25%" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100"></div>
</div>

NOTE

The sections are divided up as follows:

-----------------------------------------
|   LOW   |      NORMAL      |   HIGH   |
-----------------------------------------
|   25%   |        50%       |    25%   |
-----------------------------------------

Would love some ideas in terms of sorting this out efficiently for the low/high sections, along with the "good/normal" section (as below).

Which leaves us stumped on how to work on the "good" result section currently. We've currently thought of doing the following:

  • Finding out which "range" the result is closer to
  • Running a similar calculation to the other sections specified by the ranges
  • Generating the progress bars from there...

Thanks.



Solution 1:[1]

Your question is very confusing lol, but I'd try something like this.

Assuming you want a consistent scale e.g. 0-25% is NOT equal to 0-115, I'd do the following:

  1. Don't mess around with trying to balance four progress bars, just use three for the ranges and use an absolute positioned div as the marker.

  2. Do some maths, let's use your first example (res: 128, min: 115, max: 165):

    1. Since max - min = 50% of the bar, divide that by 50 to get 1%

      • 165 - 115 = 50, 50 / 50 = 1
    2. We need to get the lowest value that can fit on the graph so we can adjust the position of the result:

      • 115 - 1 * 25 = 90
    3. Now that we know the scaling and the smallest value that can fit on the bar, subtract our smallest value from res, and divide by the 1% to adjust for scaling:

      • 128 - 90 = 38, 38 / 1 = 38%

Then just use that as the position of the div e.g. using the left property.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Piotr Płaczek