Skip to content

Commit fa6f6d6

Browse files
committed
Add static helpers
1 parent 1f38c6d commit fa6f6d6

File tree

4 files changed

+350
-0
lines changed

4 files changed

+350
-0
lines changed

src/Helpers/Czech.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mathematicator\Engine\Helper;
6+
7+
8+
use Mathematicator\Engine\MathematicatorException;
9+
use Nette\StaticClass;
10+
11+
class Czech
12+
{
13+
14+
use StaticClass;
15+
16+
/**
17+
* Format number and string by count of items by czech grammar.
18+
*
19+
* inflection($count, ['zájezd', 'zájezdy', 'zájezdů']) => 1 zájezd, 3 zájezdy, 24 zájezdů
20+
*
21+
* @param int $number
22+
* @param string[] $parameters
23+
* @return string
24+
* @throws MathematicatorException
25+
*/
26+
public static function inflection(int $number, array $parameters): string
27+
{
28+
$numberTxt = number_format($number, 0, '.', ' ');
29+
$parameters = Safe::strictScalarType($parameters);
30+
31+
if (!isset($parameters[0], $parameters[1], $parameters[2])) {
32+
throw new MathematicatorException(
33+
'Parameter [0, 1, 2] does not set. Given: ["' . implode('", "', $parameters) . '"].'
34+
);
35+
}
36+
37+
[$for1, $for234, $forOthers] = $parameters;
38+
39+
if (!$number) {
40+
$result = '0 ' . $forOthers;
41+
} elseif ($number === 1) {
42+
$result = '1 ' . $for1;
43+
} elseif ($number >= 2 && $number <= 4) {
44+
$result = $numberTxt . ' ' . $for234;
45+
} else {
46+
$result = $numberTxt . ' ' . $forOthers;
47+
}
48+
49+
return $result;
50+
}
51+
52+
53+
}

src/Helpers/DateTime.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mathematicator\Engine\Helper;
6+
7+
8+
use Mathematicator\Engine\MathematicatorException;
9+
use Nette\StaticClass;
10+
11+
class DateTime
12+
{
13+
14+
use StaticClass;
15+
16+
/**
17+
* Format datetime to "Y-m-d H:i:s", if null return current datetime.
18+
*
19+
* @param int|null $timestamp
20+
* @return string (Y-m-d H:i:s)
21+
*/
22+
public static function getDateTimeIso(int $timestamp = null): string
23+
{
24+
return date('Y-m-d H:i:s', $timestamp ?? \time());
25+
}
26+
27+
28+
/**
29+
* @param int $time
30+
* @param bool $moreAccurate
31+
* @param string $lang [cz, sk, en]
32+
* @return string
33+
* @throws MathematicatorException
34+
*/
35+
public static function formatTimeAgo(int $time, bool $moreAccurate = true, string $lang = 'cz'): string
36+
{
37+
if ($lang === 'cz') {
38+
$labels = [
39+
['sekunda', 'sekundy', 'sekund'],
40+
['minuta', 'minuty', 'minut'],
41+
['hodina', 'hodiny', 'hodin'],
42+
['den', 'dny', 'dní'],
43+
['měsíc', 'měsíce', 'měsíců'],
44+
['rok', 'roky', 'let'],
45+
];
46+
} elseif ($lang === 'sk') {
47+
$labels = [
48+
['sekunda', 'sekundy', 'sekúnd'],
49+
['minúta', 'minúty', 'minút'],
50+
['hodina', 'hodiny', 'hodín'],
51+
['deň', 'dni', 'dní'],
52+
['mesiac', 'mesiace', 'mesiacov'],
53+
['rok', 'roky', 'rokov'],
54+
];
55+
} elseif ($lang === 'en') {
56+
$labels = ['second', 'minute', 'hour', 'day', 'month', 'year'];
57+
} else {
58+
throw new MathematicatorException('Unsupported lang "' . $lang . '" (supported languages: cz/sk/en)');
59+
}
60+
61+
$currentTime = time();
62+
$diff = $currentTime - $time;
63+
$no = 0;
64+
$lengths = [1, 60, 3600, 86400, 2630880, 31570560];
65+
$v = \count($lengths) - 1;
66+
67+
for (true; ($v >= 0) && (($no = $diff / $lengths[$v]) <= 1); true) {
68+
$v--;
69+
}
70+
71+
if ($v < 0) {
72+
$v = 0;
73+
}
74+
75+
$x = $currentTime - ($diff % $lengths[$v]);
76+
$no = (int) floor($no);
77+
$label = null;
78+
79+
if (isset($labels[$v]) && \is_string($labels[$v])) {
80+
$label = $labels[$v];
81+
if ($lang === 'en' && $no !== 1) {
82+
$label .= 's';
83+
}
84+
} elseif (\is_array($labels[$v])) {
85+
if ($no === 1) {
86+
$label = $labels[$v][0];
87+
} elseif ($no >= 2 && $no <= 4) {
88+
$label = $labels[$v][1];
89+
} else {
90+
$label = $labels[$v][2];
91+
}
92+
}
93+
94+
$result = $no . ' ' . $label . ' ';
95+
if ($moreAccurate && ($v >= 1) && (($currentTime - $x) > 0)) {
96+
$result .= self::formatTimeAgo($x, false, $lang);
97+
}
98+
99+
return trim($result);
100+
}
101+
102+
}

