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

ResultsProcess::cleanupCompute()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

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 8
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
namespace CondorcetPHP\Condorcet\ElectionProcess;
12
13
use CondorcetPHP\Condorcet\Condorcet;
14
use CondorcetPHP\Condorcet\CondorcetException;
15
use CondorcetPHP\Condorcet\Result;
16
use CondorcetPHP\Condorcet\Algo\Pairwise;
17
use CondorcetPHP\Condorcet\Timer\Chrono as Timer_Chrono;
18
19
// Manage Results for Election class
20
trait ResultsProcess
21
{
22
23
/////////// CONSTRUCTOR ///////////
24
25
    // Result
26
    protected $_Pairwise;
27
    protected $_Calculator;
28
29
30
/////////// GET RESULTS ///////////
31
32
    // Generic function for default result with ability to change default object method
33 91
    public function getResult (?string $method = null, array $options = []) : Result
34
    {
35 91
        $options = self::formatResultOptions($options);
36
37
        // Filter if tag is provided & return
38 91
        if ($options['%tagFilter']) :
39 2
            $chrono = new Timer_Chrono ($this->_timer, 'GetResult with filter');
40
41 2
            $filter = new self;
42
43 2
            foreach ($this->getCandidatesList() as $candidate) :
44 2
                $filter->addCandidate($candidate);
45
            endforeach;
46
47 2
            foreach ($this->getVotesList($options['tags'], $options['withTag']) as $vote) :
48 2
                $filter->addVote($vote);
49
            endforeach;
50
51 2
            unset($chrono);
52
53 2
            return $filter->getResult($method);
54
        endif;
55
56
            ////// Start //////
57
58
        // Prepare
59 91
        $this->prepareResult();
60
61
            //////
62
63 90
        $chrono = new Timer_Chrono ($this->_timer);
64
65 90
        if ($method === null) :
66 8
            $this->initResult(Condorcet::getDefaultMethod());
67 8
            $result = $this->_Calculator[Condorcet::getDefaultMethod()]->getResult();
68 85
        elseif ($method = Condorcet::isAuthMethod((string) $method)) :
69 85
            $this->initResult($method);
70 83
            $result = $this->_Calculator[$method]->getResult();
71
        else :
72
            throw new CondorcetException(8,$method);
73
        endif;
74
75 87
        $chrono->setRole('GetResult for '.$method);
76
77 87
        return $result;
78
    }
79
80
81 93
    public function getWinner (?string $substitution = null)
82
    {
83 93
        $algo = Condorcet::condorcetBasicSubstitution($substitution);
84
85
            //////
86
87 93
        if ($algo === Condorcet::CONDORCET_BASIC_CLASS) :
88 91
            new Timer_Chrono ($this->_timer, 'GetWinner for CondorcetBasic');
89 91
            $this->initResult($algo);
90 91
            $result = $this->_Calculator[$algo]->getWinner();
91
92 91
            return ($result === null) ? null : $this->getCandidateObjectFromKey($result);
0 ignored issues
show
Bug introduced by
It seems like getCandidateObjectFromKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
93
        else :
94 51
            return $this->getResult($algo)->getWinner();
95
        endif;
96
    }
97
98
99 90
    public function getLoser (?string $substitution = null)
100
    {
101 90
        $algo = Condorcet::condorcetBasicSubstitution($substitution);
102
103
            //////
104
105 90
        if ($algo === Condorcet::CONDORCET_BASIC_CLASS) :
106 90
            new Timer_Chrono ($this->_timer, 'GetLoser for CondorcetBasic');
107 90
            $this->initResult($algo);
108 90
            $result = $this->_Calculator[$algo]->getLoser();
109
110 90
            return ($result === null) ? null : $this->getCandidateObjectFromKey($result);
0 ignored issues
show
Bug introduced by
It seems like getCandidateObjectFromKey() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
111
        else :
112 2
            return $this->getResult($algo)->getLoser();
113
        endif;
114
    }
115
116 92
    public function getPairwise () : Pairwise
117
    {
118 92
        $this->prepareResult();
0 ignored issues
show
Bug introduced by
It seems like prepareResult() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
119 92
        return $this->_Pairwise;
120
    }
121
122 1
    public function getExplicitPairwise () : array
123
    {
124 1
        return $this->getPairwise()->getExplicitPairwise();
125
    }
126
127
128
129
/////////// MAKE RESULTS ///////////
130
131 1
    public function computeResult (?string $method = null) : void
132
    {
133 1
        $this->getResult($method);
134 1
    }
135
136 95
    protected function makePairwise () : void
137
    {
138 95
        $this->_Pairwise = new Pairwise ($this);
139 95
    }
140
141 95
    protected function initResult (string $class) : void
142
    {
143 95
        if ( !isset($this->_Calculator[$class]) ) :
144 95
            $this->_Calculator[$class] = new $class($this);
145
        endif;
146 93
    }
147
148
    // Cleanup results to compute again with new votes
149 96
    protected function cleanupCompute () : void
150
    {
151
        // Clean pairwise
152 96
        $this->cleanupPairwise();
153
154
        // Algos
155 96
        $this->cleanupCalculator();
156 96
    }
157
158 96
    public function cleanupPairwise () : void
159
    {
160
        // Reset state
161 96
        if ($this->_State > 2) : 
162 11
            $this->_State = 2;
163
        endif;
164
165 96
        $this->_Pairwise = null;
166 96
        $this->cleanupCalculator();
167 96
    }
168
169 96
    public function cleanupCalculator () : void
170
    {
171 96
        $this->_Calculator = null;
172 96
    }
173
174
175
/////////// UTILS ///////////
176
177 91
    protected static function formatResultOptions (array $arg) : array
178
    {
179
        // About tag filter
180 91
        if (isset($arg['tags'])):
181 2
            $arg['%tagFilter'] = true;
182
183 2
            if ( !isset($arg['withTag']) || !is_bool($arg['withTag']) ) :
184 2
                $arg['withTag'] = true;
185
            endif;
186
        else:
187 91
            $arg['%tagFilter'] = false;
188
        endif;
189
190 91
        return $arg;
191
    }
192
}
193