Completed
Branch dev-2.0 (18c912)
by Boudry
03:14
created

Pairwise   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 175
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 97.3%

Importance

Changes 0
Metric Value
dl 0
loc 175
ccs 72
cts 74
cp 0.973
rs 9.68
c 0
b 0
f 0
wmc 34
lcom 1
cbo 2

15 Methods

Rating   Name   Duplication   Size   Complexity  
A offsetSet() 0 1 1
A offsetExists() 0 3 1
A offsetUnset() 0 1 1
A offsetGet() 0 3 1
A rewind() 0 4 1
A current() 0 3 1
A key() 0 3 1
A next() 0 5 2
A valid() 0 3 1
A __construct() 0 5 1
A __clone() 0 4 1
A setElection() 0 4 1
A getExplicitPairwise() 0 20 4
C doPairwise() 0 68 13
A formatNewpairwise() 0 18 4
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\Timer\Chrono as Timer_Chrono;
17
18
class Pairwise implements \ArrayAccess, \Iterator
19
{
20
    use CondorcetVersion;
21
22
    // Implement ArrayAccess
23
    public function offsetSet($offset, $value) : void {}
24
25
    public function offsetExists($offset) : bool {
26
        return isset($this->_Pairwise[$offset]);
27
    }
28
29
    public function offsetUnset($offset) : void {}
30
31 37
    public function offsetGet($offset) : ?array {
32 37
        return $this->_Pairwise[$offset] ?? null;
33
    }
34
35
36
    // Implement Iterator
37
    private $valid = true;
38
39 90
    public function rewind() : void {
40 90
        reset($this->_Pairwise);
41 90
        $this->valid = true;
42 90
    }
43
44 90
    public function current() : array {
45 90
        return $this->_Pairwise[$this->key()];
46
    }
47
48 90
    public function key() : ?int {
49 90
        return key($this->_Pairwise);
50
    }
51
52 90
    public function next() : void {
53 90
        if (next($this->_Pairwise) === false) :
54 68
            $this->valid = false;
55
        endif;
56 90
    }
57
58 90
    public function valid() : bool {
59 90
        return $this->valid;
60
    }   
61
62
63
    // Pairwise
64
65
    protected $_Election;
66
    protected $_Pairwise = [];
67
68 93
    public function __construct (Election &$link)
69
    {
70 93
        $this->setElection($link);
71 93
        $this->doPairwise();
72 93
    }
73
74 1
    public function __clone ()
75
    {
76 1
        $this->_Election = null;
77 1
    }
78
79 93
    public function setElection (Election $election) : void
80
    {
81 93
        $this->_Election = $election;
82 93
    }
83
84 4
    public function getExplicitPairwise () : array
85
    {
86 4
        $explicit_pairwise = [];
87
88 4
        foreach ($this->_Pairwise as $candidate_key => $candidate_value) :
89
90 4
            $candidate_name = $this->_Election->getCandidateObjectFromKey($candidate_key)->getName();
91
            
92 4
            foreach ($candidate_value as $mode => $mode_value) :
93
94 4
                foreach ($mode_value as $candidate_list_key => $candidate_list_value) :
95 4
                    $explicit_pairwise[$candidate_name][$mode][$this->_Election->getCandidateObjectFromKey($candidate_list_key)->getName()] = $candidate_list_value;
96
                endforeach;
97
98
            endforeach;
99
100
        endforeach;
101
102 4
        return $explicit_pairwise;
103
    }
104
105 93
    protected function doPairwise () : void
106
    {
107
        // Chrono
108 93
        new Timer_Chrono ( $this->_Election->getTimerManager(), 'Do Pairwise' );
109
110 93
        $this->formatNewpairwise();
111
112
        // Win && Null
113 93
        foreach ( $this->_Election->getVotesManager()->getVotesValidUnderConstraintGenerator() as $vote_id => $oneVote ) :
114
115 93
            $vote_ranking = $oneVote->getContextualRanking($this->_Election);
116
117 93
            $voteWeight = ($this->_Election->isVoteWeightIsAllowed()) ? $oneVote->getWeight() : 1;
118
119
            $vote_candidate_list = (function (array $r) : array { $list = [];
120 93
                    foreach ($r as $rank) :
121 93
                        foreach ($rank as $oneCandidate) :
122 93
                            $list[] = $oneCandidate;
123
                        endforeach;
124
                    endforeach;
125
126 93
                    return $list;})($vote_ranking);
127
128 93
            $done_Candidates = [];
129
130 93
            foreach ($vote_ranking as $candidates_in_rank) :
131
132 93
                $candidates_in_rank_keys = [];
133
134 93
                foreach ($candidates_in_rank as $candidate) :
135 93
                    $candidates_in_rank_keys[] = $this->_Election->getCandidateKey($candidate);
136
                endforeach;
137
138 93
                foreach ($candidates_in_rank as $candidate) :
139
140 93
                    $candidate_key = $this->_Election->getCandidateKey($candidate);
141
142
                    // Process
143 93
                    foreach ( $vote_candidate_list as $g_Candidate ) :
144
145 93
                        $g_candidate_key = $this->_Election->getCandidateKey($g_Candidate);
146
147 93
                        if ($candidate_key === $g_candidate_key) :
148 93
                            continue;
149
                        endif;
150
151
                        // Win & Lose
152 93
                        if (    !in_array($g_candidate_key, $done_Candidates, true) && 
153 93
                                !in_array($g_candidate_key, $candidates_in_rank_keys, true) ) :
154
155 92
                            $this->_Pairwise[$candidate_key]['win'][$g_candidate_key] += $voteWeight;
156 92
                            $this->_Pairwise[$g_candidate_key]['lose'][$candidate_key] += $voteWeight;
157
158 92
                            $done_Candidates[] = $candidate_key;
159
160
                        // Null
161 93
                        elseif (in_array($g_candidate_key, $candidates_in_rank_keys, true)) :
162 93
                            $this->_Pairwise[$candidate_key]['null'][$g_candidate_key] += $voteWeight;
163
                        endif;
164
165
                    endforeach;
166
167
                endforeach;
168
169
            endforeach;
170
171
        endforeach;
172 93
    }
173
174 93
    protected function formatNewpairwise () : void
175
    {
176 93
        foreach ( $this->_Election->getCandidatesList() as $candidate_key => $candidate_id ) :
177
178 93
            $this->_Pairwise[$candidate_key] = [ 'win' => [], 'null' => [], 'lose' => [] ];
179
180 93
            foreach ( $this->_Election->getCandidatesList() as $candidate_key_r => $candidate_id_r ) :
181
182 93
                if ($candidate_key_r !== $candidate_key) :
183 93
                    $this->_Pairwise[$candidate_key]['win'][$candidate_key_r]   = 0;
184 93
                    $this->_Pairwise[$candidate_key]['null'][$candidate_key_r]  = 0;
185 93
                    $this->_Pairwise[$candidate_key]['lose'][$candidate_key_r]  = 0;
186
                endif;
187
188
            endforeach;
189
190
        endforeach;
191 93
    }
192
}
193