src/Helpers/Safe.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mathematicator\Engine\Helper;
6+
7+
8+
use Nette\StaticClass;
9+
10+
class Safe
11+
{
12+
13+
use StaticClass;
14+
15+
/**
16+
* Convert dirty haystack to scalar haystack. If object implements __toString(), it will be called automatically.
17+
*
18+
* @param mixed $haystack
19+
* @param bool $rewriteObjectsToString
20+
* @return mixed
21+
*/
22+
public static function strictScalarType($haystack, bool $rewriteObjectsToString = true)
23+
{
24+
if (\is_array($haystack)) {
25+
$return = [];
26+
27+
foreach ($haystack as $key => $value) {
28+
$return[$key] = self::strictScalarType($value, $rewriteObjectsToString);
29+
}
30+
31+
return $return;
32+
}
33+
34+
if (\is_scalar($haystack)) {
35+
return $haystack;
36+
}
37+
38+
if (\is_object($haystack)) {
39+
if ($rewriteObjectsToString === true && method_exists($haystack, '__toString')) {
40+
return (string) $haystack;
41+
}
42+
43+
return get_class($haystack);
44+
}
45+
46+
return $haystack;
47+
}
48+
49+
50+
}

src/Helpers/Terminal.php

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Mathematicator\Engine\Helper;
6+
7+
8+
use Mathematicator\Engine\MathematicatorException;
9+
use Nette\StaticClass;
10+
11+
class Terminal
12+
{
13+
14+
use StaticClass;
15+
16+
/**
17+
* @var int
18+
*/
19+
private static $staticTtl = 0;
20+
21+
/**
22+
* Render code snippet to Terminal.
23+
*
24+
* @param string $path
25+
* @param int|null $line -> if not null mark selected line by red color
26+
*/
27+
public static function code(string $path, int $line = null): void
28+
{
29+
echo "\n" . $path . ($line === null ? '' : ' [on line ' . $line . ']') . "\n\n";
30+
if (\is_file($path)) {
31+
echo '----- file -----' . "\n";
32+
$file = str_replace(["\r\n", "\r"], "\n", (string) file_get_contents($path));
33+
$fileParser = explode("\n", $file);
34+
$start = $line > 8 ? $line - 8 : 0;
35+
36+
for ($i = $start; $i <= $start + 15; $i++) {
37+
if (!isset($fileParser[$i])) {
38+
break;
39+
}
40+
41+
$currentLine = $i + 1;
42+
$highlight = $line === $currentLine;
43+
44+
echo ($highlight ? "\e[1;37m\e[41m" : "\e[100m")
45+
. str_pad(' ' . $currentLine . ': ', 6, ' ') . ($highlight ? '' : "\e[0m")
46+
. str_replace("\t", ' ', $fileParser[$i])
47+
. ($highlight ? "\e[0m" : '')
48+
. "\n";
49+
}
50+
51+
echo '----- file -----' . "\n\n";
52+
}
53+
}
54+
55+
/**
56+
* Ask question in Terminal and return user answer (string or null if empty).
57+
*
58+
* Function will be asked since user give valid answer.
59+
*
60+
* @param string $question -> only display to user
61+
* @param string[]|null $possibilities -> if empty, answer can be every valid string or null.
62+
* @return string|null -> null if empty answer
63+
* @throws MathematicatorException
64+
*/
65+
public static function ask(string $question, ?array $possibilities = null): ?string
66+
{
67+
self::$staticTtl = 0;
68+
69+
echo "\n" . str_repeat('-', 100) . "\n";
70+
71+
if ($possibilities !== [] && $possibilities !== null) {
72+
$renderPossibilities = static function (array $possibilities): string {
73+
$return = '';
74+
$containsNull = false;
75+
76+
foreach ($possibilities as $possibility) {
77+
if ($possibility !== null) {
78+
$return .= ($return === '' ? '' : '", "') . $possibility;
79+
} elseif ($containsNull === false) {
80+
$containsNull = true;
81+
}
82+
}
83+
84+
return 'Possible values: "' . $return . '"' . ($containsNull ? ' or press ENTER' : '') . '.';
85+
};
86+
87+
echo $renderPossibilities($possibilities) . "\n";
88+
}
89+
90+
echo 'Q: ' . trim($question) . "\n" . 'A: ';
91+
92+
$fOpen = fopen('php://stdin', 'rb');
93+
94+
if (\is_resource($fOpen) === false) {
95+
throw new MathematicatorException('Problem with opening "php://stdin".');
96+
}
97+
98+
$input = trim((string) fgets($fOpen));
99+
echo "\n";
100+
101+
$input = $input === '' ? null : $input;
102+
103+
if ($possibilities !== [] && $possibilities !== null) {
104+
if (\in_array($input, $possibilities, true)) {
105+
return $input;
106+
}
107+
108+
self::renderError('!!! Invalid answer !!!');
109+
self::$staticTtl++;
110+
111+
if (self::$staticTtl > 16) {
112+
throw new MathematicatorException(
113+
'The maximum invalid response limit was exceeded. Current limit: ' . self::$staticTtl
114+
);
115+
}
116+
117+
return self::ask($question, $possibilities);
118+
}
119+
120+
return $input;
121+
}
122+
123+
/**
124+
* Render red block with error message.
125+
*
126+
* @param string $message
127+
*/
128+
public static function renderError(string $message): void
129+
{
130+
echo "\033[1;37m\033[41m";
131+
132+
for ($i = 0; $i < 100; $i++) {
133+
echo ' ';
134+
}
135+
136+
echo "\n" . str_pad(' ' . $message . ' ', 100) . "\n";
137+
138+
for ($i = 0; $i < 100; $i++) {
139+
echo ' ';
140+
}
141+
142+
echo "\033[0m";
143+
}
144+
145+
}

0 commit comments

Comments
 (0)