Completed
Branch dev-2.0 (933cbb)
by Boudry
02:44
created

Pairwise::rewind()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 4
ccs 4
cts 4
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/*
3
    Condorcet PHP - Election manager and results calculator.
4
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
5
6
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
7
    https://github.com/julien-boudry/Condorcet
8
*/
9
declare(strict_types=1);
10
11
12
namespace CondorcetPHP\Condorcet\Algo;
13
14
use CondorcetPHP\Condorcet\CondorcetVersion;
15
use CondorcetPHP\Condorcet\Election;
16
use CondorcetPHP\Condorcet\Vote;
17
use CondorcetPHP\Condorcet\Timer\Chrono as Timer_Chrono;
18
19
class Pairwise implements \ArrayAccess, \Iterator
20
{
21
    use CondorcetVersion;
22
23
    // Implement ArrayAccess
24
    public function offsetSet($offset, $value) : void {}
25
26
    public function offsetExists($offset) : bool {
27
        return isset($this->_Pairwise[$offset]);
28
    }
29
30
    public function offsetUnset($offset) : void {}
31
32 38
    public function offsetGet($offset) : ?array {
33 38
        return $this->_Pairwise[$offset] ?? null;
34
    }
35
36
37
    // Implement Iterator
38
    private $valid = true;
39
40 92
    public function rewind() : void {
41 92
        reset($this->_Pairwise);
42 92
        $this->valid = true;
43 92
    }
44
45 92
    public function current() : array {
46 92
        return $this->_Pairwise[$this->key()];
47
    }
48
49 92
    public function key() : ?int {
50 92
        return key($this->_Pairwise);
51
    }
52
53 92
    public function next() : void {
54 92
        if (next($this->_Pairwise) === false) :
55 70
            $this->valid = false;
56
        endif;
57 92
    }
58
59 92
    public function valid() : bool {
60 92
        return $this->valid;
61
    }   
62
63
64
    // Pairwise
65
66
    protected $_Election;
67
    protected $_Pairwise = [];
68
69 95
    public function __construct (Election &$link)
70
    {
71 95
        $this->setElection($link);
72 95
        $this->doPairwise();
73 95
    }
74
75 1
    public function __clone ()
76
    {
77 1
        $this->_Election = null;
78 1
    }
79
80 95
    public function setElection (Election $election) : void
81
    {
82 95
        $this->_Election = $election;
83 95
    }
84
85 2
    public function getExplicitPairwise () : array
86
    {
87 2
        $explicit_pairwise = [];
88
89 2
        foreach ($this->_Pairwise as $candidate_key => $candidate_value) :
90
91 2
            $candidate_name = $this->_Election->getCandidateObjectFromKey($candidate_key)->getName();
92
            
93 2
            foreach ($candidate_value as $mode => $mode_value) :
94
95 2
                foreach ($mode_value as $candidate_list_key => $candidate_list_value) :
96 2
                    $explicit_pairwise[$candidate_name][$mode][$this->_Election->getCandidateObjectFromKey($candidate_list_key)->getName()] = $candidate_list_value;
97
                endforeach;
98
99
            endforeach;
100
101
        endforeach;
102
103 2
        return $explicit_pairwise;
104
    }
105
106 95
    protected function formatNewpairwise () : void
107
    {
108 95
        foreach ( $this->_Election->getCandidatesList() as $candidate_key => $candidate_id ) :
109
110 95
            $this->_Pairwise[$candidate_key] = [ 'win' => [], 'null' => [], 'lose' => [] ];
111
112 95
            foreach ( $this->_Election->getCandidatesList() as $candidate_key_r => $candidate_id_r ) :
113
114 95
                if ($candidate_key_r !== $candidate_key) :
115 95
                    $this->_Pairwise[$candidate_key]['win'][$candidate_key_r]   = 0;
116 95
                    $this->_Pairwise[$candidate_key]['null'][$candidate_key_r]  = 0;
117 95
                    $this->_Pairwise[$candidate_key]['lose'][$candidate_key_r]  = 0;
118
                endif;
119
120
            endforeach;
121
122
        endforeach;
123 95
    }
124
125 95
    protected function doPairwise () : void
126
    {
127
        // Chrono
128 95
        new Timer_Chrono ( $this->_Election->getTimerManager(), 'Do Pairwise' );
129
130 95
        $this->formatNewpairwise();
131
132 95
        foreach ( $this->_Election->getVotesManager()->getVotesValidUnderConstraintGenerator() as $vote_id => $oneVote ) :
133 95
            $this->computeOneVote($oneVote);
134
        endforeach;
135 95
    }
136
137 95
    protected function computeOneVote (Vote $oneVote) : void
138
    {
139 95
        $vote_ranking = $oneVote->getContextualRanking($this->_Election);
1 ignored issue
show
Bug introduced by
It seems like $this->_Election can be null; however, getContextualRanking() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
140
141 95
        $voteWeight = ($this->_Election->isVoteWeightIsAllowed()) ? $oneVote->getWeight() : 1;
142
143 95
        $vote_candidate_list = [];
144
145 95
        foreach ($vote_ranking as $rank) :
146 95
            foreach ($rank as $oneCandidate) :
147 95
                $vote_candidate_list[] = $oneCandidate;
148
            endforeach;
149
        endforeach;
150
151 95
        $done_Candidates = [];
152
153 95
        foreach ($vote_ranking as $candidates_in_rank) :
154
155 95
            $candidates_in_rank_keys = [];
156
157 95
            foreach ($candidates_in_rank as $candidate) :
158 95
                $candidates_in_rank_keys[] = $this->_Election->getCandidateKey($candidate);
159
            endforeach;
160
161 95
            foreach ($candidates_in_rank as $candidate) :
162
163 95
                $candidate_key = $this->_Election->getCandidateKey($candidate);
164
165
                // Process
166 95
                foreach ( $vote_candidate_list as $g_Candidate ) :
167
168 95
                    $g_candidate_key = $this->_Election->getCandidateKey($g_Candidate);
169
170 95
                    if ($candidate_key === $g_candidate_key) :
171 95
                        continue;
172
                    endif;
173
174
                    // Win & Lose
175 95
                    if (    !in_array($g_candidate_key, $done_Candidates, true) && 
176 95
                            !in_array($g_candidate_key, $candidates_in_rank_keys, true) ) :
177
178 94
                        $this->_Pairwise[$candidate_key]['win'][$g_candidate_key] += $voteWeight;
179 94
                        $this->_Pairwise[$g_candidate_key]['lose'][$candidate_key] += $voteWeight;
180
181 94
                        $done_Candidates[] = $candidate_key;
182
183
                    // Null
184 95
                    elseif (in_array($g_candidate_key, $candidates_in_rank_keys, true)) :
185 95
                        $this->_Pairwise[$candidate_key]['null'][$g_candidate_key] += $voteWeight;
186
                    endif;
187
188
                endforeach;
189
190
            endforeach;
191
192
        endforeach;
193 95
    }
194
195
}
196