18add1155SRico Sonntag<?php 23976b470SGreg Roach 38add1155SRico Sonntag/** 48add1155SRico Sonntag * webtrees: online genealogy 5*34e3587bSGreg Roach * Copyright (C) 2020 webtrees development team 68add1155SRico Sonntag * This program is free software: you can redistribute it and/or modify 78add1155SRico Sonntag * it under the terms of the GNU General Public License as published by 88add1155SRico Sonntag * the Free Software Foundation, either version 3 of the License, or 98add1155SRico Sonntag * (at your option) any later version. 108add1155SRico Sonntag * This program is distributed in the hope that it will be useful, 118add1155SRico Sonntag * but WITHOUT ANY WARRANTY; without even the implied warranty of 128add1155SRico Sonntag * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138add1155SRico Sonntag * GNU General Public License for more details. 148add1155SRico Sonntag * You should have received a copy of the GNU General Public License 158add1155SRico Sonntag * along with this program. If not, see <http://www.gnu.org/licenses/>. 168add1155SRico Sonntag */ 17fcfa147eSGreg Roach 188add1155SRico Sonntagdeclare(strict_types=1); 198add1155SRico Sonntag 208add1155SRico Sonntagnamespace Fisharebest\Webtrees\Statistics\Google; 218add1155SRico Sonntag 228add1155SRico Sonntaguse Fisharebest\Webtrees\I18N; 2393ccd686SRico Sonntaguse Fisharebest\Webtrees\Statistics\Service\CenturyService; 248add1155SRico Sonntaguse Fisharebest\Webtrees\Tree; 250892c7deSRico Sonntaguse Illuminate\Database\Capsule\Manager as DB; 26a69f5655SGreg Roachuse Illuminate\Database\Query\Expression; 270892c7deSRico Sonntaguse Illuminate\Database\Query\JoinClause; 28*34e3587bSGreg Roachuse Illuminate\Support\Collection; 296ccdf4f0SGreg Roachuse stdClass; 308add1155SRico Sonntag 318add1155SRico Sonntag/** 3293ccd686SRico Sonntag * A chart showing the marriage ages by century. 338add1155SRico Sonntag */ 3493ccd686SRico Sonntagclass ChartMarriageAge 358add1155SRico Sonntag{ 368add1155SRico Sonntag /** 3793ccd686SRico Sonntag * @var Tree 388add1155SRico Sonntag */ 3993ccd686SRico Sonntag private $tree; 4093ccd686SRico Sonntag 4193ccd686SRico Sonntag /** 4293ccd686SRico Sonntag * @var CenturyService 4393ccd686SRico Sonntag */ 4493ccd686SRico Sonntag private $century_service; 458add1155SRico Sonntag 468add1155SRico Sonntag /** 478add1155SRico Sonntag * Constructor. 488add1155SRico Sonntag * 498add1155SRico Sonntag * @param Tree $tree 508add1155SRico Sonntag */ 518add1155SRico Sonntag public function __construct(Tree $tree) 528add1155SRico Sonntag { 5393ccd686SRico Sonntag $this->tree = $tree; 5493ccd686SRico Sonntag $this->century_service = new CenturyService(); 558add1155SRico Sonntag } 568add1155SRico Sonntag 578add1155SRico Sonntag /** 588add1155SRico Sonntag * Returns the related database records. 598add1155SRico Sonntag * 60*34e3587bSGreg Roach * @return Collection<stdClass> 618add1155SRico Sonntag */ 62*34e3587bSGreg Roach private function queryRecords(): Collection 638add1155SRico Sonntag { 640892c7deSRico Sonntag $prefix = DB::connection()->getTablePrefix(); 650892c7deSRico Sonntag 660892c7deSRico Sonntag $male = DB::table('dates as married') 670892c7deSRico Sonntag ->select([ 68*34e3587bSGreg Roach new Expression('AVG(' . $prefix . 'married.d_julianday2 - ' . $prefix . 'birth.d_julianday1 - 182.5) / 365.25 AS age'), 69a69f5655SGreg Roach new Expression('ROUND((' . $prefix . 'married.d_year + 49) / 100) AS century'), 70a69f5655SGreg Roach new Expression("'M' as sex") 710892c7deSRico Sonntag ]) 720b5fd0a6SGreg Roach ->join('families as fam', static function (JoinClause $join): void { 730892c7deSRico Sonntag $join->on('fam.f_id', '=', 'married.d_gid') 740892c7deSRico Sonntag ->on('fam.f_file', '=', 'married.d_file'); 750892c7deSRico Sonntag }) 760b5fd0a6SGreg Roach ->join('dates as birth', static function (JoinClause $join): void { 770892c7deSRico Sonntag $join->on('birth.d_gid', '=', 'fam.f_husb') 780892c7deSRico Sonntag ->on('birth.d_file', '=', 'fam.f_file'); 790892c7deSRico Sonntag }) 800892c7deSRico Sonntag ->whereIn('married.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 810892c7deSRico Sonntag ->where('married.d_file', '=', $this->tree->id()) 820892c7deSRico Sonntag ->where('married.d_fact', '=', 'MARR') 830892c7deSRico Sonntag ->where('married.d_julianday1', '>', 'birth.d_julianday1') 840892c7deSRico Sonntag ->whereIn('birth.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 850892c7deSRico Sonntag ->where('birth.d_fact', '=', 'BIRT') 860892c7deSRico Sonntag ->where('birth.d_julianday1', '<>', 0) 870892c7deSRico Sonntag ->groupBy(['century', 'sex']); 880892c7deSRico Sonntag 890892c7deSRico Sonntag $female = DB::table('dates as married') 900892c7deSRico Sonntag ->select([ 91a69f5655SGreg Roach new Expression('ROUND(AVG(' . $prefix . 'married.d_julianday2 - ' . $prefix . 'birth.d_julianday1 - 182.5) / 365.25, 1) AS age'), 92a69f5655SGreg Roach new Expression('ROUND((' . $prefix . 'married.d_year + 49) / 100) AS century'), 93a69f5655SGreg Roach new Expression("'F' as sex") 940892c7deSRico Sonntag ]) 950b5fd0a6SGreg Roach ->join('families as fam', static function (JoinClause $join): void { 960892c7deSRico Sonntag $join->on('fam.f_id', '=', 'married.d_gid') 970892c7deSRico Sonntag ->on('fam.f_file', '=', 'married.d_file'); 980892c7deSRico Sonntag }) 990b5fd0a6SGreg Roach ->join('dates as birth', static function (JoinClause $join): void { 1000892c7deSRico Sonntag $join->on('birth.d_gid', '=', 'fam.f_wife') 1010892c7deSRico Sonntag ->on('birth.d_file', '=', 'fam.f_file'); 1020892c7deSRico Sonntag }) 1030892c7deSRico Sonntag ->whereIn('married.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 1040892c7deSRico Sonntag ->where('married.d_file', '=', $this->tree->id()) 1050892c7deSRico Sonntag ->where('married.d_fact', '=', 'MARR') 1060892c7deSRico Sonntag ->where('married.d_julianday1', '>', 'birth.d_julianday1') 1070892c7deSRico Sonntag ->whereIn('birth.d_type', ['@#DGREGORIAN@', '@#DJULIAN@']) 1080892c7deSRico Sonntag ->where('birth.d_fact', '=', 'BIRT') 1090892c7deSRico Sonntag ->where('birth.d_julianday1', '<>', 0) 1100892c7deSRico Sonntag ->groupBy(['century', 'sex']); 1110892c7deSRico Sonntag 1120892c7deSRico Sonntag return $male->unionAll($female) 1130892c7deSRico Sonntag ->orderBy('century') 1140892c7deSRico Sonntag ->get() 115*34e3587bSGreg Roach ->map(static function (stdClass $row): stdClass { 116*34e3587bSGreg Roach return (object) [ 117*34e3587bSGreg Roach 'age' => (float) $row->age, 118*34e3587bSGreg Roach 'century' => (int) $row->century, 119*34e3587bSGreg Roach 'sex' => $row->sex, 120*34e3587bSGreg Roach ]; 121*34e3587bSGreg Roach }); 1228add1155SRico Sonntag } 1238add1155SRico Sonntag 1248add1155SRico Sonntag /** 1258add1155SRico Sonntag * General query on ages at marriage. 1268add1155SRico Sonntag * 1278add1155SRico Sonntag * @return string 1288add1155SRico Sonntag */ 12988de55fdSRico Sonntag public function chartMarriageAge(): string 1308add1155SRico Sonntag { 1318add1155SRico Sonntag $out = []; 1328add1155SRico Sonntag 1330892c7deSRico Sonntag foreach ($this->queryRecords() as $record) { 134*34e3587bSGreg Roach $out[$record->century][$record->sex] = $record->age; 1358add1155SRico Sonntag } 1368add1155SRico Sonntag 13788de55fdSRico Sonntag $data = [ 13888de55fdSRico Sonntag [ 13988de55fdSRico Sonntag I18N::translate('Century'), 14088de55fdSRico Sonntag I18N::translate('Males'), 14188de55fdSRico Sonntag I18N::translate('Females'), 14288de55fdSRico Sonntag I18N::translate('Average age'), 14388de55fdSRico Sonntag ] 14488de55fdSRico Sonntag ]; 14588de55fdSRico Sonntag 1468add1155SRico Sonntag foreach ($out as $century => $values) { 14788de55fdSRico Sonntag $female_age = $values['F'] ?? 0; 14888de55fdSRico Sonntag $male_age = $values['M'] ?? 0; 14988de55fdSRico Sonntag $average_age = ($female_age + $male_age) / 2.0; 1508add1155SRico Sonntag 15188de55fdSRico Sonntag $data[] = [ 15293ccd686SRico Sonntag $this->century_service->centuryName($century), 153*34e3587bSGreg Roach round($male_age, 1), 154*34e3587bSGreg Roach round($female_age, 1), 155*34e3587bSGreg Roach round($average_age, 1), 15688de55fdSRico Sonntag ]; 1578add1155SRico Sonntag } 1588add1155SRico Sonntag 1591b860509SRico Sonntag $chart_title = I18N::translate('Average age in century of marriage'); 1601b860509SRico Sonntag $chart_options = [ 1611b860509SRico Sonntag 'title' => $chart_title, 1621b860509SRico Sonntag 'subtitle' => I18N::translate('Average age at marriage'), 1631b860509SRico Sonntag 'vAxis' => [ 1641b860509SRico Sonntag 'title' => I18N::translate('Age'), 1651b860509SRico Sonntag ], 1661b860509SRico Sonntag 'hAxis' => [ 1671b860509SRico Sonntag 'title' => I18N::translate('Century'), 1681b860509SRico Sonntag ], 1691b860509SRico Sonntag 'colors' => [ 1701b860509SRico Sonntag '#84beff', 1711b860509SRico Sonntag '#ffd1dc', 1721b860509SRico Sonntag '#ff0000', 1731b860509SRico Sonntag ], 1741b860509SRico Sonntag ]; 1751b860509SRico Sonntag 17690a2f718SGreg Roach return view('statistics/other/charts/combo', [ 17788de55fdSRico Sonntag 'data' => $data, 1781b860509SRico Sonntag 'chart_options' => $chart_options, 1791b860509SRico Sonntag 'chart_title' => $chart_title, 18065cf5706SGreg Roach 'language' => I18N::languageTag(), 18190a2f718SGreg Roach ]); 1828add1155SRico Sonntag } 1838add1155SRico Sonntag} 184