1<?php 2/** 3 * webtrees: online genealogy 4 * Copyright (C) 2019 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\Service\CenturyService; 22use Fisharebest\Webtrees\Tree; 23use Illuminate\Database\Capsule\Manager as DB; 24use Illuminate\Database\Query\Expression; 25use Illuminate\Database\Query\JoinClause; 26use stdClass; 27 28/** 29 * A chart showing the average age of individuals related to the death century. 30 */ 31class ChartAge 32{ 33 /** 34 * @var Tree 35 */ 36 private $tree; 37 38 /** 39 * @var CenturyService 40 */ 41 private $century_service; 42 43 /** 44 * Constructor. 45 * 46 * @param Tree $tree 47 */ 48 public function __construct(Tree $tree) 49 { 50 $this->tree = $tree; 51 $this->century_service = new CenturyService(); 52 } 53 54 /** 55 * Returns the related database records. 56 * 57 * @return stdClass[] 58 */ 59 private function queryRecords(): array 60 { 61 $prefix = DB::connection()->getTablePrefix(); 62 63 return DB::table('individuals') 64 ->select([ 65 new Expression('ROUND(AVG(' . $prefix . 'death.d_julianday2 - ' . $prefix . 'birth.d_julianday1) / 365.25, 1) AS age'), 66 new Expression('ROUND((' . $prefix . 'death.d_year + 49) / 100) AS century'), 67 'i_sex AS sex' 68 ]) 69 ->join('dates AS birth', static function (JoinClause $join): void { 70 $join 71 ->on('birth.d_file', '=', 'i_file') 72 ->on('birth.d_gid', '=', 'i_id'); 73 }) 74 ->join('dates AS death', static function (JoinClause $join): void { 75 $join 76 ->on('death.d_file', '=', 'i_file') 77 ->on('death.d_gid', '=', 'i_id'); 78 }) 79 ->where('i_file', '=', $this->tree->id()) 80 ->where('birth.d_fact', '=', 'BIRT') 81 ->where('death.d_fact', '=', 'DEAT') 82 ->whereIn('birth.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 83 ->whereIn('death.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 84 ->whereColumn('death.d_julianday1', '>=', 'birth.d_julianday2') 85 ->where('birth.d_julianday2', '<>', 0) 86 ->groupBy(['century', 'sex']) 87 ->orderBy('century') 88 ->orderBy('sex') 89 ->get() 90 ->all(); 91 } 92 93 /** 94 * General query on ages. 95 * 96 * @return string 97 */ 98 public function chartAge(): string 99 { 100 $out = []; 101 foreach ($this->queryRecords() as $record) { 102 $out[(int) $record->century][$record->sex] = (float) $record->age; 103 } 104 105 $data = [ 106 [ 107 I18N::translate('Century'), 108 I18N::translate('Males'), 109 I18N::translate('Females'), 110 I18N::translate('Average age'), 111 ] 112 ]; 113 114 foreach ($out as $century => $values) { 115 $female_age = $values['F'] ?? 0; 116 $male_age = $values['M'] ?? 0; 117 $average_age = ($female_age + $male_age) / 2.0; 118 119 $data[] = [ 120 $this->century_service->centuryName($century), 121 $male_age, 122 $female_age, 123 round($average_age, 1), 124 ]; 125 } 126 127 $chart_title = I18N::translate('Average age related to death century'); 128 $chart_options = [ 129 'title' => $chart_title, 130 'subtitle' => I18N::translate('Average age at death'), 131 'vAxis' => [ 132 'title' => I18N::translate('Age'), 133 ], 134 'hAxis' => [ 135 'title' => I18N::translate('Century'), 136 ], 137 'colors' => [ 138 '#84beff', 139 '#ffd1dc', 140 '#ff0000', 141 ], 142 ]; 143 144 return view( 145 'statistics/other/charts/combo', 146 [ 147 'data' => $data, 148 'chart_options' => $chart_options, 149 'chart_title' => $chart_title, 150 ] 151 ); 152 } 153} 154