Completed
Push — feature/player-elo-seasons ( 1c85e8 )
by Vladimir
03:56
created

MatchQueryBuilder   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 24
lcom 1
cbo 4
dl 0
loc 110
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
D with() 0 46 18
A groupByMonth() 0 6 1
B getSummary() 0 29 4
A betweenMonths() 0 5 1
1
<?php
2
/**
3
 * This file contains a class to quickly generate database queries for matches
4
 *
5
 * @package    BZiON\Models\QueryBuilder
6
 * @license    https://github.com/allejo/bzion/blob/master/LICENSE.md GNU General Public License Version 3
7
 */
8
9
/**
10
 * This class can be used to search for matches with specific characteristics in
11
 * the database.
12
 *
13
 * @package    BZiON\Models\QueryBuilder
14
 */
15
class MatchQueryBuilder extends QueryBuilder
16
{
17
    /**
18
     * Only include matches where a specific team/player played
19
     *
20
     * @param  Team|Player $participant The team/player which played the matches
21
     * @param  string      $result      The outcome of the matches (win, draw or loss)
22
     * @return self
23
     */
24
    public function with($participant, $result = null)
25
    {
26
        if (!$participant || !$participant->isValid()) {
27
            return $this;
28
        }
29
30
        if ($participant instanceof Team) {
31
            $team_a_query = "team_a = ?";
32
            $team_b_query = "team_b = ?";
33
        } elseif ($participant instanceof Player) {
34
            $team_a_query = "FIND_IN_SET(?, team_a_players)";
35
            $team_b_query = "FIND_IN_SET(?, team_b_players)";
36
        } else {
37
            throw new InvalidArgumentException("Invalid model provided");
38
        }
39
40
        switch ($result) {
41
            case "wins":
42
            case "win":
43
            case "victory":
44
            case "victories":
45
                $query = "($team_a_query AND team_a_points > team_b_points) OR ($team_b_query AND team_b_points > team_a_points)";
46
                break;
47
            case "loss":
48
            case "lose":
49
            case "losses":
50
            case "defeat":
51
            case "defeats":
52
                $query = "($team_a_query AND team_b_points > team_a_points) OR ($team_b_query AND team_a_points > team_b_points)";
53
                break;
54
            case "draw":
55
            case "draws":
56
            case "tie":
57
            case "ties":
58
                $query = "($team_a_query OR $team_b_query) AND team_a_points = team_b_points";
59
                break;
60
            default:
61
                $query = "$team_a_query OR $team_b_query";
62
        }
63
64
        $this->whereConditions[] = $query;
65
        $this->parameters[] = $participant->getId();
66
        $this->parameters[] = $participant->getId();
67
68
        return $this;
69
    }
70
71
    /**
72
     * Group results by day
73
     *
74
     * @return $this
75
     */
76
    public function groupByMonth()
77
    {
78
        $this->groupQuery .= "GROUP BY YEAR(timestamp), MONTH(timestamp)";
79
80
        return $this;
81
    }
82
83
    /**
84
     * Get a count for each month's matches
85
     *
86
     * @param TimeDate|Team $timeDate The team in question
87
     * @return array
88
     */
89
    public function getSummary(TimeDate $timeDate)
90
    {
91
        $this->groupQuery = 'GROUP BY match_date';
92
93
        $query = $this->createQuery("DATE_FORMAT(timestamp, '%Y-%m') AS match_date, COUNT(*) as match_count");
94
95
        $matches = [];
96
        $results = Database::getInstance()->query($query, $this->parameters);
97
98
        foreach ($results as $match) {
99
            $matches[$match['match_date']] = $match['match_count'];
100
        }
101
102
        $interval = new DateInterval('P1M');
103
        $dateRange = new DatePeriod($timeDate, $interval, TimeDate::now());
104
105
        /** @var DateTime $month */
106
        foreach($dateRange as $month) {
107
            $key = $month->format('Y-m');
108
109
            if (!isset($matches[$key])) {
110
                $matches[$key] = 0;
111
            }
112
        }
113
114
        ksort($matches);
115
116
        return $matches;
117
    }
118
119
    public function betweenMonths(MonthDateRange $range, $year = 'now')
120
    {
121
        $this->isAfter($range->getStartOfRange($year), true);
122
        $this->isBefore($range->getEndOfRange($year), true);
123
    }
124
}
125