Skip to content

Commit a4f2849

Browse files
committed
Request-rate bug-fixes
- Multiple ratios: Use the largest rate - Rendering: Reverse ratio->rate calculation no longer fails when converting from float
1 parent 64c6827 commit a4f2849

6 files changed

Lines changed: 63 additions & 66 deletions

File tree

src/Client/Directives/RequestRateClient.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public function getValue($timestamp = null)
6565
{
6666
$values = $this->determine(is_int($timestamp) ? $timestamp : time());
6767
if (count($values) > 0 &&
68-
($rate = min($values)) > 0
68+
($rate = max($values)) > 0
6969
) {
7070
return $rate;
7171
}

src/Import.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private function buildRequestRate($array)
196196
{
197197
$result = [];
198198
foreach ($array as $pair) {
199-
$string = self::DIRECTIVE_REQUEST_RATE . ':1/' . $pair['rate'] . 's';
199+
$string = self::DIRECTIVE_REQUEST_RATE . ':' . $pair['ratio'];
200200
if (isset($pair['from']) &&
201201
isset($pair['to'])
202202
) {

src/Parser/Directives/RequestRateParser.php

Lines changed: 50 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,23 @@ public function __construct($base)
6969
public function add($line)
7070
{
7171
$array = preg_split('/\s+/', $line, 2);
72+
$parts = array_map('trim', explode('/', $array[0]));
73+
if (count($parts) != 2) {
74+
return false;
75+
}
76+
$unit = strtolower(substr(preg_replace('/[^A-Za-z]/', '', filter_var($parts[1], FILTER_SANITIZE_STRING)), 0, 1));
77+
$multiplier = isset($this->units[$unit]) ? $this->units[$unit] : 1;
78+
79+
$rate = (int)abs(filter_var($parts[0], FILTER_SANITIZE_NUMBER_INT));
80+
$time = $multiplier * (int)abs(filter_var($parts[1], FILTER_SANITIZE_NUMBER_INT));
81+
7282
$result = [
73-
'rate' => $this->draftParseRate($array[0]),
83+
'rate' => $time / $rate,
84+
'ratio' => $this->getRatio($rate, $time),
7485
'from' => null,
7586
'to' => null,
7687
];
77-
if ($result['rate'] === false) {
78-
return false;
79-
} elseif (!empty($array[1]) &&
88+
if (!empty($array[1]) &&
8089
($times = $this->draftParseTime($array[1])) !== false
8190
) {
8291
$result = array_merge($result, $times);
@@ -86,23 +95,44 @@ public function add($line)
8695
}
8796

8897
/**
89-
* Client rate as specified in the `Robot exclusion standard` version 2.0 draft
90-
* rate = numDocuments / timeUnit
91-
* @link http://www.conman.org/people/spc/robots2.html#format.directives.request-rate
98+
* Get ratio string
9299
*
93-
* @param string $string
94-
* @return float|int|false
100+
* @param int $rate
101+
* @param int $time
102+
* @return string
95103
*/
96-
private function draftParseRate($string)
104+
private function getRatio($rate, $time)
97105
{
98-
$parts = array_map('trim', explode('/', $string));
99-
if (count($parts) != 2) {
100-
return false;
106+
$gcd = $this->getGCD($rate, $time);
107+
$requests = $rate / $gcd;
108+
$time = $time / $gcd;
109+
$suffix = 's';
110+
foreach ($this->units as $unit => $sec) {
111+
if ($time % $sec === 0) {
112+
$suffix = $unit;
113+
$time /= $sec;
114+
break;
115+
}
101116
}
102-
$unit = strtolower(substr(preg_replace('/[^A-Za-z]/', '', filter_var($parts[1], FILTER_SANITIZE_STRING)), 0, 1));
103-
$multiplier = isset($this->units[$unit]) ? $this->units[$unit] : 1;
104-
$rate = abs(filter_var($parts[1], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)) * $multiplier / abs(filter_var($parts[0], FILTER_SANITIZE_NUMBER_INT));
105-
return $rate > 0 ? $rate : false;
117+
return $requests . '/' . $time . $suffix;
118+
}
119+
120+
/**
121+
* Returns the greatest common divisor of two integers using the Euclidean algorithm.
122+
*
123+
* @param int $a
124+
* @param int $b
125+
* @return int
126+
*/
127+
private function getGCD($a, $b)
128+
{
129+
if (extension_loaded('gmp')) {
130+
return gmp_intval(gmp_gcd((string)$a, (string)$b));
131+
}
132+
$large = $a > $b ? $a : $b;
133+
$small = $a > $b ? $b : $a;
134+
$remainder = $large % $small;
135+
return 0 === $remainder ? $small : $this->getGCD($small, $remainder);
106136
}
107137

108138
/**
@@ -145,58 +175,14 @@ public function render(RenderHandler $handler)
145175
{
146176
$this->sort();
147177
foreach ($this->requestRates as $array) {
148-
$multiplyFactor = $this->decimalMultiplier($array['rate']);
149-
$multipliedRate = $array['rate'] * $multiplyFactor;
150-
$gcd = $this->getGCD($multiplyFactor, $multipliedRate);
151-
$requests = $multiplyFactor / $gcd;
152-
$time = $multipliedRate / $gcd;
153-
$suffix = 's';
154-
foreach ($this->units as $unit => $sec) {
155-
if ($time % $sec === 0) {
156-
$suffix = $unit;
157-
$time /= $sec;
158-
break;
159-
}
160-
}
178+
$time = '';
161179
if (isset($array['from']) &&
162180
isset($array['to'])
163181
) {
164-
$suffix .= ' ' . $array['from'] . '-' . $array['to'];
182+
$time .= ' ' . $array['from'] . '-' . $array['to'];
165183
}
166-
$handler->add(self::DIRECTIVE_REQUEST_RATE, $requests . '/' . $time . $suffix);
184+
$handler->add(self::DIRECTIVE_REQUEST_RATE, $array['ratio'] . $time);
167185
}
168186
return true;
169187
}
170-
171-
/**
172-
* @param int|float $value
173-
* @return int
174-
*/
175-
private function decimalMultiplier($value)
176-
{
177-
$multiplier = 1;
178-
while (fmod($value, 1) != 0) {
179-
$value *= 10;
180-
$multiplier *= 10;
181-
}
182-
return $multiplier;
183-
}
184-
185-
/**
186-
* Returns the greatest common divisor of two integers using the Euclidean algorithm.
187-
*
188-
* @param int $a
189-
* @param int $b
190-
* @return int
191-
*/
192-
private function getGCD($a, $b)
193-
{
194-
if (extension_loaded('gmp')) {
195-
return gmp_intval(gmp_gcd((string)$a, (string)$b));
196-
}
197-
$large = $a > $b ? $a : $b;
198-
$small = $a > $b ? $b : $a;
199-
$remainder = $large % $small;
200-
return 0 === $remainder ? $small : $this->getGCD($small, $remainder);
201-
}
202188
}

tests/ExportTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,13 @@ public function generateDataForTest()
115115
'request-rate' => [
116116
[
117117
'rate' => 9,
118+
'ratio' => '1/9s',
118119
'from' => '0900',
119120
'to' => '1500',
120121
],
121122
[
122123
'rate' => 3.6,
124+
'ratio' => '5/18s',
123125
'from' => null,
124126
'to' => null,
125127
],

tests/ImportTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,13 @@ public function generateDataForTest()
7171
'request-rate' => [
7272
[
7373
'rate' => 9,
74+
'ratio' => '1/9s',
7475
'from' => '0900',
7576
'to' => '1500',
7677
],
7778
[
7879
'rate' => 3.6,
80+
'ratio' => '5/18s',
7981
'from' => '0900',
8082
],
8183
],
@@ -128,11 +130,13 @@ public function generateDataForTest()
128130
'request-rate' => [
129131
[
130132
'rate' => 9,
133+
'ratio' => '1/9s',
131134
'from' => '0900',
132135
'to' => '1500',
133136
],
134137
[
135138
'rate' => 3.6,
139+
'ratio' => '5/18s',
136140
'from' => null,
137141
'to' => null,
138142
],

tests/RequestRateTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,26 +64,31 @@ public function generateDataForTest()
6464
[
6565
[
6666
'rate' => 3600,
67+
'ratio' => '1/1h',
6768
'from' => '0230',
6869
'to' => '0330',
6970
],
7071
[
7172
'rate' => 37.5,
73+
'ratio' => '2/75s',
7274
'from' => null,
7375
'to' => null,
7476
],
7577
[
7678
'rate' => 15,
79+
'ratio' => '1/15s',
7780
'from' => '0700',
7881
'to' => '2100',
7982
],
8083
[
8184
'rate' => 9,
85+
'ratio' => '1/9s',
8286
'from' => '0900',
8387
'to' => '1500',
8488
],
8589
[
8690
'rate' => 1,
91+
'ratio' => '1/1s',
8792
'from' => '2200',
8893
'to' => '0600',
8994
],

0 commit comments

Comments
 (0)