.
*/
declare(strict_types=1);
namespace Fisharebest\Webtrees;
use function array_column;
use function array_map;
use function array_sum;
use function array_unshift;
use function e;
use function hexdec;
use function ltrim;
use function round;
use function sprintf as sprintf1;
use function sprintf as sprintf2;
use function str_split;
use function strip_tags;
use function view;
readonly class StatisticsFormat
{
public function age(int $days): string
{
if ($days < 31) {
return I18N::plural('%s day', '%s days', $days, I18N::number($days));
}
if ($days < 365) {
$months = (int) ($days / 30.5);
return I18N::plural('%s month', '%s months', $months, I18N::number($months));
}
$years = (int) ($days / 365.25);
return I18N::plural('%s year', '%s years', $years, I18N::number($years));
}
/**
* Century name, English => 21st, Polish => XXI, etc.
*/
public function century(int $century): string
{
if ($century < 0) {
return I18N::translate('%s BCE', $this->century(-$century));
}
// The current chart engine (Google charts) can't handle markup
switch ($century) {
case 21:
return strip_tags(I18N::translateContext('CENTURY', '21st'));
case 20:
return strip_tags(I18N::translateContext('CENTURY', '20th'));
case 19:
return strip_tags(I18N::translateContext('CENTURY', '19th'));
case 18:
return strip_tags(I18N::translateContext('CENTURY', '18th'));
case 17:
return strip_tags(I18N::translateContext('CENTURY', '17th'));
case 16:
return strip_tags(I18N::translateContext('CENTURY', '16th'));
case 15:
return strip_tags(I18N::translateContext('CENTURY', '15th'));
case 14:
return strip_tags(I18N::translateContext('CENTURY', '14th'));
case 13:
return strip_tags(I18N::translateContext('CENTURY', '13th'));
case 12:
return strip_tags(I18N::translateContext('CENTURY', '12th'));
case 11:
return strip_tags(I18N::translateContext('CENTURY', '11th'));
case 10:
return strip_tags(I18N::translateContext('CENTURY', '10th'));
case 9:
return strip_tags(I18N::translateContext('CENTURY', '9th'));
case 8:
return strip_tags(I18N::translateContext('CENTURY', '8th'));
case 7:
return strip_tags(I18N::translateContext('CENTURY', '7th'));
case 6:
return strip_tags(I18N::translateContext('CENTURY', '6th'));
case 5:
return strip_tags(I18N::translateContext('CENTURY', '5th'));
case 4:
return strip_tags(I18N::translateContext('CENTURY', '4th'));
case 3:
return strip_tags(I18N::translateContext('CENTURY', '3rd'));
case 2:
return strip_tags(I18N::translateContext('CENTURY', '2nd'));
case 1:
return strip_tags(I18N::translateContext('CENTURY', '1st'));
default:
return ($century - 1) . '01-' . $century . '00';
}
}
public function hitCount(int $count): string
{
return view('statistics/hit-count', ['count' => $count]);
}
public function percentage(int $count, int $total, int $precision = 1): string
{
return $total !== 0 ? I18N::percentage($count / $total, $precision) : '';
}
/**
* @return array
*/
public function interpolateRgb(string $start_color, string $end_color, int $steps): array
{
if ($steps === 0) {
return [];
}
$s = $this->hexToRgb($start_color);
$e = $this->hexToRgb($end_color);
$colors = [];
$factor_r = ($e[0] - $s[0]) / $steps;
$factor_g = ($e[1] - $s[1]) / $steps;
$factor_b = ($e[2] - $s[2]) / $steps;
for ($x = 1; $x < $steps; ++$x) {
$red = (int) round($s[0] + $factor_r * $x);
$green = (int) round($s[1] + $factor_g * $x);
$blue = (int) round($s[2] + $factor_b * $x);
$colors[] = sprintf2('#%02x%02x%02x', $red, $green, $blue);
}
$colors[] = sprintf1('#%02x%02x%02x', $e[0], $e[1], $e[2]);
return $colors;
}
/**
* @return array
*/
private function hexToRgb(string $hex): array
{
return array_map(static fn (string $hex): int => (int) hexdec($hex), str_split(ltrim($hex, '#'), 2));
}
public function missing(): string
{
return I18N::translate('This information is not available.');
}
/**
* @param array $data
* @param array $colors
*/
public function pieChart(
array $data,
array $colors,
string $title,
string $category,
string $quantity,
bool $percentage = false
): string {
// Cannot display a pie chart if there is no data.
if (array_sum(array_column($data, 1)) === 0) {
return $this->missing();
}
// Google Charts require a header row.
array_unshift($data, [$category, $quantity]);
return view('statistics/other/charts/pie', [
'title' => $title,
'data' => $data,
'colors' => $colors,
'labeledValueText' => $percentage ? 'percentage' : 'value',
'language' => I18N::languageTag(),
]);
}
public function record(GedcomRecord|null $record): string
{
if ($record === null) {
return $this->missing();
}
if ($record->canShow()) {
return '' . $record->fullName() . '';
}
return $record->fullName();
}
}