xref: /webtrees/app/Statistics/Google/ChartNoChildrenFamilies.php (revision 3dc8167d6e9979a1582f50778c81f57c4747eb61)
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;
24use Illuminate\Database\Capsule\Manager as DB;
25use Illuminate\Database\Query\JoinClause;
26
27/**
28 *
29 */
30class ChartNoChildrenFamilies extends AbstractGoogle
31{
32    /**
33     * @var Tree
34     */
35    private $tree;
36
37    /**
38     * @var Century
39     */
40    private $centuryHelper;
41
42    /**
43     * Constructor.
44     *
45     * @param Tree $tree
46     */
47    public function __construct(Tree $tree)
48    {
49        $this->tree          = $tree;
50        $this->centuryHelper = new Century();
51    }
52
53    /**
54     * Returns the related database records.
55     *
56     * @param int $year1
57     * @param int $year2
58     *
59     * @return \stdClass[]
60     */
61    private function queryRecords(int $year1, int $year2): array
62    {
63        $query = DB::table('families')
64            ->selectRaw('ROUND((d_year - 50) / 100) AS century')
65            ->selectRaw('COUNT(*) AS count')
66            ->join('dates', function (JoinClause $join) {
67                $join->on('d_file', '=', 'f_file')
68                    ->on('d_gid', '=', 'f_id');
69            })
70            ->where('f_file', '=', $this->tree->id())
71            ->where('f_numchil', '=', 0)
72            ->where('d_fact', '=', 'MARR')
73            ->whereIn('d_type', ['@#DGREGORIAN@', '@#DJULIAN@'])
74            ->groupBy(['century'])
75            ->orderBy('century');
76
77        if ($year1 >= 0 && $year2 >= 0) {
78            $query->whereBetween('d_year', [$year1, $year2]);
79        }
80
81        return $query->get()->all();
82    }
83
84    /**
85     * Create a chart of children with no families.
86     *
87     * @param int    $no_child_fam The number of families with no children
88     * @param string $size
89     * @param int    $year1
90     * @param int    $year2
91     *
92     * @return string
93     */
94    public function chartNoChildrenFamilies(
95        int $no_child_fam,
96        string $size = '220x200',
97        int $year1   = -1,
98        int $year2   = -1
99    ): string {
100        $sizes = explode('x', $size);
101        $max   = 0;
102        $tot   = 0;
103        $rows  = $this->queryRecords($year1, $year2);
104
105        if (empty($rows)) {
106            return '';
107        }
108
109        foreach ($rows as $values) {
110            $values->count = (int) $values->count;
111
112            if ($max < $values->count) {
113                $max = $values->count;
114            }
115            $tot += $values->count;
116        }
117
118        $unknown = $no_child_fam - $tot;
119
120        if ($unknown > $max) {
121            $max = $unknown;
122        }
123
124        $chm    = '';
125        $chxl   = '0:|';
126        $i      = 0;
127        $counts = [];
128
129        foreach ($rows as $values) {
130            $chxl     .= $this->centuryHelper->centuryName((int) $values->century) . '|';
131            $counts[] = intdiv(4095 * $values->count, $max + 1);
132            $chm      .= 't' . $values->count . ',000000,0,' . $i . ',11,1|';
133            $i++;
134        }
135
136        $counts[] = intdiv(4095 * $unknown, $max + 1);
137        $chd      = $this->arrayToExtendedEncoding($counts);
138        $chm      .= 't' . $unknown . ',000000,0,' . $i . ',11,1';
139        $chxl     .= I18N::translateContext('unknown century', 'Unknown') . '|1:||' . I18N::translate('century') . '|2:|0|';
140        $step     = $max + 1;
141
142        for ($d = ($max + 1); $d > 0; $d--) {
143            if (($max + 1) < ($d * 10 + 1) && fmod($max + 1, $d) === 0) {
144                $step = $d;
145            }
146        }
147
148        if ($step === ($max + 1)) {
149            for ($d = $max; $d > 0; $d--) {
150                if ($max < ($d * 10 + 1) && fmod($max, $d) === 0) {
151                    $step = $d;
152                }
153            }
154        }
155
156        for ($n = $step; $n <= ($max + 1); $n += $step) {
157            $chxl .= $n . '|';
158        }
159
160        $chxl .= '3:||' . I18N::translate('Total families') . '|';
161
162        $chart_url = 'https://chart.googleapis.com/chart?cht=bvg&amp;chs=' . $sizes[0] . 'x' . $sizes[1]
163            . '&amp;chf=bg,s,ffffff00|c,s,ffffff00&amp;chm=D,FF0000,0,0:'
164            . ($i - 1) . ',3,1|' . $chm . '&amp;chd=e:'
165            . $chd . '&amp;chco=0000FF,ffffff00&amp;chbh=30,3&amp;chxt=x,x,y,y&amp;chxl='
166            . rawurlencode($chxl);
167
168        return view(
169            'statistics/other/chart-google',
170            [
171                'chart_title' => I18N::translate('Number of families without children'),
172                'chart_url'   => $chart_url,
173                'sizes'       => $sizes,
174            ]
175        );
176    }
177}
178