Completed
Push — master ( 922b0c...88b497 )
by Boudry
03:58
created

Election::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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 25 and the first side effect is on line 117.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
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;
11
12
use Condorcet\Condorcet;
13
use Condorcet\CondorcetException;
14
use Condorcet\CondorcetVersion;
15
use Condorcet\Result;
16
use Condorcet\CondorcetUtil;
17
use Condorcet\Vote;
18
use Condorcet\DataManager\VotesManager;
19
use Condorcet\DataManager\DataHandlerDrivers\DataHandlerDriverInterface;
20
use Condorcet\ElectionProcess\ResultManager;
21
use Condorcet\Timer\Manager as Timer_Manager;
22
23
24
// Base Condorcet class
25
class Election
26
{
27
28
/////////// PROPERTIES ///////////
29
30
    public const MAX_LENGTH_CANDIDATE_ID = 30; // Max length for candidate identifiant string
31
32
    protected static $_maxParseIteration = null;
33
    protected static $_maxVoteNumber = null;
34
    protected static $_checksumMode = false;
35
36
/////////// STATICS METHODS ///////////
37
38
    // Change max parse iteration
39 1
    public static function setMaxParseIteration (?int $value) : ?int
40
    {
41 1
        self::$_maxParseIteration = $value;
42 1
        return self::$_maxParseIteration;
43
    }
44
45
    // Change max vote number
46 1
    public static function setMaxVoteNumber (?int $value) : ?int
47
    {
48 1
        self::$_maxVoteNumber = $value;
49 1
        return self::$_maxVoteNumber;
50
    }
51
52
53
/////////// CONSTRUCTOR ///////////
54
55
    use CondorcetVersion;
56
57
    // Data and global options
58
    protected $_Candidates = []; // Candidate list
59
    protected $_Votes; // Votes list
60
61
    // Mechanics
62
    protected $_i_CandidateId = 'A';
63
    protected $_State = 1; // 1 = Add Candidates / 2 = Voting / 3 = Some result have been computing
64
    protected $_timer;
65
    protected $_nextVoteTag = 0;
66
    protected $_ignoreStaticMaxVote = false;
67
68
    // Params
69
    protected $_ImplicitRanking = true;
70
    protected $_VoteWeightRule = false;
71
72
    // Result
73
    protected $_ResultManager;
74
75
        //////
76
77 111
    public function __construct ()
78
    {
79 111
        $this->_Candidates = [];
80 111
        $this->_Votes = new VotesManager ($this);
81 111
        $this->_timer = new Timer_Manager;
82 111
    }
83
84 1
    public function __destruct ()
85
    {
86 1
        $this->destroyAllLink();
87 1
    }
88
89 2
    public function __sleep () : array
90
    {
91
        // Don't include others data
92
        $include = [
93 2
            '_Candidates',
94
            '_Votes',
95
96
            '_i_CandidateId',
97
            '_State',
98
            '_nextVoteTag',
99
            '_objectVersion',
100
            '_ignoreStaticMaxVote',
101
102
            '_ImplicitRanking',
103
            '_VoteWeightRule',
104
105
            '_ResultManager'
106
        ];
107
108 2
        !self::$_checksumMode && array_push($include, '_timer');
109
110 2
        return $include;
111
    }
112
113 1
    public function __wakeup ()
114
    {
115 1
        if ( version_compare($this->getObjectVersion('MAJOR'),Condorcet::getVersion('MAJOR'),'!=') ) :
116
            throw new CondorcetException(11, 'Your object version is '.$this->getObjectVersion().' but the class engine version is '.Condorcet::getVersion('ENV'));
117
        endif;
118 1
    }
119
120 1
    public function __clone ()
121
    {
122 1
        $this->_Votes = clone $this->_Votes;
123 1
        $this->_Votes->setElection($this);      
124 1
        $this->registerAllLinks();
125
126 1
        $this->_timer = clone $this->_timer;
127
128 1
        if ($this->_ResultManager !== null) :
129 1
            $this->_ResultManager = clone $this->_ResultManager;
130 1
            $this->_ResultManager->setElection($this);
131
        endif;
132 1
    }
133
134
135
/////////// INTERNAL GENERIC REGULATION ///////////
136
137
138 1
    protected function registerAllLinks () : void
139
    {
140 1
        foreach ($this->_Candidates as $value) :
141 1
            $value->registerLink($this);
142
        endforeach;
143
144 1
        if ($this->_State > 1) :
145 1
            foreach ($this->_Votes as $value) :
146 1
                $value->registerLink($this);
147
            endforeach;
148
        endif;
149 1
    }
150
151 1
    protected function destroyAllLink () : void
152
    {
153 1
        foreach ($this->_Candidates as $value) :
154 1
            $value->destroyLink($this);
155
        endforeach;
156
157 1
        if ($this->_State > 1) :
158 1
            foreach ($this->_Votes as $value) :
159 1
                $value->destroyLink($this);
160
            endforeach;
161
        endif;
162 1
    }
163
164
        //////
165
166
167 2
    public function getGlobalTimer (bool $float = false) {
168 2
        return $this->_timer->getGlobalTimer($float);
169
    }
170
171 2
    public function getLastTimer (bool $float = false) {
172 2
        return $this->_timer->getLastTimer($float);
173
    }
174
175 80
    public function getTimerManager () : Timer_Manager {
176 80
        return $this->_timer;
177
    }
178
179 1
    public function getChecksum () : string
180
    {
181 1
        self::$_checksumMode = true;
182
183 1
        $r = hash_init('sha256');
184
185 1
        foreach ($this->_Candidates as $value) :
186 1
            hash_update($r, (string) $value);
187
        endforeach;
188
189 1
        foreach ($this->_Votes as $value) :
190 1
            hash_update($r, (string) $value);
191
        endforeach;
192
193 1
        $this->_ResultManager !== null
194 1
            && hash_update($r,serialize($this->_ResultManager->getPairwise()->getExplicitPairwise()));
195
196 1
        hash_update($r, $this->getObjectVersion('major'));
197
198 1
        self::$_checksumMode = false;
199
200 1
        return hash_final($r);
201
    }
202
203 1
    public function ignoreMaxVote (bool $state = true) : bool
204
    {
205 1
        return $this->_ignoreStaticMaxVote = $state;
206
    }
207
208 86
    public function getImplicitRankingRule () : bool
209
    {
210 86
        return $this->_ImplicitRanking;
211
    }
212
213 3
    public function setImplicitRanking (bool $rule = true) : bool
214
    {
215 3
        $this->_ImplicitRanking = $rule;
216 3
        $this->cleanupResult();
217 3
        return $this->getImplicitRankingRule();
218
    }
219
220 82
    public function isVoteWeightIsAllowed () : bool
221
    {
222 82
        return $this->_VoteWeightRule;
223
    }
224
225 1
    public function allowVoteWeight (bool $rule = true) : bool
226
    {
227 1
        $this->_VoteWeightRule = $rule;
228 1
        $this->cleanupResult();
229 1
        return $this->isVoteWeightIsAllowed();
230
    }
231
232
233
/////////// CANDIDATES ///////////
234
235
236
    // Add a vote candidate before voting
237 106
    public function addCandidate ($candidate_id = null) : Candidate
238
    {
239
        // only if the vote has not started
240 106
        if ( $this->_State > 1 ) :
241
            throw new CondorcetException(2);
242
        endif;
243
244
        // Filter
245 106
        if ( is_bool($candidate_id) || is_array($candidate_id) || (is_object($candidate_id) && !($candidate_id instanceof Candidate)) ) :
246
            throw new CondorcetException(1, $candidate_id);
247
        endif;
248
249
250
        // Process
251 106
        if ( empty($candidate_id) ) :
252 5
            while ( !$this->canAddCandidate($this->_i_CandidateId) ) :
253 5
                $this->_i_CandidateId++;
254
            endwhile;
255
256 5
            $newCandidate = new Candidate($this->_i_CandidateId);
257
        else : // Try to add the candidate_id
258 103
            $newCandidate = ($candidate_id instanceof Candidate) ? $candidate_id : new Candidate ((string) $candidate_id);
259
260 103
            if ( !$this->canAddCandidate($newCandidate) ) :
261
                throw new CondorcetException(3,$candidate_id);
262
            endif;
263
        endif;
264
265
        // Register it
266 106
        $this->_Candidates[] = $newCandidate;
267
268
        // Linking
269 106
        $newCandidate->registerLink($this);
270
271
        // Disallow other candidate object name matching 
272 106
        $newCandidate->setProvisionalState(false);
273
274 106
        return $newCandidate;
275
    }
276
277 106
        public function canAddCandidate ($candidate_id) : bool
278
        {
279 106
            return !$this->existCandidateId($candidate_id, false);
280
        }
281
282
283
    // Destroy a register vote candidate before voting
284 3
    public function removeCandidate ($list) : array
285
    {
286
        // only if the vote has not started
287 3
        if ( $this->_State > 1 ) :
288
            throw new CondorcetException(2);
289
        endif;
290
        
291 3
        if ( !is_array($list) ) :
292 3
            $list = [$list];
293
        endif;
294
295 3
        foreach ($list as &$candidate_id) :
296 3
            $candidate_key = $this->getCandidateKey($candidate_id);
297
298 3
            if ( $candidate_key === false ) :
299
                throw new CondorcetException(4,$candidate_id);
300
            endif;
301
302 3
            $candidate_id = $candidate_key;
303
        endforeach;
304
305 3
        $rem = [];
306 3
        foreach ($list as $candidate_key) :
307 3
            $this->_Candidates[$candidate_key]->destroyLink($this);
308
309 3
            $rem[] = $this->_Candidates[$candidate_key];
310
311 3
            unset($this->_Candidates[$candidate_key]);
312
        endforeach;
313
314 3
        return $rem;
315
    }
316
317
318 1
    public function jsonCandidates (string $input)
319
    {
320 1
        $input = CondorcetUtil::prepareJson($input);
321 1
        if ($input === false) :
322
            return $input;
323
        endif;
324
325
            //////
326
327 1
        $adding = [];
328 1
        foreach ($input as $candidate) :
329
            try {
330 1
                $adding[] = $this->addCandidate($candidate);
331
            }
332 1
            catch (CondorcetException $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
333
        endforeach;
334
335 1
        return $adding;
336
    }
337
338 7
    public function parseCandidates (string $input, bool $allowFile = true)
339
    {
340 7
        $input = CondorcetUtil::prepareParse($input, $allowFile);
341 7
        if ($input === false) :
342
            return $input;
343
        endif;
344
345 7
        $adding = [];
346 7
        foreach ($input as $line) :
347
            // Empty Line
348 7
            if (empty($line)) :
349 1
                continue;
350
            endif;
351
352
            // addCandidate
353
            try {
354 7
                if (self::$_maxParseIteration !== null && count($adding) >= self::$_maxParseIteration) :
355
                    throw new CondorcetException(12, self::$_maxParseIteration);
356
                endif;
357
358 7
                $adding[] = $this->addCandidate($line);
359
            } catch (CondorcetException $e) {
360
                if ($e->getCode() === 12)
361 7
                    {throw $e;}
362
            }
363
        endforeach;
364
365 7
        return $adding;
366
    }
367
368
369
        //:: CANDIDATES TOOLS :://
370
371
        // Count registered candidates
372 87
        public function countCandidates () : int
373
        {
374 87
            return count($this->_Candidates);
375
        }
376
377
        // Get the list of registered CANDIDATES
378 88
        public function getCandidatesList (bool $stringMode = false) : array
379
        {
380 88
            if (!$stringMode) :
381 86
                return $this->_Candidates;
382
            else :
383 4
                $result = [];
384
385 4
                foreach ($this->_Candidates as $candidateKey => &$oneCandidate) :
386 4
                    $result[$candidateKey] = $oneCandidate->getName();
387
                endforeach;
388
389 4
                return $result;
390
            endif;
391
        }
392
393 93
        public function getCandidateKey ($candidate_id)
394
        {
395 93
            if ($candidate_id instanceof Candidate) :
396 80
                return array_search($candidate_id, $this->_Candidates, true);
397
            else:
398 91
                return array_search(trim((string) $candidate_id), $this->_Candidates, false);
399
            endif;
400
        }
401
402 77
        public function getCandidateId (int $candidate_key, bool $onlyName = false)
403
        {
404 77
            if (!array_key_exists($candidate_key, $this->_Candidates)) :
405
                return false;
406
            else :
407 77
                return ($onlyName) ? $this->_Candidates[$candidate_key]->getName() : $this->_Candidates[$candidate_key];
408
            endif;
409
        }
410
411 106
        public function existCandidateId ($candidate_id, bool $strict = true) : bool
412
        {
413 106
            return ($strict) ? in_array($candidate_id, $this->_Candidates, true) : in_array((string) $candidate_id, $this->_Candidates);
414
        }
415
416 3
        public function getCandidateObjectByName (string $s)
417
        {
418 3
            foreach ($this->_Candidates as $oneCandidate) :
419
420 3
                if ($oneCandidate->getName() === $s) :
421 3
                    return $oneCandidate;
422
                endif;
423
            endforeach;
424
425 1
            return false;
426
        }
427
428
429
430
/////////// VOTING ///////////
431
432
433
    // Close the candidate config, be ready for voting (optional)
434 98
    public function setStateToVote () : bool
435
    {
436 98
        if ( $this->_State === 1 ) :
437 98
                if (empty($this->_Candidates)) :
438
                    throw new CondorcetException(20);
439
                endif;
440
441 98
                $this->_State = 2;
442
443
        // If voting continues after a first set of results
444 86
        elseif ( $this->_State > 2 ) :
445 5
                $this->cleanupResult();
446
        endif;
447
448 98
        return true;
449
    }
450
451
452
    // 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.
453 98
    public function addVote ($vote, $tag = null) : Vote
454
    {
455 98
        $this->prepareVoteInput($vote, $tag);
456
457
        // Check Max Vote Count
458 98
        if ( self::$_maxVoteNumber !== null && !$this->_ignoreStaticMaxVote && $this->countVotes() >= self::$_maxVoteNumber ) :
459 1
            throw new CondorcetException(16, self::$_maxVoteNumber);
460
        endif;
461
462
463
        // Register vote
464 98
        return $this->registerVote($vote, $tag); // Return the vote object
465
    }
466
467
        // return True or throw an Exception
468 5
        public function prepareModifyVote (Vote $existVote)
469
        {
470
            try {
471 5
                $this->prepareVoteInput($existVote);
472 5
                $this->setStateToVote();
473
            }
474
            catch (\Exception $e) {
475
                throw $e;
476
            }
477 5
        }
478
479
        // Return the well formated vote to use.
480 98
        protected function prepareVoteInput (&$vote, $tag = null) : void
481
        {
482 98
            if (!($vote instanceof Vote)) :
483 82
                $vote = new Vote ($vote, $tag);
484
            endif;
485
486
            // Check array format && Make checkVoteCandidate
487 98
            if ( !$this->checkVoteCandidate($vote) ) :
488
                throw new CondorcetException(5);
489
            endif;
490 98
        }
491
492
493 98
        public function checkVoteCandidate (Vote $vote) : bool
494
        {
495 98
            $linkCount = $vote->countLinks();
496 98
            $links = $vote->getLinks();
497
498 98
            $mirror = $vote->getRanking();
499 98
            $change = false;
500 98
            foreach ($vote as $rank => $choice) :
501 98
                foreach ($choice as $choiceKey => $candidate) :
502 98
                    if ( !$this->existCandidateId($candidate, true) ) :
503 91
                        if ($candidate->getProvisionalState() && $this->existCandidateId($candidate, false)) :
504 90
                            if ( $linkCount === 0 || ($linkCount === 1 && reset($links) === $this) ) :
505 90
                                $mirror[$rank][$choiceKey] = $this->_Candidates[$this->getCandidateKey((string) $candidate)];
506 90
                                $change = true;
507
                            else :
508 98
                                return false;
509
                            endif;
510
                        endif;
511
                    endif;
512
                endforeach;
513
            endforeach;
514
515 98
            if ($change) :
516 90
                $vote->setRanking(
517 90
                                    $mirror,
518 90
                                    ( abs($vote->getTimestamp() - microtime(true)) > 0.5 ) ? ($vote->getTimestamp() + 0.001) : null
519
                );
520
            endif;
521
522 98
            return true;
523
        }
524
525
        // Write a new vote
526 98
        protected function registerVote (Vote $vote, $tag = null) : Vote
527
        {
528
            // Vote identifiant
529 98
            $vote->addTags($tag);
530
            
531
            // Register
532
            try {
533 98
                $vote->registerLink($this);
534 98
                $this->_Votes[] = $vote;
535
            } catch (CondorcetException $e) {
536
                // Security : Check if vote object not already register
537
                throw new CondorcetException(6,'Vote object already registred');
538
            }
539
540 98
            return $vote;
541
        }
542
543
544 5
    public function removeVote ($in, bool $with = true) : array
545
    {    
546 5
        $rem = [];
547
548 5
        if ($in instanceof Vote) :
549 4
            $key = $this->getVoteKey($in);
550 4
            if ($key !== false) :
551 4
                $this->_Votes[$key]->destroyLink($this);
552
553 4
                $rem[] = $this->_Votes[$key];
554
555 4
                unset($this->_Votes[$key]);
556
            endif;
557
        else :
558
            // Prepare Tags
559 3
            $tag = Vote::tagsConvert($in);
560
561
            // Deleting
562 3
            foreach ($this->getVotesList($tag, $with) as $key => $value) :
563 3
                $this->_Votes[$key]->destroyLink($this);
564
565 3
                $rem[] = $this->_Votes[$key];
566
567 3
                unset($this->_Votes[$key]);
568
            endforeach;
569
570
        endif;
571
572 5
        return $rem;
573
    }
574
575
576 2
    public function jsonVotes (string $input)
577
    {
578 2
        $input = CondorcetUtil::prepareJson($input);
579 1
        if ($input === false) :
580
            return $input;
581
        endif;
582
583
            //////
584
585 1
        $adding = [];
586
587 1
        foreach ($input as $record) :
588 1
            if (empty($record['vote'])) :
589 1
                continue;
590
            endif;
591
592 1
            $tags = (!isset($record['tag'])) ? null : $record['tag'];
593 1
            $multi = (!isset($record['multi'])) ? 1 : $record['multi'];
594
595 1
            for ($i = 0; $i < $multi; $i++) :
596 1
                if (self::$_maxParseIteration !== null && $this->countVotes() >= self::$_maxParseIteration) :
597
                    throw new CondorcetException(12, self::$_maxParseIteration);
598
                endif;
599
600
                try {
601 1
                    $adding[] = $this->addVote($record['vote'], $tags);
602
                } catch (\Exception $e) {}
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
603
            endfor;
604
        endforeach;
605
606 1
        return $adding;
607
    }
608
609 70
    public function parseVotes (string $input, bool $allowFile = true)
610
    {
611 70
        $input = CondorcetUtil::prepareParse($input, $allowFile);
612 70
        if ($input === false) :
613
            return $input;
614
        endif;
615
616
        // Check each lines
617 70
        $adding = [];
618 70
        foreach ($input as $line) :
619
            // Empty Line
620 70
            if (empty($line)) :
621 63
                continue;
622
            endif;
623
624
            // Multiples
625 70
            $is_multiple = mb_strpos($line, '*');
626 70
            if ($is_multiple !== false) :
627 63
                $multiple = trim( substr($line, $is_multiple + 1) );
628
629
                // Errors
630 63
                if ( !is_numeric($multiple) ) :
631
                    throw new CondorcetException(13, null);
632
                endif;
633
634 63
                $multiple = intval($multiple);
635
636
                // Reformat line
637 63
                $line = substr($line, 0, $is_multiple);
638
            else :
639 9
                $multiple = 1;
640
            endif;
641
642
            // Vote Weight
643 70
            $is_voteWeight = mb_strpos($line, '^');
644 70
            if ($is_voteWeight !== false) :
645 2
                $weight = trim( substr($line, $is_voteWeight + 1) );
646
647
                // Errors
648 2
                if ( !is_numeric($weight) ) :
649
                    throw new CondorcetException(13, null);
650
                endif;
651
652 2
                $weight = intval($weight);
653
654
                // Reformat line
655 2
                $line = substr($line, 0, $is_voteWeight);
656
            else :
657 69
                $weight = 1;
658
            endif;
659
660
            // Tags + vote
661 70
            if (mb_strpos($line, '||') !== false) :
662 4
                $data = explode('||', $line);
663
664 4
                $vote = $data[1];
665 4
                $tags = $data[0];
666
            // Vote without tags
667
            else :
668 69
                $vote = $line;
669 69
                $tags = null;
670
            endif;
671
672
            // addVote
673 70
            for ($i = 0; $i < $multiple; $i++) :
674 70
                if (self::$_maxParseIteration !== null && count($adding) >= self::$_maxParseIteration) :
675 1
                    throw new CondorcetException(12, self::$_maxParseIteration);
676
                endif;
677
678
                try {
679 70
                    $adding[] = ($newVote = $this->addVote($vote, $tags));
680 70
                    $newVote->setWeight($weight);
681 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...
682
            endfor;
683
        endforeach;
684
685 70
        return $adding;
686
    }
687
688
689
    //:: LARGE ELECTION MODE :://
690
691 3
    public function setExternalDataHandler (DataHandlerDriverInterface $driver) : bool
692
    {
693 3
        if (!$this->_Votes->isUsingHandler()) :
694 3
            $this->_Votes->importHandler($driver);
695 3
            return true;
696
        else :
697
            throw new CondorcetException(24);
698
        endif;
699
    }
700
701 1
    public function removeExternalDataHandler () : bool
702
    {
703 1
        if ($this->_Votes->isUsingHandler()) :
704 1
            $this->_Votes->closeHandler();
705 1
            return true;
706
        else :
707
            throw new CondorcetException(23);
708
        endif;
709
    }
710
711
712
    //:: VOTING TOOLS :://
713
714
    // How many votes are registered ?
715 10
    public function countVotes ($tag = null, bool $with = true) : int
716
    {
717 10
        return $this->_Votes->countVotes(Vote::tagsConvert($tag),$with);
718
    }
719
720
    // Get the votes registered list
721 9
    public function getVotesList ($tag = null, bool $with = true) : array
722
    {
723 9
        return $this->_Votes->getVotesList(Vote::tagsConvert($tag), $with);
724
    }
725
726 4
    public function getVotesListAsString () : string
727
    {
728 4
        return $this->_Votes->getVotesListAsString();
729
    }
730
731 81
    public function getVotesManager () : VotesManager {
732 81
        return $this->_Votes;
733
    }
734
735 4
    public function getVoteKey (Vote $vote) {
736 4
        return $this->_Votes->getVoteKey($vote);
737
    }
738
739
740
/////////// RESULTS ///////////
741
742
    //:: PUBLIC FUNCTIONS :://
743
744
    // Generic function for default result with ability to change default object method
745 48
    public function getResult ($method = true, array $options = []) : Result
746
    {
747 48
        $this->prepareResult();
748
749 48
        return $this->_ResultManager->getResult($method,$options);
750
    }
751
752
753 78
    public function getWinner (?string $substitution = null)
754
    {
755 78
        $this->prepareResult();
756
757 78
        return $this->_ResultManager->getWinner($substitution);
758
    }
759
760
761 75
    public function getLoser (?string $substitution = null)
762
    {
763 75
        $this->prepareResult();
764
765 75
        return $this->_ResultManager->getLoser($substitution);
766
    }
767
768
769 1
    public function computeResult ($method = true) : void
770
    {
771 1
        $this->getResult($method);
772 1
    }
773
774
775
    //:: TOOLS FOR RESULT PROCESS :://
776
777
778
    // Prepare to compute results & caching system
779 80
    protected function prepareResult () : bool
780
    {
781 80
        if ($this->_State > 2) :
782 77
            return false;
783 80
        elseif ($this->_State === 2) :
784 80
            $this->cleanupResult();
785
786 80
            $this->_ResultManager = new ResultManager ($this);
787
788
            // Change state to result
789 80
            $this->_State = 3;
790
791
            // Return
792 80
            return true;
793
        else :
794
            throw new CondorcetException(6);
795
        endif;
796
    }
797
798
799
    // Cleanup results to compute again with new votes
800 80
    protected function cleanupResult () : void
801
    {
802
        // Reset state
803 80
        if ($this->_State > 2) : 
804 7
            $this->_State = 2;
805
        endif;
806
807
            //////
808
809 80
        $this->_ResultManager = null;
810 80
    }
811
812
813
    //:: GET RAW DATA :://
814
815 77
    public function getPairwise (bool $explicit = true)
816
    {
817 77
        $this->prepareResult();
818
819 77
        $pairwise = $this->_ResultManager->getPairwise($explicit);
820
821 77
        return (!$explicit) ? $pairwise : $pairwise->getExplicitPairwise($explicit);
822
    }
823
824
}
825