1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees\Statistics\Google; 21 22use Fisharebest\Webtrees\I18N; 23use Fisharebest\Webtrees\Statistics\Service\ColorService; 24use Fisharebest\Webtrees\SurnameTradition\PolishSurnameTradition; 25use Fisharebest\Webtrees\SurnameTradition\SurnameTraditionInterface; 26 27use function array_sum; 28use function count; 29use function preg_replace; 30use function view; 31 32/** 33 * A chart showing the top surnames. 34 */ 35class ChartCommonSurname 36{ 37 private ColorService $color_service; 38 39 private SurnameTraditionInterface $surname_tradition; 40 41 /** 42 * @param ColorService $color_service 43 * @param SurnameTraditionInterface $surname_tradition 44 */ 45 public function __construct(ColorService $color_service, SurnameTraditionInterface $surname_tradition) 46 { 47 $this->surname_tradition = $surname_tradition; 48 $this->color_service = $color_service; 49 } 50 51 /** 52 * Count up the different versions of a name and returns the one with the most matches. Takes 53 * different surname traditions into account. 54 * 55 * @param array<string,int> $surns 56 * 57 * @return array{0:string,1:int} 58 */ 59 private function getTopNameAndCount(array $surns): array 60 { 61 $max_name = 0; 62 $count_per = 0; 63 $top_name = ''; 64 65 foreach ($surns as $spfxsurn => $count) { 66 $per = $count; 67 $count_per += $per; 68 69 // select most common surname from all variants 70 if ($per > $max_name) { 71 $max_name = $per; 72 $top_name = $spfxsurn; 73 } 74 } 75 76 if ($this->surname_tradition instanceof PolishSurnameTradition) { 77 // Most common surname should be in male variant (Kowalski, not Kowalska) 78 $top_name = preg_replace( 79 [ 80 '/ska$/', 81 '/cka$/', 82 '/dzka$/', 83 '/żka$/', 84 ], 85 [ 86 'ski', 87 'cki', 88 'dzki', 89 'żki', 90 ], 91 $top_name 92 ); 93 } 94 95 return [ 96 (string) $top_name, 97 $count_per 98 ]; 99 } 100 101 /** 102 * Create a chart of common surnames. 103 * 104 * @param int $tot_indi The total number of individuals 105 * @param array<array<int>> $all_surnames The list of common surnames 106 * @param string|null $color_from 107 * @param string|null $color_to 108 * 109 * @return string 110 */ 111 public function chartCommonSurnames( 112 int $tot_indi, 113 array $all_surnames, 114 string|null $color_from = null, 115 string $color_to = null 116 ): string { 117 $color_from ??= 'ffffff'; 118 $color_to ??= '84beff'; 119 120 $tot = 0; 121 foreach ($all_surnames as $surnames) { 122 $tot += array_sum($surnames); 123 } 124 125 $data = [ 126 [ 127 I18N::translate('Name'), 128 I18N::translate('Total') 129 ], 130 ]; 131 132 foreach ($all_surnames as $surns) { 133 $data[] = $this->getTopNameAndCount($surns); 134 } 135 136 $data[] = [ 137 I18N::translate('Other'), 138 $tot_indi - $tot 139 ]; 140 141 $colors = $this->color_service->interpolateRgb($color_from, $color_to, count($data) - 1); 142 143 return view('statistics/other/charts/pie', [ 144 'title' => null, 145 'data' => $data, 146 'colors' => $colors, 147 'language' => I18N::languageTag(), 148 ]); 149 } 150} 151