Passed
Push — master ( 88b497...e86a88 )
by Boudry
03:07
created

VotesProcess::getVotesListAsString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
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\CondorcetException;
13
use Condorcet\CondorcetUtil;
14
use Condorcet\Vote;
15
use Condorcet\DataManager\VotesManager;
16
17
// Manage Results for Election class
18
trait VotesProcess
19
{
20
21
/////////// CONSTRUCTOR ///////////
22
23
    // Data and global options
24
    protected $_Votes; // Votes list
25
    protected $_ignoreStaticMaxVote = false;
26
27
28 1
    public function ignoreMaxVote (bool $state = true) : bool
29
    {
30 1
        return $this->_ignoreStaticMaxVote = $state;
31
    }
32
33
34
/////////// VOTES LIST ///////////
35
36
    // How many votes are registered ?
37 10
    public function countVotes ($tag = null, bool $with = true) : int
38
    {
39 10
        return $this->_Votes->countVotes(VoteUtil::tagsConvert($tag),$with);
40
    }
41
42
    // Get the votes registered list
43 9
    public function getVotesList ($tag = null, bool $with = true) : array
44
    {
45 9
        return $this->_Votes->getVotesList(VoteUtil::tagsConvert($tag), $with);
46
    }
47
48 4
    public function getVotesListAsString () : string
49
    {
50 4
        return $this->_Votes->getVotesListAsString();
51
    }
52
53 81
    public function getVotesManager () : VotesManager {
54 81
        return $this->_Votes;
55
    }
56
57 4
    public function getVoteKey (Vote $vote) {
58 4
        return $this->_Votes->getVoteKey($vote);
59
    }
60
61
62
/////////// ADD & REMOVE VOTE ///////////
63
64
    // Add a single vote. Array key is the rank, each candidate in a rank are separate by ',' It is not necessary to register the last rank.
65 98
    public function addVote ($vote, $tag = null) : Vote
66
    {
67 98
        $this->prepareVoteInput($vote, $tag);
68
69
        // Check Max Vote Count
70 98
        if ( self::$_maxVoteNumber !== null && !$this->_ignoreStaticMaxVote && $this->countVotes() >= self::$_maxVoteNumber ) :
71 1
            throw new CondorcetException(16, self::$_maxVoteNumber);
72
        endif;
73
74
75
        // Register vote
76 98
        return $this->registerVote($vote, $tag); // Return the vote object
77
    }
78
79
    // return True or throw an Exception
80 5
    public function prepareModifyVote (Vote $existVote)
81
    {
82
        try {
83 5
            $this->prepareVoteInput($existVote);
84 5
            $this->setStateToVote();
85
        }
86
        catch (\Exception $e) {
87
            throw $e;
88
        }
89 5
    }
90
91 98
    public function checkVoteCandidate (Vote $vote) : bool
92
    {
93 98
        $linkCount = $vote->countLinks();
94 98
        $links = $vote->getLinks();
95
96 98
        $mirror = $vote->getRanking();
97 98
        $change = false;
98 98
        foreach ($vote as $rank => $choice) :
99 98
            foreach ($choice as $choiceKey => $candidate) :
100 98
                if ( !$this->existCandidateId($candidate, true) ) :
101 91
                    if ($candidate->getProvisionalState() && $this->existCandidateId($candidate, false)) :
102 90
                        if ( $linkCount === 0 || ($linkCount === 1 && reset($links) === $this) ) :
103 90
                            $mirror[$rank][$choiceKey] = $this->_Candidates[$this->getCandidateKey((string) $candidate)];
104 90
                            $change = true;
105
                        else :
106 98
                            return false;
107
                        endif;
108
                    endif;
109
                endif;
110
            endforeach;
111
        endforeach;
112
113 98
        if ($change) :
114 90
            $vote->setRanking(  $mirror,
115 90
                                ( abs($vote->getTimestamp() - microtime(true)) > 0.5 ) ? ($vote->getTimestamp() + 0.001) : null
116
            );
117
        endif;
118
119 98
        return true;
120
    }
121
122
    // Write a new vote
123 98
    protected function registerVote (Vote $vote, $tag = null) : Vote
124
    {
125
        // Vote identifiant
126 98
        $vote->addTags($tag);
127
        
128
        // Register
129
        try {
130 98
            $vote->registerLink($this);
131 98
            $this->_Votes[] = $vote;
132
        } catch (CondorcetException $e) {
133
            // Security : Check if vote object not already register
134
            throw new CondorcetException(6,'Vote object already registred');
135
        }
136
137 98
        return $vote;
138
    }
139
140 5
    public function removeVote ($in, bool $with = true) : array
141
    {    
142 5
        $rem = [];
143
144 5
        if ($in instanceof Vote) :
145 4
            $key = $this->getVoteKey($in);
146 4
            if ($key !== false) :
147 4
                $this->_Votes[$key]->destroyLink($this);
148
149 4
                $rem[] = $this->_Votes[$key];
150
151 4
                unset($this->_Votes[$key]);
152
            endif;
153
        else :
154
            // Prepare Tags
155 3
            $tag = VoteUtil::tagsConvert($in);
156
157
            // Deleting
158 3
            foreach ($this->getVotesList($tag, $with) as $key => $value) :
159 3
                $this->_Votes[$key]->destroyLink($this);
160
161 3
                $rem[] = $this->_Votes[$key];
162
163 3
                unset($this->_Votes[$key]);
164
            endforeach;
165
166
        endif;
167
168 5
        return $rem;
169
    }
170
171
172
/////////// PARSE VOTE ///////////
173
174
    // Return the well formated vote to use.
175 98
    protected function prepareVoteInput (&$vote, $tag = null) : void
176
    {
177 98
        if (!($vote instanceof Vote)) :
178 82
            $vote = new Vote ($vote, $tag);
179
        endif;
180
181
        // Check array format && Make checkVoteCandidate
182 98
        if ( !$this->checkVoteCandidate($vote) ) :
183
            throw new CondorcetException(5);
184
        endif;
185 98
    }
186
187 2
    public function jsonVotes (string $input)
188
    {
189 2
        $input = CondorcetUtil::prepareJson($input);
190 1
        if ($input === false) :
191
            return $input;
192
        endif;
193
194
            //////
195
196 1
        $adding = [];
197
198 1
        foreach ($input as $record) :
199 1
            if (empty($record['vote'])) :
200 1
                continue;
201
            endif;
202
203 1
            $tags = (!isset($record['tag'])) ? null : $record['tag'];
204 1
            $multi = (!isset($record['multi'])) ? 1 : $record['multi'];
205
206 1
            for ($i = 0; $i < $multi; $i++) :
207 1
                if (self::$_maxParseIteration !== null && $this->countVotes() >= self::$_maxParseIteration) :
208
                    throw new CondorcetException(12, self::$_maxParseIteration);
209
                endif;
210
211
                try {
212 1
                    $adding[] = $this->addVote($record['vote'], $tags);
213
                } catch (\Exception $e) {
214
                    // Ignore invalid vote
215
                }
216
            endfor;
217
        endforeach;
218
219 1
        return $adding;
220
    }
221
222 70
    public function parseVotes (string $input, bool $allowFile = true)
223
    {
224 70
        $input = CondorcetUtil::prepareParse($input, $allowFile);
225 70
        if ($input === false) :
226
            return $input;
227
        endif;
228
229
        // Check each lines
230 70
        $adding = [];
231 70
        foreach ($input as $line) :
232
            // Empty Line
233 70
            if (empty($line)) :
234 63
                continue;
235
            endif;
236
237
            // Multiples
238 70
            $is_multiple = mb_strpos($line, '*');
239 70 View Code Duplication
            if ($is_multiple !== false) :
240 63
                $multiple = trim( substr($line, $is_multiple + 1) );
241
242
                // Errors
243 63
                if ( !is_numeric($multiple) ) :
244
                    throw new CondorcetException(13, null);
245
                endif;
246
247 63
                $multiple = intval($multiple);
248
249
                // Reformat line
250 63
                $line = substr($line, 0, $is_multiple);
251
            else :
252 9
                $multiple = 1;
253
            endif;
254
255
            // Vote Weight
256 70
            $is_voteWeight = mb_strpos($line, '^');
257 70 View Code Duplication
            if ($is_voteWeight !== false) :
258 2
                $weight = trim( substr($line, $is_voteWeight + 1) );
259
260
                // Errors
261 2
                if ( !is_numeric($weight) ) :
262
                    throw new CondorcetException(13, null);
263
                endif;
264
265 2
                $weight = intval($weight);
266
267
                // Reformat line
268 2
                $line = substr($line, 0, $is_voteWeight);
269
            else :
270 69
                $weight = 1;
271
            endif;
272
273
            // Tags + vote
274 70
            if (mb_strpos($line, '||') !== false) :
275 4
                $data = explode('||', $line);
276
277 4
                $vote = $data[1];
278 4
                $tags = $data[0];
279
            // Vote without tags
280
            else :
281 69
                $vote = $line;
282 69
                $tags = null;
283
            endif;
284
285
            // addVote
286 70
            for ($i = 0; $i < $multiple; $i++) :
287 70 View Code Duplication
                if (self::$_maxParseIteration !== null && count($adding) >= self::$_maxParseIteration) :
288 1
                    throw new CondorcetException(12, self::$_maxParseIteration);
289
                endif;
290
291
                try {
292 70
                    $adding[] = ($newVote = $this->addVote($vote, $tags));
293 70
                    $newVote->setWeight($weight);
294 1
                } catch (CondorcetException $e) {}
1 ignored issue
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
295
            endfor;
296
        endforeach;
297
298 70
        return $adding;
299
    }
300
301
}
302