1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2018 webtrees development team 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16declare(strict_types=1); 17 18namespace Fisharebest\Webtrees\Statistics\Google; 19 20use Fisharebest\Webtrees\I18N; 21use Fisharebest\Webtrees\Statistics\AbstractGoogle; 22use Fisharebest\Webtrees\Statistics\Helper\Century; 23use Fisharebest\Webtrees\Tree; 24 25/** 26 * 27 */ 28class ChartAge extends AbstractGoogle 29{ 30 /** 31 * @var Tree 32 */ 33 private $tree; 34 35 /** 36 * @var Century 37 */ 38 private $centuryHelper; 39 40 /** 41 * Constructor. 42 * 43 * @param Tree $tree 44 */ 45 public function __construct(Tree $tree) 46 { 47 $this->tree = $tree; 48 $this->centuryHelper = new Century(); 49 } 50 51 /** 52 * Returns the related database records. 53 * 54 * @return \stdClass[] 55 */ 56 private function queryRecords(): array 57 { 58 return $this->runSql( 59 'SELECT' 60 . ' ROUND(AVG(death.d_julianday2-birth.d_julianday1)/365.25,1) AS age,' 61 . ' FLOOR(death.d_year/100+1) AS century,' 62 . ' i_sex AS sex' 63 . ' FROM' 64 . ' `##dates` AS death,' 65 . ' `##dates` AS birth,' 66 . ' `##individuals` AS indi' 67 . ' WHERE' 68 . ' indi.i_id=birth.d_gid AND' 69 . ' birth.d_gid=death.d_gid AND' 70 . ' death.d_file=' . $this->tree->id() . ' AND' 71 . ' birth.d_file=death.d_file AND' 72 . ' birth.d_file=indi.i_file AND' 73 . " birth.d_fact='BIRT' AND" 74 . " death.d_fact='DEAT' AND" 75 . ' birth.d_julianday1<>0 AND' 76 . " birth.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND" 77 . " death.d_type IN ('@#DGREGORIAN@', '@#DJULIAN@') AND" 78 . ' death.d_julianday1>birth.d_julianday2' 79 . ' GROUP BY century, sex ORDER BY century, sex' 80 ); 81 } 82 83 /** 84 * General query on ages. 85 * 86 * @param string $size 87 * 88 * @return string 89 */ 90 public function chartAge(string $size = '230x250'): string 91 { 92 $sizes = explode('x', $size); 93 $rows = $this->queryRecords(); 94 95 if (empty($rows)) { 96 return ''; 97 } 98 99 $chxl = '0:|'; 100 $countsm = ''; 101 $countsf = ''; 102 $countsa = ''; 103 $out = []; 104 105 foreach ($rows as $values) { 106 $out[(int) $values->century][$values->sex] = $values->age; 107 } 108 109 foreach ($out as $century => $values) { 110 if ($sizes[0] < 980) { 111 $sizes[0] += 50; 112 } 113 $chxl .= $this->centuryHelper->centuryName($century) . '|'; 114 115 $female_age = $values['F'] ?? 0; 116 $male_age = $values['M'] ?? 0; 117 $average_age = $female_age + $male_age; 118 119 if ($female_age > 0 && $male_age > 0) { 120 $average_age /= 2.0; 121 } 122 123 $countsf .= $female_age . ','; 124 $countsm .= $male_age . ','; 125 $countsa .= $average_age . ','; 126 } 127 128 $countsm = substr($countsm, 0, -1); 129 $countsf = substr($countsf, 0, -1); 130 $countsa = substr($countsa, 0, -1); 131 $chd = 't2:' . $countsm . '|' . $countsf . '|' . $countsa; 132 $decades = ''; 133 134 for ($i = 0; $i <= 100; $i += 10) { 135 $decades .= '|' . I18N::number($i); 136 } 137 138 $chxl .= '1:||' . I18N::translate('century') . '|2:' . $decades . '|3:||' . I18N::translate('Age') . '|'; 139 $title = I18N::translate('Average age related to death century'); 140 141 if (\count($rows) > 6 || mb_strlen($title) < 30) { 142 $chtt = $title; 143 } else { 144 $offset = 0; 145 $counter = []; 146 147 while ($offset = strpos($title, ' ', $offset + 1)) { 148 $counter[] = $offset; 149 } 150 151 $half = intdiv(\count($counter), 2); 152 $chtt = substr_replace($title, '|', $counter[$half], 1); 153 } 154 155 $chart_url = 'https://chart.googleapis.com/chart?cht=bvg&chs=' . $sizes[0] . 'x' . $sizes[1] 156 . '&chm=D,FF0000,2,0,3,1|N*f1*,000000,0,-1,11,1|N*f1*,000000,1,-1,11,1&chf=bg,s,ffffff00|c,s,ffffff00&chtt=' 157 . rawurlencode($chtt) . '&chd=' . $chd . '&chco=0000FF,FFA0CB,FF0000&chbh=20,3&chxt=x,x,y,y&chxl=' 158 . rawurlencode($chxl) . '&chdl=' 159 . rawurlencode(I18N::translate('Males') . '|' . I18N::translate('Females') . '|' . I18N::translate('Average age at death')); 160 161 return view( 162 'statistics/other/chart-google', 163 [ 164 'chart_title' => I18N::translate('Average age related to death century'), 165 'chart_url' => $chart_url, 166 'sizes' => $sizes, 167 ] 168 ); 169 } 170} 171