Passed
Push — master ( ae19d2...73e9f3 )
by
unknown
05:05
created

PolicyDistribution::getVerboseDescription()   B

Complexity

Conditions 8
Paths 128

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 18
c 1
b 0
f 0
nc 128
nop 0
dl 0
loc 29
rs 8.2111
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_agreements_same) {
63
            $items[] = $this->num_strong_agreements_same . make_plural(" agreement", $this->num_strong_agreements_same . "for");
64
        }
65
        if ($this->num_strong_agreements_different) {
66
            $items[] = $this->num_strong_agreements_different . make_plural(" agreement", $this->num_strong_agreements_different . "against");
67
        }
68
        if ($this->num_strong_votes_absent) {
69
            $items[] = $this->num_strong_votes_absent . make_plural(" absence", $this->num_strong_votes_absent);
70
        }
71
        if ($this->num_strong_votes_abstain) {
72
            $items[] = $this->num_strong_votes_abstain . make_plural(" abstention", $this->num_strong_votes_abstain);
73
        }
74
        if ($this->start_year == $this->end_year) {
75
            $items[] = "in " . $this->start_year . ".";
76
        } else {
77
            $items[] = "between " . $this->start_year . " and " . $this->end_year . ".";
78
        }
79
80
        return implode(", ", $items);
81
    }
82
83
    public function getVerboseScoreLower(): string {
84
        $verbose_score = $this->getVerboseScore();
85
        return strtolower($verbose_score);
86
    }
87
88
    public function noDataAvailable(): bool {
89
        return $this->distance_score == -1;
90
    }
91
92
    public function getVerboseScore(): string {
93
        if ($this->distance_score >= 0 && $this->distance_score <= 0.05) {
94
            return "Consistently voted for";
95
        } elseif ($this->distance_score > 0.05 && $this->distance_score <= 0.15) {
96
            return "Almost always voted for";
97
        } elseif ($this->distance_score > 0.15 && $this->distance_score <= 0.4) {
98
            return "Generally voted for";
99
        } elseif ($this->distance_score > 0.4 && $this->distance_score <= 0.6) {
100
            return "Voted a mixture of for and against";
101
        } elseif ($this->distance_score > 0.6 && $this->distance_score <= 0.85) {
102
            return "Generally voted against";
103
        } elseif ($this->distance_score > 0.85 && $this->distance_score <= 0.95) {
104
            return "Almost always voted against";
105
        } elseif ($this->distance_score > 0.95 && $this->distance_score <= 1) {
106
            return "Consistently voted against";
107
        } elseif ($this->distance_score == -1) {
108
            return "No data available";
109
        } else {
110
            throw new \InvalidArgumentException("Score must be between 0 and 1");
111
        }
112
    }
113
114
    /**
115
     * Retrieves the policy distributions for a specific person, party, period, and chamber.
116
     *
117
     * @param int $person_id The ID of the person.
118
     * @param string $party_slug The slug of the party.
119
     * @param string $period_slug The slug of the period.
120
     * @param int $house The ID of the house (default is HOUSE_TYPE_COMMONS).
121
     * @return PolicyDistribution[] An array of PolicyDistribution objects.
122
     */
123
    public static function getPersonDistributions(int $person_id, string $party_slug, string $period_slug, int $house = HOUSE_TYPE_COMMONS): array {
124
        $db = new \ParlDB();
125
        // need to join to policyorganisationsto get the party_id
126
        // need to join to policycomparisonperiod to get slug to id
127
        // need to special case the query for independent mps because the results for this are in a null party_id
128
        if ($party_slug == "independent") {
129
            $sql = "SELECT
130
                        pd.*,
131
                        \"independent\" as party_slug,
132
                        \"Independent\" as party_name,
133
                        pp.slug as period_slug,
134
                        pp.description as period_description
135
                    FROM policyvotedistribution pd
136
                    JOIN policycomparisonperiod pp ON pd.period_id = pp.id
137
                    WHERE pd.person_id = :person_id
138
                    AND pd.party_id IS NULL
139
                    AND pp.slug = :period_slug
140
                    AND pd.chamber_id = :house
141
                    AND pp.chamber_id = :house
142
                    ";
143
            $params = ['person_id' => $person_id,
144
                'period_slug' => $period_slug,
145
                'house' => $house];
146
        } else {
147
            $sql = "SELECT
148
                        pd.*,
149
                        po.slug as party_slug,
150
                        po.name as party_name,
151
                        pp.slug as period_slug,
152
                        pp.description as period_description
153
                    FROM policyvotedistribution pd
154
                    JOIN policycomparisonperiod pp ON pd.period_id = pp.id
155
                    JOIN policyorganization po ON pd.party_id = po.id
156
                    WHERE pd.person_id = :person_id
157
                    AND po.slug = :party_slug
158
                    AND pp.slug = :period_slug
159
                    AND pd.chamber_id = :house
160
                    AND pp.chamber_id = :house
161
                    ";
162
163
            $params = ['person_id' => $person_id,
164
                'party_slug' => $party_slug,
165
                'period_slug' => $period_slug,
166
                'house' => $house];
167
        }
168
169
        $rows = $db->query($sql, $params);
170
171
        $distributions = [];
172
        foreach ($rows as $row) {
173
            $distributions[] = self::fromRow($row);
174
        }
175
176
        return $distributions;
177
    }
178
179
    public static function fromRow(array $row): PolicyDistribution {
180
        $pd = new PolicyDistribution();
181
        $pd->id = (int) $row['id'];
182
        $pd->policy_id = (int) $row['policy_id'];
183
        $pd->person_id = (int) $row['person_id'];
184
        $pd->period_id = (int) $row['period_id'];
185
        $pd->chamber_id = (int) $row['chamber_id'];
186
        $pd->party_id = (int) $row['party_id'];
187
        $pd->is_target = (int) $row['is_target'];
188
        $pd->num_votes_same = (float) $row['num_votes_same'];
189
        $pd->num_strong_votes_same = (float) $row['num_strong_votes_same'];
190
        $pd->num_votes_different = (float) $row['num_votes_different'];
191
        $pd->num_strong_votes_different = (float) $row['num_strong_votes_different'];
192
        $pd->num_votes_absent = (float) $row['num_votes_absent'];
193
        $pd->num_strong_votes_absent = (float) $row['num_strong_votes_absent'];
194
        $pd->num_votes_abstain = (float) $row['num_votes_abstain'];
195
        $pd->num_strong_votes_abstain = (float) $row['num_strong_votes_abstain'];
196
        $pd->num_agreements_same = (float) $row['num_agreements_same'];
197
        $pd->num_strong_agreements_same = (float) $row['num_strong_agreements_same'];
198
        $pd->num_agreements_different = (float) $row['num_agreements_different'];
199
        $pd->num_strong_agreements_different = (float) $row['num_strong_agreements_different'];
200
        $pd->start_year = (int) $row['start_year'];
201
        $pd->end_year = (int) $row['end_year'];
202
        $pd->distance_score = (float) $row['distance_score'];
203
        $pd->party_slug = $row['party_slug'];
204
        $pd->period_slug = $row['period_slug'];
205
        $pd->party_name = $row['party_name'];
206
        $pd->period_description = $row['period_description'];
207
        return $pd;
208
    }
209
}
210