Completed
Push — dev-1.6.x ( c638bc...048fe7 )
by Boudry
04:21
created

ResultsManager::initResult()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
/*
3
    Condorcet PHP Class, with Schulze Methods and others !
4
5
    By Julien Boudry - MIT LICENSE (Please read LICENSE.txt)
6
    https://github.com/julien-boudry/Condorcet
7
*/
8
declare(strict_types=1);
9
10
namespace Condorcet\ElectionProcess;
11
12
use Condorcet\Condorcet;
13
use Condorcet\CondorcetException;
14
use Condorcet\Result;
15
use Condorcet\Algo\Pairwise;
16
use Condorcet\Timer\Chrono as Timer_Chrono;
17
18
// Manage Results for Election class
19
trait ResultsManager
20
{
21
22
/////////// CONSTRUCTOR ///////////
23
24
    // Params
25
    protected $_ImplicitRanking = true;
26
    protected $_VoteWeightRule = false;
27
28
    // Result
29
    protected $_Pairwise;
30
    protected $_Calculator;
31
32
33
/////////// RESULTS TYPE ///////////
34
35
36
    public function getImplicitRankingRule () : bool
37
    {
38
        return $this->_ImplicitRanking;
39
    }
40
41
    public function setImplicitRanking (bool $rule = true) : bool
42
    {
43
        $this->_ImplicitRanking = $rule;
44
        $this->cleanupResult();
45
        return $this->getImplicitRankingRule();
46
    }
47
48
49
/////////// RESULTS ///////////
50
51
52
    //:: PUBLIC FUNCTIONS :://
53
54
    // Generic function for default result with ability to change default object method
55 75
    public function getResult ($method = true, array $options = []) : Result
56
    {
57 75
        $options = $this->formatResultOptions($options);
58
59
        // Filter if tag is provided & return
60 75
        if ($options['%tagFilter']) :
61 2
            $chrono = new Timer_Chrono ($this->_timer, 'GetResult with filter');
1 ignored issue
show
Bug introduced by
The property _timer does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
62
63 2
            $filter = new self;
64
65 2
            foreach ($this->getCandidatesList() as $candidate) :
1 ignored issue
show
Bug introduced by
It seems like getCandidatesList() 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...
66 2
                $filter->addCandidate($candidate);
1 ignored issue
show
Bug introduced by
It seems like addCandidate() 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...
67
            endforeach;
68
69 2
            foreach ($this->getVotesList($options['tags'], $options['withTag']) as $vote) :
1 ignored issue
show
Bug introduced by
It seems like getVotesList() 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...
70 2
                $filter->addVote($vote);
1 ignored issue
show
Bug introduced by
It seems like addVote() 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...
71
            endforeach;
72
73 2
            unset($chrono);
74
75 2
            return $filter->getResult($method);
76
        endif;
77
78
            ////// Start //////
79
80
        // Prepare
81 75
        $this->prepareResult();
82
83
            //////
84
85 75
        $chrono = new Timer_Chrono ($this->_timer);
86
87 75
        if ($method === true) :
88 7
            $this->initResult(Condorcet::getDefaultMethod());
89 7
            $result = $this->_Calculator[Condorcet::getDefaultMethod()]->getResult();
90 71
        elseif ($method = Condorcet::isAuthMethod((string) $method)) :
91 71
            $this->initResult($method);
92 69
            $result = $this->_Calculator[$method]->getResult();
93
        else :
94
            throw new CondorcetException(8,$method);
95
        endif;
96
97 72
        $chrono->setRole('GetResult for '.$method);
98
99 72
        return $result;
100
    }
101
102
103 78
    public function getWinner (?string $substitution = null)
104
    {
105 78
        $algo = Condorcet::condorcetBasicSubstitution($substitution);
106
107
            //////
108
109 78
        if ($algo === Condorcet::CONDORCET_BASIC_CLASS) :
110 76
            new Timer_Chrono ($this->_timer, 'GetWinner for CondorcetBasic');
111 76
            $this->initResult($algo);
112 76
            $result = $this->_Calculator[$algo]->getWinner();
113
114 76
            return ($result === null) ? null : $this->getCandidateId($result);
1 ignored issue
show
Bug introduced by
It seems like getCandidateId() 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...
115
        else :
116 50
            return $this->getResult($algo)->getWinner();
117
        endif;
118
    }
119
120
121 75
    public function getLoser (?string $substitution = null)
122
    {
123 75
        $algo = Condorcet::condorcetBasicSubstitution($substitution);
124
125
            //////
126
127 75
        if ($algo === Condorcet::CONDORCET_BASIC_CLASS) :
128 75
            new Timer_Chrono ($this->_timer, 'GetLoser for CondorcetBasic');
129 75
            $this->initResult($algo);
130 75
            $result = $this->_Calculator[$algo]->getLoser();
131
132 75
            return ($result === null) ? null : $this->getCandidateId($result);
1 ignored issue
show
Bug introduced by
It seems like getCandidateId() 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...
133
        else :
134 2
            return $this->getResult($algo)->getLoser();
135
        endif;
136
    }
137
138 1
    public function computeResult ($method = true) : void
139
    {
140 1
        $this->getResult($method);
141 1
    }
142
143
144
    //:: TOOLS FOR RESULT PROCESS :://
145
146
147
    // Prepare to compute results & caching system
148 80
    protected function prepareResult () : bool
149
    {
150 80
        if ($this->_State > 2) :
151 74
            return false;
152 80
        elseif ($this->_State === 2) :
1 ignored issue
show
Bug introduced by
The property _State does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
153 80
            $this->cleanupResult();
154
155
            // Do Pairewise
156 80
            $this->_Pairwise = new Pairwise ($this);
157
158
            // Change state to result
159 80
            $this->_State = 3;
160
161
            // Return
162 80
            return true;
163
        else :
164
            throw new CondorcetException(6);
165
        endif;
166
    }
167
168
169 80
    protected function initResult (string $class) : void
170
    {
171 80
        if ( !isset($this->_Calculator[$class]) ) :
172 80
            $this->_Calculator[$class] = new $class($this);
173
        endif;
174 78
    }
175
176
177
    // Cleanup results to compute again with new votes
178 80
    protected function cleanupResult () : void
179
    {
180
        // Reset state
181 80
        if ($this->_State > 2) : 
182 7
            $this->_State = 2;
183
        endif;
184
185
            //////
186
187
        // Clean pairwise
188 80
        $this->_Pairwise = null;
189
190
        // Algos
191 80
        $this->_Calculator = null;
192 80
    }
193
194
195 75
    protected function formatResultOptions (array $arg) : array
196
    {
197
        // About tag filter
198 75
        if (isset($arg['tags'])):
199 2
            $arg['%tagFilter'] = true;
200
201 2
            if ( !isset($arg['withTag']) || !is_bool($arg['withTag']) ) :
202 2
                $arg['withTag'] = true;
203
            endif;
204
        else:
205 75
            $arg['%tagFilter'] = false;
206
        endif;
207
208 75
        return $arg;
209
    }
210
211
212
    //:: GET RAW DATA :://
213
214 77
    public function getPairwise (bool $explicit = true)
215
    {
216 77
        $this->prepareResult();
217
218 77
        return (!$explicit) ? $this->_Pairwise : $this->_Pairwise->getExplicitPairwise();
219
    }
220
}
221