Passed
Pull Request — master (#1868)
by
unknown
31:46
created

PolicyDistribution::totalVotes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 2
rs 10
1
<?php
2
3
/**
4
 * Party Cohort Class
5
 *
6
 * @package TheyWorkForYou
7
 */
8
9
namespace MySociety\TheyWorkForYou;
10
11
/**
12
 * Policy Distribution
13
 * This contains all the calculated information about the
14
 * number of votes and agreements relevant to the policy
15
 * distribution of a person (or their comparable MPs).
16
 * $is_target is 1 if the person is the target of the comparison,
17
 * 0 if they are the comparison.
18
 */
19
20
class PolicyDistribution {
21
    public int $id;
22
    public int $policy_id;
23
    public int $person_id;
24
    public int $period_id;
25
    public int $chamber_id;
26
    public ?int $party_id;
27
    public int $is_target;
28
    public float $num_votes_same;
29
    public float $num_strong_votes_same;
30
    public float $num_votes_different;
31
    public float $num_strong_votes_different;
32
    public float $num_votes_absent;
33
    public float $num_strong_votes_absent;
34
    public float $num_votes_abstain;
35
    public float $num_strong_votes_abstain;
36
    public float $num_agreements_same;
37
    public float $num_strong_agreements_same;
38
    public float $num_agreements_different;
39
    public float $num_strong_agreements_different;
40
    public int $start_year;
41
    public int $end_year;
42
    public float $distance_score;
43
    public string $party_slug;
44
    public string $period_slug;
45
    public string $party_name;
46
    public string $period_description;
47
48
    public function totalVotes(): float {
49
        return $this->num_votes_same + $this->num_votes_different + $this->num_strong_votes_same + $this->num_strong_votes_different;
50
    }
51
52
    public function getVerboseDescription(): string {
53
54
        $items = [];
55
56
        if ($this->num_strong_votes_same) {
57
            $items[] = $this->num_strong_votes_same . make_plural(" vote", $this->num_strong_votes_same) . " for";
58
        }
59
        if ($this->num_strong_votes_different) {
60
            $items[] = $this->num_strong_votes_different . make_plural(" vote", $this->num_strong_votes_different) . " against";
61
        }
62
        if ($this->num_strong_votes_absent) {
63
            $items[] = $this->num_strong_votes_absent . make_plural(" absence", $this->num_strong_votes_absent);
64
        }
65
        if ($this->num_strong_votes_abstain) {
66
            $items[] = $this->num_strong_votes_abstain . make_plural(" abstention", $this->num_strong_votes_abstain);
67
        }
68
        if ($this->start_year == $this->end_year) {
69
            $items[] = "in " . $this->start_year . ".";
70
        } else {
71
            $items[] = "between " . $this->start_year . " and " . $this->end_year . ".";
72
        }
73
74
        return implode(", ", $items);
75
    }
76
77
    public function getVerboseScoreLower(): string {
78
        $verbose_score = $this->getVerboseScore();
79
        return strtolower($verbose_score);
80
    }
81
82
    public function noDataAvailable(): bool {
83
        return $this->distance_score == -1;
84
    }
85
86
    public function getVerboseScore(): string {
87
        if ($this->distance_score >= 0 && $this->distance_score <= 0.05) {
88
            return "Consistently voted for";
89
        } elseif ($this->distance_score > 0.05 && $this->distance_score <= 0.15) {
90
            return "Almost always voted for";
91
        } elseif ($this->distance_score > 0.15 && $this->distance_score <= 0.4) {
92
            return "Generally voted for";
93
        } elseif ($this->distance_score > 0.4 && $this->distance_score <= 0.6) {
94
            return "Voted a mixture of for and against";
95
        } elseif ($this->distance_score > 0.6 && $this->distance_score <= 0.85) {
96
            return "Generally voted against";
97
        } elseif ($this->distance_score > 0.85 && $this->distance_score <= 0.95) {
98
            return "Almost always voted against";
99
        } elseif ($this->distance_score > 0.95 && $this->distance_score <= 1) {
100
            return "Consistently voted against";
101
        } elseif ($this->distance_score == -1) {
102
            return "No data available";
103
        } else {
104
            throw new \InvalidArgumentException("Score must be between 0 and 1");
105
        }
106
    }
107
108
    /**
109
     * Retrieves the policy distributions for a specific person, party, period, and chamber.
110
     *
111
     * @param int $person_id The ID of the person.
112
     * @param string $party_slug The slug of the party.
113
     * @param string $period_slug The slug of the period.
114
     * @param int $house The ID of the house (default is HOUSE_TYPE_COMMONS).
115
     * @return PolicyDistribution[] An array of PolicyDistribution objects.
116
     */
117
    public static function getPersonDistributions(int $person_id, string $party_slug, string $period_slug, int $house = HOUSE_TYPE_COMMONS): array {
118
        $db = new \ParlDB();
119
        // need to join to policyorganisationsto get the party_id
120
        // need to join to policycomparisonperiod to get slug to id
121
        // need to special case the query for independent mps because the results for this are in a null party_id
122
        if ($party_slug == "independent") {
123
            $sql = "SELECT
124
                        pd.*,
125
                        \"independent\" as party_slug,
126
                        \"Independent\" as party_name,
127
                        pp.slug as period_slug,
128
                        pp.description as period_description
129
                    FROM policyvotedistribution pd
130
                    JOIN policycomparisonperiod pp ON pd.period_id = pp.id
131
                    WHERE pd.person_id = :person_id
132
                    AND pd.party_id IS NULL
133
                    AND pp.slug = :period_slug
134
                    AND pd.chamber_id = :house
135
                    AND pp.chamber_id = :house
136
                    ";
137
            $params = ['person_id' => $person_id,
138
                'period_slug' => $period_slug,
139
                'house' => $house];
140
        } else {
141
            $sql = "SELECT
142
                        pd.*,
143
                        po.slug as party_slug,
144
                        po.name as party_name,
145
                        pp.slug as period_slug,
146
                        pp.description as period_description
147
                    FROM policyvotedistribution pd
148
                    JOIN policycomparisonperiod pp ON pd.period_id = pp.id
149
                    JOIN policyorganization po ON pd.party_id = po.id
150
                    WHERE pd.person_id = :person_id
151
                    AND po.slug = :party_slug
152
                    AND pp.slug = :period_slug
153
                    AND pd.chamber_id = :house
154
                    AND pp.chamber_id = :house
155
                    ";
156
157
            $params = ['person_id' => $person_id,
158
                'party_slug' => $party_slug,
159
                'period_slug' => $period_slug,
160
                'house' => $house];
161
        }
162
163
        $rows = $db->query($sql, $params);
164
165
        $distributions = [];
166
        foreach ($rows as $row) {
167
            $distributions[] = self::fromRow($row);
168
        }
169
170
        return $distributions;
171
    }
172
173
    public static function fromRow(array $row): PolicyDistribution {
174
        $pd = new PolicyDistribution();
175
        $pd->id = (int) $row['id'];
176
        $pd->policy_id = (int) $row['policy_id'];
177
        $pd->person_id = (int) $row['person_id'];
178
        $pd->period_id = (int) $row['period_id'];
179
        $pd->chamber_id = (int) $row['chamber_id'];
180
        $pd->party_id = (int) $row['party_id'];
181
        $pd->is_target = (int) $row['is_target'];
182
        $pd->num_votes_same = (float) $row['num_votes_same'];
183
        $pd->num_strong_votes_same = (float) $row['num_strong_votes_same'];
184
        $pd->num_votes_different = (float) $row['num_votes_different'];
185
        $pd->num_strong_votes_different = (float) $row['num_strong_votes_different'];
186
        $pd->num_votes_absent = (float) $row['num_votes_absent'];
187
        $pd->num_strong_votes_absent = (float) $row['num_strong_votes_absent'];
188
        $pd->num_votes_abstain = (float) $row['num_votes_abstain'];
189
        $pd->num_strong_votes_abstain = (float) $row['num_strong_votes_abstain'];
190
        $pd->num_agreements_same = (float) $row['num_agreements_same'];
191
        $pd->num_strong_agreements_same = (float) $row['num_strong_agreements_same'];
192
        $pd->num_agreements_different = (float) $row['num_agreements_different'];
193
        $pd->num_strong_agreements_different = (float) $row['num_strong_agreements_different'];
194
        $pd->start_year = (int) $row['start_year'];
195
        $pd->end_year = (int) $row['end_year'];
196
        $pd->distance_score = (float) $row['distance_score'];
197
        $pd->party_slug = $row['party_slug'];
198
        $pd->period_slug = $row['period_slug'];
199
        $pd->party_name = $row['party_name'];
200
        $pd->period_description = $row['period_description'];
201
        return $pd;
202
    }
203
}
204