Schulze_Core::makeStrongestPaths()   B
last analyzed

Complexity

Conditions 11
Paths 30

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 11

Importance

Changes 0
Metric Value
cc 11
nc 30
nop 0
dl 0
loc 28
rs 7.3166
c 0
b 0
f 0
ccs 16
cts 16
cp 1
crap 11

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
    Part of SCHULZE method Module - From the original Condorcet PHP
4
5
    Condorcet PHP - Election manager and results calculator.
6
    Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
7
8
    By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
9
    https://github.com/julien-boudry/Condorcet
10
*/
11
declare(strict_types=1);
12
13
namespace CondorcetPHP\Condorcet\Algo\Methods\Schulze;
14
15
use CondorcetPHP\Condorcet\Result;
16
use CondorcetPHP\Condorcet\Algo\{Method, MethodInterface};
17
18
// Schulze is a Condorcet Algorithm | http://en.wikipedia.org/wiki/Schulze_method
19
abstract class Schulze_Core extends Method implements MethodInterface
20
{
21
    // Schulze
22
    protected $_StrongestPaths;
23
24
25
/////////// PUBLIC ///////////
26
27
    abstract protected function schulzeVariant (int &$i,int &$j);
28
29 32
    public function getResult () : Result
30
    {
31
        // Cache
32 32
        if ( $this->_Result !== null ) :
33 11
            return $this->_Result;
34
        endif;
35
36
            //////
37
38
        // Format array
39 32
        $this->prepareStrongestPath();
40
41
        // Strongest Paths calculation
42 32
        $this->makeStrongestPaths();
43
44
        // Ranking calculation
45 32
        $this->makeRanking();
46
47
48
        // Return
49 32
        return $this->_Result;
50
    }
51
52
53
    // Get the Schulze ranking
54 32
    protected function getStats () : array
55
    {
56 32
        $explicit = [];
57
58 32
        foreach ($this->_StrongestPaths as $candidate_key => $candidate_value) :
59 32
            $candidate_key = $this->_selfElection->getCandidateObjectFromKey($candidate_key)->getName();
60
61 32
            foreach ($candidate_value as $challenger_key => $challenger_value) :
62 32
                $explicit[$candidate_key][$this->_selfElection->getCandidateObjectFromKey($challenger_key)->getName()] = $challenger_value;
63
            endforeach;
64
        endforeach;
65
66 32
        return $explicit;
67
    }
68
69
70
71
/////////// COMPUTE ///////////
72
73
74
    //:: SCHULZE ALGORITHM. :://
75
76
77
    // Calculate the strongest Paths for Schulze Method
78 32
    protected function prepareStrongestPath () : void
79
    {
80 32
        $this->_StrongestPaths = [];
81
82 32
        foreach ( $this->_selfElection->getCandidatesList() as $candidate_key => $candidate_id ) :
83 32
            $this->_StrongestPaths[$candidate_key] = [];
84
85
            // Format array for the strongest path
86 32
            foreach ( $this->_selfElection->getCandidatesList() as $candidate_key_r => $candidate_id_r ) :
87 32
                if ($candidate_key_r != $candidate_key) :
88 32
                    $this->_StrongestPaths[$candidate_key][$candidate_key_r] = 0;
89
                endif;
90
            endforeach;
91
        endforeach;
92 32
    }
93
94
95
    // Calculate the Strongest Paths
96 32
    protected function makeStrongestPaths () : void
97
    {
98 32
        foreach ($this->_selfElection->getCandidatesList() as $i => $i_value) :
99 32
            foreach ($this->_selfElection->getCandidatesList() as $j => $j_value) :
100 32
                if ($i !== $j) :
101 32
                    if ( $this->_selfElection->getPairwise()[$i]['win'][$j] > $this->_selfElection->getPairwise()[$j]['win'][$i] ) :
102 32
                        $this->_StrongestPaths[$i][$j] = $this->schulzeVariant($i,$j);                      
103
                    else :
104 32
                        $this->_StrongestPaths[$i][$j] = 0;
105
                    endif;
106
                endif;
107
            endforeach;
108
        endforeach;
109
110 32
        foreach ($this->_selfElection->getCandidatesList() as $i => $i_value) :
111 32
            foreach ($this->_selfElection->getCandidatesList() as $j => $j_value) :
112 32
                if ($i !== $j) :
113 32
                    foreach ($this->_selfElection->getCandidatesList() as $k => $k_value) :
114 32
                        if ($i !== $k && $j !== $k) :
115 32
                            $this->_StrongestPaths[$j][$k] = 
116 32
                                max( $this->_StrongestPaths[$j][$k], 
117 32
                                     min($this->_StrongestPaths[$j][$i], $this->_StrongestPaths[$i][$k]) );
118
                        endif;
119
                    endforeach;
120
                endif;
121
            endforeach;
122
        endforeach;
123 32
    }
124
125
126
    // Calculate && Format human readable ranking
127 32
    protected function makeRanking () : void
128
    {       
129 32
        $result = [];
130
131
        // Calculate ranking
132 32
        $done = [];
133 32
        $rank = 1;
134
135 32
        while (count($done) < $this->_selfElection->countCandidates()) :
136 32
            $to_done = [];
137
138 32
            foreach ( $this->_StrongestPaths as $candidate_key => $challengers_key ) :
139 32
                if ( in_array($candidate_key, $done, true) ) :
140 32
                    continue;
141
                endif;
142
143 32
                $winner = true;
144
145 32
                foreach ($challengers_key as $beaten_key => $beaten_value) :
146 32
                    if ( in_array($beaten_key, $done, true) ) :
147 32
                        continue;
148
                    endif;
149
150 32
                    if ( $beaten_value < $this->_StrongestPaths[$beaten_key][$candidate_key] ) :
151 32
                        $winner = false;
152
                    endif;
153
                endforeach;
154
155 32
                if ($winner) :
156 32
                    $result[$rank][] = $candidate_key;
157
158 32
                    $to_done[] = $candidate_key;
159
                endif;
160
            endforeach;
161
162 32
            $done = array_merge($done, $to_done);
163
164 32
            $rank++;
165
        endwhile;
166
167 32
        $this->_Result = $this->createResult($result);
168 32
    }
169
}
170