Truncator   A
last analyzed

Complexity

Total Complexity 22

Size/Duplication

Total Lines 135
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 49
dl 0
loc 135
rs 10
c 0
b 0
f 0
wmc 22

6 Methods

Rating   Name   Duplication   Size   Complexity  
B pad() 0 17 7
B truncate() 0 32 7
A outerBound() 0 9 3
A compareToLimit() 0 9 3
A maxBound() 0 5 1
A minBound() 0 5 1
1
<?php
2
3
namespace Vctls\IntervalGraph;
4
5
6
use InvalidArgumentException;
7
8
/**
9
 * Truncate an array of intervals according to a low and high bound.
10
 *
11
 * @package Vctls\IntervalGraph
12
 */
13
class Truncator implements TruncatorInterface
14
{
15
    /**
16
     * Truncate all intervals to the given lower and upper limits.
17
     *
18
     * @param array $intervals
19
     * @param mixed $lowerLimit
20
     * @param mixed $upperLimit
21
     * @param bool $padding Add null value intervals between the bounds and the first and last bounds.
22
     * @return array
23
     */
24
    public static function truncate(array $intervals, $lowerLimit = null, $upperLimit = null, $padding = false): array
25
    {
26
        $limits = [
27
            0 => $lowerLimit,
28
            1 => $upperLimit
29
        ];
30
        foreach ($limits as $type => $limit) {
31
            if (isset($limit)) {
32
                foreach ($intervals as $key => $interval) {
33
                    if (self::compareToLimit($interval[$type], $limit, $type)) {
34
                        if (self::compareToLimit($interval[(int)!$type], $limit, $type)) {
35
                            // If both bounds are beyond the limit, set the interval to false for removal.
36
                            $intervals[$key] = false;
37
                        } else {
38
                            // If only the outer bound is beyond the limit, set it to the limit value.
39
                            $intervals[$key][$type] = $limit;
40
                        }
41
                    }
42
                }
43
44
                // Remove false elements.
45
                $intervals = array_filter($intervals);
46
47
                // If padding is required and a limit is set and is beyond the limit,
48
                // add a valueless interval between that bound and the limit.
49
                if ($padding) {
50
                    self::pad($intervals, $limit, $type);
51
                }
52
            }
53
        }
54
55
        return $intervals;
56
    }
57
58
    /**
59
     * Pad the interval array if needed, from left OR right depending on the type.
60
     *
61
     * @param $intervals
62
     * @param $value
63
     * @param $type
64
     */
65
    public static function pad(&$intervals, $value, $type): void
66
    {
67
        switch ($type) {
68
            case 0:
69
                $bound = self::minBound($intervals);
70
                if (isset($bound) && $bound > $value) {
71
                    array_unshift($intervals, [$value, $bound]);
72
                }
73
                break;
74
            case 1:
75
                $bound = self::maxBound($intervals);
76
                if (isset($bound) && $bound < $value) {
77
                    $intervals[] = [$bound, $value];
78
                }
79
                break;
80
            default:
81
                throw new InvalidArgumentException('Type should be 0 (low padding) or 1 (high padding).');
82
        }
83
    }
84
85
    /**
86
     * Return the minimum or maximum bound depending on the type.
87
     *
88
     * @param $intervals
89
     * @param int $type 0 (min) or 1 (max)
90
     * @return mixed
91
     */
92
    public static function outerBound($intervals, int $type)
93
    {
94
        switch ($type) {
95
            case 0:
96
                return self::minBound($intervals);
97
            case 1:
98
                return self::maxBound($intervals);
99
            default:
100
                throw new InvalidArgumentException('Type must be 0 (min) or 1 (max)');
101
        }
102
    }
103
104
    /**
105
     * Get the minimum bound in an array of intervals.
106
     *
107
     * @param $intervals
108
     * @return mixed
109
     */
110
    public static function minBound($intervals)
111
    {
112
        $bounds = array_column($intervals, 0);
113
        sort($bounds);
114
        return array_shift($bounds);
115
    }
116
117
    /**
118
     * Get the maximum bound in an array of intervals.
119
     *
120
     * @param $intervals
121
     * @return mixed
122
     */
123
    public static function maxBound($intervals)
124
    {
125
        $bounds = array_column($intervals, 1);
126
        sort($bounds);
127
        return array_pop($bounds);
128
    }
129
130
    /**
131
     * Checks if the value is inferior to a lower (type 0) limit,
132
     * or superior to an upper (type 1) limit.
133
     *
134
     * @param $value
135
     * @param $limit
136
     * @param int $type 0 (lower limit) or 1 (upper limit)
137
     * @return bool
138
     */
139
    public static function compareToLimit($value, $limit, int $type): bool
140
    {
141
        switch ($type) {
142
            case 0 :
143
                return $value < $limit;
144
            case 1 :
145
                return $value > $limit;
146
            default :
147
                throw new InvalidArgumentException('Limit type must be 0 (lower) or 1 (upper)');
148
        }
149
    }
150
}
151