models/classes/runner/time/QtiTimeLine.php
protected function fixRange($range, $lastTimestamp = null)
    {
        $fixedRange = [];
        $last = null;
        $open = false;

        foreach ($range as $point) {
            if ($this->isStartPoint($point)) {              // start of range
                // the last range could be still open...
                if ($last && $open) {
                    $fixedRange[] = $this->cloneTimePoint($point, TimePoint::TYPE_END);
                }
                $open = true;
            } else if ($this->isEndPoint($point)) {         // end of range
                // this range could not be started...
                if (!$open) {
                    $fixedRange[] = $this->cloneTimePoint($last ? $last : $point, TimePoint::TYPE_START);
                }
                $open = false;
            }
            $fixedRange[] = $point;
            $last = $point;
        }

        // the last range could be still open...
        if ($last && $open) {
            $fixedRange[] = $this->cloneTimePoint($last, TimePoint::TYPE_END, $lastTimestamp);
        }
        
        return $fixedRange;
    }
protected function fixRange($range, $lastTimestamp = null)
    {
        $fixedRange = [];
        $last = null;
        $open = false;

        foreach ($range as $point) {
            if ($this->isStartPoint($point)) {              // start of range
                // the last range could be still open...
                if ($last && $open) {
                    $fixedRange[] = $this->cloneTimePoint($point, TimePoint::TYPE_END);
                }
                $open = true;
            } else if ($this->isEndPoint($point)) {         // end of range
                // this range could not be started...
                if (!$open) {
                    $fixedRange[] = $this->cloneTimePoint($last ? $last : $point, TimePoint::TYPE_START);
                }
                $open = false;
            }
            $fixedRange[] = $point;
            $last = $point;
        }

        // the last range could be still open...
        if ($last && $open) {
            $fixedRange[] = $this->cloneTimePoint($last, TimePoint::TYPE_END, $lastTimestamp);
        }
        
        return $fixedRange;
    }
Ensures the ranges are well formed. They should have been sorted before, otherwise the process won't work.
Tries to fix a range by adding missing points
@param array $range
@param float $lastTimestamp - An optional timestamp to apply on the last TimePoint if missing
@return array