test adding condorcet vote
This commit is contained in:
82
include/Condorcet/Tests/Examples/ExamplesTest.php
Normal file
82
include/Condorcet/Tests/Examples/ExamplesTest.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Examples;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ExamplesTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testOverviewExample(): void
|
||||
{
|
||||
$r = true;
|
||||
|
||||
try {
|
||||
include __DIR__.'/../../Examples/1. Overview.php';
|
||||
} catch (\Exception $e) {
|
||||
$r = false;
|
||||
throw $e;
|
||||
}
|
||||
|
||||
self::assertTrue($r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testAdvancedObjectManagementExample(): void
|
||||
{
|
||||
$r = true;
|
||||
|
||||
try {
|
||||
include __DIR__.'/../../Examples/2. AdvancedObjectManagement.php';
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
$r = false;
|
||||
}
|
||||
|
||||
self::assertTrue($r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testGlobalHtmlExample(): void
|
||||
{
|
||||
$r = true;
|
||||
|
||||
try {
|
||||
ob_start();
|
||||
include __DIR__.'/../../Examples/Examples-with-html/A.Global_Example.php';
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
$r = false;
|
||||
}
|
||||
|
||||
self::assertTrue($r);
|
||||
}
|
||||
|
||||
/**
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testRankingManipulationHtmlExample(): void
|
||||
{
|
||||
$r = true;
|
||||
|
||||
try {
|
||||
ob_start();
|
||||
include __DIR__.'/../../Examples/Examples-with-html/B.Ranking_Manipulation.php';
|
||||
ob_end_clean();
|
||||
} catch (\Exception $e) {
|
||||
$r = false;
|
||||
throw $e;
|
||||
}
|
||||
|
||||
self::assertTrue($r);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
A > B > C
|
||||
A > B > C * 4;tag1 || A > B > C*4 #Coucou
|
||||
|
||||
A < B < C * 10
|
||||
D <> B
|
||||
A > B > C
|
10
include/Condorcet/Tests/README.md
Normal file
10
include/Condorcet/Tests/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
> **[Presentation](../README.md) | [Manual](https://github.com/julien-boudry/Condorcet/wiki) | [Methods References](../Documentation/README.md) | Tests**
|
||||
|
||||
#### ~300 tests and more than 1000 assertions to explore on this path
|
||||
|
||||
* The implementation tests proving the implementations of each method are in this directory **=>> [Algo Tests](lib/Algo/)**
|
||||
|
||||
#### Execute the tests suite
|
||||
```
|
||||
./vendor/bin/phpunit
|
||||
```
|
87
include/Condorcet/Tests/ReadmeQuickExampleTest.php
Normal file
87
include/Condorcet/Tests/ReadmeQuickExampleTest.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Candidate, Condorcet, Election, Result, Vote};
|
||||
use CondorcetPHP\Condorcet\Utils\CondorcetUtil;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ReadmeQuickExampleTest extends TestCase
|
||||
{
|
||||
public function testReadmeQuickExample(): void
|
||||
{
|
||||
$myElection1 = new Election;
|
||||
|
||||
// Create your own candidate object
|
||||
$candidate1 = new Candidate('Candidate 1');
|
||||
$candidate2 = new Candidate('Candidate 2');
|
||||
$candidate3 = new Candidate('Candidate 3');
|
||||
|
||||
// Register your candidates
|
||||
$myElection1->addCandidate($candidate1);
|
||||
$myElection1->addCandidate($candidate2);
|
||||
$myElection1->addCandidate($candidate3);
|
||||
$candidate4 = $myElection1->addCandidate('Candidate 4');
|
||||
|
||||
// Add some votes, by some ways
|
||||
$myElection1->addVote(
|
||||
[
|
||||
$candidate2, // 1
|
||||
[$candidate1, $candidate4], // 2 - Tie
|
||||
// Last rank is optionnal. Here it's : $candidate3
|
||||
]
|
||||
);
|
||||
|
||||
$myElection1->addVote('Candidate 2 > Candidate 3 > Candidate 4 = Candidate 1'); // last rank can also be omitted
|
||||
|
||||
$myElection1->parseVotes(
|
||||
'tagX || Candidate 1 > Candidate 2 = Candidate 4 > Candidate 3 * 4
|
||||
tagX, tagY || Candidate 3 > Candidate 1 * 3'
|
||||
); // Powerfull, it add 7 votes
|
||||
|
||||
$myElection1->addVote(new Vote(
|
||||
[
|
||||
$candidate4,
|
||||
$candidate2,
|
||||
// You can ignore the over. They will be at the last rank in the contexte of each election.
|
||||
]
|
||||
));
|
||||
|
||||
|
||||
// Get Result
|
||||
|
||||
// Natural Condorcet Winner
|
||||
$myWinner = $myElection1->getCondorcetWinner(); // Return a candidate object
|
||||
$this->assertEquals('My winner is Candidate 1<br>', 'My winner is ' . $myWinner->getName() . '<br>');
|
||||
|
||||
// Natural Condorcet Loser
|
||||
$myLoser = $myElection1->getCondorcetLoser(); // Return a candidate object
|
||||
$this->assertEquals('My loser is Candidate 3', 'My loser is ' . $myLoser->getName());
|
||||
|
||||
// Schulze Ranking
|
||||
$myResultBySchulze = $myElection1->getResult('Schulze'); // Return a multi-dimensional array, filled with objects Candidate (multi-dimensional if tie on a rank)
|
||||
# Echo it easily
|
||||
$this->assertEquals([1=>'Candidate 1', 2=>'Candidate 2', 3=>'Candidate 4', 4=>'Candidate 3'], CondorcetUtil::format($myResultBySchulze));
|
||||
|
||||
// Get Schulze advanced computing data & stats
|
||||
$mySchulzeStats = $myElection1->getResult('Schulze')->getStats();
|
||||
|
||||
// Get Copeland Ranking
|
||||
$myResultByCopeland = $myElection1->getResult('Copeland');
|
||||
|
||||
// Get Pairwise
|
||||
$myPairwise = $myElection1->getPairwise();
|
||||
|
||||
|
||||
// How long computation time behind us?
|
||||
$timer = $myElection1->getGlobalTimer();
|
||||
|
||||
// SHA-2 checksum and sleep
|
||||
$myChecksum = $myElection1->getChecksum();
|
||||
$toStore = serialize($myElection1);
|
||||
$comeBack = unserialize($toStore);
|
||||
$this->assertEquals($comeBack->getChecksum(), $myChecksum); // True
|
||||
}
|
||||
}
|
@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Borda;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BordaCountTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('Borda Count', 'Starting', 1);
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/M%C3%A9thode_Borda
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'B',
|
||||
2 => 'C',
|
||||
3 => 'A',
|
||||
4 => 'D', ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'B' => 294,
|
||||
'C' => 273,
|
||||
'A' => 226,
|
||||
'D' => 207, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/M%C3%A9thode_Borda
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
B>A>C>D * 30
|
||||
B>A>D>C * 30
|
||||
A>C>D>B * 25
|
||||
A>D>C>B ^ 15
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'B',
|
||||
3 => 'C',
|
||||
4 => 'D', ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'A' => 340,
|
||||
'B' => 280,
|
||||
'C' => 195,
|
||||
'D' => 185, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => ['B', 'C'], ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'A' => 3,
|
||||
'B' => 1.5,
|
||||
'C' => 1.5, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => ['B', 'C'], ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'A' => 3,
|
||||
'B' => 0,
|
||||
'C' => 0, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/M%C3%A9thode_Borda
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'B',
|
||||
2 => 'C',
|
||||
3 => 'A',
|
||||
4 => 'D', ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'B' => 294,
|
||||
'C' => 273,
|
||||
'A' => 226,
|
||||
'D' => 207, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_variant(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/M%C3%A9thode_Borda
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
$this->election->setMethodOption('Borda Count', 'Starting', 0);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'B',
|
||||
2 => 'C',
|
||||
3 => 'A',
|
||||
4 => 'D', ],
|
||||
$this->election->getResult('Borda Count')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[
|
||||
'B' => 294 - 100,
|
||||
'C' => 273 - 100,
|
||||
'A' => 226 - 100,
|
||||
'D' => 207 - 100, ],
|
||||
$this->election->getResult('Borda Count')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testVeryHighVoteWeightAndPerformances(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
$this->election->parseCandidates('0;1');
|
||||
|
||||
$this->election->parseVotes('1 > 0 ^6973568802');
|
||||
|
||||
self::assertSame('1', $this->election->getResult('Borda Count')->getResultAsString());
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Borda;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\Borda\DowdallSystem;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DowdallSystemTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Borda_count
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
$this->election->addCandidate('F');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D>E>F
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'B',
|
||||
3 => 'C',
|
||||
4 => 'D',
|
||||
5 => 'E',
|
||||
6 => 'F', ],
|
||||
$this->election->getResult('DowdallSystem')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEqualsWithDelta(
|
||||
[
|
||||
'A' => 1/1,
|
||||
'B' => 1/2,
|
||||
'C' => 1/3,
|
||||
'D' => 1/4,
|
||||
'E' => 1/5,
|
||||
'F' => 1/6, ],
|
||||
$this->election->getResult('DowdallSystem')->getStats(),
|
||||
1 / (0.1 ** DowdallSystem::DECIMAL_PRECISION)
|
||||
);
|
||||
}
|
||||
}
|
161
include/Condorcet/Tests/src/Algo/Methods/CondorcetBasicTest.php
Normal file
161
include/Condorcet/Tests/src/Algo/Methods/CondorcetBasicTest.php
Normal file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\CondorcetBasic;
|
||||
use CondorcetPHP\Condorcet\Throwable\AlgorithmWithoutRankingFeatureException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetBasicTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_Basic(): void
|
||||
{
|
||||
$this->election->addCandidate('a');
|
||||
$this->election->addCandidate('b');
|
||||
$this->election->addCandidate('c');
|
||||
|
||||
$vote = new Vote('a');
|
||||
|
||||
$this->election->addVote($vote);
|
||||
|
||||
self::assertEquals('a', $this->election->getCondorcetWinner());
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('a');
|
||||
$this->election->addCandidate('b');
|
||||
$this->election->addCandidate('c');
|
||||
|
||||
$this->election->parseVotes('
|
||||
a > c > b * 23
|
||||
b > c > a * 19
|
||||
c > b > a * 16
|
||||
c > a > b * 2
|
||||
');
|
||||
|
||||
self::assertEquals('c', $this->election->getCondorcetWinner());
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$this->election->addCandidate('X');
|
||||
$this->election->addCandidate('Y');
|
||||
$this->election->addCandidate('Z');
|
||||
|
||||
$this->election->parseVotes('
|
||||
X > Y > Z * 41
|
||||
Y > Z > X * 33
|
||||
Z > X > Y * 22
|
||||
');
|
||||
|
||||
self::assertNull($this->election->getWinner());
|
||||
|
||||
// Schulze Substitution
|
||||
self::assertEquals('X', $this->election->getWinner('Schulze'));
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
self::assertEquals('Nashville', $this->election->getCondorcetWinner());
|
||||
self::assertEquals('Memphis', $this->election->getCondorcetLoser());
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Chattanooga > Nashville * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
self::assertEquals('Chattanooga', $this->election->getCondorcetWinner());
|
||||
}
|
||||
|
||||
public function testResult_5(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Condorcet_loser_criterion
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('L');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 1
|
||||
A > B > L * 1
|
||||
B > C > A * 3
|
||||
C > L > A * 1
|
||||
L > A > B * 1
|
||||
L > C > A * 2
|
||||
');
|
||||
|
||||
self::assertEquals('L', $this->election->getCondorcetLoser());
|
||||
self::assertNull($this->election->getCondorcetWinner());
|
||||
}
|
||||
|
||||
public function testResult_6(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Condorcet_loser_criterion
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('L');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > L
|
||||
B > C > L
|
||||
A > C > L
|
||||
');
|
||||
|
||||
self::assertEquals('L', $this->election->getCondorcetLoser());
|
||||
}
|
||||
|
||||
public function testNoResultObject(): never
|
||||
{
|
||||
$this->expectException(AlgorithmWithoutRankingFeatureException::class);
|
||||
$this->expectExceptionMessage("This algortihm can't provide a full ranking (but only Winner and Loser): ".CondorcetBasic::METHOD_NAME[0]);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('L');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > L
|
||||
B > C > L
|
||||
A > C > L
|
||||
');
|
||||
|
||||
$this->election->getResult(CondorcetBasic::class);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Copeland;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CopelandTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Copeland%27s_method
|
||||
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Nashville',
|
||||
2 => 'Chattanooga',
|
||||
3 => 'Knoxville',
|
||||
4 => 'Memphis', ],
|
||||
$this->election->getResult('Copeland')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame($this->election->getWinner('Copeland'), $this->election->getWinner());
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'Memphis' => [
|
||||
'balance' => -3,
|
||||
],
|
||||
'Nashville' => [
|
||||
'balance' => 3,
|
||||
],
|
||||
'Knoxville' => [
|
||||
'balance' => -1,
|
||||
],
|
||||
'Chattanooga' => [
|
||||
'balance' => 1,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Copeland')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Copeland%27s_method
|
||||
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > E > C > D * 31
|
||||
B > A > E * 30
|
||||
C > D > B * 29
|
||||
D > A > E * 10
|
||||
');
|
||||
|
||||
self::assertNull($this->election->getWinner());
|
||||
self::assertSame($candidateA, $this->election->getWinner('Copeland'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => $candidateA,
|
||||
2 => [$candidateB, $candidateC, $candidateE],
|
||||
3 => $candidateD,
|
||||
],
|
||||
$this->election->getResult('Copeland')->getResultAsArray()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
# From http://www.cs.wustl.edu/~legrand/rbvote/desc.html
|
||||
|
||||
$this->election->addCandidate('Abby');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Cora');
|
||||
$this->election->addCandidate('Dave');
|
||||
$this->election->addCandidate('Erin');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Abby>Cora>Erin>Dave>Brad * 98
|
||||
Brad>Abby>Erin>Cora>Dave * 64
|
||||
Brad>Abby>Erin>Dave>Cora * 12
|
||||
Brad>Erin>Abby>Cora>Dave * 98
|
||||
Brad>Erin>Abby>Dave>Cora * 13
|
||||
Brad>Erin>Dave>Abby>Cora * 125
|
||||
Cora>Abby>Erin>Dave>Brad * 124
|
||||
Cora>Erin>Abby>Dave>Brad * 76
|
||||
Dave>Abby>Brad>Erin>Cora * 21
|
||||
Dave>Brad>Abby>Erin>Cora * 30
|
||||
Dave>Brad>Erin>Cora>Abby * 98
|
||||
Dave>Cora>Abby>Brad>Erin * 139
|
||||
Dave>Cora>Brad>Abby>Erin * 23
|
||||
');
|
||||
|
||||
self::assertEquals(['Abby', 'Brad'], $this->election->getWinner('Copeland'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['Abby', 'Brad'],
|
||||
2 => ['Dave', 'Erin'],
|
||||
3 => 'Cora', ],
|
||||
$this->election->getResult('Copeland')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
}
|
534
include/Condorcet/Tests/src/Algo/Methods/Dodgson/DodgsonTest.php
Normal file
534
include/Condorcet/Tests/src/Algo/Methods/Dodgson/DodgsonTest.php
Normal file
@ -0,0 +1,534 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Dodgson;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DodgsonTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From http://www.cs.wustl.edu/~legrand/rbvote/desc.html
|
||||
|
||||
$CandidateCora = $this->election->addCandidate('Cora');
|
||||
$this->election->addCandidate('Abby');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Dave');
|
||||
$this->election->addCandidate('Erin');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Abby>Cora>Erin>Dave>Brad * 98
|
||||
Brad>Abby>Erin>Cora>Dave * 64
|
||||
Brad>Abby>Erin>Dave>Cora * 12
|
||||
Brad>Erin>Abby>Cora>Dave * 98
|
||||
Brad>Erin>Abby>Dave>Cora * 13
|
||||
Brad>Erin>Dave>Abby>Cora * 125
|
||||
Cora>Abby>Erin>Dave>Brad * 124
|
||||
Cora>Erin>Abby>Dave>Brad * 76
|
||||
Dave>Abby>Brad>Erin>Cora * 21
|
||||
Dave>Brad>Abby>Erin>Cora * 30
|
||||
Dave>Brad>Erin>Cora>Abby * 98
|
||||
Dave>Cora>Abby>Brad>Erin * 139
|
||||
Dave>Cora>Brad>Abby>Erin * 23
|
||||
');
|
||||
|
||||
self::assertSame($CandidateCora, $this->election->getWinner('DodgsonTideman'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'Cora',
|
||||
2 => 'Abby',
|
||||
3 => 'Brad',
|
||||
4 => 'Dave',
|
||||
5 => 'Erin', ],
|
||||
$this->election->getResult('DodgsonTideman')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'Cora' => [
|
||||
'sum_defeat_margin' => 4,
|
||||
],
|
||||
'Abby' => [
|
||||
'sum_defeat_margin' => 5,
|
||||
],
|
||||
'Brad' => [
|
||||
'sum_defeat_margin' => 297,
|
||||
],
|
||||
'Dave' => [
|
||||
'sum_defeat_margin' => 348,
|
||||
],
|
||||
'Erin' => [
|
||||
'sum_defeat_margin' => 426,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('DodgsonTideman')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
# Require real Dodgson method. This test fail with both approximations.
|
||||
// public function testResult_2 (): void
|
||||
// {
|
||||
// # From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 1
|
||||
|
||||
// $this->election->addCandidate('A');
|
||||
// $this->election->addCandidate('B');
|
||||
// $this->election->addCandidate('C');
|
||||
// $this->election->addCandidate('D');
|
||||
|
||||
// $this->election->parseVotes('
|
||||
// D>C>A>B*2
|
||||
// B>C>A>D*2
|
||||
// C>A>B>D*2
|
||||
// D>B>C>A*2
|
||||
// A>B>C>D*2
|
||||
// A>D>B>C*1
|
||||
// D>A>B>C*1
|
||||
// ');
|
||||
|
||||
// self::assertEquals(
|
||||
// 'A', $this->election->getWinner('DodgsonQuick'));
|
||||
// }
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
# From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 2
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
D>C>A>B*6
|
||||
B>C>A>D*6
|
||||
C>A>B>D*6
|
||||
D>B>C>A*6
|
||||
A>B>C>D*6
|
||||
A>D>B>C*3
|
||||
D>A>B>C*3
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'D',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'D' => 3.0,
|
||||
'A' => 6.0,
|
||||
'B' => 6.0,
|
||||
'C' => 6.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
# Require real Dodgson method. This test fail with both approximations.
|
||||
// public function testResult_4 (): void
|
||||
// {
|
||||
// # From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 3
|
||||
|
||||
// $this->election->addCandidate('A');
|
||||
// $this->election->addCandidate('B');
|
||||
// $this->election->addCandidate('C');
|
||||
// $this->election->addCandidate('D');
|
||||
|
||||
// $this->election->parseVotes('
|
||||
// C>A>D>B*15
|
||||
// B>D>C>A*9
|
||||
// A>B>D>C*9
|
||||
// A>C>B>D*5
|
||||
// B>A>C>D*5
|
||||
// ');
|
||||
|
||||
// self::assertEquals(
|
||||
// 'A', $this->election->getWinner('DodgsonQuick'));
|
||||
// }
|
||||
|
||||
public function testResult_5(): void
|
||||
{
|
||||
# From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 4
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
C>A>D>B*15
|
||||
B>D>C>A*9
|
||||
A>B>D>C*9
|
||||
A>C>B>D*5
|
||||
A>B>C>D*5
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'C',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['C' => 2.0,
|
||||
'A' => 3.0,
|
||||
'B' => 13.0,
|
||||
'D' => 24.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_6(): void
|
||||
{
|
||||
# From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 5
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
D>A>B>C*10
|
||||
B>C>A>D*8
|
||||
C>A>B>D*7
|
||||
D>C>A>B*4
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'D',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['D' => 3.0,
|
||||
'C' => 4.0,
|
||||
'A' => 5.0,
|
||||
'B' => 7.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_7(): void
|
||||
{
|
||||
# From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 6
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
C>B>A>D*10
|
||||
D>A>C>B*8
|
||||
D>B>A>C*7
|
||||
B>A>C>D*4
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'D',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['B' => 5.0,
|
||||
'C' => 6.0,
|
||||
'A' => 8.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_8(): void
|
||||
{
|
||||
# From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 7
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C*5
|
||||
B>C>A*4
|
||||
C>A>B*3
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'A',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['A' => 1.0,
|
||||
'B' => 2.0,
|
||||
'C' => 3.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
# Require real Dodgson method. This test fail with both approximations.
|
||||
// public function testResult_9 (): void
|
||||
// {
|
||||
// # From http://dss.in.tum.de/files/brandt-research/dodgson.pdf
|
||||
# Table 8
|
||||
|
||||
// $this->election->addCandidate('A');
|
||||
// $this->election->addCandidate('B');
|
||||
// $this->election->addCandidate('C');
|
||||
// $this->election->addCandidate('Cp');
|
||||
|
||||
// $this->election->parseVotes('
|
||||
// A>B>C>Cp*5
|
||||
// B>C>Cp>A*4
|
||||
// C>Cp>A>B*3
|
||||
// ');
|
||||
|
||||
// self::assertEquals(
|
||||
// 'B', $this->election->getWinner('DodgsonQuick'));
|
||||
// }
|
||||
|
||||
public function testResult_10(): void
|
||||
{
|
||||
# From https://link.springer.com/article/10.1007/s003550000060
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D*21
|
||||
C>D>B>A*12
|
||||
D>C>A>B*5
|
||||
B>D>A>C*12
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'B',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
'B',
|
||||
$this->election->getWinner('DodgsonTideman')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_11(): void
|
||||
{
|
||||
# From https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/September%202010/3%20Articles/6%2009-229%20Ratliff/Dodgson_CMJ_Final.pdf
|
||||
# Figure 2 with Tideman Approximation
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D*3
|
||||
D>B>A>C*1
|
||||
D>C>A>B*1
|
||||
B>D>C>A*1
|
||||
C>D>B>A*1
|
||||
');
|
||||
|
||||
self::assertEquals(1, $this->election->getResult('DodgsonTideman')->getStats()['A']['sum_defeat_margin']);
|
||||
self::assertEquals(1, $this->election->getResult('DodgsonTideman')->getStats()['B']['sum_defeat_margin']);
|
||||
self::assertEquals(4, $this->election->getResult('DodgsonTideman')->getStats()['C']['sum_defeat_margin']);
|
||||
self::assertEquals(2, $this->election->getResult('DodgsonTideman')->getStats()['D']['sum_defeat_margin']);
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B'],
|
||||
2 => 'D',
|
||||
3 => 'C',
|
||||
],
|
||||
$this->election->getResult('DodgsonTideman')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_12(): void
|
||||
{
|
||||
# From https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/September%202010/3%20Articles/6%2009-229%20Ratliff/Dodgson_CMJ_Final.pdf
|
||||
# Figure 3 with Tideman Approximation
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D*5
|
||||
D>C>A>B*6
|
||||
C>A>B>D*5
|
||||
D>B>C>A*5
|
||||
B>C>A>D*4
|
||||
D>A>B>C*4
|
||||
C>D>A>B*1
|
||||
B>A>C>D*1
|
||||
B>D>A>C*1
|
||||
C>A>B>D*1
|
||||
A>D>B>C*1
|
||||
C>B>A>D*1
|
||||
');
|
||||
|
||||
self::assertEquals(11, $this->election->getResult('DodgsonTideman')->getStats()['A']['sum_defeat_margin']);
|
||||
self::assertEquals(11, $this->election->getResult('DodgsonTideman')->getStats()['B']['sum_defeat_margin']);
|
||||
self::assertEquals(7, $this->election->getResult('DodgsonTideman')->getStats()['C']['sum_defeat_margin']);
|
||||
self::assertEquals(3, $this->election->getResult('DodgsonTideman')->getStats()['D']['sum_defeat_margin']);
|
||||
|
||||
|
||||
self::assertEquals(
|
||||
'D',
|
||||
$this->election->getWinner('DodgsonTideman')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'D',
|
||||
2 => 'C',
|
||||
3 => ['A', 'B'],
|
||||
],
|
||||
$this->election->getResult('DodgsonTideman')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_13(): void
|
||||
{
|
||||
# From https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/September%202010/3%20Articles/6%2009-229%20Ratliff/Dodgson_CMJ_Final.pdf
|
||||
# Figure 4
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
$this->election->addCandidate('F');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D>E>F*19
|
||||
F>A>B>C>D>E*12
|
||||
E>D>C>B>F>A*12
|
||||
B>A>C>D>E>F*9
|
||||
F>E>D>C>B>A*9
|
||||
F>B>A>C>D>E*10
|
||||
E>D>C>A>F>B*10
|
||||
E>B>A>C>D>F*10
|
||||
F>D>C>A>E>B*10
|
||||
D>B>A>C>E>F*10
|
||||
F>E>C>A>D>B*10
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
'A',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['A' => 3.0,
|
||||
'B' => 4.0,
|
||||
'C' => 20.0,
|
||||
'D' => 20.0,
|
||||
'E' => 30.0,
|
||||
'F' => 30.0,
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_14(): void
|
||||
{
|
||||
# From https://www.maa.org/sites/default/files/pdf/cmj_ftp/CMJ/September%202010/3%20Articles/6%2009-229%20Ratliff/Dodgson_CMJ_Final.pdf
|
||||
# Figure 4: each voters add 4 friends.
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
$this->election->addCandidate('F');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D>E>F*95
|
||||
F>A>B>C>D>E*60
|
||||
E>D>C>B>F>A*60
|
||||
B>A>C>D>E>F*45
|
||||
F>E>D>C>B>A*45
|
||||
F>B>A>C>D>E*50
|
||||
E>D>C>A>F>B*50
|
||||
E>B>A>C>D>F*50
|
||||
F>D>C>A>E>B*50
|
||||
D>B>A>C>E>F*50
|
||||
F>E>C>A>D>B*50
|
||||
');
|
||||
|
||||
self::assertEquals(
|
||||
13,
|
||||
$this->election->getResult('DodgsonQuick')->getStats()['A']
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
12,
|
||||
$this->election->getResult('DodgsonQuick')->getStats()['B']
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
'B',
|
||||
$this->election->getWinner('DodgsonQuick')
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_15(): void
|
||||
{
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Chattanooga > Nashville * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
self::assertSame($this->election->getWinner(null), $this->election->getWinner('DodgsonQuick'));
|
||||
}
|
||||
|
||||
public function testResult_16(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A
|
||||
B
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => ['A', 'B'],
|
||||
2 => ['C', 'D'],
|
||||
],
|
||||
$this->election->getResult('DodgsonQuick')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,736 @@
|
||||
# Specifications: https://github.com/CondorcetPHP/CondorcetElectionFormat
|
||||
|
||||
# This election has 989 votes
|
||||
#/Candidates: 1 ; 2 ; 3 ; 4 ; 5 ; 6 ; 7 ; 8 ; 9 ; 10 ; 11 ; 12 ; 13 ; 14 ; 15
|
||||
#/Number of Seats: 7
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
6 > 5 > 4 > 11 > 7 > 10 > 12 > 13 > 8 > 9 > 14 > 15 * 30
|
||||
6 * 14
|
||||
4 * 13
|
||||
8 * 13
|
||||
2 * 11
|
||||
/EMPTY_RANKING/ * 8
|
||||
8 > 11 * 8
|
||||
2 > 7 * 6
|
||||
6 > 8 > 14 * 6
|
||||
8 > 5 > 11 > 9 * 6
|
||||
8 > 6 * 6
|
||||
14 * 6
|
||||
5 * 5
|
||||
6 > 8 * 5
|
||||
8 > 11 > 5 * 5
|
||||
8 > 12 * 5
|
||||
11 * 5
|
||||
1 > 3 > 13 * 4
|
||||
6 > 8 > 11 * 4
|
||||
6 > 8 > 12 * 4
|
||||
6 > 11 > 14 * 4
|
||||
8 > 6 > 14 * 4
|
||||
12 * 4
|
||||
1 * 3
|
||||
2 > 1 * 3
|
||||
2 > 7 > 9 * 3
|
||||
3 * 3
|
||||
4 > 6 > 5 * 3
|
||||
4 > 6 > 8 * 3
|
||||
5 > 6 > 8 * 3
|
||||
6 > 4 > 8 * 3
|
||||
6 > 4 > 11 * 3
|
||||
6 > 8 > 4 * 3
|
||||
6 > 11 * 3
|
||||
7 * 3
|
||||
8 > 5 * 3
|
||||
8 > 5 > 9 > 11 * 3
|
||||
8 > 6 > 11 * 3
|
||||
8 > 6 > 12 * 3
|
||||
8 > 11 > 5 > 9 * 3
|
||||
8 > 14 * 3
|
||||
9 * 3
|
||||
11 > 6 > 4 * 3
|
||||
11 > 14 > 6 * 3
|
||||
14 > 8 * 3
|
||||
1 > 2 > 7 * 2
|
||||
1 > 4 > 6 * 2
|
||||
1 > 6 * 2
|
||||
1 > 13 > 3 * 2
|
||||
2 > 5 > 10 * 2
|
||||
2 > 9 > 10 * 2
|
||||
2 > 10 > 9 * 2
|
||||
3 > 8 * 2
|
||||
4 > 5 > 3 * 2
|
||||
4 > 6 * 2
|
||||
4 > 6 > 3 * 2
|
||||
4 > 6 > 11 * 2
|
||||
4 > 8 > 6 * 2
|
||||
4 > 8 > 11 * 2
|
||||
4 > 11 * 2
|
||||
4 > 14 > 11 * 2
|
||||
5 > 6 > 11 * 2
|
||||
5 > 6 > 14 * 2
|
||||
5 > 8 * 2
|
||||
5 > 11 * 2
|
||||
5 > 11 > 4 * 2
|
||||
5 > 11 > 6 * 2
|
||||
5 > 11 > 8 * 2
|
||||
6 > 3 > 5 * 2
|
||||
6 > 4 > 8 > 12 > 11 > 14 > 3 > 5 > 13 * 2
|
||||
6 > 4 > 10 > 14 > 7 > 5 > 8 > 11 * 2
|
||||
6 > 4 > 12 * 2
|
||||
6 > 5 > 4 > 14 > 7 > 10 > 12 > 13 > 8 > 9 > 11 > 15 * 2
|
||||
6 > 5 > 8 > 11 * 2
|
||||
6 > 5 > 11 * 2
|
||||
6 > 11 > 12 * 2
|
||||
6 > 11 > 15 * 2
|
||||
6 > 12 * 2
|
||||
7 > 10 > 6 * 2
|
||||
8 > 5 > 6 > 11 * 2
|
||||
8 > 5 > 11 * 2
|
||||
8 > 5 > 11 > 12 * 2
|
||||
8 > 6 > 5 * 2
|
||||
8 > 9 > 12 * 2
|
||||
8 > 11 > 9 > 5 * 2
|
||||
8 > 11 > 14 * 2
|
||||
8 > 14 > 5 * 2
|
||||
9 > 10 > 12 > 6 > 14 > 13 > 1 * 2
|
||||
10 * 2
|
||||
11 > 4 > 6 * 2
|
||||
11 > 4 > 8 * 2
|
||||
11 > 4 > 14 > 7 > 8 > 3 * 2
|
||||
11 > 5 > 3 * 2
|
||||
11 > 5 > 6 * 2
|
||||
11 > 5 > 6 > 14 * 2
|
||||
11 > 6 > 5 * 2
|
||||
11 > 6 > 5 > 8 * 2
|
||||
11 > 6 > 12 * 2
|
||||
11 > 7 * 2
|
||||
11 > 8 * 2
|
||||
11 > 8 > 6 * 2
|
||||
11 > 12 > 14 * 2
|
||||
12 > 8 * 2
|
||||
12 > 14 * 2
|
||||
14 > 4 > 6 * 2
|
||||
14 > 5 * 2
|
||||
14 > 6 > 8 * 2
|
||||
14 > 6 > 10 * 2
|
||||
14 > 11 > 6 * 2
|
||||
1 > 2 > 3 > 4 > 5 > 6 > 7 > 8 > 9 > 10 > 11 > 12 > 13 > 14 * 1
|
||||
1 > 2 > 3 > 6 > 10 * 1
|
||||
1 > 2 > 3 > 7 > 8 > 15 > 10 > 13 * 1
|
||||
1 > 2 > 15 > 9 * 1
|
||||
1 > 3 > 2 > 15 > 6 * 1
|
||||
1 > 3 > 5 > 13 > 7 > 11 * 1
|
||||
1 > 3 > 7 * 1
|
||||
1 > 3 > 10 * 1
|
||||
1 > 3 > 13 > 4 * 1
|
||||
1 > 3 > 14 * 1
|
||||
1 > 3 > 15 * 1
|
||||
1 > 4 > 5 > 13 * 1
|
||||
1 > 4 > 6 > 11 > 12 > 13 > 15 > 8 > 14 > 7 > 5 > 2 > 9 > 10 * 1
|
||||
1 > 4 > 6 > 13 > 11 > 14 * 1
|
||||
1 > 5 * 1
|
||||
1 > 6 > 2 > 15 > 11 > 7 > 3 > 10 * 1
|
||||
1 > 6 > 4 > 11 * 1
|
||||
1 > 6 > 8 > 9 > 15 * 1
|
||||
1 > 7 * 1
|
||||
1 > 7 > 15 * 1
|
||||
1 > 8 > 4 > 11 * 1
|
||||
1 > 8 > 5 * 1
|
||||
1 > 8 > 12 * 1
|
||||
1 > 9 > 2 > 3 > 6 > 5 * 1
|
||||
1 > 9 > 10 > 13 > 3 > 5 * 1
|
||||
1 > 10 > 2 > 3 > 7 * 1
|
||||
1 > 10 > 2 > 8 * 1
|
||||
1 > 11 > 13 * 1
|
||||
1 > 13 > 2 > 3 > 7 * 1
|
||||
1 > 13 > 5 > 4 > 6 * 1
|
||||
1 > 14 > 15 > 11 * 1
|
||||
1 > 15 > 4 > 6 > 7 > 8 > 3 > 2 > 9 > 10 > 13 > 11 > 14 > 12 * 1
|
||||
2 > 1 > 4 * 1
|
||||
2 > 1 > 4 > 13 * 1
|
||||
2 > 1 > 7 * 1
|
||||
2 > 1 > 7 > 15 * 1
|
||||
2 > 1 > 10 * 1
|
||||
2 > 3 > 1 > 7 > 8 > 9 > 13 > 5 > 12 > 15 > 10 > 14 > 4 > 11 * 1
|
||||
2 > 3 > 1 > 13 * 1
|
||||
2 > 3 > 5 > 11 * 1
|
||||
2 > 6 * 1
|
||||
2 > 6 > 7 > 10 * 1
|
||||
2 > 6 > 7 > 10 > 1 > 13 > 3 * 1
|
||||
2 > 6 > 7 > 10 > 9 * 1
|
||||
2 > 6 > 10 * 1
|
||||
2 > 7 > 1 > 3 > 10 > 13 * 1
|
||||
2 > 7 > 1 > 6 > 10 > 15 * 1
|
||||
2 > 7 > 5 > 1 > 3 > 10 > 9 * 1
|
||||
2 > 7 > 9 > 1 > 3 * 1
|
||||
2 > 7 > 9 > 13 > 10 * 1
|
||||
2 > 7 > 10 > 9 > 8 * 1
|
||||
2 > 7 > 10 > 9 > 13 > 3 > 8 > 6 * 1
|
||||
2 > 7 > 12 > 13 > 9 > 10 > 6 * 1
|
||||
2 > 8 * 1
|
||||
2 > 8 > 6 * 1
|
||||
2 > 8 > 15 > 11 * 1
|
||||
2 > 9 > 6 * 1
|
||||
2 > 10 > 6 * 1
|
||||
2 > 10 > 7 > 9 * 1
|
||||
2 > 13 * 1
|
||||
2 > 13 > 6 > 3 > 8 * 1
|
||||
2 > 13 > 7 * 1
|
||||
2 > 13 > 9 > 10 > 7 * 1
|
||||
3 > 1 * 1
|
||||
3 > 1 > 7 > 13 > 15 * 1
|
||||
3 > 2 * 1
|
||||
3 > 2 > 7 > 15 * 1
|
||||
3 > 2 > 7 > 15 > 13 * 1
|
||||
3 > 4 > 10 * 1
|
||||
3 > 4 > 10 > 14 * 1
|
||||
3 > 4 > 12 > 13 > 11 > 8 > 9 * 1
|
||||
3 > 6 > 4 * 1
|
||||
3 > 6 > 4 > 1 * 1
|
||||
3 > 6 > 7 * 1
|
||||
3 > 6 > 11 * 1
|
||||
3 > 7 > 11 * 1
|
||||
3 > 8 > 6 * 1
|
||||
3 > 9 > 13 * 1
|
||||
3 > 11 > 6 > 10 > 14 * 1
|
||||
3 > 11 > 8 * 1
|
||||
3 > 13 * 1
|
||||
3 > 13 > 1 > 7 > 15 > 2 > 9 > 10 * 1
|
||||
3 > 14 > 5 > 10 > 13 * 1
|
||||
3 > 14 > 6 > 8 * 1
|
||||
4 > 1 > 5 * 1
|
||||
4 > 1 > 6 > 9 > 11 > 3 > 5 > 2 > 7 > 10 > 12 > 14 > 15 > 13 * 1
|
||||
4 > 1 > 6 > 11 * 1
|
||||
4 > 1 > 6 > 11 > 2 > 8 * 1
|
||||
4 > 2 > 7 > 8 > 5 > 13 > 14 > 9 > 10 > 3 > 1 > 6 > 15 > 11 * 1
|
||||
4 > 3 > 1 > 5 * 1
|
||||
4 > 3 > 5 > 8 > 14 * 1
|
||||
4 > 3 > 6 > 8 > 11 * 1
|
||||
4 > 3 > 13 * 1
|
||||
4 > 5 * 1
|
||||
4 > 5 > 6 > 7 > 11 > 14 * 1
|
||||
4 > 5 > 6 > 8 > 3 > 11 * 1
|
||||
4 > 5 > 6 > 8 > 11 > 14 > 15 > 13 > 12 > 3 > 1 > 2 > 7 > 9 * 1
|
||||
4 > 5 > 6 > 11 * 1
|
||||
4 > 5 > 6 > 11 > 12 > 15 * 1
|
||||
4 > 5 > 6 > 11 > 14 * 1
|
||||
4 > 5 > 6 > 11 > 14 > 12 > 8 > 7 > 15 > 3 > 10 * 1
|
||||
4 > 5 > 6 > 13 > 14 * 1
|
||||
4 > 5 > 7 > 11 * 1
|
||||
4 > 5 > 8 > 3 > 11 * 1
|
||||
4 > 5 > 11 * 1
|
||||
4 > 5 > 14 * 1
|
||||
4 > 6 > 1 * 1
|
||||
4 > 6 > 1 > 8 * 1
|
||||
4 > 6 > 1 > 11 * 1
|
||||
4 > 6 > 1 > 11 > 3 > 5 * 1
|
||||
4 > 6 > 2 * 1
|
||||
4 > 6 > 5 > 2 > 1 > 13 > 12 > 11 > 7 > 3 > 8 > 9 > 10 > 14 * 1
|
||||
4 > 6 > 5 > 11 * 1
|
||||
4 > 6 > 5 > 11 > 7 > 10 > 12 > 13 > 8 > 9 > 14 > 15 * 1
|
||||
4 > 6 > 7 > 5 > 11 * 1
|
||||
4 > 6 > 7 > 10 > 14 > 11 > 3 > 5 > 8 > 9 > 12 > 13 > 15 > 1 * 1
|
||||
4 > 6 > 8 > 1 * 1
|
||||
4 > 6 > 8 > 11 * 1
|
||||
4 > 6 > 8 > 11 > 12 > 13 > 3 > 5 > 14 * 1
|
||||
4 > 6 > 8 > 11 > 14 * 1
|
||||
4 > 6 > 8 > 13 > 15 > 5 > 10 * 1
|
||||
4 > 6 > 8 > 14 > 11 * 1
|
||||
4 > 6 > 10 * 1
|
||||
4 > 6 > 10 > 7 > 11 > 14 > 12 * 1
|
||||
4 > 6 > 10 > 11 > 5 > 12 > 8 * 1
|
||||
4 > 6 > 10 > 12 * 1
|
||||
4 > 6 > 11 > 1 > 3 * 1
|
||||
4 > 6 > 11 > 1 > 7 * 1
|
||||
4 > 6 > 11 > 1 > 8 > 13 > 2 > 14 * 1
|
||||
4 > 6 > 11 > 1 > 13 > 15 > 14 > 7 > 5 > 3 > 2 > 12 > 8 > 9 * 1
|
||||
4 > 6 > 11 > 5 > 10 > 12 > 14 * 1
|
||||
4 > 6 > 11 > 7 > 10 > 12 > 14 * 1
|
||||
4 > 6 > 11 > 8 > 5 * 1
|
||||
4 > 6 > 11 > 8 > 7 > 1 * 1
|
||||
4 > 6 > 11 > 10 * 1
|
||||
4 > 6 > 11 > 10 > 13 > 12 > 14 * 1
|
||||
4 > 6 > 11 > 12 > 14 > 10 > 8 > 5 > 13 > 7 > 15 > 3 > 2 > 1 * 1
|
||||
4 > 6 > 11 > 13 * 1
|
||||
4 > 6 > 11 > 14 * 1
|
||||
4 > 6 > 12 * 1
|
||||
4 > 6 > 12 > 13 * 1
|
||||
4 > 7 > 9 > 15 * 1
|
||||
4 > 8 * 1
|
||||
4 > 8 > 1 * 1
|
||||
4 > 8 > 2 > 7 * 1
|
||||
4 > 8 > 3 > 5 > 11 > 14 * 1
|
||||
4 > 8 > 3 > 6 > 11 > 9 > 14 > 15 > 2 > 1 > 5 > 13 > 7 > 12 * 1
|
||||
4 > 8 > 5 * 1
|
||||
4 > 8 > 6 > 1 > 14 > 11 * 1
|
||||
4 > 8 > 6 > 5 > 11 > 14 * 1
|
||||
4 > 8 > 6 > 11 * 1
|
||||
4 > 8 > 11 > 14 > 12 > 13 > 3 * 1
|
||||
4 > 8 > 12 * 1
|
||||
4 > 8 > 14 > 1 * 1
|
||||
4 > 8 > 14 > 3 * 1
|
||||
4 > 9 > 12 > 14 * 1
|
||||
4 > 9 > 15 > 1 > 3 > 2 > 5 > 7 * 1
|
||||
4 > 11 > 3 > 6 * 1
|
||||
4 > 11 > 5 > 14 > 6 * 1
|
||||
4 > 11 > 6 * 1
|
||||
4 > 11 > 6 > 5 > 14 * 1
|
||||
4 > 11 > 6 > 10 > 15 * 1
|
||||
4 > 11 > 8 * 1
|
||||
4 > 11 > 8 > 5 > 6 > 3 > 7 > 14 > 15 > 13 > 12 > 10 > 9 * 1
|
||||
4 > 11 > 8 > 6 * 1
|
||||
4 > 11 > 8 > 6 > 5 * 1
|
||||
4 > 11 > 12 * 1
|
||||
4 > 11 > 14 * 1
|
||||
4 > 11 > 14 > 8 * 1
|
||||
4 > 11 > 15 > 8 > 6 > 5 > 3 > 10 * 1
|
||||
4 > 12 > 5 * 1
|
||||
4 > 12 > 6 > 1 > 3 > 13 * 1
|
||||
4 > 12 > 8 > 5 > 11 * 1
|
||||
4 > 13 > 3 * 1
|
||||
4 > 13 > 3 > 5 > 7 > 10 > 11 > 14 * 1
|
||||
4 > 13 > 5 > 1 > 11 > 3 > 8 * 1
|
||||
4 > 14 > 11 > 8 * 1
|
||||
5 > 4 > 3 * 1
|
||||
5 > 4 > 6 > 11 > 13 > 1 > 3 > 8 * 1
|
||||
5 > 4 > 8 > 1 * 1
|
||||
5 > 4 > 11 > 15 * 1
|
||||
5 > 6 * 1
|
||||
5 > 6 > 1 > 7 > 8 > 15 > 13 > 11 > 12 > 4 > 3 > 9 > 14 > 2 * 1
|
||||
5 > 6 > 3 > 11 > 12 * 1
|
||||
5 > 6 > 4 > 11 > 8 * 1
|
||||
5 > 6 > 8 > 14 * 1
|
||||
5 > 6 > 11 > 4 > 14 > 8 * 1
|
||||
5 > 6 > 11 > 12 * 1
|
||||
5 > 6 > 14 > 8 > 7 * 1
|
||||
5 > 6 > 14 > 11 > 12 > 8 * 1
|
||||
5 > 6 > 15 > 8 > 11 * 1
|
||||
5 > 7 > 2 * 1
|
||||
5 > 7 > 8 > 11 > 14 > 13 > 4 > 1 > 15 > 12 > 6 > 3 > 9 > 10 * 1
|
||||
5 > 7 > 11 * 1
|
||||
5 > 8 > 1 * 1
|
||||
5 > 8 > 1 > 11 > 12 > 13 > 9 > 2 > 3 > 14 > 7 > 10 > 4 > 6 * 1
|
||||
5 > 8 > 6 > 14 * 1
|
||||
5 > 8 > 7 > 10 > 3 > 11 * 1
|
||||
5 > 8 > 9 * 1
|
||||
5 > 8 > 11 * 1
|
||||
5 > 8 > 11 > 2 > 6 > 14 * 1
|
||||
5 > 8 > 11 > 6 > 12 * 1
|
||||
5 > 8 > 11 > 12 * 1
|
||||
5 > 8 > 11 > 13 > 6 > 15 > 1 > 7 > 3 * 1
|
||||
5 > 8 > 11 > 14 > 7 > 6 * 1
|
||||
5 > 8 > 12 > 11 * 1
|
||||
5 > 8 > 13 * 1
|
||||
5 > 8 > 14 > 1 > 11 * 1
|
||||
5 > 9 > 11 * 1
|
||||
5 > 11 > 4 > 13 > 6 * 1
|
||||
5 > 11 > 6 > 8 > 1 * 1
|
||||
5 > 11 > 8 > 4 > 3 * 1
|
||||
5 > 11 > 8 > 4 > 6 * 1
|
||||
5 > 11 > 8 > 6 > 1 > 7 > 2 > 4 > 3 > 9 > 10 > 14 > 15 > 13 * 1
|
||||
5 > 11 > 8 > 14 * 1
|
||||
5 > 11 > 15 * 1
|
||||
5 > 11 > 15 > 14 > 8 * 1
|
||||
5 > 12 > 9 > 2 > 1 > 15 > 8 > 6 > 7 > 13 > 10 > 3 > 14 > 4 * 1
|
||||
5 > 14 > 4 * 1
|
||||
5 > 14 > 4 > 6 > 15 > 8 > 11 > 12 > 3 * 1
|
||||
5 > 14 > 8 * 1
|
||||
6 > 1 * 1
|
||||
6 > 1 > 3 * 1
|
||||
6 > 1 > 7 * 1
|
||||
6 > 1 > 7 > 5 * 1
|
||||
6 > 1 > 8 > 2 > 5 > 3 > 4 > 7 > 9 > 12 > 15 > 13 > 10 > 11 * 1
|
||||
6 > 2 * 1
|
||||
6 > 2 > 3 > 5 > 4 > 8 > 1 > 7 > 13 * 1
|
||||
6 > 2 > 5 * 1
|
||||
6 > 2 > 13 > 15 * 1
|
||||
6 > 3 > 4 * 1
|
||||
6 > 3 > 5 > 9 > 10 > 4 > 7 > 8 > 11 > 13 > 15 > 14 > 2 > 12 * 1
|
||||
6 > 3 > 8 * 1
|
||||
6 > 3 > 10 > 4 * 1
|
||||
6 > 4 > 1 > 13 * 1
|
||||
6 > 4 > 2 > 7 > 11 > 13 > 14 * 1
|
||||
6 > 4 > 3 * 1
|
||||
6 > 4 > 3 > 1 > 7 > 8 > 5 > 9 > 14 > 12 > 10 > 11 * 1
|
||||
6 > 4 > 3 > 1 > 13 * 1
|
||||
6 > 4 > 3 > 8 * 1
|
||||
6 > 4 > 5 > 11 > 14 > 8 > 15 > 12 * 1
|
||||
6 > 4 > 8 > 5 > 11 > 12 > 14 > 15 * 1
|
||||
6 > 4 > 8 > 7 > 5 > 3 > 14 > 15 * 1
|
||||
6 > 4 > 8 > 11 > 5 * 1
|
||||
6 > 4 > 8 > 11 > 7 > 5 > 14 > 10 > 3 * 1
|
||||
6 > 4 > 8 > 11 > 12 > 13 > 10 > 5 > 7 > 14 > 15 > 1 > 9 > 2 * 1
|
||||
6 > 4 > 8 > 11 > 14 * 1
|
||||
6 > 4 > 8 > 12 * 1
|
||||
6 > 4 > 10 > 11 > 7 * 1
|
||||
6 > 4 > 11 > 3 > 12 > 13 * 1
|
||||
6 > 4 > 11 > 5 > 12 > 8 > 10 * 1
|
||||
6 > 4 > 11 > 5 > 12 > 14 > 15 > 13 * 1
|
||||
6 > 4 > 11 > 7 * 1
|
||||
6 > 4 > 11 > 7 > 10 > 12 > 13 > 8 > 9 > 14 * 1
|
||||
6 > 4 > 11 > 7 > 10 > 12 > 13 > 8 > 9 > 14 > 15 * 1
|
||||
6 > 4 > 11 > 10 > 5 > 12 > 13 > 14 > 15 > 7 > 9 > 8 * 1
|
||||
6 > 4 > 11 > 12 > 8 * 1
|
||||
6 > 4 > 12 > 11 > 13 * 1
|
||||
6 > 4 > 13 > 14 * 1
|
||||
6 > 4 > 14 > 11 * 1
|
||||
6 > 5 * 1
|
||||
6 > 5 > 1 > 4 > 11 > 2 * 1
|
||||
6 > 5 > 3 > 4 > 8 > 13 * 1
|
||||
6 > 5 > 3 > 8 > 13 > 9 > 14 > 10 > 7 > 1 * 1
|
||||
6 > 5 > 4 > 8 > 9 > 10 > 11 * 1
|
||||
6 > 5 > 4 > 8 > 11 * 1
|
||||
6 > 5 > 4 > 11 > 7 > 3 * 1
|
||||
6 > 5 > 4 > 11 > 7 > 10 > 12 > 13 > 8 * 1
|
||||
6 > 5 > 4 > 11 > 7 > 10 > 12 > 13 > 14 > 9 > 8 > 15 * 1
|
||||
6 > 5 > 4 > 11 > 8 > 12 * 1
|
||||
6 > 5 > 4 > 13 * 1
|
||||
6 > 5 > 8 * 1
|
||||
6 > 5 > 8 > 3 > 13 > 7 > 15 > 14 > 12 > 1 > 11 > 9 > 10 > 4 * 1
|
||||
6 > 5 > 8 > 4 * 1
|
||||
6 > 5 > 8 > 4 > 11 * 1
|
||||
6 > 5 > 8 > 9 > 3 > 2 * 1
|
||||
6 > 5 > 8 > 9 > 12 > 11 > 13 * 1
|
||||
6 > 5 > 8 > 11 > 14 * 1
|
||||
6 > 5 > 8 > 11 > 14 > 15 > 9 > 4 * 1
|
||||
6 > 5 > 11 > 2 > 10 > 3 > 7 > 13 > 4 > 1 * 1
|
||||
6 > 5 > 11 > 7 > 4 > 10 > 12 > 13 > 8 > 9 > 14 > 15 * 1
|
||||
6 > 5 > 11 > 8 > 4 * 1
|
||||
6 > 5 > 11 > 12 > 14 > 13 > 4 > 15 * 1
|
||||
6 > 7 > 2 > 9 > 10 > 15 > 1 > 3 > 12 > 14 > 13 > 4 > 11 > 5 * 1
|
||||
6 > 7 > 2 > 10 > 9 * 1
|
||||
6 > 7 > 3 > 4 * 1
|
||||
6 > 7 > 4 > 3 > 5 > 2 > 14 > 8 > 1 > 15 * 1
|
||||
6 > 7 > 10 > 3 > 12 > 2 > 1 * 1
|
||||
6 > 7 > 10 > 12 > 13 > 3 > 4 * 1
|
||||
6 > 7 > 11 > 10 > 2 > 13 > 3 > 1 > 9 * 1
|
||||
6 > 8 > 1 * 1
|
||||
6 > 8 > 4 > 3 > 11 > 14 * 1
|
||||
6 > 8 > 4 > 11 * 1
|
||||
6 > 8 > 4 > 11 > 13 * 1
|
||||
6 > 8 > 4 > 14 > 11 * 1
|
||||
6 > 8 > 4 > 14 > 12 > 5 > 11 > 15 > 9 > 7 * 1
|
||||
6 > 8 > 9 > 5 > 11 * 1
|
||||
6 > 8 > 9 > 10 * 1
|
||||
6 > 8 > 11 > 4 > 3 > 13 > 14 > 12 > 15 * 1
|
||||
6 > 8 > 12 > 11 * 1
|
||||
6 > 8 > 14 > 4 * 1
|
||||
6 > 8 > 15 * 1
|
||||
6 > 9 > 7 > 13 > 15 > 14 > 8 * 1
|
||||
6 > 9 > 10 > 3 > 4 > 1 > 7 > 11 > 13 > 8 * 1
|
||||
6 > 10 > 2 * 1
|
||||
6 > 10 > 2 > 9 * 1
|
||||
6 > 10 > 2 > 11 > 7 > 14 > 12 > 13 * 1
|
||||
6 > 10 > 14 > 8 * 1
|
||||
6 > 11 > 1 * 1
|
||||
6 > 11 > 1 > 3 > 4 > 8 > 15 * 1
|
||||
6 > 11 > 2 > 1 > 13 > 3 * 1
|
||||
6 > 11 > 2 > 13 > 15 > 8 * 1
|
||||
6 > 11 > 3 > 12 > 7 * 1
|
||||
6 > 11 > 4 * 1
|
||||
6 > 11 > 4 > 10 > 14 > 5 * 1
|
||||
6 > 11 > 4 > 14 > 12 * 1
|
||||
6 > 11 > 5 * 1
|
||||
6 > 11 > 5 > 3 > 14 * 1
|
||||
6 > 11 > 5 > 15 * 1
|
||||
6 > 11 > 8 > 12 > 5 > 4 > 1 > 13 > 14 * 1
|
||||
6 > 11 > 13 > 4 > 14 > 8 * 1
|
||||
6 > 12 > 8 * 1
|
||||
6 > 12 > 8 > 3 * 1
|
||||
6 > 12 > 8 > 4 > 11 > 14 * 1
|
||||
6 > 13 * 1
|
||||
6 > 13 > 4 > 3 > 5 * 1
|
||||
6 > 13 > 5 * 1
|
||||
6 > 13 > 12 > 11 * 1
|
||||
6 > 13 > 12 > 11 > 9 > 15 * 1
|
||||
6 > 14 * 1
|
||||
6 > 14 > 8 * 1
|
||||
6 > 14 > 9 * 1
|
||||
6 > 14 > 11 * 1
|
||||
6 > 14 > 11 > 1 * 1
|
||||
6 > 14 > 12 > 10 > 8 > 9 > 11 > 1 > 4 > 13 * 1
|
||||
7 > 1 > 2 * 1
|
||||
7 > 1 > 2 > 3 > 10 > 9 * 1
|
||||
7 > 1 > 2 > 8 > 3 * 1
|
||||
7 > 1 > 3 > 2 > 6 > 13 > 15 * 1
|
||||
7 > 1 > 3 > 15 > 13 > 6 > 2 * 1
|
||||
7 > 1 > 4 * 1
|
||||
7 > 2 * 1
|
||||
7 > 2 > 3 > 1 > 13 > 15 * 1
|
||||
7 > 2 > 6 * 1
|
||||
7 > 2 > 8 > 10 * 1
|
||||
7 > 2 > 9 * 1
|
||||
7 > 2 > 13 * 1
|
||||
7 > 4 > 2 * 1
|
||||
7 > 4 > 3 > 1 > 6 > 13 > 14 > 15 > 5 > 2 > 8 > 9 > 10 > 12 * 1
|
||||
7 > 4 > 6 > 10 > 15 > 14 > 11 > 13 > 8 > 3 > 12 > 1 > 5 > 2 * 1
|
||||
7 > 4 > 8 > 6 > 5 * 1
|
||||
7 > 5 > 8 * 1
|
||||
7 > 5 > 12 * 1
|
||||
7 > 6 * 1
|
||||
7 > 6 > 1 * 1
|
||||
7 > 6 > 2 > 5 > 4 > 8 > 14 * 1
|
||||
7 > 6 > 10 > 11 > 1 * 1
|
||||
7 > 6 > 12 > 8 * 1
|
||||
7 > 8 > 2 > 13 > 6 > 3 * 1
|
||||
7 > 8 > 5 * 1
|
||||
7 > 8 > 12 * 1
|
||||
7 > 8 > 15 * 1
|
||||
7 > 9 > 10 * 1
|
||||
7 > 10 > 4 > 2 > 13 > 3 * 1
|
||||
7 > 10 > 6 > 4 * 1
|
||||
7 > 10 > 8 * 1
|
||||
7 > 11 > 12 > 3 > 4 > 6 > 5 > 8 * 1
|
||||
7 > 11 > 14 * 1
|
||||
7 > 13 > 6 * 1
|
||||
7 > 15 > 1 > 3 > 13 * 1
|
||||
7 > 15 > 3 * 1
|
||||
7 > 15 > 3 > 1 > 2 * 1
|
||||
7 > 15 > 5 * 1
|
||||
8 > 1 * 1
|
||||
8 > 1 > 3 * 1
|
||||
8 > 1 > 4 * 1
|
||||
8 > 1 > 6 * 1
|
||||
8 > 2 > 3 > 6 * 1
|
||||
8 > 2 > 7 > 10 > 9 * 1
|
||||
8 > 3 > 7 * 1
|
||||
8 > 3 > 10 > 13 > 1 * 1
|
||||
8 > 3 > 12 * 1
|
||||
8 > 3 > 13 > 10 * 1
|
||||
8 > 4 * 1
|
||||
8 > 4 > 3 > 6 > 1 > 2 > 5 > 7 > 13 > 11 > 10 > 15 > 14 > 9 * 1
|
||||
8 > 4 > 5 * 1
|
||||
8 > 4 > 5 > 11 > 14 * 1
|
||||
8 > 4 > 6 > 14 > 15 * 1
|
||||
8 > 4 > 11 * 1
|
||||
8 > 4 > 11 > 5 > 6 > 12 > 14 > 15 > 9 * 1
|
||||
8 > 4 > 12 > 14 > 15 > 3 > 6 > 5 > 1 > 2 > 7 > 9 > 10 > 11 * 1
|
||||
8 > 5 > 2 > 6 > 7 > 9 > 10 * 1
|
||||
8 > 5 > 3 > 4 > 9 > 11 > 14 * 1
|
||||
8 > 5 > 4 * 1
|
||||
8 > 5 > 4 > 6 > 1 > 11 > 14 > 7 > 10 > 3 > 9 > 15 * 1
|
||||
8 > 5 > 4 > 11 > 6 * 1
|
||||
8 > 5 > 6 * 1
|
||||
8 > 5 > 6 > 4 > 11 > 12 > 10 > 13 * 1
|
||||
8 > 5 > 9 > 3 > 11 * 1
|
||||
8 > 5 > 9 > 6 > 4 > 14 * 1
|
||||
8 > 5 > 11 > 4 > 12 > 14 * 1
|
||||
8 > 5 > 11 > 9 > 6 * 1
|
||||
8 > 5 > 11 > 12 > 6 > 4 * 1
|
||||
8 > 5 > 11 > 13 > 6 > 1 * 1
|
||||
8 > 5 > 11 > 14 * 1
|
||||
8 > 5 > 12 * 1
|
||||
8 > 5 > 12 > 4 > 6 * 1
|
||||
8 > 5 > 14 * 1
|
||||
8 > 6 > 1 * 1
|
||||
8 > 6 > 2 * 1
|
||||
8 > 6 > 3 > 11 > 14 * 1
|
||||
8 > 6 > 4 * 1
|
||||
8 > 6 > 4 > 3 * 1
|
||||
8 > 6 > 4 > 11 > 5 > 1 > 15 > 14 > 13 > 12 > 10 > 9 > 2 > 3 * 1
|
||||
8 > 6 > 5 > 9 * 1
|
||||
8 > 6 > 5 > 14 * 1
|
||||
8 > 6 > 5 > 14 > 11 > 12 > 15 * 1
|
||||
8 > 6 > 11 > 9 * 1
|
||||
8 > 6 > 11 > 14 * 1
|
||||
8 > 6 > 14 > 3 > 4 * 1
|
||||
8 > 6 > 14 > 12 * 1
|
||||
8 > 6 > 15 * 1
|
||||
8 > 7 > 1 * 1
|
||||
8 > 7 > 2 > 1 > 15 > 11 * 1
|
||||
8 > 7 > 6 * 1
|
||||
8 > 7 > 11 * 1
|
||||
8 > 9 > 5 * 1
|
||||
8 > 9 > 5 > 11 * 1
|
||||
8 > 9 > 11 * 1
|
||||
8 > 9 > 11 > 5 * 1
|
||||
8 > 9 > 11 > 5 > 6 * 1
|
||||
8 > 10 > 12 * 1
|
||||
8 > 11 > 2 * 1
|
||||
8 > 11 > 3 > 14 * 1
|
||||
8 > 11 > 4 * 1
|
||||
8 > 11 > 4 > 14 > 5 > 9 > 3 * 1
|
||||
8 > 11 > 5 > 4 > 6 > 9 > 14 > 15 * 1
|
||||
8 > 11 > 5 > 6 * 1
|
||||
8 > 11 > 5 > 9 > 6 * 1
|
||||
8 > 11 > 6 * 1
|
||||
8 > 11 > 6 > 3 > 4 > 14 * 1
|
||||
8 > 11 > 6 > 5 > 14 > 3 > 15 > 12 * 1
|
||||
8 > 11 > 6 > 12 * 1
|
||||
8 > 11 > 6 > 14 * 1
|
||||
8 > 11 > 10 * 1
|
||||
8 > 11 > 10 > 4 * 1
|
||||
8 > 11 > 14 > 12 * 1
|
||||
8 > 12 > 3 * 1
|
||||
8 > 12 > 6 * 1
|
||||
8 > 12 > 15 > 6 > 14 * 1
|
||||
8 > 13 > 15 * 1
|
||||
8 > 14 > 4 * 1
|
||||
8 > 14 > 10 * 1
|
||||
8 > 14 > 11 * 1
|
||||
8 > 14 > 13 > 6 * 1
|
||||
9 > 6 > 12 * 1
|
||||
9 > 6 > 12 > 14 > 8 * 1
|
||||
9 > 8 > 6 > 4 * 1
|
||||
9 > 8 > 11 > 13 > 3 > 4 > 10 * 1
|
||||
9 > 8 > 11 > 14 > 3 > 4 * 1
|
||||
9 > 8 > 11 > 14 > 3 > 4 > 10 * 1
|
||||
9 > 8 > 12 * 1
|
||||
9 > 10 > 2 * 1
|
||||
9 > 10 > 8 > 2 * 1
|
||||
9 > 12 > 6 * 1
|
||||
9 > 12 > 6 > 8 > 2 * 1
|
||||
9 > 14 > 8 * 1
|
||||
10 > 2 > 6 * 1
|
||||
10 > 2 > 7 > 9 * 1
|
||||
10 > 5 > 6 * 1
|
||||
10 > 6 > 4 > 11 > 12 * 1
|
||||
10 > 7 > 2 * 1
|
||||
10 > 8 > 7 * 1
|
||||
10 > 9 > 11 * 1
|
||||
10 > 11 > 14 * 1
|
||||
10 > 14 > 4 > 5 > 7 > 6 > 8 > 11 * 1
|
||||
10 > 14 > 6 * 1
|
||||
10 > 14 > 6 > 11 > 4 * 1
|
||||
10 > 14 > 7 > 6 > 4 > 12 > 11 * 1
|
||||
10 > 14 > 15 > 11 > 9 > 4 > 5 > 6 > 7 > 12 > 13 * 1
|
||||
11 > 1 > 4 > 2 * 1
|
||||
11 > 1 > 4 > 7 > 5 > 8 > 9 > 12 > 10 > 3 > 2 > 14 > 15 > 6 * 1
|
||||
11 > 2 > 6 * 1
|
||||
11 > 3 > 5 * 1
|
||||
11 > 3 > 8 * 1
|
||||
11 > 4 > 1 * 1
|
||||
11 > 4 > 5 > 6 > 14 > 3 > 12 * 1
|
||||
11 > 4 > 5 > 12 * 1
|
||||
11 > 4 > 6 > 1 > 7 > 10 > 5 > 14 * 1
|
||||
11 > 4 > 6 > 3 > 14 * 1
|
||||
11 > 4 > 6 > 8 * 1
|
||||
11 > 4 > 13 > 14 > 12 * 1
|
||||
11 > 4 > 14 > 6 * 1
|
||||
11 > 5 * 1
|
||||
11 > 5 > 4 > 6 * 1
|
||||
11 > 5 > 6 > 4 > 8 > 3 > 13 > 14 * 1
|
||||
11 > 5 > 6 > 8 * 1
|
||||
11 > 5 > 8 * 1
|
||||
11 > 5 > 8 > 3 > 4 > 14 * 1
|
||||
11 > 5 > 12 > 14 * 1
|
||||
11 > 5 > 14 > 4 * 1
|
||||
11 > 6 * 1
|
||||
11 > 6 > 4 > 3 * 1
|
||||
11 > 6 > 4 > 8 * 1
|
||||
11 > 6 > 5 > 14 * 1
|
||||
11 > 6 > 7 > 14 * 1
|
||||
11 > 6 > 8 * 1
|
||||
11 > 6 > 8 > 3 > 4 > 5 > 13 > 14 * 1
|
||||
11 > 6 > 8 > 3 > 4 > 13 > 14 > 15 > 12 > 7 > 2 > 1 > 9 > 10 * 1
|
||||
11 > 6 > 10 * 1
|
||||
11 > 6 > 12 > 14 > 1 > 3 > 4 > 7 > 13 * 1
|
||||
11 > 6 > 13 > 12 > 8 > 14 > 1 * 1
|
||||
11 > 6 > 14 * 1
|
||||
11 > 7 > 15 * 1
|
||||
11 > 8 > 2 * 1
|
||||
11 > 8 > 3 > 5 > 4 > 6 * 1
|
||||
11 > 8 > 4 > 3 > 5 * 1
|
||||
11 > 8 > 5 * 1
|
||||
11 > 8 > 5 > 6 * 1
|
||||
11 > 8 > 5 > 6 > 14 > 12 > 1 > 4 * 1
|
||||
11 > 8 > 6 > 10 > 12 * 1
|
||||
11 > 8 > 10 * 1
|
||||
11 > 8 > 12 * 1
|
||||
11 > 8 > 15 > 14 > 3 > 6 * 1
|
||||
11 > 9 * 1
|
||||
11 > 9 > 7 > 4 > 3 > 14 > 12 * 1
|
||||
11 > 10 > 7 > 2 > 6 > 14 > 15 > 12 > 13 > 9 > 1 > 8 > 5 > 3 * 1
|
||||
11 > 12 > 5 > 6 > 15 * 1
|
||||
11 > 12 > 6 * 1
|
||||
11 > 12 > 8 > 6 * 1
|
||||
11 > 13 > 12 > 2 > 14 * 1
|
||||
11 > 13 > 12 > 6 > 14 * 1
|
||||
11 > 14 * 1
|
||||
11 > 14 > 4 * 1
|
||||
11 > 14 > 5 * 1
|
||||
11 > 14 > 6 > 5 > 8 * 1
|
||||
11 > 14 > 6 > 5 > 8 > 4 * 1
|
||||
11 > 14 > 6 > 12 * 1
|
||||
11 > 14 > 8 * 1
|
||||
11 > 14 > 8 > 6 > 3 > 10 > 12 * 1
|
||||
11 > 14 > 9 * 1
|
||||
11 > 15 > 6 * 1
|
||||
11 > 15 > 14 > 12 > 8 > 6 * 1
|
||||
12 > 2 > 6 * 1
|
||||
12 > 3 > 4 > 6 > 13 * 1
|
||||
12 > 3 > 8 * 1
|
||||
12 > 4 > 13 * 1
|
||||
12 > 5 > 8 > 4 * 1
|
||||
12 > 6 * 1
|
||||
12 > 6 > 1 * 1
|
||||
12 > 6 > 1 > 8 * 1
|
||||
12 > 6 > 3 * 1
|
||||
12 > 6 > 5 > 4 > 11 > 7 > 10 > 13 > 8 > 9 > 14 > 15 * 1
|
||||
12 > 6 > 8 * 1
|
||||
12 > 8 > 4 * 1
|
||||
12 > 8 > 6 * 1
|
||||
12 > 8 > 6 > 11 > 5 * 1
|
||||
12 > 8 > 13 * 1
|
||||
12 > 9 * 1
|
||||
12 > 9 > 8 * 1
|
||||
12 > 11 > 5 * 1
|
||||
12 > 11 > 8 > 6 > 4 * 1
|
||||
12 > 14 > 6 * 1
|
||||
13 > 1 > 3 > 7 > 15 > 2 * 1
|
||||
13 > 1 > 6 * 1
|
||||
13 > 3 > 7 > 15 > 1 > 9 * 1
|
||||
13 > 6 * 1
|
||||
13 > 6 > 3 * 1
|
||||
13 > 7 > 6 * 1
|
||||
13 > 8 * 1
|
||||
13 > 8 > 4 > 6 > 1 * 1
|
||||
13 > 11 > 1 > 6 > 8 > 5 > 10 * 1
|
||||
13 > 11 > 6 > 5 * 1
|
||||
13 > 11 > 6 > 15 * 1
|
||||
13 > 12 > 4 * 1
|
||||
14 > 1 > 11 > 6 > 8 > 10 * 1
|
||||
14 > 3 > 8 > 10 > 13 * 1
|
||||
14 > 4 * 1
|
||||
14 > 4 > 5 * 1
|
||||
14 > 5 > 11 * 1
|
||||
14 > 6 * 1
|
||||
14 > 6 > 4 > 3 * 1
|
||||
14 > 6 > 4 > 11 > 10 > 5 > 8 > 1 * 1
|
||||
14 > 6 > 7 * 1
|
||||
14 > 6 > 8 > 5 > 4 > 11 > 3 > 12 * 1
|
||||
14 > 6 > 8 > 11 > 4 > 3 * 1
|
||||
14 > 6 > 11 * 1
|
||||
14 > 6 > 11 > 15 > 8 > 7 > 4 > 12 > 5 > 13 > 9 * 1
|
||||
14 > 8 > 6 > 2 * 1
|
||||
14 > 8 > 10 * 1
|
||||
14 > 8 > 10 > 6 * 1
|
||||
14 > 8 > 11 > 3 > 4 > 6 * 1
|
||||
14 > 10 > 8 * 1
|
||||
14 > 10 > 11 * 1
|
||||
14 > 11 > 4 * 1
|
||||
14 > 11 > 4 > 5 > 8 * 1
|
||||
14 > 11 > 4 > 5 > 13 * 1
|
||||
14 > 11 > 4 > 7 > 2 * 1
|
||||
14 > 11 > 8 > 12 * 1
|
||||
14 > 11 > 12 * 1
|
||||
14 > 12 * 1
|
||||
14 > 12 > 8 > 6 > 1 > 10 * 1
|
||||
14 > 12 > 8 > 11 > 10 * 1
|
||||
14 > 12 > 15 > 4 > 8 > 7 > 13 > 10 > 1 > 3 > 6 > 5 > 2 > 11 * 1
|
||||
14 > 15 > 6 > 11 > 10 > 5 * 1
|
||||
15 > 3 > 2 > 1 * 1
|
||||
15 > 3 > 13 > 7 > 10 * 1
|
||||
15 > 6 > 7 * 1
|
||||
15 > 7 * 1
|
||||
15 > 7 > 2 * 1
|
||||
15 > 7 > 2 > 11 > 10 * 1
|
||||
15 > 7 > 14 * 1
|
||||
15 > 8 > 6 * 1
|
||||
15 > 11 * 1
|
||||
15 > 11 > 4 > 2 > 6 > 8 > 14 > 13 > 12 > 1 > 3 > 5 > 7 > 10 * 1
|
||||
15 > 12 > 6 * 1
|
||||
15 > 12 > 11 * 1
|
||||
15 > 14 * 1
|
||||
15 > 14 > 11 > 3 > 4 * 1
|
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\HighestAverage;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class JeffersonTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
# https://fr.wikipedia.org/wiki/Scrutin_proportionnel_plurinominal#M%C3%A9thode_de_Jefferson_ou_m%C3%A9thode_D'Hondt
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->setNumberOfSeats(6);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('A * 42; B ^31; C *15; D ^12'); // Mix weight and number
|
||||
|
||||
self::assertSame(['A' =>3, 'B' => 2, 'C' => 1, 'D' => 0], $this->election->getResult('Jefferson')->getStats()['Seats per Candidates']);
|
||||
}
|
||||
|
||||
public function testResult_Tideman_A03(): void
|
||||
{
|
||||
$cef = new CondorcetElectionFormat(__DIR__.'/'.'A03.cvotes');
|
||||
$cef->setDataToAnElection($this->election);
|
||||
|
||||
$this->election->setImplicitRanking(false); // Empty ranking was throw an error.
|
||||
|
||||
$this->election->getResult('Jefferson');
|
||||
|
||||
self::assertTrue(true);
|
||||
}
|
||||
}
|
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\HighestAverage;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SainteLagueTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('SainteLague', 'FirstDivisor', 1);
|
||||
}
|
||||
|
||||
# https://fr.wikipedia.org/wiki/Scrutin_proportionnel_plurinominal#M%C3%A9thode_de_Sainte-Lagu%C3%AB
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->setNumberOfSeats(7);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('A ^53; B ^24; C ^23');
|
||||
|
||||
self::assertSame('A > B > C > A > A > B > C', $this->election->getResult('SainteLague')->getResultAsString());
|
||||
|
||||
self::assertSame([
|
||||
'Rounds' => [
|
||||
1 => [
|
||||
'A' => [
|
||||
'Quotient' => 53.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 24.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 23.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
],
|
||||
2 => [
|
||||
'A' => [
|
||||
'Quotient' => 17.666666666666668,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 24.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 23.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
],
|
||||
3 => [
|
||||
'A' => [
|
||||
'Quotient' => 17.666666666666668,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 8.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 23.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 0,
|
||||
],
|
||||
],
|
||||
4 => [
|
||||
'A' => [
|
||||
'Quotient' => 17.666666666666668,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 8.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 7.666666666666667,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
],
|
||||
5 => [
|
||||
'A' => [
|
||||
'Quotient' => 10.6,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 2,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 8.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 7.666666666666667,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
],
|
||||
6 => [
|
||||
'A' => [
|
||||
'Quotient' => 7.571428571428571,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 3,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 8.0,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 7.666666666666667,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
],
|
||||
7 => [
|
||||
'A' => [
|
||||
'Quotient' => 7.571428571428571,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 3,
|
||||
],
|
||||
'B' => [
|
||||
'Quotient' => 4.8,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 2,
|
||||
],
|
||||
'C' => [
|
||||
'Quotient' => 7.666666666666667,
|
||||
'NumberOfSeatsAllocatedBeforeRound' => 1,
|
||||
],
|
||||
],
|
||||
],
|
||||
'Seats per Candidates' => [
|
||||
'A' => 3,
|
||||
'B' => 2,
|
||||
'C' => 2,
|
||||
],
|
||||
], $this->election->getResult('SainteLague')->getStats());
|
||||
}
|
||||
|
||||
# https://www.regjeringen.no/no/tema/valg-og-demokrati/den-norske-valgordningen/valgordningen/id456636/
|
||||
public function testNorwegianVariant_1(): void
|
||||
{
|
||||
$this->election->setMethodOption('SainteLague', 'FirstDivisor', 1.4);
|
||||
|
||||
$this->election->parseCandidates('H;Ap;FrP;SV;SP;KrF');
|
||||
|
||||
$this->election->setNumberOfSeats(11);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('H ^81140; Ap ^80862; FrP ^39851; SV ^26295; SP ^12187; KrF ^11229');
|
||||
|
||||
self::assertSame('H > Ap > FrP > H > Ap > SV > H > Ap > FrP > H > Ap', $this->election->getResult('SainteLague')->getResultAsString());
|
||||
}
|
||||
}
|
@ -0,0 +1,259 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\HighestAverage;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\StvQuotas;
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class HighestAveragesAndLargestRemainderMethodsTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE);
|
||||
}
|
||||
|
||||
public function testFranceLegislatives2022_1erTour(): void
|
||||
{
|
||||
$this->election->setNumberOfSeats(577);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseCandidates(
|
||||
'Divers extrême gauche
|
||||
Parti radical de gauche
|
||||
Nouvelle union populaire écologique et sociale
|
||||
Divers gauche
|
||||
Ecologistes
|
||||
Divers
|
||||
Régionaliste
|
||||
Ensemble ! (Majorité présidentielle)
|
||||
Divers centre
|
||||
Union des Démocrates et des Indépendants
|
||||
Les Républicains
|
||||
Divers droite
|
||||
Droite souverainiste
|
||||
Reconquête !
|
||||
Rassemblement National
|
||||
Divers extrême droite'
|
||||
);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Divers extrême gauche ^266412
|
||||
Parti radical de gauche ^126689
|
||||
Nouvelle union populaire écologique et sociale ^5836079
|
||||
Divers gauche ^713574
|
||||
Ecologistes ^608314
|
||||
Divers ^192624
|
||||
Régionaliste ^291384
|
||||
Ensemble ! (Majorité présidentielle) ^5857364
|
||||
Divers centre ^283612
|
||||
Union des Démocrates et des Indépendants ^198062
|
||||
Les Républicains ^2370440
|
||||
Divers droite ^530782
|
||||
Droite souverainiste ^249603
|
||||
Reconquête ! ^964775
|
||||
Rassemblement National ^4248537
|
||||
Divers extrême droite ^6457
|
||||
');
|
||||
|
||||
// SainteLeague
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 7,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 148,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 5,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 149,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 14,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 25,
|
||||
'Rassemblement National' => 108,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('SainteLague')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('SainteLague')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('SainteLague')->getResultAsArray());
|
||||
|
||||
// Jefferson
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 6,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 150,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 4,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 150,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 13,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 24,
|
||||
'Rassemblement National' => 109,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('Jefferson')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('Jefferson')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('Jefferson')->getResultAsArray());
|
||||
|
||||
// Hare-LR
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE); // Hare-LR
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 7,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 148,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 5,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 149,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 14,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 25,
|
||||
'Rassemblement National' => 108,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('LargestRemainder')->getResultAsArray());
|
||||
|
||||
// Droop-LR
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::DROOP); // Droop-LR
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 7,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 148,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 5,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 149,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 14,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 25,
|
||||
'Rassemblement National' => 108,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('LargestRemainder')->getResultAsArray());
|
||||
|
||||
// Hagenbach-Bischoff-LR
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HAGENBACH_BISCHOFF); // Hagenbach-Bischoff-LR
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 7,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 148,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 5,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 149,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 14,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 25,
|
||||
'Rassemblement National' => 108,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('LargestRemainder')->getResultAsArray());
|
||||
|
||||
// Imperiali-LR
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::IMPERIALI); // Imperiali-LR
|
||||
self::assertSame([
|
||||
'Divers extrême gauche' => 7,
|
||||
'Parti radical de gauche' => 3,
|
||||
'Nouvelle union populaire écologique et sociale' => 149,
|
||||
'Divers gauche' => 18,
|
||||
'Ecologistes' => 15,
|
||||
'Divers' => 5,
|
||||
'Régionaliste' => 7,
|
||||
'Ensemble ! (Majorité présidentielle)' => 149,
|
||||
'Divers centre' => 7,
|
||||
'Union des Démocrates et des Indépendants' => 5,
|
||||
'Les Républicains' => 60,
|
||||
'Divers droite' => 13,
|
||||
'Droite souverainiste' => 6,
|
||||
'Reconquête !' => 25,
|
||||
'Rassemblement National' => 108,
|
||||
'Divers extrême droite' => 0,
|
||||
], $this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']);
|
||||
|
||||
$this->assertSame(577, array_sum($this->election->getResult('LargestRemainder')->getStats()['Seats per Candidates']));
|
||||
$this->assertCount(577, $this->election->getResult('LargestRemainder')->getResultAsArray());
|
||||
}
|
||||
|
||||
# https://www.electoral-reform.org.uk/what-is-the-difference-between-dhondt-sainte-lague-and-hare/
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->parseCandidates('Con;Lab;LD;Brexit;Ash Ind;Green;Others');
|
||||
$this->election->setNumberOfSeats(11);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('Con ^258794; Lab ^204011; LD ^33604; Brexit ^15728; Ash Ind ^13498; Green ^10375; Others ^9743');
|
||||
|
||||
self::assertSame('Con > Lab > Con > Lab > Con > Lab > Con > LD > Lab > Con > Con', $this->election->getResult('SainteLague')->getResultAsString());
|
||||
self::assertSame('Con > Lab > Con > Lab > Con > Lab > Con > Con > Lab > Con > Lab', $this->election->getResult('Jefferson')->getResultAsString());
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE); // Hare-LR
|
||||
self::assertSame('Con > Con > Lab > Con > Lab > Con > Lab > Con > Lab > LD > Brexit', $this->election->getResult('LargestRemainder')->getResultAsString());
|
||||
}
|
||||
|
||||
# https://en.wikipedia.org/wiki/Webster/Sainte-Lagu%C3%AB_method
|
||||
# https://en.wikipedia.org/wiki/D%27Hondt_method
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->setNumberOfSeats(8);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('A ^100000; B ^80000; C ^30000; D ^20000');
|
||||
|
||||
self::assertSame('A > B > A > C > B > A > D > B', $this->election->getResult('SainteLague')->getResultAsString());
|
||||
self::assertSame('A > B > A > B > A > C > B > A', $this->election->getResult('Jefferson')->getResultAsString());
|
||||
}
|
||||
|
||||
public function testTiesOnFirstRank(): void
|
||||
{
|
||||
$this->election->setNumberOfSeats(1);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->addVote('A = B > C');
|
||||
self::assertSame([], $this->election->getResult('SainteLague')->getResultAsArray());
|
||||
|
||||
$this->election->addVote('B>A');
|
||||
self::assertSame('B', $this->election->getResult('SainteLague')->getResultAsString());
|
||||
}
|
||||
}
|
@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\InstantRunoff;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\DavidHillFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class InstantRunoffTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/Vote_alternatif
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'D',
|
||||
2 => 'A',
|
||||
3 => 'B',
|
||||
4 => 'C', ],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'majority' => 50.0,
|
||||
'rounds' => [
|
||||
1 => [
|
||||
'A' => 42,
|
||||
'B' => 26,
|
||||
'C' => 15,
|
||||
'D' => 17,
|
||||
],
|
||||
2 => [
|
||||
'A' => 42,
|
||||
'B' => 26,
|
||||
'D' => 32,
|
||||
],
|
||||
3 => [
|
||||
'A' => 42,
|
||||
'D' => 58,
|
||||
],
|
||||
],
|
||||
],
|
||||
$this->election->getResult('InstantRunoff')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Instant-runoff_voting#Examples
|
||||
|
||||
$this->election->addCandidate('bob');
|
||||
$this->election->addCandidate('sue');
|
||||
$this->election->addCandidate('bill');
|
||||
|
||||
$this->election->parseVotes('
|
||||
bob > bill > sue
|
||||
sue > bob > bill
|
||||
bill > sue > bob
|
||||
bob > bill > sue
|
||||
sue > bob > bill
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'sue',
|
||||
2 => 'bob',
|
||||
3 => 'bill', ],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->addCandidate('bob');
|
||||
$this->election->addCandidate('sue');
|
||||
$this->election->addCandidate('bill');
|
||||
|
||||
$this->election->parseVotes('
|
||||
bob > bill > sue
|
||||
sue > bob > bill
|
||||
bill > sue > bob
|
||||
bob > bill > sue
|
||||
sue > bob > bill
|
||||
bill > bob > sue
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'bob',
|
||||
2 => 'bill',
|
||||
3 => 'sue', ],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A=B=C
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => ['A', 'B', 'C'], ],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_Equality(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A
|
||||
B
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => ['A', 'B'], ],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_TieBreaking(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A * 4
|
||||
B * 4
|
||||
C>A * 2
|
||||
D>C>B * 2
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => ['A', 'B'],
|
||||
3 => 'C',
|
||||
4 => 'D',
|
||||
],
|
||||
$this->election->getResult('InstantRunoff')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testInfiniteLoopOnTidemanDataset3IfExplicitRanking(): void
|
||||
{
|
||||
$election = (new DavidHillFormat(__DIR__.'/../../../Tools/Converters/TidemanData/A3.HIL'))->setDataToAnElection();
|
||||
|
||||
$election->setImplicitRanking(false);
|
||||
|
||||
self::assertSame('6 > 8 > 4 > 11 > 2 > 5 > 14 > 1 = 7 > 12 > 3 > 9 > 10 > 15 > 13', $election->getResult('InstantRunoff')->getResultAsString());
|
||||
}
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\KemenyYoung;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung;
|
||||
use CondorcetPHP\Condorcet\Algo\StatsVerbosity;
|
||||
use CondorcetPHP\Condorcet\Throwable\CandidatesMaxNumberReachedException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class KemenyYoungTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Nashville',
|
||||
2 => 'Chattanooga',
|
||||
3 => 'Knoxville',
|
||||
4 => 'Memphis',
|
||||
],
|
||||
$this->election->getResult('KemenyYoung')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(393, $this->election->getResult('KemenyYoung')->getStats()['Best Score']);
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('KemenyYoung'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
*/
|
||||
public function testResult2(): void
|
||||
{
|
||||
$this->election->parseCandidates('Elliot;Roland;Meredith;Selden');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Elliot > Roland ^30
|
||||
Elliot > Meredith ^60
|
||||
Elliot > Selden ^60
|
||||
Roland > Meredith ^70
|
||||
Roland > Selden ^60
|
||||
Meredith > Selden ^40
|
||||
');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Elliot',
|
||||
2 => 'Roland',
|
||||
3 => 'Meredith',
|
||||
4 => 'Selden',
|
||||
],
|
||||
$this->election->getResult('KemenyYoung')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testStats_1(): void
|
||||
{
|
||||
$this->election->setStatsVerbosity(StatsVerbosity::FULL);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
|
||||
$this->election->parseVotes($r = 'A > B');
|
||||
|
||||
self::assertSame(
|
||||
$r,
|
||||
$this->election->getResult('KemenyYoung')->getResultAsString()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'Best Score' => 1,
|
||||
'Ranking In Conflicts' => 0,
|
||||
'Ranking Scores' => [
|
||||
[1 => 'A', 2 => 'B', 'score' => 1],
|
||||
[1 => 'B', 2 => 'A', 'score' => 0],
|
||||
],
|
||||
],
|
||||
$this->election->getResult('KemenyYoung')->getStats()
|
||||
);
|
||||
|
||||
$this->election->setStatsVerbosity(StatsVerbosity::STD);
|
||||
|
||||
self::assertArrayNotHasKey('rankingScores', $this->election->getResult('KemenyYoung')->getStats());
|
||||
}
|
||||
|
||||
public function testMaxCandidates(): never
|
||||
{
|
||||
$this->expectException(CandidatesMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage("Maximum number of candidates reached: The method 'Kemeny–Young' is configured to accept only ".KemenyYoung::$MaxCandidates.' candidates');
|
||||
|
||||
for ($i=0; $i < (KemenyYoung::$MaxCandidates + 1); $i++) {
|
||||
$this->election->addCandidate();
|
||||
}
|
||||
|
||||
$this->election->parseVotes('A');
|
||||
|
||||
$this->election->getWinner('KemenyYoung');
|
||||
}
|
||||
|
||||
public function testConflicts(): void
|
||||
{
|
||||
$this->election->parseCandidates('A;B;C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C;
|
||||
B>C>A;
|
||||
C>A>B');
|
||||
|
||||
$result = $this->election->getResult('KemenyYoung');
|
||||
|
||||
self::assertEquals(
|
||||
[0 => [
|
||||
'type' => 42,
|
||||
'msg' => '3;5',
|
||||
],
|
||||
],
|
||||
$result->getWarning(\CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung::CONFLICT_WARNING_CODE)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[0 => [
|
||||
'type' => 42,
|
||||
'msg' => '3;5',
|
||||
],
|
||||
],
|
||||
$result->getWarning()
|
||||
);
|
||||
|
||||
self::assertSame(3, $result->getStats()['Ranking In Conflicts']);
|
||||
|
||||
$this->election->addVote('A>B>C');
|
||||
|
||||
$result = $this->election->getResult('KemenyYoung');
|
||||
|
||||
self::assertEquals(
|
||||
[],
|
||||
$result->getWarning(\CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung::CONFLICT_WARNING_CODE)
|
||||
);
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('KemenyYoung'));
|
||||
}
|
||||
|
||||
public function testKemenyWithOnly1Candidate(): void
|
||||
{
|
||||
$candidate[] = $this->election->addCandidate();
|
||||
|
||||
$this->election->addVote($candidate);
|
||||
|
||||
self::assertSame($candidate[0], $this->election->getWinner('KemenyYoung'));
|
||||
}
|
||||
|
||||
public function ManyCandidatesProvider(): array
|
||||
{
|
||||
return [
|
||||
9 => [9],
|
||||
10 => [10],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @group large
|
||||
* @dataProvider ManyCandidatesProvider
|
||||
*/
|
||||
public function testKemenyWithManyCandidates(int $candidatesCount): void
|
||||
{
|
||||
$original = KemenyYoung::$MaxCandidates;
|
||||
KemenyYoung::$MaxCandidates = null;
|
||||
|
||||
for ($i=0; $i<$candidatesCount; $i++) {
|
||||
$candidates[] = $this->election->addCandidate();
|
||||
}
|
||||
|
||||
$this->election->addVote($candidates);
|
||||
|
||||
self::assertSame($candidates[0], $this->election->getWinner('KemenyYoung'));
|
||||
|
||||
KemenyYoung::$MaxCandidates = $original;
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\HighestAverage;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\StvQuotas;
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class LargestRemainderTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE);
|
||||
}
|
||||
|
||||
# https://en.wikipedia.org/wiki/Largest_remainder_method
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->parseCandidates('Yellows;Whites;Reds;Greens;Blues;Pinks');
|
||||
|
||||
$this->election->setNumberOfSeats(10);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('Yellows ^47000;Whites ^16000;Reds ^15800;Greens ^12000;Blues ^6100;Pinks ^3100');
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE); // Hare-LR
|
||||
self::assertSame(
|
||||
[
|
||||
'Yellows' => 5,
|
||||
'Whites' => 2,
|
||||
'Reds' => 1,
|
||||
'Greens' => 1,
|
||||
'Blues' => 1,
|
||||
'Pinks' => 0, ],
|
||||
$this->election->getResult('LR')->getStats()['Seats per Candidates']
|
||||
);
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::DROOP); // Hare-LR
|
||||
self::assertSame(
|
||||
[
|
||||
'Yellows' => 5,
|
||||
'Whites' => 2,
|
||||
'Reds' => 2,
|
||||
'Greens' => 1,
|
||||
'Blues' => 0,
|
||||
'Pinks' => 0, ],
|
||||
$this->election->getResult('LR')->getStats()['Seats per Candidates']
|
||||
);
|
||||
}
|
||||
|
||||
# https://en.wikipedia.org/wiki/Largest_remainder_method
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$this->election->parseCandidates('A;B;C;D;E;F');
|
||||
|
||||
$this->election->setNumberOfSeats(25);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('A ^1500;B ^1500;C ^900;D^500;E ^500;F ^200');
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE); // Hare-LR
|
||||
self::assertSame(
|
||||
[
|
||||
'A' => 7,
|
||||
'B' => 7,
|
||||
'C' => 4,
|
||||
'D' => 3,
|
||||
'E' => 3,
|
||||
'F' => 1, ],
|
||||
$this->election->getResult('LR')->getStats()['Seats per Candidates']
|
||||
);
|
||||
}
|
||||
|
||||
# https://en.wikipedia.org/wiki/Largest_remainder_method
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->parseCandidates('A;B;C;D;E;F');
|
||||
|
||||
$this->election->setNumberOfSeats(26);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('A ^1500;B ^1500;C ^900;D^500;E ^500;F ^200');
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::HARE); // Hare-LR
|
||||
self::assertSame(
|
||||
[
|
||||
'A' => 8,
|
||||
'B' => 8,
|
||||
'C' => 5,
|
||||
'D' => 2,
|
||||
'E' => 2,
|
||||
'F' => 1, ],
|
||||
$this->election->getResult('LR')->getStats()['Seats per Candidates']
|
||||
);
|
||||
}
|
||||
|
||||
// Fixing error with Droop Quotas in some cases
|
||||
public function testResult_4_LR(): void
|
||||
{
|
||||
$this->election->parseCandidates('A;B;C');
|
||||
$this->election->setNumberOfSeats(99);
|
||||
|
||||
$this->election->parseVotes('A>B>C;C>B>A;B>A>C');
|
||||
|
||||
$this->election->setMethodOption('LargestRemainder', 'Quota', StvQuotas::DROOP); // Hare-LR
|
||||
self::assertSame(
|
||||
[
|
||||
'A' => 33,
|
||||
'B' => 33,
|
||||
'C' => 33,
|
||||
],
|
||||
$this->election->getResult('LR')->getStats()['Seats per Candidates']
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Majority;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FirstPastThePostTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
|
||||
public function testResult_French2002(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->addCandidate('Chirac');
|
||||
$this->election->addCandidate('Jospin');
|
||||
$this->election->addCandidate('Le Pen');
|
||||
$this->election->addCandidate('Bayrou');
|
||||
$this->election->addCandidate('Laguiller');
|
||||
$this->election->addCandidate('Chevènement');
|
||||
$this->election->addCandidate('Mamère');
|
||||
$this->election->addCandidate('Besancenot');
|
||||
$this->election->addCandidate('Saint-Josse');
|
||||
$this->election->addCandidate('Madelin');
|
||||
$this->election->addCandidate('Robert Hue');
|
||||
$this->election->addCandidate('Mégret');
|
||||
$this->election->addCandidate('Taubira');
|
||||
$this->election->addCandidate('Lepage');
|
||||
$this->election->addCandidate('Boutin');
|
||||
$this->election->addCandidate('Gluckstein');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Chirac > Bayrou = Jospin = Madelin = Chevénement = Mamère = Robert Hue = Taubira = Lepage = Boutin > Saint-Josse ^1988
|
||||
Jospin > Chevénement = Taubira = Mamère > Bayrou > Robert Hue > Chirac = Lepage = Boutin > Madelin > Saint-Josse ^ 1618
|
||||
Le Pen ^1686
|
||||
Bayrou ^684
|
||||
Laguiller ^572
|
||||
Chevènement ^533
|
||||
Mamère ^525
|
||||
Besancenot ^425
|
||||
Saint-Josse ^423
|
||||
Madelin ^391
|
||||
Robert Hue ^337
|
||||
Mégret > Le Pen ^234
|
||||
Taubira ^232
|
||||
Lepage ^188
|
||||
Boutin ^119
|
||||
Gluckstein ^47
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Chirac',
|
||||
2 => 'Le Pen',
|
||||
3 => 'Jospin',
|
||||
4 => 'Bayrou',
|
||||
5 => 'Laguiller',
|
||||
6 => 'Chevènement',
|
||||
7 => 'Mamère',
|
||||
8 => 'Besancenot',
|
||||
9 => 'Saint-Josse',
|
||||
10 => 'Madelin',
|
||||
11 => 'Robert Hue',
|
||||
12 => 'Mégret',
|
||||
13 => 'Taubira',
|
||||
14 => 'Lepage',
|
||||
15 => 'Boutin',
|
||||
16 => 'Gluckstein',
|
||||
],
|
||||
$this->election->getResult('Fptp')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1 => [
|
||||
'Chirac' => 1988,
|
||||
'Le Pen' => 1686,
|
||||
'Jospin' => 1618,
|
||||
'Bayrou' => 684,
|
||||
'Laguiller' => 572,
|
||||
'Chevènement' => 533,
|
||||
'Mamère' => 525,
|
||||
'Besancenot' => 425,
|
||||
'Saint-Josse' => 423,
|
||||
'Madelin' => 391,
|
||||
'Robert Hue' => 337,
|
||||
'Mégret' => 234,
|
||||
'Taubira' => 232,
|
||||
'Lepage' => 188,
|
||||
'Boutin' => 119,
|
||||
'Gluckstein' => 47,
|
||||
]],
|
||||
$this->election->getResult('Fptp')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'B',
|
||||
3 => 'D',
|
||||
4 => 'C', ],
|
||||
$this->election->getResult('Fptp')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1 => [
|
||||
'A' => 42,
|
||||
'B' => 26,
|
||||
'D' => 17,
|
||||
'C' => 15,
|
||||
]],
|
||||
$this->election->getResult('Fptp')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D ^ 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A ^ 15
|
||||
D>C>B>A * 17
|
||||
D>B=C=A ^ 25
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => ['A', 'D'],
|
||||
2 => 'B',
|
||||
3 => 'C', ],
|
||||
$this->election->getResult('Fptp')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => [
|
||||
'A' => (float) 42,
|
||||
'D' => (float) 42,
|
||||
'B' => (float) 26,
|
||||
'C' => (float) 15,
|
||||
]],
|
||||
$this->election->getResult('Fptp')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C
|
||||
A=C>B
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'C',
|
||||
3 => 'B', ],
|
||||
$this->election->getResult('Fptp')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1 => [
|
||||
'A' => 1 + 1/2,
|
||||
'C' => 1/2,
|
||||
'B' => 0,
|
||||
]],
|
||||
$this->election->getResult('Fptp')->getStats()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Methods\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MultipleRoundsSystemTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->resetOptions();
|
||||
}
|
||||
|
||||
protected function resetOptions(): void
|
||||
{
|
||||
$methodClass = Condorcet::getMethodClass('runoff voting');
|
||||
|
||||
$this->election->setMethodOption($methodClass, 'MAX_ROUND', 2);
|
||||
$this->election->setMethodOption($methodClass, 'TARGET_NUMBER_OF_CANDIDATES_FOR_THE_NEXT_ROUND', 2);
|
||||
$this->election->setMethodOption($methodClass, 'NUMBER_OF_TARGETED_CANDIDATES_AFTER_EACH_ROUND', 0);
|
||||
}
|
||||
|
||||
public function testResult_MajorityTest_systematic_triangular(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
$methodClass = Condorcet::getMethodClass('Multiple Rounds System');
|
||||
|
||||
$this->election->setMethodOption($methodClass, 'MAX_ROUND', 2);
|
||||
$this->election->setMethodOption($methodClass, 'TARGET_NUMBER_OF_CANDIDATES_FOR_THE_NEXT_ROUND', 3);
|
||||
$this->election->setMethodOption($methodClass, 'NUMBER_OF_TARGETED_CANDIDATES_AFTER_EACH_ROUND', 0);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'D',
|
||||
3 => 'B',
|
||||
4 => 'C', ],
|
||||
$this->election->getResult('Multiple Rounds System')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 42,
|
||||
'B' => 26,
|
||||
'D' => 17,
|
||||
'C' => 15,
|
||||
],
|
||||
2=> [
|
||||
'A' => 42,
|
||||
'D' => 32,
|
||||
'B' => 26,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Multiple Rounds System')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testResult_MajorityTest_three_round(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B ^10
|
||||
B ^12
|
||||
C>B ^10
|
||||
D>E>A>B ^9
|
||||
E>B ^5
|
||||
');
|
||||
|
||||
$methodClass = Condorcet::getMethodClass('runoff voting');
|
||||
|
||||
$this->election->setMethodOption($methodClass, 'MAX_ROUND', 3);
|
||||
$this->election->setMethodOption($methodClass, 'TARGET_NUMBER_OF_CANDIDATES_FOR_THE_NEXT_ROUND', 2);
|
||||
$this->election->setMethodOption($methodClass, 'NUMBER_OF_TARGETED_CANDIDATES_AFTER_EACH_ROUND', 0);
|
||||
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'B', 2 => 'A', 3 => 'C', 4=> 'D', 5=> 'E'],
|
||||
$this->election->getResult('Multiple Rounds System')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'B' => 12,
|
||||
'A' => 10,
|
||||
'C' => 10,
|
||||
'D' => 9,
|
||||
'E' => 5,
|
||||
],
|
||||
2=> [
|
||||
'A' => 19,
|
||||
'B' => 17,
|
||||
'C' => 10,
|
||||
],
|
||||
3=> [
|
||||
'B' => 27,
|
||||
'A' => 19,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('runoff voting')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_MajorityTest_Many_Round(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
$this->election->addCandidate('F');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D>E>F ^100
|
||||
B>A>C>D>E>F ^99
|
||||
C>A>B>D>E>F ^98
|
||||
D>A=B>C>E>F ^97
|
||||
E>B>A>C>D>F ^96
|
||||
F>A>B>C>D>E ^95
|
||||
');
|
||||
|
||||
$methodClass = Condorcet::getMethodClass('Multiple Rounds System');
|
||||
|
||||
$this->election->setMethodOption($methodClass, 'MAX_ROUND', 100);
|
||||
$this->election->setMethodOption($methodClass, 'TARGET_NUMBER_OF_CANDIDATES_FOR_THE_NEXT_ROUND', 5);
|
||||
$this->election->setMethodOption($methodClass, 'NUMBER_OF_TARGETED_CANDIDATES_AFTER_EACH_ROUND', -1);
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'A', 2 => 'B', 3 => 'C', 4=> 'D', 5=> 'E', 6 => 'F'],
|
||||
$this->election->getResult('Multiple Rounds System')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 100,
|
||||
'B' => 99,
|
||||
'C' => 98,
|
||||
'D' => 97,
|
||||
'E' => 96,
|
||||
'F' => 95,
|
||||
],
|
||||
2=> [
|
||||
'A' => 100 + 95,
|
||||
'B' => 99,
|
||||
'C' => 98,
|
||||
'D' => 97,
|
||||
'E' => 96,
|
||||
],
|
||||
3=> [
|
||||
'A' => 100 + 95,
|
||||
'B' => 99 + 96,
|
||||
'C' => 98,
|
||||
'D' => 97,
|
||||
],
|
||||
4=> [
|
||||
'A' => 100 + 95 + (97/2),
|
||||
'B' => 99 + 96 + (97/2),
|
||||
'C' => 98,
|
||||
],
|
||||
5=> [
|
||||
'A' => 100 + 95 + (97/2) + 98,
|
||||
'B' => 99 + 96 + (97/2),
|
||||
],
|
||||
],
|
||||
$this->election->getResult('runoff voting')->getStats()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,544 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Methods\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\Majority\MultipleRoundsSystem;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TwoRoundSystemTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_French2002(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
$this->election->addCandidate('Chirac');
|
||||
$this->election->addCandidate('Jospin');
|
||||
$this->election->addCandidate('Le Pen');
|
||||
$this->election->addCandidate('Bayrou');
|
||||
$this->election->addCandidate('Laguiller');
|
||||
$this->election->addCandidate('Chevènement');
|
||||
$this->election->addCandidate('Mamère');
|
||||
$this->election->addCandidate('Besancenot');
|
||||
$this->election->addCandidate('Saint-Josse');
|
||||
$this->election->addCandidate('Madelin');
|
||||
$this->election->addCandidate('Robert Hue');
|
||||
$this->election->addCandidate('Mégret');
|
||||
$this->election->addCandidate('Taubira');
|
||||
$this->election->addCandidate('Lepage');
|
||||
$this->election->addCandidate('Boutin');
|
||||
$this->election->addCandidate('Gluckstein');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Chirac > Bayrou = Jospin = Madelin = Chevénement = Mamère = Robert Hue = Taubira = Lepage = Boutin > Saint-Josse ^1988
|
||||
Jospin > Chevénement = Taubira = Mamère > Bayrou > Robert Hue > Chirac = Lepage = Boutin > Madelin > Saint-Josse ^ 1618
|
||||
Le Pen > Mégret ^1686
|
||||
Bayrou > Chirac ^684
|
||||
Laguiller > Besancenot = Gluckstein > ^572
|
||||
Chevènement > Chirac ^533
|
||||
Mamère > Jospin > Chirac ^525
|
||||
Besancenot > Gluckstein = Laguillier ^425
|
||||
Saint-Josse > Chirac > Jospin ^423
|
||||
Madelin > Chirac ^391
|
||||
Robert Hue > Jospin > Chirac ^337
|
||||
Mégret > Le Pen ^234
|
||||
Taubira > Jospin > Chirac ^232
|
||||
Lepage > Chirac ^188
|
||||
Boutin > Chirac ^119
|
||||
Gluckstein > Besancenot = Laguillier ^47
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Chirac',
|
||||
2 => 'Le Pen',
|
||||
3 => 'Jospin',
|
||||
4 => 'Bayrou',
|
||||
5 => 'Laguiller',
|
||||
6 => 'Chevènement',
|
||||
7 => 'Mamère',
|
||||
8 => 'Besancenot',
|
||||
9 => 'Saint-Josse',
|
||||
10 => 'Madelin',
|
||||
11 => 'Robert Hue',
|
||||
12 => 'Mégret',
|
||||
13 => 'Taubira',
|
||||
14 => 'Lepage',
|
||||
15 => 'Boutin',
|
||||
16 => 'Gluckstein',
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'Chirac' => 1988,
|
||||
'Le Pen' => 1686,
|
||||
'Jospin' => 1618,
|
||||
'Bayrou' => 684,
|
||||
'Laguiller' => 572,
|
||||
'Chevènement' => 533,
|
||||
'Mamère' => 525,
|
||||
'Besancenot' => 425,
|
||||
'Saint-Josse' => 423,
|
||||
'Madelin' => 391,
|
||||
'Robert Hue' => 337,
|
||||
'Mégret' => 234,
|
||||
'Taubira' => 232,
|
||||
'Lepage' => 188,
|
||||
'Boutin' => 119,
|
||||
'Gluckstein' => 47,
|
||||
],
|
||||
2=> [
|
||||
'Chirac' => 7038,
|
||||
'Le Pen' => 1920,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A * 15
|
||||
D>C>B>A * 17
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'B',
|
||||
2 => 'A',
|
||||
3 => 'D',
|
||||
4 => 'C', ],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 42,
|
||||
'B' => 26,
|
||||
'D' => 17,
|
||||
'C' => 15,
|
||||
],
|
||||
2=> [
|
||||
'B' => 58,
|
||||
'A' => 42,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D ^ 42
|
||||
B>C>D>A * 26
|
||||
C>D>B>A ^ 15
|
||||
D>C>B>A * 17
|
||||
D>B=C=A ^ 25
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'D',
|
||||
2 => 'A',
|
||||
3 => 'B',
|
||||
4 => 'C', ],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 42,
|
||||
'D' => 42,
|
||||
'B' => 26,
|
||||
'C' => 15,
|
||||
],
|
||||
2=> [
|
||||
'D' => 83,
|
||||
'A' => 42,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C
|
||||
A=C>B
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'C',
|
||||
3 => 'B', ],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 1.5,
|
||||
'C' => 0.5,
|
||||
'B' => 0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_5(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 51
|
||||
B>C>D>A * 24
|
||||
C>D>B>A * 25
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'C',
|
||||
3 => 'B',
|
||||
4 => 'D', ],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 51,
|
||||
'C' => 25,
|
||||
'B' => 24,
|
||||
'D' => 0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_6(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 50
|
||||
B>C>D>A * 50
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B'], 2 => 'C'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 50,
|
||||
'B' => 50,
|
||||
'C' => 0,
|
||||
],
|
||||
2=> [
|
||||
'A' => 50,
|
||||
'B' => 50,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_7(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D * 50
|
||||
B>C>D>A * 50
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B']],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 50,
|
||||
'B' => 50,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_8(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
D>E * 50
|
||||
E>D * 50
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C']],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
$stats = $this->election->getResult('Two Rounds')->getStats();
|
||||
// \array_walk_recursive($stats, function (float &$value): float {
|
||||
// return $value = round($value, 10);
|
||||
// });
|
||||
|
||||
self::assertSame(
|
||||
[1=> [
|
||||
'A' => round(100/3, MultipleRoundsSystem::DECIMAL_PRECISION),
|
||||
'B' => round(100/3, MultipleRoundsSystem::DECIMAL_PRECISION),
|
||||
'C' => round(100/3, MultipleRoundsSystem::DECIMAL_PRECISION),
|
||||
],
|
||||
],
|
||||
$stats
|
||||
);
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C']],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1=> [
|
||||
'A' => 0.0,
|
||||
'B' => 0.0,
|
||||
'C' => 0.0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_9(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B ^10
|
||||
B ^12
|
||||
C ^10
|
||||
D>E>A>B ^9
|
||||
E>B ^5
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'A', 2 => 'B', 3 => 'C', 4=> 'D', 5=> 'E'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'B' => 12,
|
||||
'A' => 10,
|
||||
'C' => 10,
|
||||
'D' => 9,
|
||||
'E' => 5,
|
||||
],
|
||||
2=> [
|
||||
'A' => 19,
|
||||
'B' => 17,
|
||||
'C' => 10,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
|
||||
$this->election->addVote('E>B ^2');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B'], 2 => 'C', 3=> 'D', 4 => 'E'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'B' => 12,
|
||||
'A' => 10,
|
||||
'C' => 10,
|
||||
'D' => 9,
|
||||
'E' => 7,
|
||||
],
|
||||
2=> [
|
||||
'A' => 19,
|
||||
'B' => 19,
|
||||
'C' => 10,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
|
||||
$this->election->addVote('C');
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'B', 2 => 'C', 3=> 'A', 4 => 'D', 5 => 'E'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'B' => 12,
|
||||
'C' => 11,
|
||||
'A' => 10,
|
||||
'D' => 9,
|
||||
'E' => 7,
|
||||
],
|
||||
2=> [
|
||||
'B' => 38,
|
||||
'C' => 11,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_10(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A ^10
|
||||
B ^10
|
||||
C ^10
|
||||
D>E ^9
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C'], 2 => 'D', 3 => 'E'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1=> [
|
||||
'A' => (float) 10,
|
||||
'B' => (float) 10,
|
||||
'C' => (float) 10,
|
||||
'D' => (float) 9,
|
||||
'E' => (float) 0,
|
||||
],
|
||||
2=> [
|
||||
'A' => (float) 13,
|
||||
'B' => (float) 13,
|
||||
'C' => (float) 13,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C'], 2 => 'D', 3 => 'E'],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
[1=> [
|
||||
'A' => 10,
|
||||
'B' => 10,
|
||||
'C' => 10,
|
||||
'D' => 9,
|
||||
'E' => 0,
|
||||
],
|
||||
2=> [
|
||||
'A' => 10,
|
||||
'B' => 10,
|
||||
'C' => 10,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_11(): void
|
||||
{
|
||||
$this->election->allowsVoteWeight(true);
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A ^10
|
||||
B ^10
|
||||
C ^10
|
||||
D>E ^9
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C']],
|
||||
$this->election->getResult('Two Rounds')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1=> [
|
||||
'A' => (float) 10,
|
||||
'B' => (float) 10,
|
||||
'C' => (float) 10,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('Two Rounds')->getStats()
|
||||
);
|
||||
}
|
||||
}
|
273
include/Condorcet/Tests/src/Algo/Methods/Minimax/MinimaxTest.php
Normal file
273
include/Condorcet/Tests/src/Algo/Methods/Minimax/MinimaxTest.php
Normal file
@ -0,0 +1,273 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Minimax;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class MinimaxTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Minimax_Condorcet
|
||||
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('Minimax Winning'));
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('Minimax Margin'));
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('Minimax Opposition'));
|
||||
|
||||
$expectedRanking = [
|
||||
1 => 'Nashville',
|
||||
2 => 'Memphis',
|
||||
3 => 'Chattanooga',
|
||||
4 => 'Knoxville',
|
||||
];
|
||||
|
||||
self::assertSame(
|
||||
$expectedRanking,
|
||||
$this->election->getResult('Minimax Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expectedRanking,
|
||||
$this->election->getResult('Minimax Margin')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expectedRanking,
|
||||
$this->election->getResult('Minimax Opposition')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['Memphis' => ['worst_pairwise_defeat_winning' => 58],
|
||||
'Nashville' => ['worst_pairwise_defeat_winning' => 0],
|
||||
'Chattanooga' => ['worst_pairwise_defeat_winning' => 68],
|
||||
'Knoxville' => ['worst_pairwise_defeat_winning' => 83], ],
|
||||
$this->election->getResult('Minimax Winning')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['Memphis' => ['worst_pairwise_defeat_margin' => 16],
|
||||
'Nashville' => ['worst_pairwise_defeat_margin' => -16],
|
||||
'Chattanooga' => ['worst_pairwise_defeat_margin' => 36],
|
||||
'Knoxville' => ['worst_pairwise_defeat_margin' => 66], ],
|
||||
$this->election->getResult('Minimax Margin')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['Memphis' => ['worst_pairwise_opposition' => 58],
|
||||
'Nashville' => ['worst_pairwise_opposition' => 42],
|
||||
'Chattanooga' => ['worst_pairwise_opposition' => 68],
|
||||
'Knoxville' => ['worst_pairwise_opposition' => 83], ],
|
||||
$this->election->getResult('Minimax Opposition')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Minimax_Condorcet
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A = C > B * 4
|
||||
A > C > B * 47
|
||||
C > B > A * 43
|
||||
B > A = C * 6
|
||||
');
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('Minimax Winning'));
|
||||
|
||||
self::assertSame($this->election->getWinner(), $this->election->getWinner('Minimax Margin'));
|
||||
|
||||
self::assertEquals('C', $this->election->getWinner('Minimax Opposition'));
|
||||
|
||||
$expectedRanking1 = [
|
||||
1 => 'A',
|
||||
2 => 'C',
|
||||
3 => 'B',
|
||||
];
|
||||
|
||||
self::assertSame(
|
||||
$expectedRanking1,
|
||||
$this->election->getResult('Minimax Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expectedRanking1,
|
||||
$this->election->getResult('Minimax Margin')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'C',
|
||||
2 => 'A',
|
||||
3 => 'B', ],
|
||||
$this->election->getResult('Minimax Opposition')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_defeat_winning' => 0],
|
||||
'B' => ['worst_pairwise_defeat_winning' => 94],
|
||||
'C' => ['worst_pairwise_defeat_winning' => 47], ],
|
||||
$this->election->getResult('Minimax Winning')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_defeat_margin' => -2],
|
||||
'B' => ['worst_pairwise_defeat_margin' => 88],
|
||||
'C' => ['worst_pairwise_defeat_margin' => 4], ],
|
||||
$this->election->getResult('Minimax Margin')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_opposition' => 49],
|
||||
'B' => ['worst_pairwise_opposition' => 94],
|
||||
'C' => ['worst_pairwise_opposition' => 47], ],
|
||||
$this->election->getResult('Minimax Opposition')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
# From http://www.cs.wustl.edu/~legrand/rbvote/desc.html
|
||||
|
||||
$this->election->addCandidate('Abby');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Cora');
|
||||
$this->election->addCandidate('Dave');
|
||||
$this->election->addCandidate('Erin');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Abby>Cora>Erin>Dave>Brad * 98
|
||||
Brad>Abby>Erin>Cora>Dave * 64
|
||||
Brad>Abby>Erin>Dave>Cora * 12
|
||||
Brad>Erin>Abby>Cora>Dave * 98
|
||||
Brad>Erin>Abby>Dave>Cora * 13
|
||||
Brad>Erin>Dave>Abby>Cora * 125
|
||||
Cora>Abby>Erin>Dave>Brad * 124
|
||||
Cora>Erin>Abby>Dave>Brad * 76
|
||||
Dave>Abby>Brad>Erin>Cora * 21
|
||||
Dave>Brad>Abby>Erin>Cora * 30
|
||||
Dave>Brad>Erin>Cora>Abby * 98
|
||||
Dave>Cora>Abby>Brad>Erin * 139
|
||||
Dave>Cora>Brad>Abby>Erin * 23
|
||||
');
|
||||
|
||||
self::assertEquals('Cora', $this->election->getWinner('Minimax Winning'));
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Condorcet_loser_criterion
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('L');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 1
|
||||
A > B > L * 1
|
||||
B > C > A * 3
|
||||
C > L > A * 1
|
||||
L > A > B * 1
|
||||
L > C > A * 2
|
||||
');
|
||||
|
||||
self::assertEquals('L', $this->election->getWinner('Minimax Winning'));
|
||||
}
|
||||
|
||||
public function testResult_5(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Condorcet_loser_criterion
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > B > D * 30
|
||||
D > B > A > C * 15
|
||||
D > B > C > A * 14
|
||||
B > C > A > D * 6
|
||||
D > C > A = B * 4
|
||||
C > A = B * 16
|
||||
B > C * 14
|
||||
C > A * 3
|
||||
');
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('Minimax Winning'));
|
||||
self::assertEquals('B', $this->election->getWinner('Minimax Margin'));
|
||||
self::assertEquals('D', $this->election->getWinner('Minimax Opposition'));
|
||||
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_defeat_winning' => 35],
|
||||
'B' => ['worst_pairwise_defeat_winning' => 50],
|
||||
'C' => ['worst_pairwise_defeat_winning' => 45],
|
||||
'D' => ['worst_pairwise_defeat_winning' => 36], ],
|
||||
$this->election->getResult('Minimax Winning')->getStats()
|
||||
);
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_defeat_margin' => 5],
|
||||
'B' => ['worst_pairwise_defeat_margin' => 1],
|
||||
'C' => ['worst_pairwise_defeat_margin' => 2],
|
||||
'D' => ['worst_pairwise_defeat_margin' => 3], ],
|
||||
$this->election->getResult('Minimax Margin')->getStats()
|
||||
);
|
||||
self::assertSame(
|
||||
['A' => ['worst_pairwise_opposition' => 43],
|
||||
'B' => ['worst_pairwise_opposition' => 50],
|
||||
'C' => ['worst_pairwise_opposition' => 49],
|
||||
'D' => ['worst_pairwise_opposition' => 36], ],
|
||||
$this->election->getResult('Minimax Opposition')->getStats()
|
||||
);
|
||||
|
||||
// Implicit Ranking
|
||||
$this->election->setImplicitRanking(true);
|
||||
|
||||
self::assertNotEquals('A', $this->election->getWinner('Minimax Winning'));
|
||||
}
|
||||
|
||||
public function testResult_6(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Minimax_Condorcet
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C
|
||||
C > B > A
|
||||
');
|
||||
|
||||
self::assertNotNull($this->election->getWinner('Minimax Margin'));
|
||||
}
|
||||
}
|
176
include/Condorcet/Tests/src/Algo/Methods/PairwiseTest.php
Normal file
176
include/Condorcet/Tests/src/Algo/Methods/PairwiseTest.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\RankedPairs;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PairwiseTest extends TestCase
|
||||
{
|
||||
private readonly Election $election1;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('A>B>C');
|
||||
}
|
||||
|
||||
public function testPairwiseOffsetGet(): void
|
||||
{
|
||||
$pairwise = $this->election1->getPairwise();
|
||||
|
||||
self::assertIsArray($pairwise[1]);
|
||||
|
||||
self::assertNull($pairwise[42]);
|
||||
}
|
||||
|
||||
public function testExplicitPairwise(): void
|
||||
{
|
||||
self::assertSame(
|
||||
[
|
||||
'A' => [
|
||||
'win' => [
|
||||
'B' => 1,
|
||||
'C' => 1,
|
||||
],
|
||||
'null' => [
|
||||
'B' => 0,
|
||||
'C' => 0,
|
||||
],
|
||||
'lose' => [
|
||||
'B' => 0,
|
||||
'C' => 0,
|
||||
],
|
||||
],
|
||||
'B' => [
|
||||
'win' => [
|
||||
'A' => 0,
|
||||
'C' => 1,
|
||||
],
|
||||
'null' => [
|
||||
'A' => 0,
|
||||
'C' => 0,
|
||||
],
|
||||
'lose' => [
|
||||
'A' => 1,
|
||||
'C' => 0,
|
||||
],
|
||||
],
|
||||
'C' => [
|
||||
'win' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
],
|
||||
'null' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
],
|
||||
'lose' => [
|
||||
'A' => 1,
|
||||
'B' => 1,
|
||||
],
|
||||
],
|
||||
],
|
||||
$this->election1->getPairwise()->getExplicitPairwise()
|
||||
);
|
||||
}
|
||||
|
||||
public function testVotesWeight(): void
|
||||
{
|
||||
$electionOff = new Election;
|
||||
|
||||
$electionOff->addCandidate('A');
|
||||
$electionOff->addCandidate('B');
|
||||
$electionOff->addCandidate('C');
|
||||
$electionOff->addCandidate('D');
|
||||
|
||||
$electionOff->addVote('A>B>C=D ^3');
|
||||
$electionOff->addVote('A>B>C=D ^4');
|
||||
|
||||
$electionOn = clone $electionOff;
|
||||
$electionOn->allowsVoteWeight(true);
|
||||
|
||||
self::assertNotSame($electionOff->getExplicitPairwise(), $electionOn->getExplicitPairwise());
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
'A' => [
|
||||
'win' => [
|
||||
'B' => 7,
|
||||
'C' => 7,
|
||||
'D' => 7,
|
||||
],
|
||||
'null' => [
|
||||
'B' => 0,
|
||||
'C' => 0,
|
||||
'D' => 0,
|
||||
],
|
||||
'lose' => [
|
||||
'B' => 0,
|
||||
'C' => 0,
|
||||
'D' => 0,
|
||||
],
|
||||
],
|
||||
'B' => [
|
||||
'win' => [
|
||||
'A' => 0,
|
||||
'C' => 7,
|
||||
'D' => 7,
|
||||
],
|
||||
'null' => [
|
||||
'A' => 0,
|
||||
'C' => 0,
|
||||
'D' => 0,
|
||||
],
|
||||
'lose' => [
|
||||
'A' => 7,
|
||||
'C' => 0,
|
||||
'D' => 0,
|
||||
],
|
||||
],
|
||||
'C' => [
|
||||
'win' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
'D' => 0,
|
||||
],
|
||||
'null' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
'D' => 7,
|
||||
],
|
||||
'lose' => [
|
||||
'A' => 7,
|
||||
'B' => 7,
|
||||
'D' => 0,
|
||||
],
|
||||
],
|
||||
'D' => [
|
||||
'win' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
'C' => 0,
|
||||
],
|
||||
'null' => [
|
||||
'A' => 0,
|
||||
'B' => 0,
|
||||
'C' => 7,
|
||||
],
|
||||
'lose' => [
|
||||
'A' => 7,
|
||||
'B' => 7,
|
||||
'C' => 0,
|
||||
],
|
||||
],
|
||||
],
|
||||
$electionOn->getPairwise()->getExplicitPairwise()
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,464 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\RankedPairs;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Candidate, Condorcet, Election};
|
||||
use CondorcetPHP\Condorcet\Throwable\CandidatesMaxNumberReachedException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class RankedPairsTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/M%C3%A9thode_Condorcet_avec_rangement_des_paires_par_ordre_d%C3%A9croissant
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > B > E * 5
|
||||
A > D > E > C * 5
|
||||
B > E > D > A * 8
|
||||
C > A > B > E * 3
|
||||
C > A > E > B * 7
|
||||
C > B > A > D * 2
|
||||
D > C > E > B * 7
|
||||
E > B > A > D * 8
|
||||
');
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
$expected = [1 => 'A',
|
||||
2 => 'C',
|
||||
3 => 'E',
|
||||
4 => 'B',
|
||||
5 => 'D', ];
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:10:{i:0;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"D";s:3:"win";i:33;s:8:"minority";i:12;s:6:"margin";i:21;}}i:1;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"D";s:3:"win";i:31;s:8:"minority";i:14;s:6:"margin";i:17;}}i:2;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";s:3:"win";i:30;s:8:"minority";i:15;s:6:"margin";i:15;}}i:3;a:1:{i:0;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";s:3:"win";i:29;s:8:"minority";i:16;s:6:"margin";i:13;}}i:4;a:1:{i:0;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";s:3:"win";i:28;s:8:"minority";i:17;s:6:"margin";i:11;}}i:5;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"B";s:3:"win";i:27;s:8:"minority";i:18;s:6:"margin";i:9;}}i:6;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";s:3:"win";i:26;s:8:"minority";i:19;s:6:"margin";i:7;}}i:7;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";s:3:"win";i:25;s:8:"minority";i:20;s:6:"margin";i:5;}}i:8;a:1:{i:0;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"E";s:3:"win";i:24;s:8:"minority";i:21;s:6:"margin";i:3;}}i:9;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"A";s:3:"win";i:23;s:8:"minority";i:22;s:6:"margin";i:1;}}}s:4:"arcs";a:7:{i:0;a:2:{s:4:"from";s:1:"B";s:2:"to";s:1:"D";}i:1;a:2:{s:4:"from";s:1:"E";s:2:"to";s:1:"D";}i:2;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";}i:3;a:2:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";}i:4;a:2:{s:4:"from";s:1:"E";s:2:"to";s:1:"B";}i:5;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";}i:6;a:2:{s:4:"from";s:1:"C";s:2:"to";s:1:"E";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Winning')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:10:{i:0;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"D";s:3:"win";i:33;s:8:"minority";i:12;s:6:"margin";i:21;}}i:1;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"D";s:3:"win";i:31;s:8:"minority";i:14;s:6:"margin";i:17;}}i:2;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";s:3:"win";i:30;s:8:"minority";i:15;s:6:"margin";i:15;}}i:3;a:1:{i:0;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";s:3:"win";i:29;s:8:"minority";i:16;s:6:"margin";i:13;}}i:4;a:1:{i:0;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";s:3:"win";i:28;s:8:"minority";i:17;s:6:"margin";i:11;}}i:5;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"B";s:3:"win";i:27;s:8:"minority";i:18;s:6:"margin";i:9;}}i:6;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";s:3:"win";i:26;s:8:"minority";i:19;s:6:"margin";i:7;}}i:7;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";s:3:"win";i:25;s:8:"minority";i:20;s:6:"margin";i:5;}}i:8;a:1:{i:0;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"E";s:3:"win";i:24;s:8:"minority";i:21;s:6:"margin";i:3;}}i:9;a:1:{i:0;a:5:{s:4:"from";s:1:"E";s:2:"to";s:1:"A";s:3:"win";i:23;s:8:"minority";i:22;s:6:"margin";i:1;}}}s:4:"arcs";a:7:{i:0;a:2:{s:4:"from";s:1:"B";s:2:"to";s:1:"D";}i:1;a:2:{s:4:"from";s:1:"E";s:2:"to";s:1:"D";}i:2;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";}i:3;a:2:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";}i:4;a:2:{s:4:"from";s:1:"E";s:2:"to";s:1:"B";}i:5;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";}i:6;a:2:{s:4:"from";s:1:"C";s:2:"to";s:1:"E";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Margin')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Ranked_pairs
|
||||
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
$expected = [1 => 'Nashville',
|
||||
2 => 'Chattanooga',
|
||||
3 => 'Knoxville',
|
||||
4 => 'Memphis', ];
|
||||
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:3:{i:0;a:1:{i:0;a:5:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:9:"Knoxville";s:3:"win";i:83;s:8:"minority";i:17;s:6:"margin";i:66;}}i:1;a:2:{i:0;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:9:"Knoxville";s:3:"win";i:68;s:8:"minority";i:32;s:6:"margin";i:36;}i:1;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:11:"Chattanooga";s:3:"win";i:68;s:8:"minority";i:32;s:6:"margin";i:36;}}i:2;a:3:{i:0;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}i:1;a:5:{s:4:"from";s:9:"Knoxville";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}i:2;a:5:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}}}s:4:"arcs";a:6:{i:0;a:2:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:9:"Knoxville";}i:1;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:9:"Knoxville";}i:2;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:11:"Chattanooga";}i:3;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:7:"Memphis";}i:4;a:2:{s:4:"from";s:9:"Knoxville";s:2:"to";s:7:"Memphis";}i:5;a:2:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:7:"Memphis";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Winning')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:3:{i:0;a:1:{i:0;a:5:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:9:"Knoxville";s:3:"win";i:83;s:8:"minority";i:17;s:6:"margin";i:66;}}i:1;a:2:{i:0;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:9:"Knoxville";s:3:"win";i:68;s:8:"minority";i:32;s:6:"margin";i:36;}i:1;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:11:"Chattanooga";s:3:"win";i:68;s:8:"minority";i:32;s:6:"margin";i:36;}}i:2;a:3:{i:0;a:5:{s:4:"from";s:9:"Nashville";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}i:1;a:5:{s:4:"from";s:9:"Knoxville";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}i:2;a:5:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:7:"Memphis";s:3:"win";i:58;s:8:"minority";i:42;s:6:"margin";i:16;}}}s:4:"arcs";a:6:{i:0;a:2:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:9:"Knoxville";}i:1;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:9:"Knoxville";}i:2;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:11:"Chattanooga";}i:3;a:2:{s:4:"from";s:9:"Nashville";s:2:"to";s:7:"Memphis";}i:4;a:2:{s:4:"from";s:9:"Knoxville";s:2:"to";s:7:"Memphis";}i:5;a:2:{s:4:"from";s:11:"Chattanooga";s:2:"to";s:7:"Memphis";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Margin')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
# from http://www.cs.wustl.edu/~legrand/rbvote/desc.html
|
||||
|
||||
$this->election->addCandidate('Abby');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Cora');
|
||||
$this->election->addCandidate('Dave');
|
||||
$this->election->addCandidate('Erin');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Abby>Cora>Erin>Dave>Brad * 98
|
||||
Brad>Abby>Erin>Cora>Dave * 64
|
||||
Brad>Abby>Erin>Dave>Cora * 12
|
||||
Brad>Erin>Abby>Cora>Dave * 98
|
||||
Brad>Erin>Abby>Dave>Cora * 13
|
||||
Brad>Erin>Dave>Abby>Cora * 125
|
||||
Cora>Abby>Erin>Dave>Brad * 124
|
||||
Cora>Erin>Abby>Dave>Brad * 76
|
||||
Dave>Abby>Brad>Erin>Cora * 21
|
||||
Dave>Brad>Abby>Erin>Cora * 30
|
||||
Dave>Brad>Erin>Cora>Abby * 98
|
||||
Dave>Cora>Abby>Brad>Erin * 139
|
||||
Dave>Cora>Brad>Abby>Erin * 23
|
||||
');
|
||||
|
||||
$expected =[1 => 'Brad',
|
||||
2 => 'Abby',
|
||||
3 => 'Erin',
|
||||
4 => 'Dave',
|
||||
5 => 'Cora', ];
|
||||
|
||||
self::assertEquals('Brad', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Ranked_pairs
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B * 68
|
||||
B > C * 72
|
||||
C > A * 52
|
||||
');
|
||||
|
||||
// Not supporting not ranked candidate
|
||||
self::assertNotEquals('A', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
// Supporting not ranked candidate
|
||||
$this->election->setImplicitRanking(false);
|
||||
self::assertEquals('A', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
}
|
||||
|
||||
public function testResult_5(): void
|
||||
{
|
||||
# From http://ericgorr.net/condorcet/rankedpairs/example1/
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 7
|
||||
B > A > C * 5
|
||||
C > A > B * 4
|
||||
B > C > A * 2
|
||||
');
|
||||
|
||||
$expected = [1 => 'A',
|
||||
2 => 'B',
|
||||
3 => 'C', ];
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_6(): void
|
||||
{
|
||||
# From http://ericgorr.net/condorcet/rankedpairs/example2/
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 40
|
||||
B > C > A * 35
|
||||
C > A > B * 25
|
||||
');
|
||||
|
||||
$expected = [1 => 'A',
|
||||
2 => 'B',
|
||||
3 => 'C', ];
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_7(): void
|
||||
{
|
||||
# From http://ericgorr.net/condorcet/rankedpairs/example3/
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 7
|
||||
B > A > C * 7
|
||||
C > A > B * 2
|
||||
C > B > A * 2
|
||||
');
|
||||
|
||||
$expected = [1 => ['A', 'B'],
|
||||
2 => 'C', ];
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_8(): void
|
||||
{
|
||||
# From http://ericgorr.net/condorcet/rankedpairs/example4/
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>D>C>B*12
|
||||
B>A>C>D*3
|
||||
B>C>A>D*25
|
||||
C>B>A>D*21
|
||||
D>A>B>C*12
|
||||
D>A>C>B*21
|
||||
D>B>A>C*6
|
||||
');
|
||||
|
||||
$expected = [1 => 'B',
|
||||
2 => 'A',
|
||||
3 => 'D',
|
||||
4 => 'C', ];
|
||||
|
||||
self::assertEquals('B', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:4:{i:0;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";s:3:"win";i:61;s:8:"minority";i:39;s:6:"margin";i:22;}}i:1;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";s:3:"win";i:55;s:8:"minority";i:45;s:6:"margin";i:10;}}i:2;a:2:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";s:3:"win";i:54;s:8:"minority";i:46;s:6:"margin";i:8;}i:1;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";s:3:"win";i:54;s:8:"minority";i:46;s:6:"margin";i:8;}}i:3;a:2:{i:0;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"B";s:3:"win";i:51;s:8:"minority";i:49;s:6:"margin";i:2;}i:1;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";s:3:"win";i:51;s:8:"minority";i:49;s:6:"margin";i:2;}}}s:4:"arcs";a:3:{i:0;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";}i:1;a:2:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";}i:2;a:2:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Winning')->getStats()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:2:{s:5:"tally";a:4:{i:0;a:1:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";s:3:"win";i:61;s:8:"minority";i:39;s:6:"margin";i:22;}}i:1;a:1:{i:0;a:5:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";s:3:"win";i:55;s:8:"minority";i:45;s:6:"margin";i:10;}}i:2;a:2:{i:0;a:5:{s:4:"from";s:1:"A";s:2:"to";s:1:"C";s:3:"win";i:54;s:8:"minority";i:46;s:6:"margin";i:8;}i:1;a:5:{s:4:"from";s:1:"C";s:2:"to";s:1:"B";s:3:"win";i:54;s:8:"minority";i:46;s:6:"margin";i:8;}}i:3;a:2:{i:0;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"B";s:3:"win";i:51;s:8:"minority";i:49;s:6:"margin";i:2;}i:1;a:5:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";s:3:"win";i:51;s:8:"minority";i:49;s:6:"margin";i:2;}}}s:4:"arcs";a:3:{i:0;a:2:{s:4:"from";s:1:"A";s:2:"to";s:1:"D";}i:1;a:2:{s:4:"from";s:1:"B";s:2:"to";s:1:"A";}i:2;a:2:{s:4:"from";s:1:"D";s:2:"to";s:1:"C";}}}'),
|
||||
$this->election->getResult('Ranked Pairs Winning')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_9(): void
|
||||
{
|
||||
# Test fix for rare bug
|
||||
|
||||
for ($i=0; $i < 8; $i++) {
|
||||
$this->election->addCandidate();
|
||||
}
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > E > B > H > G > F > D > C * 1
|
||||
B > F > E > H > C > A > G > D * 1
|
||||
G > F > B > C > D > E > H > A * 1
|
||||
H > A > B > F > E > C > D > G * 1
|
||||
B > H > A > E > G > F > D > C * 1
|
||||
E > D > H > C > B > A > F > G * 1
|
||||
C > A > F > B > E > D > H > G * 1
|
||||
G > H > D > C > E > F > B > A * 1
|
||||
F > E > H > A > B > C > G > D * 1
|
||||
D > B > F > C > G > E > A > H * 1
|
||||
H > G > A > E > B > C > F > D * 1
|
||||
E > D > G > F > A > B > H > C * 1
|
||||
C > D > G > A > E > H > B > F * 1
|
||||
H > C > B > G > A > D > F > E * 1
|
||||
C > B > G > A > D > H > F > E * 1
|
||||
B > D > F > H > G > E > A > C * 1
|
||||
B > C > E > F > G > H > D > A * 1
|
||||
C > G > H > F > D > E > A > B * 1
|
||||
E > A > H > C > F > D > G > B * 1
|
||||
C > D > G > H > B > A > E > F * 1
|
||||
B > D > A > C > G > F > E > H * 1
|
||||
C > A > B > G > E > D > H > F * 1
|
||||
E > G > H > A > D > C > F > B * 1
|
||||
F > G > B > H > E > C > D > A * 1
|
||||
A > H > D > C > F > E > B > G * 1
|
||||
');
|
||||
|
||||
self::assertEquals('B', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
}
|
||||
|
||||
public function testResult_10(): void
|
||||
{
|
||||
# Tideman: Independence of Clones as a Criterion for Voting Rules (1987)
|
||||
# Example 5
|
||||
|
||||
$this->election->addCandidate('v');
|
||||
$this->election->addCandidate('w');
|
||||
$this->election->addCandidate('x');
|
||||
$this->election->addCandidate('y');
|
||||
$this->election->addCandidate('z');
|
||||
|
||||
$this->election->parseVotes('
|
||||
v>w>x>y>z*7
|
||||
z>y>v>w>x*3
|
||||
y>z>w>x>v*6
|
||||
w>x>v>z>y*3
|
||||
z>x>v>w>y*5
|
||||
y>x>v>w>z*3
|
||||
');
|
||||
|
||||
|
||||
self::assertEquals('v', $this->election->getWinner('Ranked Pairs Winning'));
|
||||
|
||||
$expected = [1 => 'v',
|
||||
2 => 'w',
|
||||
3 => 'x',
|
||||
4 => 'y',
|
||||
5 => 'z', ];
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$expected,
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_11(): void
|
||||
{
|
||||
# From http://rangevoting.org/WinningVotes.htmls
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
|
||||
$this->election->parseVotes('
|
||||
B > C > A * 9
|
||||
C = A > B * 6
|
||||
A > B > C * 5
|
||||
');
|
||||
|
||||
self::assertNotEquals(
|
||||
$this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true),
|
||||
$this->election->getResult('Ranked Pairs Margin')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMaxCandidates(): never
|
||||
{
|
||||
$this->expectException(CandidatesMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage("Maximum number of candidates reached: The method 'Ranked Pairs Winning' is configured to accept only 60 candidates");
|
||||
|
||||
for ($i=0; $i < 61; $i++) {
|
||||
$this->election->addCandidate();
|
||||
}
|
||||
|
||||
$this->election->parseVotes('A');
|
||||
|
||||
$this->election->getWinner('Ranked Pairs Winning');
|
||||
}
|
||||
|
||||
// public function testResult_stressTests (): void
|
||||
// {
|
||||
// $rounds = 1;
|
||||
// $candidates = 332;
|
||||
// $votes = 500;
|
||||
|
||||
// # Test fix for rare bug
|
||||
// for ($j=0; $j < $rounds; $j++) {
|
||||
// $this->election = new Election;
|
||||
|
||||
// for ($i=0; $i < $candidates ; $i++) {
|
||||
// $this->election->addCandidate();
|
||||
// }
|
||||
|
||||
|
||||
// $VoteModel = $this->election->getCandidatesList();
|
||||
// \shuffle($VoteModel);
|
||||
|
||||
// for ($i = 0 ; $i < $votes ; $i++) {
|
||||
// \shuffle($VoteModel);
|
||||
// $this->election->addVote( $VoteModel );
|
||||
// }
|
||||
|
||||
// \var_dump($j);
|
||||
|
||||
// \var_dump($this->election->getVotesListAsString());
|
||||
|
||||
// \var_dump($this->election->getResult('Ranked Pairs Winning')->getResultAsArray(true));
|
||||
|
||||
// self::assertEquals(true,true);
|
||||
// }
|
||||
// }
|
||||
}
|
319
include/Condorcet/Tests/src/Algo/Methods/STV/CPO_StvTest.php
Normal file
319
include/Condorcet/Tests/src/Algo/Methods/STV/CPO_StvTest.php
Normal file
@ -0,0 +1,319 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\STV;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\STV\CPO_STV;
|
||||
use CondorcetPHP\Condorcet\Algo\StatsVerbosity;
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\StvQuotas;
|
||||
use CondorcetPHP\Condorcet\Throwable\MethodLimitReachedException;
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CPO_StvTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::DROOP);
|
||||
$this->election->setMethodOption('CPO STV', 'Quota', StvQuotas::HAGENBACH_BISCHOFF);
|
||||
$this->election->setMethodOption('CPO STV', 'CondorcetCompletionMethod', CPO_STV::DEFAULT_METHODS_CHAINING);
|
||||
$this->election->setMethodOption('CPO STV', 'TieBreakerMethods', CPO_STV::DEFAULT_METHODS_CHAINING);
|
||||
}
|
||||
|
||||
# From https://en.wikipedia.org/wiki/CPO-STV
|
||||
public function testCPO1(): void
|
||||
{
|
||||
$this->election->setStatsVerbosity(StatsVerbosity::FULL);
|
||||
|
||||
$this->election->addCandidate('Andrea'); // key 0
|
||||
$this->election->addCandidate('Brad'); // key 1
|
||||
$this->election->addCandidate('Carter'); // key 2
|
||||
$this->election->addCandidate('Delilah'); // key 3
|
||||
$this->election->addCandidate('Scott'); // key 4
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea ^25
|
||||
Carter > Brad > Delilah ^34
|
||||
Brad > Delilah ^7
|
||||
Delilah > Brad ^8
|
||||
Delilah > Scott ^5
|
||||
Scott > Delilah ^21
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(3);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Carter',
|
||||
2 => 'Andrea',
|
||||
3 => 'Delilah',
|
||||
],
|
||||
$this->election->getResult('CPO STV')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
$stats = $this->election->getResult('CPO STV')->getStats();
|
||||
|
||||
self::assertSame(25.0, $stats['Votes Needed to Win']);
|
||||
self::assertSame(['Andrea'=> 25.0,
|
||||
'Brad'=> 7.0,
|
||||
'Carter'=> 34.0,
|
||||
'Delilah'=> 13.0,
|
||||
'Scott'=> 21.0,
|
||||
], $stats['Initial Score Table']);
|
||||
|
||||
self::assertSame(['Andrea', 'Carter'], $stats['Candidates elected from first round']);
|
||||
self::assertSame(['Brad', 'Delilah', 'Scott'], $stats['Candidates eliminated from first round']);
|
||||
|
||||
self::assertSame([
|
||||
['Andrea', 'Carter', 'Scott'],
|
||||
['Andrea', 'Carter', 'Delilah'],
|
||||
['Andrea', 'Brad', 'Carter'],
|
||||
], $stats['Outcomes']);
|
||||
|
||||
self::assertSame('Schulze Margin', $stats['Completion Method']);
|
||||
|
||||
self::assertSame(
|
||||
['Outcome N° 0 compared to Outcome N° 1' => [
|
||||
'candidates_excluded' => [
|
||||
0 => 'Brad',
|
||||
],
|
||||
'scores_after_exclusion' => [
|
||||
'Andrea' => 25.0,
|
||||
'Carter' => 34.0,
|
||||
'Delilah' => 20.0,
|
||||
'Scott' => 21.0,
|
||||
],
|
||||
'scores_after_surplus' => [
|
||||
'Andrea' => 25.0,
|
||||
'Carter' => 25.0,
|
||||
'Delilah' => 29.0,
|
||||
'Scott' => 21.0,
|
||||
],
|
||||
'outcomes_scores' => [
|
||||
0 => 71.0,
|
||||
1 => 79.0,
|
||||
],
|
||||
],
|
||||
'Outcome N° 0 compared to Outcome N° 2' => [
|
||||
'candidates_excluded' => [
|
||||
0 => 'Delilah',
|
||||
],
|
||||
'scores_after_exclusion' => [
|
||||
'Andrea' => 25.0,
|
||||
'Brad' => 15.0,
|
||||
'Carter' => 34.0,
|
||||
'Scott' => 26.0,
|
||||
],
|
||||
'scores_after_surplus' => [
|
||||
'Andrea' => 25.0,
|
||||
'Brad' => 24.0,
|
||||
'Carter' => 25.0,
|
||||
'Scott' => 26.0,
|
||||
],
|
||||
'outcomes_scores' => [
|
||||
0 => 76.0,
|
||||
2 => 74.0,
|
||||
],
|
||||
],
|
||||
'Outcome N° 1 compared to Outcome N° 2' => [
|
||||
'candidates_excluded' => [
|
||||
0 => 'Scott',
|
||||
],
|
||||
'scores_after_exclusion' => [
|
||||
'Andrea' => 25.0,
|
||||
'Brad' => 7.0,
|
||||
'Carter' => 34.0,
|
||||
'Delilah' => 34.0,
|
||||
],
|
||||
'scores_after_surplus' => [
|
||||
'Andrea' => 25.0,
|
||||
'Brad' => 16.0,
|
||||
'Carter' => 25.0,
|
||||
'Delilah' => 34.0,
|
||||
],
|
||||
'outcomes_scores' => [
|
||||
1 => 84.0,
|
||||
2 => 66.0,
|
||||
],
|
||||
],
|
||||
],
|
||||
$stats['Outcomes Comparison']
|
||||
);
|
||||
|
||||
self::assertArrayHasKey('Condorcet Completion Method Stats', $stats);
|
||||
}
|
||||
|
||||
|
||||
# From https://electowiki.org/wiki/CPO-STV
|
||||
public function testCPO2(): void
|
||||
{
|
||||
// $this->election->setStatsVerbosity(StatsVerbosity::FULL);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$file = new \SplTempFileObject(-1);
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Number of Seats: 3
|
||||
Escher ^ 100
|
||||
Andre>Nader>Gore ^ 110
|
||||
Nader>Gore ^ 18
|
||||
Gore>Nader ^ 21
|
||||
Gore>Bush ^ 6
|
||||
Bush>Gore ^ 45
|
||||
CVOTES);
|
||||
|
||||
$cef = new CondorcetElectionFormat($file);
|
||||
|
||||
$cef->setDataToAnElection($this->election);
|
||||
|
||||
$this->election->setMethodOption('CPO-STV', 'Quota', StvQuotas::HARE);
|
||||
|
||||
self::assertSame('Andre > Escher > Gore', $this->election->getResult('CPO STV')->getResultAsString());
|
||||
|
||||
self::assertSame((float) 100, $this->election->getResult('CPO STV')->getStats()['Votes Needed to Win']);
|
||||
}
|
||||
|
||||
# From https://electowiki.org/wiki/CPO-STV
|
||||
public function testCPO3(): void
|
||||
{
|
||||
$this->election->setStatsVerbosity(StatsVerbosity::FULL);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$file = new \SplTempFileObject(-1);
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Number of Seats: 2
|
||||
A>B>C>D * 5
|
||||
A>C>B>D * 17
|
||||
D * 8
|
||||
CVOTES);
|
||||
|
||||
$cef = new CondorcetElectionFormat($file);
|
||||
|
||||
$cef->setDataToAnElection($this->election);
|
||||
|
||||
$this->election->setMethodOption('CPO-STV', 'Quota', StvQuotas::DROOP);
|
||||
|
||||
self::assertSame('A > C', $this->election->getResult('CPO STV')->getResultAsString());
|
||||
|
||||
self::assertSame((float) 11, $this->election->getResult('CPO STV')->getStats()['Votes Needed to Win']);
|
||||
self::assertSame([0=>19.0, 2=>22.0], $this->election->getResult('CPO STV')->getStats()['Outcomes Comparison']['Outcome N° 0 compared to Outcome N° 2']['outcomes_scores']);
|
||||
self::assertSame([0=>19.0, 1=>22.0], $this->election->getResult('CPO STV')->getStats()['Outcomes Comparison']['Outcome N° 0 compared to Outcome N° 1']['outcomes_scores']);
|
||||
self::assertSame([1=>19.5, 2=>13.5], $this->election->getResult('CPO STV')->getStats()['Outcomes Comparison']['Outcome N° 1 compared to Outcome N° 2']['outcomes_scores']);
|
||||
}
|
||||
|
||||
public function testLessOrEqualCandidatesThanSeats(): void
|
||||
{
|
||||
$expectedRanking = [
|
||||
1 => 'Memphis',
|
||||
2 => 'Nashville',
|
||||
3 => 'Chattanooga',
|
||||
4 => 'Knoxville',
|
||||
];
|
||||
|
||||
// Ref
|
||||
$this->election->setNumberOfSeats(4);
|
||||
|
||||
$this->election->addCandidate('Memphis');
|
||||
$this->election->addCandidate('Nashville');
|
||||
$this->election->addCandidate('Knoxville');
|
||||
$this->election->addCandidate('Chattanooga');
|
||||
|
||||
$this->election->parseVotes(' Memphis * 4
|
||||
Nashville * 3
|
||||
Chattanooga * 2
|
||||
Knoxville * 1');
|
||||
|
||||
self::assertSame($expectedRanking, $this->election->getResult('CPO STV')->getResultAsArray(true));
|
||||
|
||||
$this->election->setNumberOfSeats(5);
|
||||
|
||||
self::assertSame($expectedRanking, $this->election->getResult('CPO STV')->getResultAsArray(true));
|
||||
}
|
||||
|
||||
public function testEquality1(): void
|
||||
{
|
||||
$this->election->setNumberOfSeats(2);
|
||||
|
||||
$this->election->parseCandidates('A;B;C');
|
||||
|
||||
$this->election->addVote('A>B>C');
|
||||
$this->election->addVote('B>A>C');
|
||||
$this->election->addVote('B>C>A');
|
||||
$this->election->addVote('A>B>C');
|
||||
|
||||
self::assertSame([1=>['A', 'B']], $this->election->getResult('CPO STV')->getResultAsArray(true));
|
||||
|
||||
$this->election->setNumberOfSeats(3);
|
||||
|
||||
self::assertSame([1=>['A', 'B'], 3=> 'C'], $this->election->getResult('CPO STV')->getResultAsArray(true));
|
||||
}
|
||||
|
||||
public function testEquality2(): void
|
||||
{
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->setNumberOfSeats(3);
|
||||
|
||||
$this->election->parseCandidates('A;B;C;D');
|
||||
|
||||
$this->election->addVote('A>B>C>D');
|
||||
$this->election->addVote('A>B>D>C');
|
||||
|
||||
self::assertSame([1=>'A', 2=>['B', 'D']], $this->election->getResult('CPO STV')->getResultAsArray(true));
|
||||
}
|
||||
|
||||
public function testLimit1(): void
|
||||
{
|
||||
$this->expectException(MethodLimitReachedException::class);
|
||||
$this->expectExceptionMessage('CPO-STV is currently limited to 12000 comparisons in order to avoid unreasonable deadlocks due to non-polyminial runtime aspects of the algorithm. Consult the manual to increase or remove this limit.');
|
||||
|
||||
|
||||
$this->election->setNumberOfSeats(10);
|
||||
$this->election->parseCandidates('1;2;3;4;5;6;7;8;9;10;11;12;13;14;15');
|
||||
$this->election->addVote('1>2');
|
||||
|
||||
$this->election->getResult('CPO STV');
|
||||
}
|
||||
|
||||
public function testCPO40Candidates(): void
|
||||
{
|
||||
$this->expectException(MethodLimitReachedException::class);
|
||||
$this->expectExceptionMessage('CPO-STV is currently limited to 12000 comparisons in order to avoid unreasonable deadlocks due to non-polyminial runtime aspects of the algorithm. Consult the manual to increase or remove this limit.');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->setNumberOfSeats((int) (40 / 3));
|
||||
|
||||
$candidates = [];
|
||||
for ($i=0; $i < 40; $i++) {
|
||||
$candidates[] = $this->election->addCandidate();
|
||||
}
|
||||
|
||||
if (version_compare(\PHP_VERSION, '8.2') >= 0) {
|
||||
$randomizer = new \Random\Randomizer(new \Random\Engine\Xoshiro256StarStar('CondorcetReproductibleRandomSeed'));
|
||||
|
||||
$shuffle = static fn (array $candidates): array => $randomizer->shuffleArray($candidates);
|
||||
} else {
|
||||
$shuffle = static function (array $candidates): array {
|
||||
$newCandidates = $candidates;
|
||||
shuffle($newCandidates);
|
||||
return $newCandidates;
|
||||
};
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 100; $i++) {
|
||||
$this->election->addVote($shuffle($candidates));
|
||||
}
|
||||
|
||||
$this->election->getResult('CPO STV')->getResultAsString();
|
||||
}
|
||||
}
|
@ -0,0 +1,477 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\STV;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Throwable\StvQuotaNotImplementedException;
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\STV\SingleTransferableVote;
|
||||
use CondorcetPHP\Condorcet\Algo\StatsVerbosity;
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\StvQuotas;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SingleTransferableVoteTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::DROOP);
|
||||
}
|
||||
|
||||
public function testQuotaOption(): never
|
||||
{
|
||||
self::assertSame(StvQuotas::DROOP, StvQuotas::make('droop'));
|
||||
|
||||
self::assertTrue(
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::make('Hagenbach-Bischoff'))
|
||||
);
|
||||
|
||||
$this->expectException(StvQuotaNotImplementedException::class);
|
||||
$this->expectExceptionMessage('This STV quota is not implemented: "another quota"');
|
||||
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::make('another quota'));
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
# From https://fr.wikipedia.org/wiki/Scrutin_%C3%A0_vote_unique_transf%C3%A9rable
|
||||
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('A');
|
||||
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>B>C>D ^ 28
|
||||
A>C>D>B ^ 14
|
||||
B>C>A>D ^ 15
|
||||
C>A>B>D ^ 17
|
||||
D>B>C>A ^ 26
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(2);
|
||||
|
||||
|
||||
self::assertEqualsWithDelta(
|
||||
[
|
||||
1 => [
|
||||
'A' => 42.0,
|
||||
'D' => 26.0,
|
||||
'C' => 17.0,
|
||||
'B' => 15.0,
|
||||
],
|
||||
2 => [
|
||||
'D' => 26.0,
|
||||
'B' => 20.33333333333,
|
||||
'C' => 19.66666666667,
|
||||
],
|
||||
3 => [
|
||||
'B' => 37.33333333333,
|
||||
'D' => 28.66666666667,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds'],
|
||||
1 / (0.1 ** SingleTransferableVote::DECIMAL_PRECISION)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
(float) 34,
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'B',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Single_transferable_vote
|
||||
|
||||
$this->election->addCandidate('Orange');
|
||||
$this->election->addCandidate('Pear');
|
||||
$this->election->addCandidate('Chocolate');
|
||||
$this->election->addCandidate('Strawberry');
|
||||
$this->election->addCandidate('Hamburger');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->setNumberOfSeats(3);
|
||||
|
||||
|
||||
$this->election->parseVotes('
|
||||
Orange ^ 4
|
||||
Pear > Orange * 2
|
||||
Chocolate > Strawberry * 8
|
||||
Chocolate > Hamburger * 4
|
||||
Strawberry
|
||||
Hamburger
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
(float) 6,
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => [
|
||||
'Chocolate' => 12.0,
|
||||
'Orange' => 4.0,
|
||||
'Pear' => 2.0,
|
||||
'Strawberry' => 1.0,
|
||||
'Hamburger' => 1.0,
|
||||
],
|
||||
2 => [
|
||||
'Strawberry' => 5.0,
|
||||
'Orange' => 4.0,
|
||||
'Hamburger' => 3.0,
|
||||
'Pear' => 2.0,
|
||||
],
|
||||
3 => [
|
||||
'Orange' => 6.0,
|
||||
'Strawberry' => 5.0,
|
||||
'Hamburger' => 3.0,
|
||||
],
|
||||
4 => [
|
||||
'Strawberry' => 5.0,
|
||||
'Hamburger' => 3.0,
|
||||
],
|
||||
5 => [
|
||||
'Strawberry' => 5.0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Chocolate',
|
||||
2 => 'Orange',
|
||||
3 => 'Strawberry',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_3(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Schulze_STV
|
||||
|
||||
$this->election->addCandidate('Andrea');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Carter');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->setNumberOfSeats(2);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea > Brad > Carter ^ 12
|
||||
Andrea > Carter > Brad ^ 26
|
||||
Andrea > Carter > Brad ^ 12
|
||||
Carter > Andrea > Brad ^ 13
|
||||
Brad ^ 27
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
(float) 31,
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => [
|
||||
'Andrea' => 50.0,
|
||||
'Brad' => 27.0,
|
||||
'Carter' => 13.0,
|
||||
],
|
||||
2 => [
|
||||
'Brad' => 31.56,
|
||||
'Carter' => 27.44,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Andrea',
|
||||
2 => 'Brad',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
$this->election->setStatsVerbosity(StatsVerbosity::LOW);
|
||||
self::assertArrayNotHasKey('rounds', $this->election->getResult('STV')->getStats());
|
||||
}
|
||||
|
||||
public function testResult_4(): void
|
||||
{
|
||||
# From https://it.wikipedia.org/wiki/Voto_singolo_trasferibile
|
||||
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('A');
|
||||
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
A>D ^ 40
|
||||
B>A ^ 10
|
||||
B>C ^ 5
|
||||
C>B ^ 25
|
||||
D>B ^ 20
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(3);
|
||||
|
||||
self::assertSame(
|
||||
(float) 26,
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'A',
|
||||
2 => 'D',
|
||||
3 => 'C',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function testResult_AlternativeQuotas1(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Hagenbach-Bischoff_quota
|
||||
|
||||
$this->election->addCandidate('Andrea');
|
||||
$this->election->addCandidate('Carter');
|
||||
$this->election->addCandidate('Brad');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea > Carter ^45
|
||||
Carter ^25
|
||||
Brad ^30
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(2);
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::make('Hagenbach-Bischoff'));
|
||||
|
||||
self::assertSame(
|
||||
round(33 + 1/3, SingleTransferableVote::DECIMAL_PRECISION, \PHP_ROUND_HALF_DOWN),
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertEqualsWithDelta(
|
||||
[
|
||||
1 => [
|
||||
'Andrea' => 45.0,
|
||||
'Brad' => 30.0,
|
||||
'Carter' => 25.0,
|
||||
],
|
||||
2 => [
|
||||
'Carter' => 36.0 + 2/3,
|
||||
'Brad' => 30.0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds'],
|
||||
delta: 1 / (0.1 ** SingleTransferableVote::DECIMAL_PRECISION)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Andrea',
|
||||
2 => 'Carter',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertsame($this->election->getResult('STV')->getMethodOptions()['Quota'], StvQuotas::make('Hagenbach-Bischoff'));
|
||||
}
|
||||
|
||||
public function testResult_AlternativeQuotas2(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Imperiali_quota
|
||||
|
||||
$this->election->addCandidate('Andrea');
|
||||
$this->election->addCandidate('Carter');
|
||||
$this->election->addCandidate('Brad');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea > Carter ^65
|
||||
Carter ^15
|
||||
Brad ^20
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(2);
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::IMPERIALI);
|
||||
|
||||
self::assertSame(
|
||||
(float) (100 / (2 + 2)),
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => [
|
||||
'Andrea' => 65.0,
|
||||
'Brad' => 20.0,
|
||||
'Carter' => 15.0,
|
||||
],
|
||||
2 => [
|
||||
'Carter' => 55.0,
|
||||
'Brad' => 20.0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Andrea',
|
||||
2 => 'Carter',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertsame($this->election->getResult('STV')->getMethodOptions()['Quota'], StvQuotas::make('Imperiali quota'));
|
||||
}
|
||||
|
||||
public function testResult_AlternativeQuotas3(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/Hare_quota
|
||||
|
||||
$this->election->addCandidate('Andrea');
|
||||
$this->election->addCandidate('Carter');
|
||||
$this->election->addCandidate('Brad');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea > Carter ^60
|
||||
Carter ^14
|
||||
Brad ^26
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(2);
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::make('Hare quota'));
|
||||
|
||||
self::assertSame(
|
||||
(float) (100 / 2),
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => [
|
||||
'Andrea' => 60.0,
|
||||
'Brad' => 26.0,
|
||||
'Carter' => 14.0,
|
||||
],
|
||||
2 => [
|
||||
'Brad' => 26.0,
|
||||
'Carter' => 24.0,
|
||||
],
|
||||
3 => ['Brad' => 26.0],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Andrea',
|
||||
2 => 'Brad',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
|
||||
self::assertsame($this->election->getResult('STV')->getMethodOptions()['Quota'], StvQuotas::HARE);
|
||||
}
|
||||
|
||||
public function testResult_AlternativeQuotas4(): void
|
||||
{
|
||||
# From https://en.wikipedia.org/wiki/CPO-STV
|
||||
|
||||
$this->election->addCandidate('Andrea');
|
||||
$this->election->addCandidate('Carter');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Delilah');
|
||||
$this->election->addCandidate('Scott');
|
||||
|
||||
$this->election->setImplicitRanking(false);
|
||||
$this->election->allowsVoteWeight(true);
|
||||
|
||||
$this->election->parseVotes('
|
||||
Andrea ^25
|
||||
Carter > Brad > Delilah ^34
|
||||
Brad > Delilah ^7
|
||||
Delilah > Brad ^8
|
||||
Delilah > Scott ^5
|
||||
Scott > Delilah ^21
|
||||
');
|
||||
|
||||
$this->election->setNumberOfSeats(3);
|
||||
$this->election->setMethodOption('STV', 'Quota', StvQuotas::HAGENBACH_BISCHOFF);
|
||||
|
||||
self::assertSame(
|
||||
(float) 25,
|
||||
$this->election->getResult('STV')->getStats()['Votes Needed to Win']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => [
|
||||
'Carter' => 34.0,
|
||||
'Andrea' => 25.0,
|
||||
'Scott' => 21.0,
|
||||
'Delilah' => 13.0,
|
||||
'Brad' => 7.0,
|
||||
],
|
||||
2 => [
|
||||
'Scott' => 21.0,
|
||||
'Brad' => 16.0,
|
||||
'Delilah' => 13.0,
|
||||
],
|
||||
3 => [
|
||||
'Scott' => 26.0,
|
||||
'Brad' => 24.0,
|
||||
],
|
||||
],
|
||||
$this->election->getResult('STV')->getStats()['rounds']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[
|
||||
1 => 'Carter',
|
||||
2 => 'Andrea',
|
||||
3 => 'Scott',
|
||||
],
|
||||
$this->election->getResult('STV')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
}
|
367
include/Condorcet/Tests/src/Algo/Methods/Schulze/SchulzeTest.php
Normal file
367
include/Condorcet/Tests/src/Algo/Methods/Schulze/SchulzeTest.php
Normal file
@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Methods\Schulze;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class SchulzeTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
}
|
||||
|
||||
public function testResult_1(): void
|
||||
{
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
$this->election->addCandidate('D');
|
||||
$this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > B > E * 5
|
||||
A > D > E > C * 5
|
||||
B > E > D > A * 8
|
||||
C > A > B > E * 3
|
||||
C > A > E > B * 7
|
||||
C > B > A > D * 2
|
||||
D > C > E > B * 7
|
||||
E > B > A > D * 8
|
||||
');
|
||||
|
||||
self::assertEquals('E', $this->election->getWinner('Schulze Winning'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'E',
|
||||
2 => 'A',
|
||||
3 => 'C',
|
||||
4 => 'B',
|
||||
5 => 'D', ],
|
||||
$this->election->getResult('Schulze Winning')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testResult_2(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 3
|
||||
D > A > B * 2
|
||||
D > B > C * 2
|
||||
C > B > D * 2
|
||||
');
|
||||
|
||||
self::assertSame([$candidateB, $candidateD], $this->election->getWinner('Schulze Winning'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['B', 'D'],
|
||||
2 => ['A', 'C'], ],
|
||||
$this->election->getResult('Schulze Winning')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_1(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > D * 8
|
||||
B > A > D * 2
|
||||
C > D > B * 4
|
||||
D > B > A * 4
|
||||
D > C > B * 3
|
||||
');
|
||||
|
||||
self::assertSame($candidateD, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_2(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 3
|
||||
C > B > D * 2
|
||||
D > A > B * 2
|
||||
D > B > C * 2
|
||||
');
|
||||
|
||||
self::assertSame([$candidateB, $candidateD], $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_3(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C * 12
|
||||
A > D > B * 6
|
||||
B > C > D * 9
|
||||
C > D > A * 15
|
||||
D > B > A * 21
|
||||
');
|
||||
|
||||
self::assertSame($candidateD, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_4(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > D * 6
|
||||
B > A > D * 1
|
||||
C > B > D * 3
|
||||
D > B > A * 3
|
||||
D > C > B * 2
|
||||
');
|
||||
|
||||
self::assertSame([$candidateA, $candidateD], $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_5(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
$candidateF = $this->election->addCandidate('F');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > D > E > B > C * 3
|
||||
B > F > E > C > D * 3
|
||||
C > A > B > F > D * 4
|
||||
D > B > C > E > F * 1
|
||||
D > E > F > A > B * 4
|
||||
E > C > B > D > F * 2
|
||||
F > A > C > D > B * 2
|
||||
');
|
||||
|
||||
# Situation 1
|
||||
self::assertSame($candidateA, $this->election->getWinner('Schulze Winning'));
|
||||
|
||||
# Situation 2
|
||||
$this->election->parseVotes('A > E > F > C > B * 2');
|
||||
|
||||
self::assertSame($candidateD, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_6_situation_1(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > D * 3
|
||||
A > D > B * 5
|
||||
A > D > C * 1
|
||||
B > A > D * 2
|
||||
B > D > C * 2
|
||||
C > A > B * 4
|
||||
C > B > A * 6
|
||||
D > B > C * 2
|
||||
D > C > A * 5
|
||||
');
|
||||
|
||||
self::assertSame($candidateA, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_6_situation_2(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > D > E * 3
|
||||
A > D > E > B * 5
|
||||
A > D > E > C * 1
|
||||
B > A > D > E * 2
|
||||
B > D > E > C * 2
|
||||
C > A > B > D * 4
|
||||
C > B > A > D * 6
|
||||
D > B > E > C * 2
|
||||
D > E > C > A * 5
|
||||
');
|
||||
|
||||
self::assertSame($candidateB, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_7(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > B > C > D * 6
|
||||
A = B * 8
|
||||
A = C * 8
|
||||
A = C > D * 18
|
||||
A = C = D * 8
|
||||
B * 40
|
||||
C > B > D * 4
|
||||
C > D > A * 9
|
||||
C = D * 8
|
||||
D > A > B * 14
|
||||
D > B > C * 11
|
||||
D > C > A * 4
|
||||
');
|
||||
|
||||
# Margin
|
||||
self::assertSame($candidateA, $this->election->getWinner('Schulze Margin'));
|
||||
|
||||
# Ratio
|
||||
self::assertSame($candidateB, $this->election->getWinner('Schulze Ratio'));
|
||||
|
||||
# Winning
|
||||
self::assertSame($candidateD, $this->election->getWinner('Schulze Winning'));
|
||||
|
||||
# Losing Votes
|
||||
// not implemented
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_8(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > D > B > E * 9
|
||||
B > C > A > D * 6
|
||||
B > C > D > E * 5
|
||||
C > D > B > E * 2
|
||||
D > E > C > B * 6
|
||||
E > A > C > B * 14
|
||||
E > C > A > B * 2
|
||||
E > D > A > C * 1
|
||||
');
|
||||
|
||||
self::assertSame($candidateB, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_9(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > D > B > E * 9
|
||||
B > A > C > E * 1
|
||||
C > B > A > D * 6
|
||||
C > D > B > E * 2
|
||||
C > D > E > A * 5
|
||||
D > E > C > A * 6
|
||||
E > B > A > C * 14
|
||||
E > B > C > A * 2
|
||||
');
|
||||
|
||||
self::assertSame($candidateE, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testSchulzeOfficialExampleResult_10(): void
|
||||
{
|
||||
$candidateA = $this->election->addCandidate('A');
|
||||
$candidateB = $this->election->addCandidate('B');
|
||||
$candidateC = $this->election->addCandidate('C');
|
||||
$candidateD = $this->election->addCandidate('D');
|
||||
$candidateE = $this->election->addCandidate('E');
|
||||
|
||||
$this->election->parseVotes('
|
||||
A > C > B > E * 5
|
||||
A > D > E > C * 5
|
||||
B > E > D > A * 8
|
||||
C > A > B > E * 3
|
||||
C > A > E > B * 7
|
||||
C > B > A > D * 2
|
||||
D > C > E > B * 7
|
||||
E > B > A > D * 8
|
||||
');
|
||||
|
||||
self::assertSame($candidateE, $this->election->getWinner('Schulze Winning'));
|
||||
}
|
||||
|
||||
public function testResult_11(): void
|
||||
{
|
||||
$this->election->addCandidate('Abby');
|
||||
$this->election->addCandidate('Brad');
|
||||
$this->election->addCandidate('Cora');
|
||||
$this->election->addCandidate('Dave');
|
||||
$this->election->addCandidate('Erin');
|
||||
|
||||
$this->election->parseVotes('
|
||||
Abby>Cora>Erin>Dave>Brad * 98
|
||||
Brad>Abby>Erin>Cora>Dave * 64
|
||||
Brad>Abby>Erin>Dave>Cora * 12
|
||||
Brad>Erin>Abby>Cora>Dave * 98
|
||||
Brad>Erin>Abby>Dave>Cora * 13
|
||||
Brad>Erin>Dave>Abby>Cora * 125
|
||||
Cora>Abby>Erin>Dave>Brad * 124
|
||||
Cora>Erin>Abby>Dave>Brad * 76
|
||||
Dave>Abby>Brad>Erin>Cora * 21
|
||||
Dave>Brad>Abby>Erin>Cora * 30
|
||||
Dave>Brad>Erin>Cora>Abby * 98
|
||||
Dave>Cora>Abby>Brad>Erin * 139
|
||||
Dave>Cora>Brad>Abby>Erin * 23
|
||||
');
|
||||
|
||||
self::assertEquals('Abby', $this->election->getWinner('Schulze Winning'));
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'Abby',
|
||||
2 => 'Brad',
|
||||
3 => 'Erin',
|
||||
4 => 'Dave',
|
||||
5 => 'Cora', ],
|
||||
$this->election->getResult('Schulze Winning')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSchulzeRatioEquality(): void
|
||||
{
|
||||
$this->election->parseCandidates('A;B;C;D');
|
||||
$this->election->parseVotes('A>B=C>D * 10');
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'A',
|
||||
2 => ['B', 'C'],
|
||||
3 => 'D',
|
||||
],
|
||||
$this->election->getResult('Schulze Ratio')->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
}
|
76
include/Condorcet/Tests/src/Algo/Tools/CombinationsTest.php
Normal file
76
include/Condorcet/Tests/src/Algo/Tools/CombinationsTest.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Tools;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\Combinations;
|
||||
use CondorcetPHP\Condorcet\Throwable\Internal\{CondorcetInternalException, IntegerOverflowException};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CombinationsTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Combinations::$useBigIntegerIfAvailable = true;
|
||||
}
|
||||
|
||||
public function testCountPossibleCombinationsResultWithBigInt(): void
|
||||
{
|
||||
// Usual permutation for CPO STV 11 candidates and 3 seats left
|
||||
self::assertSame(
|
||||
13_530,
|
||||
Combinations::getPossibleCountOfCombinations(
|
||||
count: Combinations::getPossibleCountOfCombinations(
|
||||
count: 11,
|
||||
length: 3
|
||||
),
|
||||
length: 2
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(2_598_960, Combinations::getPossibleCountOfCombinations(52, 5)); // Card Game
|
||||
|
||||
self::assertSame(4_367_914_309_753_280, Combinations::getPossibleCountOfCombinations(78, 15)); // Tarot Card Game - 5 players
|
||||
self::assertSame(212_566_476_905_162_380, Combinations::getPossibleCountOfCombinations(78, 18)); // Tarot Card Game - 4 players
|
||||
|
||||
$this->expectException(IntegerOverflowException::class);
|
||||
Combinations::getPossibleCountOfCombinations(78, 24); // Tarot Card Game - 3 players - Result is 79_065_487_387_985_398_300, it's above PHP_MAX_INT
|
||||
}
|
||||
|
||||
public function testCountPossibleCombinationsResultWithoutBigInt(): void
|
||||
{
|
||||
Combinations::$useBigIntegerIfAvailable = false;
|
||||
|
||||
// Usual permutation for CPO STV 11 candidates and 3 seats left
|
||||
self::assertSame(
|
||||
13_530,
|
||||
Combinations::getPossibleCountOfCombinations(
|
||||
count: Combinations::getPossibleCountOfCombinations(
|
||||
count: 11,
|
||||
length: 3
|
||||
),
|
||||
length: 2
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(2_598_960, Combinations::getPossibleCountOfCombinations(52, 5)); // Card Game - Result is - 4_367_914_309_753_280
|
||||
|
||||
$this->expectException(IntegerOverflowException::class);
|
||||
Combinations::getPossibleCountOfCombinations(78, 15); // Tarot Card Game - 5 players - - Result is 4_367_914_309_753_280, it's NOT above PHP_MAX_INT but the intermediate calculations are.
|
||||
}
|
||||
|
||||
public function testCountPossibleCombinationsBadParameters1(): void
|
||||
{
|
||||
$this->expectException(CondorcetInternalException::class);
|
||||
|
||||
Combinations::getPossibleCountOfCombinations(2, 3);
|
||||
}
|
||||
|
||||
public function testIntegerOverflow(): void
|
||||
{
|
||||
$this->expectException(IntegerOverflowException::class);
|
||||
|
||||
Combinations::getPossibleCountOfCombinations(\PHP_INT_MAX - 1, 2);
|
||||
}
|
||||
}
|
75
include/Condorcet/Tests/src/Algo/Tools/PermutationsTest.php
Normal file
75
include/Condorcet/Tests/src/Algo/Tools/PermutationsTest.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Tools;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\Permutations;
|
||||
use CondorcetPHP\Condorcet\Throwable\Internal\{CondorcetInternalException, IntegerOverflowException};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class PermutationsTest extends TestCase
|
||||
{
|
||||
protected function tearDown(): void
|
||||
{
|
||||
Permutations::$useBigIntegerIfAvailable = true;
|
||||
}
|
||||
|
||||
public function testCountPossiblePermutations(): void
|
||||
{
|
||||
self::assertSame(6, Permutations::getPossibleCountOfPermutations(3));
|
||||
|
||||
Permutations::$useBigIntegerIfAvailable = false;
|
||||
self::assertSame(6, Permutations::getPossibleCountOfPermutations(3));
|
||||
|
||||
$this->expectException(CondorcetInternalException::class);
|
||||
Permutations::getPossibleCountOfPermutations(0);
|
||||
}
|
||||
|
||||
public function testIntegerOverflowWithBigInt(): void
|
||||
{
|
||||
$this->expectException(IntegerOverflowException::class);
|
||||
Permutations::getPossibleCountOfPermutations(42);
|
||||
}
|
||||
|
||||
public function testIntegerOverflowWithoutBigInt(): void
|
||||
{
|
||||
Permutations::$useBigIntegerIfAvailable = false;
|
||||
|
||||
$this->expectException(IntegerOverflowException::class);
|
||||
Permutations::getPossibleCountOfPermutations(42);
|
||||
}
|
||||
|
||||
public function testPermutationsAllResultsFor3(): void
|
||||
{
|
||||
$p = new Permutations([0, 1, 2]);
|
||||
|
||||
$r = $p->getResults();
|
||||
|
||||
self::assertInstanceOf(\SplFixedArray::class, $r);
|
||||
self::assertSame(6, $r->getSize());
|
||||
|
||||
self::assertSame(
|
||||
[[1=>0, 2=>1, 3=>2],
|
||||
[1=>1, 2=>0, 3=>2],
|
||||
[1=>1, 2=>2, 3=>0],
|
||||
[1=>0, 2=>2, 3=>1],
|
||||
[1=>2, 2=>0, 3=>1],
|
||||
[1=>2, 2=>1, 3=>0],
|
||||
],
|
||||
$r->toArray()
|
||||
);
|
||||
}
|
||||
|
||||
public function testPermutationsAllResultsFor1(): void
|
||||
{
|
||||
$p = new Permutations([42]);
|
||||
|
||||
$r = $p->getResults();
|
||||
|
||||
self::assertInstanceOf(\SplFixedArray::class, $r);
|
||||
self::assertSame(1, $r->getSize());
|
||||
|
||||
self::assertSame([[1=>42]], $r->toArray());
|
||||
}
|
||||
}
|
30
include/Condorcet/Tests/src/Algo/Tools/VirtualVoteTest.php
Normal file
30
include/Condorcet/Tests/src/Algo/Tools/VirtualVoteTest.php
Normal file
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Algo\Tools;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Algo\Tools\VirtualVote;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VirtualVoteTest extends TestCase
|
||||
{
|
||||
public function testVirtualVote(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->parseCandidates('A;B;C');
|
||||
|
||||
$vote1 = new Vote('A>B>C');
|
||||
$election->addVote($vote1);
|
||||
|
||||
$vote2 = VirtualVote::removeCandidates($vote1, ['B']);
|
||||
|
||||
self::assertNotSame($vote1->getSimpleRanking(), $vote2->getSimpleRanking());
|
||||
self::assertSame('A > C', $vote2->getSimpleRanking());
|
||||
|
||||
self::assertSame(1, $vote1->countLinks());
|
||||
self::assertSame(0, $vote2->countLinks());
|
||||
self::assertSame(1, $election->countVotes());
|
||||
}
|
||||
}
|
176
include/Condorcet/Tests/src/CandidateTest.php
Normal file
176
include/Condorcet/Tests/src/CandidateTest.php
Normal file
@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Candidate, Election};
|
||||
use CondorcetPHP\Condorcet\Throwable\{CandidateExistsException, CandidateInvalidNameException};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CandidateTest extends TestCase
|
||||
{
|
||||
private readonly Candidate $candidate1;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->candidate1 = new Candidate('candidate1.n1');
|
||||
}
|
||||
|
||||
public function testCreateTimestamp(): void
|
||||
{
|
||||
self::assertEquals($this->candidate1->getCreateTimestamp(), $this->candidate1->getTimestamp());
|
||||
}
|
||||
|
||||
public function testChangeName(): void
|
||||
{
|
||||
self::assertTrue($this->candidate1->setName('candidate1.n2'));
|
||||
|
||||
self::assertEquals('candidate1.n2', $this->candidate1->getName());
|
||||
|
||||
self::assertLessThan($this->candidate1->getTimestamp(), $this->candidate1->getCreateTimestamp());
|
||||
self::assertCount(2, $this->candidate1->getHistory());
|
||||
}
|
||||
|
||||
public function testTrimName(): void
|
||||
{
|
||||
$candidate = new Candidate(' candidateName ');
|
||||
self::assertSame('candidateName', (string) $candidate);
|
||||
}
|
||||
|
||||
public function testMatchingAndTooLongName(): never
|
||||
{
|
||||
$name = '';
|
||||
while (mb_strlen($name) < Election::MAX_CANDIDATE_NAME_LENGTH) {
|
||||
$name .= uniqid();
|
||||
}
|
||||
$name = mb_substr($name, 0, Election::MAX_CANDIDATE_NAME_LENGTH);
|
||||
|
||||
// The name is exactly as long as allowed.
|
||||
$candidate = new Candidate($name);
|
||||
$this->assertEquals($name, (string) $candidate);
|
||||
|
||||
// Now the name is one character too long.
|
||||
$name .= 'A';
|
||||
|
||||
$this->expectException(CandidateInvalidNameException::class);
|
||||
$this->expectExceptionMessage("This name is not valid: {$name}");
|
||||
|
||||
new Candidate($name);
|
||||
}
|
||||
|
||||
public function testBadName(): never
|
||||
{
|
||||
$this->expectException(CandidateInvalidNameException::class);
|
||||
$this->expectExceptionMessage('This name is not valid');
|
||||
|
||||
new Candidate('<$"');
|
||||
}
|
||||
|
||||
public function testBadNameWithNewline(): never
|
||||
{
|
||||
$this->expectException(CandidateInvalidNameException::class);
|
||||
$this->expectExceptionMessage('This name is not valid');
|
||||
|
||||
new Candidate("A name with\n a newline");
|
||||
}
|
||||
|
||||
public function testCandidateBadClass(): never
|
||||
{
|
||||
$this->expectException(\TypeError::class);
|
||||
|
||||
(new Election)->addCandidate(new \stdClass);
|
||||
}
|
||||
|
||||
public function testAddSameCandidate1(): never
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
$this->expectExceptionMessage('This candidate already exists: Schizophrenic');
|
||||
|
||||
$election1 = new Election;
|
||||
|
||||
$candidate = new Candidate('Schizophrenic');
|
||||
|
||||
$election1->addCandidate($candidate);
|
||||
$election1->addCandidate($candidate);
|
||||
}
|
||||
|
||||
public function testAddSameCandidate2(): never
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
$this->expectExceptionMessage('This candidate already exists: candidate1');
|
||||
|
||||
$election1 = new Election;
|
||||
|
||||
$election1->parseCandidates('candidate1;candidate2;candidate1');
|
||||
}
|
||||
|
||||
public function testAddSameCandidate3(): never
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
$this->expectExceptionMessage('This candidate already exists: candidate1');
|
||||
|
||||
$election1 = new Election;
|
||||
|
||||
$election1->addCandidate('candidate1');
|
||||
$election1->parseCandidates('candidate2;candidate1');
|
||||
}
|
||||
|
||||
public function testAddSameCandidate4(): void
|
||||
{
|
||||
$election1 = new Election;
|
||||
|
||||
$candidate1= $election1->addCandidate('candidate1');
|
||||
|
||||
try {
|
||||
$election1->parseCandidates('candidate2;candidate1');
|
||||
} catch (\Exception) {
|
||||
}
|
||||
|
||||
self::assertsame([$candidate1], $election1->getCandidatesList());
|
||||
}
|
||||
|
||||
public function testSameCandidateToMultipleElection(): void
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
$this->expectExceptionMessage("This candidate already exists: the name 'Debussy' is taken by another candidate");
|
||||
|
||||
$election1 = new Election;
|
||||
$election2 = new Election;
|
||||
$election3 = new Election;
|
||||
|
||||
// Add candidate to election
|
||||
self::assertSame($this->candidate1, $election1->addCandidate($this->candidate1));
|
||||
self::assertSame($this->candidate1, $election2->addCandidate($this->candidate1));
|
||||
self::assertSame($this->candidate1, $election3->addCandidate($this->candidate1));
|
||||
|
||||
// Check Candidate Link
|
||||
self::assertTrue($this->candidate1->haveLink($election1));
|
||||
self::assertTrue($this->candidate1->haveLink($election2));
|
||||
self::assertTrue($this->candidate1->haveLink($election3));
|
||||
self::assertCount(3, $this->candidate1->getLinks());
|
||||
|
||||
$election3->removeCandidates('candidate1.n1');
|
||||
|
||||
self::assertCount(2, $this->candidate1->getLinks());
|
||||
|
||||
// Add some conflicts
|
||||
self::assertTrue($this->candidate1->setName('candidate1.n2'));
|
||||
self::assertSame('candidate1.n2', $this->candidate1->getName());
|
||||
self::assertNotSame($this->candidate1, $election1->addCandidate('candidate1.n1'));
|
||||
|
||||
$election2->addCandidate('Debussy');
|
||||
$this->candidate1->setName('Debussy');
|
||||
}
|
||||
|
||||
public function testCloneCandidate(): void
|
||||
{
|
||||
($election = new Election)->addCandidate($this->candidate1);
|
||||
|
||||
self::assertsame(1, $this->candidate1->countLinks());
|
||||
|
||||
$cloneCandidate = clone $this->candidate1;
|
||||
|
||||
self::assertsame(0, $cloneCandidate->countLinks());
|
||||
}
|
||||
}
|
204
include/Condorcet/Tests/src/CondorcetTest.php
Normal file
204
include/Condorcet/Tests/src/CondorcetTest.php
Normal file
@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Result};
|
||||
use CondorcetPHP\Condorcet\Algo\{Method, MethodInterface};
|
||||
use CondorcetPHP\Condorcet\Throwable\AlgorithmException;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetTest extends TestCase
|
||||
{
|
||||
public function testgetVersion(): void
|
||||
{
|
||||
self::assertSame(Condorcet::VERSION, CONDORCET::getVersion());
|
||||
self::assertMatchesRegularExpression('/^[1-9]+\.[0-9]+$/', CONDORCET::getVersion(true));
|
||||
}
|
||||
|
||||
public function testAddExistingMethod(): void
|
||||
{
|
||||
$algoClassPath = Condorcet::getDefaultMethod();
|
||||
|
||||
self::assertEquals($algoClassPath, Condorcet::getMethodClass($algoClassPath));
|
||||
|
||||
self::assertFalse(Condorcet::addMethod($algoClassPath));
|
||||
}
|
||||
|
||||
public function testBadClassMethod(): never
|
||||
{
|
||||
$this->expectException(AlgorithmException::class);
|
||||
$this->expectExceptionMessage("The voting algorithm is not available: no class found for 'sjskkdlkkzksh'");
|
||||
|
||||
Condorcet::addMethod('sjskkdlkkzksh');
|
||||
}
|
||||
|
||||
public function testAuthMethod(): void
|
||||
{
|
||||
self::assertFalse(Condorcet::isAuthMethod('skzljdpmzk'));
|
||||
self::assertNull(Condorcet::getMethodClass('skzljdpmzk'));
|
||||
self::assertSame(\CondorcetPHP\Condorcet\Algo\Methods\Schulze\SchulzeWinning::class, Condorcet::getMethodClass('Schulze Winning'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testAddMethod(): never
|
||||
{
|
||||
$this->expectException(AlgorithmException::class);
|
||||
$this->expectExceptionMessage('The voting algorithm is not available: the given class is using an existing alias');
|
||||
|
||||
$algoClassPath = CondorcetTest_ValidAlgorithmName::class;
|
||||
|
||||
self::assertTrue(Condorcet::addMethod($algoClassPath));
|
||||
|
||||
self::assertEquals($algoClassPath, Condorcet::getMethodClass($algoClassPath));
|
||||
|
||||
// Try to add existing alias
|
||||
$algoClassPath = CondorcetTest_DuplicateAlgorithmAlias::class;
|
||||
|
||||
self::assertFalse(Condorcet::addMethod($algoClassPath));
|
||||
}
|
||||
|
||||
public function testAddUnvalidMethod(): never
|
||||
{
|
||||
$this->expectException(AlgorithmException::class);
|
||||
$this->expectExceptionMessage('The voting algorithm is not available: the given class is not correct');
|
||||
|
||||
$algoClassPath = CondorcetTest_UnvalidAlgorithmName::class;
|
||||
|
||||
self::assertFalse(Condorcet::addMethod($algoClassPath));
|
||||
|
||||
self::assertSame(
|
||||
CondorcetTest_UnvalidAlgorithmName::class,
|
||||
Condorcet::getMethodClass('FirstMethodName')
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnvalidDefaultMethod(): void
|
||||
{
|
||||
self::assertFalse(Condorcet::setDefaultMethod('dgfbdwcd'));
|
||||
}
|
||||
|
||||
public function testEmptyMethod(): never
|
||||
{
|
||||
$this->expectException(AlgorithmException::class);
|
||||
$this->expectExceptionMessage('The voting algorithm is not available: no method name given');
|
||||
|
||||
Condorcet::isAuthMethod('');
|
||||
}
|
||||
|
||||
public function testMethodAlias(): void
|
||||
{
|
||||
self::assertSame(
|
||||
\CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung::class,
|
||||
Condorcet::getMethodClass('kemeny–Young')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
\CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung::class,
|
||||
Condorcet::getMethodClass('Maximum likelihood Method')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class CondorcetTest_ValidAlgorithmName extends Method implements MethodInterface
|
||||
{
|
||||
public const METHOD_NAME = ['FirstMethodName', 'Alias1', 'Alias_2', 'Alias 3'];
|
||||
|
||||
|
||||
// Get the Result object
|
||||
public function getResult($options = null): Result
|
||||
{
|
||||
// Cache
|
||||
if ($this->Result !== null) {
|
||||
return $this->Result;
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
// Ranking calculation
|
||||
$this->makeRanking();
|
||||
|
||||
// Return
|
||||
return $this->Result;
|
||||
}
|
||||
|
||||
|
||||
// Compute the Stats
|
||||
protected function getStats(): array
|
||||
{
|
||||
return []; // You are free to do all you wants. Must be an array.;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////// COMPUTE ///////////
|
||||
|
||||
|
||||
//:: ALGORITHM. :://
|
||||
|
||||
protected function makeRanking(): void
|
||||
{
|
||||
$this->selfElection->get()->getPairwise();
|
||||
|
||||
$result = [0=>1, 1=>2, 2=>3]; // Candidate must be valid candidates
|
||||
|
||||
$this->Result = $this->createResult($result);
|
||||
}
|
||||
}
|
||||
|
||||
class CondorcetTest_DuplicateAlgorithmAlias extends CondorcetTest_ValidAlgorithmName implements MethodInterface
|
||||
{
|
||||
public const METHOD_NAME = ['SecondMethodName', 'Alias_2'];
|
||||
}
|
||||
|
||||
|
||||
class CondorcetTest_UnvalidAlgorithmName
|
||||
{
|
||||
public const METHOD_NAME = ['FirstMethodName', 'Alias1', 'Alias_2', 'Alias 3'];
|
||||
|
||||
|
||||
// Get the Result object
|
||||
public function getResult($options = null): Result
|
||||
{
|
||||
// Cache
|
||||
if ($thisResult !== null) {
|
||||
return $this->Result;
|
||||
}
|
||||
|
||||
// Ranking calculation
|
||||
$this->makeRanking();
|
||||
|
||||
// Return
|
||||
return $this->Result;
|
||||
}
|
||||
|
||||
|
||||
// Compute the Stats
|
||||
protected function getStats(): array
|
||||
{
|
||||
return []; // You are free to do all you wants. Must be an array.;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/////////// COMPUTE ///////////
|
||||
|
||||
|
||||
//:: ALGORITHM. :://
|
||||
|
||||
protected function makeRanking(): void
|
||||
{
|
||||
$this->selfElection->getPairwise();
|
||||
|
||||
$result = [0=>0, 1=> [1, 2], 2=> 3]; // Candidate must be valid internal candidate key.
|
||||
|
||||
$this->Result = $result;
|
||||
}
|
||||
}
|
26
include/Condorcet/Tests/src/CondorcetUtilTest.php
Normal file
26
include/Condorcet/Tests/src/CondorcetUtilTest.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Utils\CondorcetUtil;
|
||||
use CondorcetPHP\Condorcet\Vote;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetUtilTest extends TestCase
|
||||
{
|
||||
public function testFormatVote(): void
|
||||
{
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
$this->assertSame('A > B > C', CondorcetUtil::format($vote, true));
|
||||
}
|
||||
|
||||
public function testDeleteComments(): void
|
||||
{
|
||||
$result = CondorcetUtil::prepareParse('A > B # This is a comment', false);
|
||||
|
||||
$this->assertSame(['A > B'], $result);
|
||||
}
|
||||
}
|
19
include/Condorcet/Tests/src/CondorcetVersionTest.php
Normal file
19
include/Condorcet/Tests/src/CondorcetVersionTest.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetVersionTest extends TestCase
|
||||
{
|
||||
public function testObjectVersion(): void
|
||||
{
|
||||
$election = new Election;
|
||||
|
||||
self::assertSame(CONDORCET::getVersion(), $election->getObjectVersion());
|
||||
self::assertSame(CONDORCET::getVersion(true), $election->getObjectVersion(true));
|
||||
}
|
||||
}
|
@ -0,0 +1,404 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Console\Commands;
|
||||
|
||||
use CondorcetPHP\Condorcet\Console\Commands\ElectionCommand;
|
||||
use CondorcetPHP\Condorcet\Throwable\{CandidateExistsException, ResultRequestedWithoutVotesException};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use CondorcetPHP\Condorcet\Console\CondorcetApplication;
|
||||
use CondorcetPHP\Condorcet\Console\Style\CondorcetStyle;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Tester\CommandTester;
|
||||
|
||||
class ElectionCommandTest extends TestCase
|
||||
{
|
||||
private readonly CommandTester $electionCommand;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
CondorcetApplication::create();
|
||||
|
||||
$this->electionCommand = new CommandTester(CondorcetApplication::$SymfonyConsoleApplication->find('election'));
|
||||
}
|
||||
|
||||
public function testConsoleSimpleElection(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
'--stats' => null,
|
||||
'--natural-condorcet' => null,
|
||||
'--allows-votes-weight' => null,
|
||||
'--no-tie' => null,
|
||||
'--list-votes' => null,
|
||||
'--deactivate-implicit-ranking' => null,
|
||||
'--show-pairwise' => null,
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('3 candidates registered || 3 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('Schulze', $output);
|
||||
self::assertStringContainsString('Registered candidates', $output);
|
||||
self::assertStringContainsString('Stats - votes registration', $output);
|
||||
self::assertStringContainsString('Registered Votes List', $output);
|
||||
self::assertStringContainsString('Pairwise', $output);
|
||||
self::assertStringContainsString('Stats:', $output);
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+TRUE/', $output);
|
||||
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+FALSE/', $output);
|
||||
}
|
||||
|
||||
public function testConsoleSeats(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
'--stats' => null,
|
||||
'--natural-condorcet' => null,
|
||||
'--allows-votes-weight' => null,
|
||||
'--no-tie' => null,
|
||||
'--list-votes' => null,
|
||||
'--deactivate-implicit-ranking' => null,
|
||||
'--show-pairwise' => null,
|
||||
|
||||
'--seats' => 42,
|
||||
'methods' => ['STV'],
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('3 candidates registered || 3 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('Seats:', $output);
|
||||
self::assertStringContainsString('42', $output);
|
||||
}
|
||||
|
||||
public function testQuotas(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
|
||||
'methods' => ['STV'],
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
|
||||
self::assertStringContainsString('Droop Quota', $output);
|
||||
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
|
||||
'methods' => ['STV'],
|
||||
'--quota' => 'imperiali',
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('Imperiali', $output);
|
||||
}
|
||||
|
||||
public function testConsoleAllMethodsArgument(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
|
||||
'methods' => ['all'],
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
|
||||
self::assertStringContainsString('Copeland', $output);
|
||||
}
|
||||
|
||||
public function testConsoleMultiplesMethods(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
|
||||
'methods' => ['Copeland', 'RankedPairs', 'Minimax'],
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
|
||||
self::assertStringContainsString('Copeland', $output);
|
||||
self::assertStringContainsString('Ranked Pairs M', $output);
|
||||
self::assertStringContainsString('Minimax Winning', $output);
|
||||
}
|
||||
|
||||
public function testConsoleFileInput(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => __DIR__.'/data.candidates',
|
||||
'--votes' => __DIR__.'/data.votes',
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
|
||||
self::assertStringContainsString('Schulze', $output);
|
||||
self::assertStringContainsString('A,B', $output);
|
||||
self::assertStringContainsString('C '.CondorcetStyle::CONDORCET_LOSER_SYMBOL, $output);
|
||||
}
|
||||
|
||||
public function testInteractiveCommand(): void
|
||||
{
|
||||
$this->electionCommand->setInputs([
|
||||
'A',
|
||||
'B',
|
||||
'C',
|
||||
'',
|
||||
'A>B>C',
|
||||
'B>A>C',
|
||||
'A>C>B',
|
||||
'',
|
||||
]);
|
||||
|
||||
$this->electionCommand->execute([
|
||||
'command' => 'election',
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
|
||||
self::assertStringContainsString('Results: Schulze Winning', $output);
|
||||
}
|
||||
|
||||
public function testNonInteractionMode(): never
|
||||
{
|
||||
$this->expectException(ResultRequestedWithoutVotesException::class);
|
||||
$this->expectExceptionMessage('The result cannot be requested without votes');
|
||||
|
||||
$this->electionCommand->execute([], ['interactive' => false]);
|
||||
|
||||
// $output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
}
|
||||
|
||||
public function testCustomizeVotesPerMb(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A>B>C;C>B>A;B>A>C',
|
||||
'--votes-per-mb' => 42,
|
||||
]);
|
||||
|
||||
self::assertSame(42, \CondorcetPHP\Condorcet\Console\Commands\ElectionCommand::$VotesPerMB);
|
||||
|
||||
// $output = $this->electionCommand->getDisplay();
|
||||
// \var_dump($output);
|
||||
}
|
||||
|
||||
public function testVoteWithDb1(): void
|
||||
{
|
||||
ElectionCommand::$forceIniMemoryLimitTo = '128M';
|
||||
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes-per-mb' => 1,
|
||||
'--votes' => 'A>B>C * '.(((int) preg_replace('`[^0-9]`', '', ElectionCommand::$forceIniMemoryLimitTo)) + 1), # Must be superior to memory limit in MB
|
||||
], [
|
||||
'verbosity' => OutputInterface::VERBOSITY_DEBUG,
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertMatchesRegularExpression('/Votes per Mb +1/', $output);
|
||||
self::assertMatchesRegularExpression('/Db is used +yes, using path\\:/', $output);
|
||||
|
||||
ElectionCommand::$forceIniMemoryLimitTo = null;
|
||||
|
||||
# And absence of this error: unlink(path): Resource temporarily unavailable
|
||||
}
|
||||
|
||||
|
||||
public function testNaturalCondorcet(): void
|
||||
{
|
||||
$this->electionCommand->execute([
|
||||
'--candidates' => 'A;B;C',
|
||||
'--votes' => 'A=B=C',
|
||||
'--natural-condorcet' => true,
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString(CondorcetStyle::CONDORCET_WINNER_SYMBOL.' Condorcet Winner | -', $output);
|
||||
self::assertStringContainsString(CondorcetStyle::CONDORCET_LOSER_SYMBOL.' Condorcet Loser | -', $output);
|
||||
}
|
||||
|
||||
public function testFromCondorcetElectionFormat_DoubleCandidates(): void
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--candidates' => 'A;B;C',
|
||||
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test1.cvotes',
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testFromCondorcetElectionFormat_ArgumentpriorityAndDoubleVoteArgument(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test1.cvotes',
|
||||
'--votes' => 'C>A',
|
||||
'--deactivate-implicit-ranking' => null,
|
||||
'--no-tie' => null,
|
||||
'--allows-votes-weight' => null,
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('3 candidates registered || 2 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('Schulze', $output);
|
||||
self::assertStringContainsString('Registered candidates', $output);
|
||||
self::assertStringContainsString('Stats - votes registration', $output);
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+TRUE/', $output);
|
||||
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+FALSE/', $output);
|
||||
|
||||
self::assertStringContainsString('Sum vote weight | 3', $output);
|
||||
}
|
||||
|
||||
public function testFromCondorcetElectionFormat_Arguments(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test2.cvotes',
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('3 candidates registered || 2 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('Schulze', $output);
|
||||
self::assertStringContainsString('Registered candidates', $output);
|
||||
self::assertStringContainsString('Stats - votes registration', $output);
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
|
||||
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+FALSE./', $output);
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
|
||||
|
||||
self::assertStringContainsString('Sum vote weight | 2', $output);
|
||||
|
||||
self::assertStringContainsString('B '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
|
||||
}
|
||||
|
||||
public function testVoteWithDb_CondorcetElectionFormat(): void
|
||||
{
|
||||
ElectionCommand::$forceIniMemoryLimitTo = '128M';
|
||||
|
||||
$this->electionCommand->execute([
|
||||
'--votes-per-mb' => 1,
|
||||
'--import-condorcet-election-format' => __DIR__.'/../../Tools/Converters/CondorcetElectionFormatData/test3.cvotes',
|
||||
], [
|
||||
'verbosity' => OutputInterface::VERBOSITY_DEBUG,
|
||||
]);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertMatchesRegularExpression('/Votes per Mb +1/', $output);
|
||||
self::assertStringContainsString('Db is used', $output);
|
||||
self::assertStringContainsString('yes, using path:', $output);
|
||||
|
||||
ElectionCommand::$forceIniMemoryLimitTo = null;
|
||||
|
||||
# And absence of this error: unlink(path): Resource temporarily unavailable
|
||||
}
|
||||
|
||||
public function testFromDebianFormat(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--import-debian-format' => __DIR__.'/../../Tools/Converters/DebianData/leader2020_tally.txt',
|
||||
'methods' => ['STV'],
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('4 candidates registered || 339 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('STV', $output);
|
||||
self::assertStringContainsString('Registered candidates', $output);
|
||||
self::assertStringContainsString('Stats - votes registration', $output);
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
|
||||
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+TRUE./', $output);
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
|
||||
|
||||
self::assertStringContainsString('Sum vote weight | 339', $output);
|
||||
|
||||
self::assertStringContainsString('Jonathan Carter '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
|
||||
self::assertMatchesRegularExpression('/Seats: *\| 1/', $output);
|
||||
}
|
||||
|
||||
public function testFromDavidHillFormat(): void
|
||||
{
|
||||
$this->electionCommand->execute(
|
||||
[
|
||||
'--import-david-hill-format' => __DIR__.'/../../Tools/Converters/TidemanData/A1.HIL',
|
||||
'methods' => ['STV'],
|
||||
],
|
||||
[
|
||||
'verbosity' => OutputInterface::VERBOSITY_VERBOSE,
|
||||
]
|
||||
);
|
||||
|
||||
$output = $this->electionCommand->getDisplay();
|
||||
|
||||
self::assertStringContainsString('10 candidates registered || 380 votes registered', $output);
|
||||
|
||||
self::assertStringContainsString('STV', $output);
|
||||
self::assertStringContainsString('Registered candidates', $output);
|
||||
self::assertStringContainsString('Stats - votes registration', $output);
|
||||
|
||||
self::assertMatchesRegularExpression('/Is vote weight allowed\?( )+FALSE/', $output);
|
||||
self::assertMatchesRegularExpression('/Votes are evaluated according to the implicit ranking rule\?( )+TRUE./', $output);
|
||||
self::assertMatchesRegularExpression('/Is vote tie in rank allowed\?( )+TRUE/', $output);
|
||||
|
||||
self::assertStringContainsString('Sum vote weight | 380', $output);
|
||||
|
||||
self::assertStringContainsString('Candidate 1 '.CondorcetStyle::CONDORCET_WINNER_SYMBOL, $output); # Condorcet Winner
|
||||
self::assertMatchesRegularExpression('/Seats: *\| 3/', $output);
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
A
|
||||
B
|
||||
C
|
2
include/Condorcet/Tests/src/Console/Commands/data.votes
Normal file
2
include/Condorcet/Tests/src/Console/Commands/data.votes
Normal file
@ -0,0 +1,2 @@
|
||||
A>B=C
|
||||
B>A>C
|
140
include/Condorcet/Tests/src/ConstraintTest.php
Normal file
140
include/Condorcet/Tests/src/ConstraintTest.php
Normal file
@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Election, Vote, VoteConstraintInterface};
|
||||
use CondorcetPHP\Condorcet\Constraints\NoTie;
|
||||
use CondorcetPHP\Condorcet\Throwable\VoteConstraintException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ConstraintTest extends TestCase
|
||||
{
|
||||
private Election $election;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
|
||||
$this->election->addCandidate('A');
|
||||
$this->election->addCandidate('B');
|
||||
$this->election->addCandidate('C');
|
||||
}
|
||||
|
||||
public function testAddConstraintAndClear(): never
|
||||
{
|
||||
$this->expectException(VoteConstraintException::class);
|
||||
$this->expectExceptionMessage('The vote constraint could not be set up: class is already registered');
|
||||
|
||||
$class = NoTie::class;
|
||||
|
||||
self::assertTrue($this->election->addConstraint($class));
|
||||
|
||||
self::assertSame([$class], $this->election->getConstraints());
|
||||
|
||||
self::assertTrue($this->election->clearConstraints());
|
||||
|
||||
self::assertsame([], $this->election->getConstraints());
|
||||
|
||||
self::assertTrue($this->election->addConstraint($class));
|
||||
|
||||
$this->election->addConstraint($class);
|
||||
}
|
||||
|
||||
public function testPhantomClass(): never
|
||||
{
|
||||
$this->expectException(VoteConstraintException::class);
|
||||
$this->expectExceptionMessage('The vote constraint could not be set up: class is not defined');
|
||||
|
||||
$this->election->addConstraint('WrongNamespace\AndWrongClass');
|
||||
}
|
||||
|
||||
public function testBadClass(): never
|
||||
{
|
||||
$this->expectException(VoteConstraintException::class);
|
||||
$this->expectExceptionMessage('The vote constraint could not be set up: class is not a valid subclass');
|
||||
|
||||
$class = Vote::class;
|
||||
|
||||
$this->election->addConstraint($class);
|
||||
}
|
||||
|
||||
public function testConstraintsOnVote(): void
|
||||
{
|
||||
$NoTieImplementation = [NoTie::class, AlternativeNoTieConstraintClass::class];
|
||||
|
||||
foreach ($NoTieImplementation as $constraintClass) {
|
||||
$this->setUp();
|
||||
|
||||
$this->election->parseVotes('
|
||||
tag1 || A>B>C
|
||||
C>B=A * 3
|
||||
B^42
|
||||
');
|
||||
|
||||
$this->election->allowsVoteWeight();
|
||||
|
||||
self::assertEquals('B', $this->election->getWinner());
|
||||
|
||||
$this->election->addConstraint($constraintClass);
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner());
|
||||
|
||||
$this->election->clearConstraints();
|
||||
|
||||
self::assertEquals('B', $this->election->getWinner());
|
||||
|
||||
$this->election->addConstraint($constraintClass);
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner());
|
||||
|
||||
self::assertEquals(1, $this->election->sumValidVotesWeightWithConstraints());
|
||||
self::assertEquals(46, $this->election->sumVotesWeight());
|
||||
self::assertEquals(5, $this->election->countVotes());
|
||||
self::assertEquals(1, $this->election->countValidVoteWithConstraints());
|
||||
self::assertEquals(4, $this->election->countInvalidVoteWithConstraints());
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner('FTPT'));
|
||||
|
||||
self::assertFalse($this->election->setImplicitRanking(false));
|
||||
|
||||
self::assertEquals('B', $this->election->getWinner('FTPT'));
|
||||
self::assertEquals('A', $this->election->getWinner());
|
||||
|
||||
self::assertEquals(43, $this->election->sumValidVotesWeightWithConstraints());
|
||||
self::assertEquals(46, $this->election->sumVotesWeight());
|
||||
self::assertEquals(5, $this->election->countVotes());
|
||||
self::assertEquals(2, $this->election->countValidVoteWithConstraints());
|
||||
self::assertEquals(3, $this->election->countInvalidVoteWithConstraints());
|
||||
|
||||
self::assertTrue($this->election->setImplicitRanking(true));
|
||||
|
||||
self::assertEquals('A', $this->election->getWinner());
|
||||
self::assertEquals('A', $this->election->getWinner('FTPT'));
|
||||
|
||||
self::assertEquals(1, $this->election->sumValidVotesWeightWithConstraints());
|
||||
self::assertEquals(46, $this->election->sumVotesWeight());
|
||||
self::assertEquals(5, $this->election->countVotes());
|
||||
self::assertEquals(1, $this->election->countValidVoteWithConstraints());
|
||||
self::assertEquals(4, $this->election->countInvalidVoteWithConstraints());
|
||||
self::assertCount(1, $this->election->getVotesValidUnderConstraintGenerator(['tag1'], true));
|
||||
self::assertCount(0, $this->election->getVotesValidUnderConstraintGenerator(['tag1'], false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AlternativeNoTieConstraintClass implements VoteConstraintInterface
|
||||
{
|
||||
public static function isVoteAllow(Election $election, Vote $vote): bool
|
||||
{
|
||||
foreach ($vote->getContextualRanking($election) as $oneRank) {
|
||||
if (\count($oneRank) > 1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
50
include/Condorcet/Tests/src/DataManager/ArrayManagerTest.php
Normal file
50
include/Condorcet/Tests/src/DataManager/ArrayManagerTest.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\DataManager;
|
||||
|
||||
use CondorcetPHP\Condorcet\DataManager\ArrayManager;
|
||||
use CondorcetPHP\Condorcet\{Election, Vote};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ArrayManagerTest extends TestCase
|
||||
{
|
||||
private readonly ArrayManager $ArrayManager;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->ArrayManager = new class (new Election) extends ArrayManager {
|
||||
protected function preDeletedTask($object): void
|
||||
{
|
||||
}
|
||||
|
||||
protected function decodeOneEntity(string $data): Vote
|
||||
{
|
||||
$vote = new Vote($data);
|
||||
$this->getElection()->checkVoteCandidate($vote);
|
||||
$vote->registerLink($this->Election->get());
|
||||
|
||||
return $vote;
|
||||
}
|
||||
|
||||
protected function encodeOneEntity(Vote $data): string
|
||||
{
|
||||
$data->destroyLink($this->getElection());
|
||||
|
||||
return str_replace([' > ', ' = '], ['>', '='], (string) $data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public function testOffsetSetAndOffetsetGet(): void
|
||||
{
|
||||
self::assertNull($this->ArrayManager->key());
|
||||
|
||||
$this->ArrayManager[42] = 'foo';
|
||||
|
||||
self::assertSame('foo', $this->ArrayManager[42]);
|
||||
|
||||
self::assertNull($this->ArrayManager[43]);
|
||||
}
|
||||
}
|
@ -0,0 +1,304 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\DataManager\DataHandlerDrivers\PdoDriver;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\DataManager\ArrayManager;
|
||||
use CondorcetPHP\Condorcet\DataManager\DataHandlerDrivers\PdoDriver\PdoHandlerDriver;
|
||||
use CondorcetPHP\Condorcet\Throwable\DataHandlerException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @group DataHandlerDrivers
|
||||
*/
|
||||
class PdoHandlerDriverTest extends TestCase
|
||||
{
|
||||
protected function getPDO(): \PDO
|
||||
{
|
||||
return new \PDO('sqlite::memory:', '', '', [\PDO::ATTR_PERSISTENT => false]);
|
||||
}
|
||||
|
||||
protected function hashVotesList(Election $elec): string
|
||||
{
|
||||
$c = 0;
|
||||
$voteCompil = '';
|
||||
foreach ($elec->getVotesManager() as $oneVote) {
|
||||
$c++;
|
||||
$voteCompil .= (string) $oneVote;
|
||||
}
|
||||
|
||||
return $c.'||'.hash('md5', $voteCompil);
|
||||
}
|
||||
|
||||
|
||||
public function testManyVoteManipulation(): never
|
||||
{
|
||||
// Setup
|
||||
ArrayManager::$CacheSize = 10;
|
||||
ArrayManager::$MaxContainerLength = 10;
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionInMemory = new Election;
|
||||
$electionWithDb->setExternalDataHandler($handlerDriver = new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
// Run Test
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C;D;E');
|
||||
$electionInMemory->parseCandidates('A;B;C;D;E');
|
||||
|
||||
// 45 Votes
|
||||
$votes = 'A > C > B > E * 5
|
||||
A > D > E > C * 5
|
||||
B > E > D > A * 8
|
||||
C > A > B > E * 3
|
||||
C > A > E > B * 7
|
||||
C > B > A > D * 2
|
||||
D > C > E > B * 7
|
||||
E > B > A > D * 8';
|
||||
|
||||
$electionWithDb->parseVotes($votes);
|
||||
$electionInMemory->parseVotes($votes);
|
||||
|
||||
self::assertSame(
|
||||
$electionWithDb->countVotes(),
|
||||
$handlerDriver->countEntities() + $electionWithDb->getVotesManager()->getContainerSize()
|
||||
);
|
||||
|
||||
self::assertSame($electionInMemory->countVotes(), $electionWithDb->countVotes());
|
||||
self::assertSame($electionInMemory->getVotesListAsString(), $electionWithDb->getVotesListAsString());
|
||||
self::assertSame($this->hashVotesList($electionInMemory), $this->hashVotesList($electionWithDb));
|
||||
|
||||
self::assertEquals($electionInMemory->getPairwise()->getExplicitPairwise(), $electionWithDb->getPairwise()->getExplicitPairwise());
|
||||
self::assertEquals((string) $electionInMemory->getWinner('Ranked Pairs Winning'), (string) $electionWithDb->getWinner('Ranked Pairs Winning'));
|
||||
self::assertEquals((string) $electionInMemory->getWinner(), (string) $electionWithDb->getWinner());
|
||||
self::assertEquals((string) $electionInMemory->getCondorcetWinner(), (string) $electionWithDb->getCondorcetWinner());
|
||||
|
||||
|
||||
// 58 Votes
|
||||
$votes = 'A > B > C > E * 58';
|
||||
|
||||
$electionWithDb->parseVotes($votes);
|
||||
$electionInMemory->parseVotes($votes);
|
||||
|
||||
self::assertSame(58 % ArrayManager::$MaxContainerLength, $electionWithDb->getVotesManager()->getContainerSize());
|
||||
self::assertSame(
|
||||
$electionWithDb->countVotes(),
|
||||
$handlerDriver->countEntities() + $electionWithDb->getVotesManager()->getContainerSize()
|
||||
);
|
||||
|
||||
self::assertEquals('A', $electionWithDb->getWinner());
|
||||
self::assertEquals((string) $electionInMemory->getWinner(), (string) $electionWithDb->getWinner());
|
||||
|
||||
self::assertSame($electionInMemory->countVotes(), $electionWithDb->countVotes());
|
||||
self::assertSame($electionInMemory->getVotesListAsString(), $electionWithDb->getVotesListAsString());
|
||||
self::assertSame($this->hashVotesList($electionInMemory), $this->hashVotesList($electionWithDb));
|
||||
self::assertSame(0, $electionWithDb->getVotesManager()->getContainerSize());
|
||||
self::assertLessThanOrEqual(ArrayManager::$CacheSize, $electionWithDb->getVotesManager()->getCacheSize());
|
||||
|
||||
// Delete 3 votes
|
||||
unset($electionInMemory->getVotesManager()[13]);
|
||||
unset($electionInMemory->getVotesManager()[100]);
|
||||
unset($electionInMemory->getVotesManager()[102]);
|
||||
unset($electionWithDb->getVotesManager()[13]);
|
||||
unset($electionWithDb->getVotesManager()[100]);
|
||||
unset($electionWithDb->getVotesManager()[102]);
|
||||
|
||||
self::assertSame(
|
||||
$electionWithDb->countVotes(),
|
||||
$handlerDriver->countEntities() + $electionWithDb->getVotesManager()->getContainerSize()
|
||||
);
|
||||
self::assertSame($electionInMemory->countVotes(), $electionWithDb->countVotes());
|
||||
self::assertSame($electionInMemory->getVotesListAsString(), $electionWithDb->getVotesListAsString());
|
||||
self::assertSame($this->hashVotesList($electionInMemory), $this->hashVotesList($electionWithDb));
|
||||
self::assertSame(0, $electionWithDb->getVotesManager()->getContainerSize());
|
||||
self::assertLessThanOrEqual(ArrayManager::$CacheSize, $electionWithDb->getVotesManager()->getCacheSize());
|
||||
self::assertArrayNotHasKey(13, $electionWithDb->getVotesManager()->debugGetCache());
|
||||
self::assertArrayNotHasKey(102, $electionWithDb->getVotesManager()->debugGetCache());
|
||||
self::assertArrayNotHasKey(100, $electionWithDb->getVotesManager()->debugGetCache());
|
||||
self::assertArrayHasKey(101, $electionWithDb->getVotesManager()->debugGetCache());
|
||||
|
||||
|
||||
// Unset Handler
|
||||
$electionWithDb->removeExternalDataHandler();
|
||||
|
||||
self::assertEmpty($electionWithDb->getVotesManager()->debugGetCache());
|
||||
self::assertSame($electionInMemory->getVotesManager()->getContainerSize(), $electionWithDb->getVotesManager()->getContainerSize());
|
||||
self::assertSame($electionInMemory->countVotes(), $electionWithDb->countVotes());
|
||||
self::assertSame($electionInMemory->getVotesListAsString(), $electionWithDb->getVotesListAsString());
|
||||
self::assertSame($this->hashVotesList($electionInMemory), $this->hashVotesList($electionWithDb));
|
||||
|
||||
// Change my mind : Set again the a new handler
|
||||
unset($handlerDriver);
|
||||
$electionWithDb->setExternalDataHandler($handlerDriver = new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
self::assertEmpty($electionWithDb->getVotesManager()->debugGetCache());
|
||||
self::assertSame(0, $electionWithDb->getVotesManager()->getContainerSize());
|
||||
self::assertSame($electionInMemory->countVotes(), $electionWithDb->countVotes());
|
||||
self::assertSame($electionInMemory->getVotesListAsString(), $electionWithDb->getVotesListAsString());
|
||||
self::assertSame($this->hashVotesList($electionInMemory), $this->hashVotesList($electionWithDb));
|
||||
|
||||
self::assertTrue($electionWithDb->removeExternalDataHandler());
|
||||
|
||||
$this->expectException(DataHandlerException::class);
|
||||
$this->expectExceptionMessage('Problem with data handler: external data handler cannot be removed, is already in use');
|
||||
|
||||
$electionWithDb->removeExternalDataHandler();
|
||||
}
|
||||
|
||||
public function testVotePreserveTag(): void
|
||||
{
|
||||
// Setup
|
||||
ArrayManager::$CacheSize = 10;
|
||||
ArrayManager::$MaxContainerLength = 10;
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C');
|
||||
|
||||
$electionWithDb->parseVotes('A > B > C * 5
|
||||
tag1 || B > A > C * 3');
|
||||
|
||||
self::assertSame(5, $electionWithDb->countVotes('tag1', false));
|
||||
self::assertSame(3, $electionWithDb->countVotes('tag1', true));
|
||||
|
||||
$electionWithDb->parseVotes('A > B > C * 5
|
||||
tag1 || B > A > C * 3');
|
||||
|
||||
self::assertSame(10, $electionWithDb->countVotes('tag1', false));
|
||||
self::assertSame(6, $electionWithDb->countVotes('tag1', true));
|
||||
}
|
||||
|
||||
public function testVoteObjectIntoDataHandler(): void
|
||||
{
|
||||
// Setup
|
||||
ArrayManager::$CacheSize = 10;
|
||||
ArrayManager::$MaxContainerLength = 10;
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C');
|
||||
|
||||
$myVote = $electionWithDb->addVote('A>B>C');
|
||||
|
||||
$electionWithDb->getVotesManager()->regularize();
|
||||
self::assertSame(0, $electionWithDb->getVotesManager()->getContainerSize());
|
||||
|
||||
// myVote is no longer a part of the election. Internally, it will work with clones.
|
||||
self::assertSame(0, $myVote->countLinks());
|
||||
self::assertNotSame($electionWithDb->getVotesList()[0], $myVote);
|
||||
self::assertTrue($electionWithDb->getVotesList()[0]->haveLink($electionWithDb));
|
||||
}
|
||||
|
||||
public function testUpdateEntity(): void
|
||||
{
|
||||
// Setup
|
||||
ArrayManager::$CacheSize = 10;
|
||||
ArrayManager::$MaxContainerLength = 10;
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C');
|
||||
|
||||
$electionWithDb->parseVotes('A>B>C * 19');
|
||||
$electionWithDb->addVote('C>B>A', 'voteToUpdate');
|
||||
|
||||
$vote = $electionWithDb->getVotesList('voteToUpdate', true)[19];
|
||||
$vote->setRanking('B>A>C');
|
||||
$vote = null;
|
||||
|
||||
$electionWithDb->parseVotes('A>B>C * 20');
|
||||
|
||||
self::assertSame(
|
||||
"A > B > C * 39\n".
|
||||
'B > A > C * 1',
|
||||
$electionWithDb->getVotesListAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetVotesListGenerator(): void
|
||||
{
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C');
|
||||
|
||||
$electionWithDb->parseVotes('A>B>C * 10;tag42 || C>B>A * 42');
|
||||
|
||||
$votesListGenerator = [];
|
||||
|
||||
foreach ($electionWithDb->getVotesListGenerator() as $key => $value) {
|
||||
$votesListGenerator[$key] = $value;
|
||||
}
|
||||
|
||||
self::assertCount(52, $votesListGenerator);
|
||||
|
||||
|
||||
$votesListGenerator = [];
|
||||
|
||||
foreach ($electionWithDb->getVotesListGenerator('tag42') as $key => $value) {
|
||||
$votesListGenerator[$key] = $value;
|
||||
}
|
||||
|
||||
self::assertCount(42, $votesListGenerator);
|
||||
}
|
||||
|
||||
public function testSliceInput(): void
|
||||
{
|
||||
// Setup
|
||||
ArrayManager::$CacheSize = 462;
|
||||
ArrayManager::$MaxContainerLength = 462;
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
|
||||
$electionWithDb->parseCandidates('A;B;C');
|
||||
|
||||
$electionWithDb->parseVotes('A>B>C * 463');
|
||||
|
||||
self::assertSame(463, $electionWithDb->countVotes());
|
||||
}
|
||||
|
||||
public function testMultipleHandler(): never
|
||||
{
|
||||
$this->expectException(DataHandlerException::class);
|
||||
$this->expectExceptionMessage('external data handler cannot be imported');
|
||||
|
||||
$electionWithDb = new Election;
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
$electionWithDb->setExternalDataHandler(new PdoHandlerDriver($this->getPDO(), true));
|
||||
}
|
||||
|
||||
public function testBadTableSchema1(): never
|
||||
{
|
||||
$this->expectException(DataHandlerException::class);
|
||||
$this->expectExceptionMessage('Problem with data handler: invalid structure template for PdoHandler');
|
||||
|
||||
$pdo = $this->getPDO();
|
||||
$handlerDriver = new PdoHandlerDriver($pdo, true, ['tableName' => 'Entity', 'primaryColumnName' => 42]);
|
||||
}
|
||||
|
||||
public function testBadTableSchema2(): never
|
||||
{
|
||||
$this->expectException(\Exception::class);
|
||||
|
||||
$pdo = $this->getPDO();
|
||||
$handlerDriver = new PdoHandlerDriver($pdo, true, ['tableName' => 'B@adName', 'primaryColumnName' => 'id', 'dataColumnName' => 'data']);
|
||||
}
|
||||
|
||||
public function testEmptyEntities(): void
|
||||
{
|
||||
$pdo = $this->getPDO();
|
||||
$handlerDriver = new PdoHandlerDriver($pdo, true, ['tableName' => 'Entity', 'primaryColumnName' => 'id', 'dataColumnName' => 'data']);
|
||||
|
||||
self::assertFalse($handlerDriver->selectOneEntity(500));
|
||||
|
||||
self::assertSame([], $handlerDriver->selectRangeEntities(500, 5));
|
||||
}
|
||||
}
|
104
include/Condorcet/Tests/src/DataManager/VotesManagerTest.php
Normal file
104
include/Condorcet/Tests/src/DataManager/VotesManagerTest.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\DataManager;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Throwable\{VoteManagerException, VoteNotLinkedException};
|
||||
use CondorcetPHP\Condorcet\DataManager\VotesManager;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VotesManagerTest extends TestCase
|
||||
{
|
||||
private readonly Election $election;
|
||||
private readonly VotesManager $votes_manager;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election = new Election;
|
||||
$this->election->parseCandidates('A;B;C');
|
||||
|
||||
$this->votes_manager = $this->election->getVotesManager();
|
||||
}
|
||||
|
||||
public function testOffsetSet(): never
|
||||
{
|
||||
$this->expectException(VoteNotLinkedException::class);
|
||||
$this->expectExceptionMessage('The vote is not linked to an election');
|
||||
|
||||
$vote = new Vote([]);
|
||||
|
||||
// add valid vote
|
||||
$this->votes_manager[] = $vote;
|
||||
self::assertSame($vote, $this->votes_manager->getVotesList()[0]);
|
||||
|
||||
// add invalid vote
|
||||
$this->votes_manager[] = null;
|
||||
}
|
||||
|
||||
public function testOffsetSetArgumentType(): never
|
||||
{
|
||||
$this->expectException(VoteManagerException::class);
|
||||
|
||||
// add invalid vote
|
||||
$this->votes_manager[] = new \stdClass;
|
||||
}
|
||||
|
||||
public function testOffsetUnset(): void
|
||||
{
|
||||
$before_list = $this->votes_manager->getVotesList();
|
||||
|
||||
// unset non existent vote
|
||||
unset($this->votes_manager[0]);
|
||||
self::assertSame($before_list, $this->votes_manager->getVotesList());
|
||||
|
||||
// unset existing vote
|
||||
$vote = new Vote([]);
|
||||
$vote->registerLink($this->election);
|
||||
$this->votes_manager[] = $vote;
|
||||
unset($this->votes_manager[0]);
|
||||
self::assertEmpty($this->votes_manager->getVotesList());
|
||||
}
|
||||
|
||||
public function testGetVoteKey(): void
|
||||
{
|
||||
self::assertNull($this->votes_manager->getVoteKey(new Vote([])));
|
||||
}
|
||||
|
||||
public function testGetVotesList(): void
|
||||
{
|
||||
// With Election
|
||||
self::assertEmpty($this->votes_manager->getVotesList());
|
||||
|
||||
$this->election->addCandidate('candidate');
|
||||
$this->election->addVote(new Vote(['candidate']));
|
||||
|
||||
self::assertNotEmpty($this->votes_manager->getVotesList());
|
||||
}
|
||||
|
||||
public function testGetVotesListGenerator(): void
|
||||
{
|
||||
$this->election->parseVotes('A>B>C * 10;tag42 || C>B>A * 42');
|
||||
|
||||
$votesListGenerator = [];
|
||||
|
||||
foreach ($this->election->getVotesListGenerator() as $key => $value) {
|
||||
$votesListGenerator[$key] = $value;
|
||||
}
|
||||
|
||||
self::assertEquals($this->election->getVotesList(), $votesListGenerator);
|
||||
self::assertCount(52, $votesListGenerator);
|
||||
|
||||
|
||||
$votesListGenerator = [];
|
||||
|
||||
foreach ($this->election->getVotesListGenerator('tag42') as $key => $value) {
|
||||
$votesListGenerator[$key] = $value;
|
||||
}
|
||||
|
||||
self::assertEquals($this->election->getVotesList('tag42'), $votesListGenerator);
|
||||
self::assertCount(42, $votesListGenerator);
|
||||
}
|
||||
}
|
Binary file not shown.
985
include/Condorcet/Tests/src/ElectionTest.php
Normal file
985
include/Condorcet/Tests/src/ElectionTest.php
Normal file
@ -0,0 +1,985 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\ElectionProcess\ElectionState;
|
||||
use CondorcetPHP\Condorcet\{Candidate, Condorcet, Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Throwable\{CandidateDoesNotExistException, CandidateExistsException, ElectionObjectVersionMismatchException, FileDoesNotExistException, NoCandidatesException, NoSeatsException, ResultRequestedWithoutVotesException, VoteException, VoteInvalidFormatException, VoteMaxNumberReachedException, VotingHasStartedException};
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ElectionTest extends TestCase
|
||||
{
|
||||
private Election $election1;
|
||||
private Election $election2;
|
||||
|
||||
private Candidate $candidate1;
|
||||
private Candidate $candidate2;
|
||||
private Candidate $candidate3;
|
||||
|
||||
private Vote $vote1;
|
||||
private Vote $vote2;
|
||||
private Vote $vote3;
|
||||
private Vote $vote4;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->candidate1 = $this->election1->addCandidate('candidate1');
|
||||
$this->candidate2 = $this->election1->addCandidate('candidate2');
|
||||
$this->candidate3 = $this->election1->addCandidate('candidate3');
|
||||
|
||||
$this->election1->addVote($this->vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]));
|
||||
$this->election1->addVote($this->vote2 = new Vote([$this->candidate2, $this->candidate3, $this->candidate1]));
|
||||
$this->election1->addVote($this->vote3 = new Vote([$this->candidate3, $this->candidate1, $this->candidate2]));
|
||||
$this->election1->addVote($this->vote4 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]));
|
||||
|
||||
$this->election2 = new Election;
|
||||
}
|
||||
|
||||
public function testRemoveVotes(): never
|
||||
{
|
||||
$this->expectException(VoteException::class);
|
||||
$this->expectExceptionMessage('Problem handling vote: cannot remove vote, is not registered in this election');
|
||||
|
||||
self::assertTrue($this->election1->removeVote($this->vote2));
|
||||
self::assertCount(3, $this->election1->getVotesList());
|
||||
|
||||
$badRemoveVote = new Vote('A');
|
||||
|
||||
$this->election1->removeVote($badRemoveVote);
|
||||
}
|
||||
|
||||
public function testRemoveVotesByTags(): void
|
||||
{
|
||||
$this->vote1->addtags('tag1,tag2,tag3');
|
||||
$this->vote2->addtags('tag3,tag4');
|
||||
$this->vote3->addtags('tag3,tag4,tag5');
|
||||
$this->vote4->addtags('tag1,tag4');
|
||||
|
||||
self::assertCount(3, $r = $this->election1->removeVotesByTags(['tag1', 'tag5']));
|
||||
|
||||
self::assertSame([$this->vote1, $this->vote3, $this->vote4], $r);
|
||||
|
||||
self::assertSame([1 => $this->vote2], $this->election1->getVotesList());
|
||||
|
||||
$this->setUp();
|
||||
|
||||
$this->vote1->addtags('tag1,tag2,tag3');
|
||||
$this->vote2->addtags('tag3,tag4');
|
||||
$this->vote3->addtags('tag3,tag4,tag5');
|
||||
$this->vote4->addtags('tag1,tag4');
|
||||
|
||||
self::assertCount(1, $r = $this->election1->removeVotesByTags('tag1,tag5', false));
|
||||
|
||||
self::assertSame([$this->vote2], $r);
|
||||
|
||||
self::assertSame([0 => $this->vote1, 2=> $this->vote3, 3 => $this->vote4], $this->election1->getVotesList());
|
||||
}
|
||||
|
||||
|
||||
public function testTagsFilter(): void
|
||||
{
|
||||
$this->vote1->addtags('tag1,tag2,tag3');
|
||||
$this->vote2->addtags('tag3,tag4');
|
||||
$this->vote3->addtags('tag3,tag4,tag5');
|
||||
$this->vote4->addtags('tag1,tag4');
|
||||
|
||||
self::assertSame($this->election1->getVotesList('tag1,tag2', true), [0=>$this->vote1, 3=>$this->vote4]);
|
||||
self::assertSame($this->election1->countVotes('tag1,tag2', true), 2);
|
||||
|
||||
self::assertSame($this->election1->getVotesList('tag1,tag2', false), [1=>$this->vote2, 2=>$this->vote3]);
|
||||
self::assertSame($this->election1->countVotes('tag1,tag2', false), 2);
|
||||
|
||||
$resultGlobal = $this->election1->getResult('Schulze');
|
||||
$resultFilter1 = $this->election1->getResult('Schulze', ['tags' => 'tag1', 'withTag' => true]);
|
||||
$resultFilter2 = $this->election1->getResult('Schulze', ['tags' => 'tag1', 'withTag' => false]);
|
||||
|
||||
self::assertNotSame($resultGlobal, $resultFilter1);
|
||||
self::assertNotSame($resultGlobal, $resultFilter2);
|
||||
self::assertNotSame($resultFilter1, $resultFilter2);
|
||||
}
|
||||
|
||||
public function testParseCandidates(): void
|
||||
{
|
||||
self::assertCount(
|
||||
4,
|
||||
$this->election2->parseCandidates('Bruckner; Mahler ;
|
||||
Debussy
|
||||
Bibendum')
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
['Bruckner', 'Mahler', 'Debussy', 'Bibendum'],
|
||||
$this->election2->getCandidatesListAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testgetCandidateObjectFromName(): void
|
||||
{
|
||||
self::assertSame($this->candidate1, $this->election1->getCandidateObjectFromName('candidate1'));
|
||||
self::assertNull($this->election1->getCandidateObjectFromName('candidate42'));
|
||||
}
|
||||
|
||||
public function testParseError(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage("The format of the vote is invalid: the value 'text' is not an integer.");
|
||||
|
||||
$this->election1->parseVotes('candidate1>candidate2 * text');
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testMaxParseIteration1(): never
|
||||
{
|
||||
$this->expectException(VoteMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage('The maximal number of votes for the method is reached: 42');
|
||||
|
||||
self::assertSame(42, Election::setMaxParseIteration(42));
|
||||
|
||||
self::assertCount(42, $this->election1->parseVotes('candidate1>candidate2 * 42'));
|
||||
|
||||
self::assertCount(42, $this->election1->parseVotes('candidate1>candidate2 * 42'));
|
||||
|
||||
self::assertNull(Election::setMaxParseIteration(null));
|
||||
|
||||
self::assertCount(43, $this->election1->parseVotes('candidate1>candidate2 * 43'));
|
||||
|
||||
self::assertSame(42, Election::setMaxParseIteration(42));
|
||||
|
||||
$this->election1->parseVotes('candidate1>candidate2 * 43');
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testMaxParseIteration2(): never
|
||||
{
|
||||
$this->expectException(VoteMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage('The maximal number of votes for the method is reached: 42');
|
||||
|
||||
self::assertSame(42, Election::setMaxParseIteration(42));
|
||||
|
||||
self::assertSame(42, $this->election1->parseVotes('
|
||||
candidate1>candidate2 * 21
|
||||
candidate1>candidate2 * 21
|
||||
candidate1>candidate2 * 21
|
||||
'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testMaxParseIteration3(): never
|
||||
{
|
||||
$this->expectException(VoteMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage('The maximal number of votes for the method is reached: 2');
|
||||
|
||||
self::assertSame(2, Election::setMaxParseIteration(2));
|
||||
|
||||
self::assertSame([0=>'candidate1', 1=>'candidate2'], $this->election2->parseCandidates('candidate1;candidate2'));
|
||||
|
||||
self::assertSame([0=>'candidate3', 1=>'candidate4'], $this->election2->parseCandidates('candidate3;candidate4'));
|
||||
|
||||
self::assertNull(Election::setMaxParseIteration(null));
|
||||
|
||||
self::assertSame([0=>'candidate5', 1=>'candidate6', 2=>'candidate7'], $this->election2->parseCandidates('candidate5;candidate6;candidate7'));
|
||||
|
||||
self::assertSame(2, Election::setMaxParseIteration(2));
|
||||
|
||||
$this->election2->parseCandidates('candidate8;candidate9;candidate10');
|
||||
}
|
||||
|
||||
/**
|
||||
* @preserveGlobalState disabled
|
||||
* @backupStaticAttributes disabled
|
||||
* @runInSeparateProcess
|
||||
*/
|
||||
public function testMaxVoteNumber(): never
|
||||
{
|
||||
$this->expectException(VoteMaxNumberReachedException::class);
|
||||
$this->expectExceptionMessage('The maximal number of votes for the method is reached');
|
||||
|
||||
$election = new Election;
|
||||
self::assertCount(3, $election->parseCandidates('candidate1;candidate2;candidate3'));
|
||||
|
||||
self::assertSame(42, Election::setMaxVoteNumber(42));
|
||||
|
||||
self::assertSame(21, $election->parseVotes('candidate1>candidate2 * 21'));
|
||||
|
||||
try {
|
||||
$election->parseVotes('candidate1>candidate2 * 42');
|
||||
self::assertTrue(false);
|
||||
} catch (VoteMaxNumberReachedException $e) {
|
||||
$this->assertEquals('The maximal number of votes for the method is reached', $e->getMessage());
|
||||
}
|
||||
|
||||
self::assertSame(21, $election->countVotes());
|
||||
|
||||
$election->parseVotes('candidate1 * 21');
|
||||
|
||||
self::assertSame(42, $election->countVotes());
|
||||
|
||||
self::assertNull(Election::setMaxVoteNumber(null));
|
||||
|
||||
$election->addVote('candidate3');
|
||||
|
||||
self::assertSame(42, Election::setMaxVoteNumber(42));
|
||||
|
||||
try {
|
||||
$election->addVote('candidate3');
|
||||
} catch (VoteMaxNumberReachedException $e) {
|
||||
$reserveException = $e;
|
||||
}
|
||||
|
||||
self::assertNull(Election::setMaxVoteNumber(null));
|
||||
|
||||
throw $reserveException;
|
||||
}
|
||||
|
||||
public function testGetVotesListAsString(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->election1->addCandidate('C');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('D');
|
||||
$this->election1->addCandidate('E');
|
||||
$this->election1->addCandidate('A');
|
||||
|
||||
$this->election1->parseVotes('
|
||||
D * 6
|
||||
A * 6
|
||||
E = A = B *3
|
||||
A > C = B > E * 5
|
||||
Y > Z
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
"A > B = C = D = E * 6\n".
|
||||
"D > A = B = C = E * 6\n".
|
||||
"A > B = C > E > D * 5\n".
|
||||
"A = B = E > C = D * 3\n".
|
||||
'A = B = C = D = E * 1',
|
||||
$this->election1->getVotesListAsString()
|
||||
);
|
||||
|
||||
$this->election1->setImplicitRanking(false);
|
||||
|
||||
self::assertSame(
|
||||
"A * 6\n".
|
||||
"D * 6\n".
|
||||
"A > B = C > E * 5\n".
|
||||
"A = B = E * 3\n".
|
||||
'/EMPTY_RANKING/ * 1',
|
||||
$this->election1->getVotesListAsString()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
<<<'VOTES'
|
||||
A * 6
|
||||
D * 6
|
||||
A > B = C > E * 5
|
||||
A = B = E * 3
|
||||
Y > Z * 1
|
||||
VOTES,
|
||||
$this->election1->getVotesListAsString(false)
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmptyRankingExport(): void
|
||||
{
|
||||
$this->election2->parseCandidates('A;B;C');
|
||||
$this->election2->setImplicitRanking(false);
|
||||
|
||||
$this->election2->addVote(new Vote(''));
|
||||
$this->election2->addVote(new Vote('D>E'));
|
||||
|
||||
self::assertSame('/EMPTY_RANKING/ * 2', $this->election2->getVotesListAsString(true));
|
||||
self::assertSame('/EMPTY_RANKING/ * 1'. "\n" .'D > E * 1', $this->election2->getVotesListAsString(false));
|
||||
|
||||
self::assertSame(
|
||||
$cvotes_explicit_without_context =
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
|
||||
/EMPTY_RANKING/ * 1
|
||||
D > E * 1
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: true, inContext: false)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
str_replace(' * 1', '', $cvotes_explicit_without_context),
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: false, inContext: false)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
|
||||
/EMPTY_RANKING/ * 2
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: true, inContext: true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
|
||||
/EMPTY_RANKING/
|
||||
/EMPTY_RANKING/
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: false, inContext: true)
|
||||
);
|
||||
|
||||
$this->election2->setImplicitRanking(true);
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
A = B = C * 2
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: true, inContext: true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
A = B = C
|
||||
A = B = C
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: false, inContext: true)
|
||||
);
|
||||
|
||||
$this->election2 = new Election;
|
||||
$this->election2->parseCandidates('A;B;C;D');
|
||||
$this->election2->setImplicitRanking(true);
|
||||
|
||||
$this->election2->addVote(new Vote('A>B'));
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C ; D
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
A > B > C = D * 1
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: true, inContext: true)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$cvotes_implicit_without_context =
|
||||
<<<'CVOTES'
|
||||
#/Candidates: A ; B ; C ; D
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
A > B * 1
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: true, inContext: false)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
str_replace(' * 1', '', $cvotes_implicit_without_context),
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $this->election2, includeNumberOfSeats: false, aggregateVotes: false, inContext: false)
|
||||
);
|
||||
}
|
||||
|
||||
public function testParseVoteCandidateCoherence(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$cA = $this->election1->addCandidate('A');
|
||||
$cB = $this->election1->addCandidate('B');
|
||||
$cC = $this->election1->addCandidate('C');
|
||||
|
||||
self::assertSame(2, $this->election1->parseVotes('
|
||||
A>B>C * 2
|
||||
'));
|
||||
|
||||
$votes = $this->election1->getVotesList();
|
||||
|
||||
foreach ($votes as $vote) {
|
||||
$ranking = $vote->getRanking();
|
||||
|
||||
self::assertSame($cA, $ranking[1][0]);
|
||||
self::assertSame($cB, $ranking[2][0]);
|
||||
self::assertSame($cC, $ranking[3][0]);
|
||||
}
|
||||
}
|
||||
|
||||
public function testParseVotesInvalidPath(): void
|
||||
{
|
||||
$this->expectException(FileDoesNotExistException::class);
|
||||
$this->expectExceptionMessageMatches('/bad_file.txt$/');
|
||||
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
|
||||
$this->election1->parseVotes('bad_file.txt', true);
|
||||
}
|
||||
|
||||
public function testParseVotesWithoutFail(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
self::assertSame(2, $this->election1->parseVotesWithoutFail('
|
||||
A > B > C
|
||||
A > B > C * 4;tag1 || A > B > C*4 #Coucou
|
||||
A < B < C * 10
|
||||
D <> B
|
||||
A > B > C
|
||||
'));
|
||||
|
||||
self::assertSame(10, $this->election1->countVotes());
|
||||
|
||||
self::assertSame(2, $this->election1->parseVotesWithoutFail(__DIR__.'/../LargeElectionData/smallVote1.votes', true));
|
||||
|
||||
self::assertSame(20, $this->election1->countVotes());
|
||||
|
||||
self::assertSame(2, $this->election1->parseVotesWithoutFail(new \SplFileObject(__DIR__.'/../LargeElectionData/smallVote1.votes'), true));
|
||||
|
||||
self::assertSame(30, $this->election1->countVotes());
|
||||
|
||||
self::assertSame(2, $this->election1->parseVotesWithoutFail(new \SplFileInfo(__DIR__.'/../LargeElectionData/smallVote1.votes'), true));
|
||||
|
||||
self::assertSame(40, $this->election1->countVotes());
|
||||
}
|
||||
|
||||
public function testParseVotesWithoutFailInvalidPath(): void
|
||||
{
|
||||
$this->expectException(FileDoesNotExistException::class);
|
||||
$this->expectExceptionMessageMatches('/bad_file.txt$/');
|
||||
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
|
||||
$this->election1->parseVotesWithoutFail('bad_file.txt', true);
|
||||
}
|
||||
|
||||
public function testVoteWeight(): void
|
||||
{
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('A');
|
||||
$election->addCandidate('B');
|
||||
$election->addCandidate('C');
|
||||
$election->addCandidate('D');
|
||||
|
||||
$election->parseVotes('
|
||||
A > C > D * 6
|
||||
B > A > D * 1
|
||||
C > B > D * 3
|
||||
D > B > A * 3
|
||||
');
|
||||
|
||||
$voteWithWeight = $election->addVote('D > C > B');
|
||||
$voteWithWeight->setWeight(2);
|
||||
|
||||
self::assertSame(
|
||||
14,
|
||||
$election->sumVotesWeight()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'D > C > B ^2',
|
||||
(string) $voteWithWeight
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'D > C > B > A',
|
||||
$voteWithWeight->getSimpleRanking($election)
|
||||
);
|
||||
|
||||
self::assertNotSame(
|
||||
'A = D > C > B',
|
||||
$election->getResult('Schulze Winning')->getResultAsString()
|
||||
);
|
||||
|
||||
$election->allowsVoteWeight(true);
|
||||
|
||||
self::assertSame(
|
||||
15,
|
||||
$election->sumVotesWeight()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'D > C > B > A ^2',
|
||||
$voteWithWeight->getSimpleRanking($election)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'A = D > C > B',
|
||||
$election->getResult('Schulze Winning')->getResultAsString()
|
||||
);
|
||||
|
||||
$election->allowsVoteWeight(false);
|
||||
|
||||
self::assertSame(
|
||||
14,
|
||||
$election->sumVotesWeight()
|
||||
);
|
||||
|
||||
self::assertNotSame(
|
||||
'A = D > C > B',
|
||||
$election->getResult('Schulze Winning')->getResultAsString()
|
||||
);
|
||||
|
||||
$election->allowsVoteWeight(!$election->isVoteWeightAllowed());
|
||||
|
||||
$election->removeVote($voteWithWeight);
|
||||
|
||||
self::assertSame(
|
||||
13,
|
||||
$election->sumVotesWeight()
|
||||
);
|
||||
|
||||
$election->parseVotes('
|
||||
D > C > B ^2 * 1
|
||||
');
|
||||
|
||||
self::assertSame(
|
||||
15,
|
||||
$election->sumVotesWeight()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'A = D > C > B',
|
||||
$election->getResult('Schulze Winning')->getResultAsString()
|
||||
);
|
||||
|
||||
$election->addVote('D > C > B');
|
||||
|
||||
self::assertSame(
|
||||
<<<'VOTES'
|
||||
A > C > D > B * 6
|
||||
C > B > D > A * 3
|
||||
D > B > A > C * 3
|
||||
D > C > B > A ^2 * 1
|
||||
B > A > D > C * 1
|
||||
D > C > B > A * 1
|
||||
VOTES,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testaddVotesFromJson(): never
|
||||
{
|
||||
$this->expectException(\JsonException::class);
|
||||
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('A');
|
||||
$election->addCandidate('B');
|
||||
$election->addCandidate('C');
|
||||
|
||||
$votes = [];
|
||||
|
||||
$votes[]['vote'] = 'B>C>A';
|
||||
$votes[]['vote'] = new \stdClass; // Invalid Vote
|
||||
$votes[]['vote'] = ['C', 'B', 'A'];
|
||||
|
||||
self::assertSame(2, $election->addVotesFromJson(json_encode($votes)));
|
||||
|
||||
self::assertSame(
|
||||
<<<'VOTES'
|
||||
B > C > A * 1
|
||||
C > B > A * 1
|
||||
VOTES,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
|
||||
$votes = [];
|
||||
|
||||
$votes[0]['vote'] = 'A>B>C';
|
||||
$votes[0]['multi'] = 5;
|
||||
$votes[0]['tag'] = 'tag1';
|
||||
$votes[0]['weight'] = '42';
|
||||
|
||||
$election->addVotesFromJson(json_encode($votes));
|
||||
|
||||
$election->allowsVoteWeight(true);
|
||||
|
||||
self::assertSame(
|
||||
<<<'VOTES'
|
||||
A > B > C ^42 * 5
|
||||
B > C > A * 1
|
||||
C > B > A * 1
|
||||
VOTES,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
self::assertSame(5, $election->countVotes('tag1'));
|
||||
|
||||
$election->addVotesFromJson(json_encode($votes).'{42');
|
||||
}
|
||||
|
||||
public function testaddCandidatesFromJson(): never
|
||||
{
|
||||
$this->expectException(CandidateExistsException::class);
|
||||
$this->expectExceptionMessage('This candidate already exists: candidate2');
|
||||
|
||||
$election = new Election;
|
||||
|
||||
$candidates = ['candidate1 ', 'candidate2'];
|
||||
|
||||
$election->addCandidatesFromJson(json_encode($candidates));
|
||||
|
||||
self::assertSame(2, $election->countCandidates());
|
||||
|
||||
self::assertEquals(['candidate1', 'candidate2'], $election->getCandidatesListAsString());
|
||||
|
||||
$election->addCandidatesFromJson(json_encode(['candidate2']));
|
||||
}
|
||||
|
||||
public function testaddCandidatesFromInvalidJson(): never
|
||||
{
|
||||
$this->expectException(\JsonException::class);
|
||||
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidatesFromJson(json_encode(['candidate3']).'{42');
|
||||
}
|
||||
|
||||
|
||||
public function testaddVotesFromJsonWithInvalidJson(): void
|
||||
{
|
||||
$errors = ['42', 'true', 'false', 'null', '', ' ', json_encode(new \stdClass)];
|
||||
|
||||
foreach ($errors as $oneError) {
|
||||
try {
|
||||
$this->election2->addVotesFromJson($oneError);
|
||||
|
||||
// Else fail
|
||||
$this->fail("{$oneError} is not a valid Json for PHP");
|
||||
} catch (\JsonException) {
|
||||
}
|
||||
}
|
||||
|
||||
self::assertEmpty($this->election2->getVotesList());
|
||||
}
|
||||
|
||||
public function testCachingResult(): void
|
||||
{
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('A');
|
||||
$election->addCandidate('B');
|
||||
$election->addCandidate('C');
|
||||
$election->addCandidate('D');
|
||||
|
||||
$election->addVote($vote1 = new Vote('A > C > D'));
|
||||
|
||||
$result1 = $election->getResult('Schulze');
|
||||
self::assertSame($result1, $election->getResult('Schulze'));
|
||||
}
|
||||
|
||||
public function testElectionSerializing(): void
|
||||
{
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('A');
|
||||
$election->addCandidate('B');
|
||||
$election->addCandidate('C');
|
||||
$election->addCandidate('D');
|
||||
|
||||
$election->addVote($vote1 = new Vote('A > C > D'));
|
||||
$result1 = $election->getResult('Schulze');
|
||||
|
||||
$election = serialize($election);
|
||||
// file_put_contents("Tests/src/ElectionData/serialized_election_v3.2.0.txt", $election); # For next test
|
||||
$election = unserialize($election);
|
||||
|
||||
self::assertNotSame($result1, $election->getResult('Schulze'));
|
||||
self::assertSame($result1->getResultAsString(), $election->getResult('Schulze')->getResultAsString());
|
||||
|
||||
self::assertNotSame($vote1, $election->getVotesList()[0]);
|
||||
self::assertSame($vote1->getSimpleRanking(), $election->getVotesList()[0]->getSimpleRanking());
|
||||
self::assertTrue($election->getVotesList()[0]->haveLink($election));
|
||||
self::assertFalse($vote1->haveLink($election));
|
||||
}
|
||||
|
||||
public function testElectionUnserializing(): void
|
||||
{
|
||||
$this->expectException(ElectionObjectVersionMismatchException::class);
|
||||
$this->expectExceptionMessage(
|
||||
"Version mismatch: The election object has version '3.2' " .
|
||||
"which is different from the current class version '".Condorcet::getVersion(true)."'"
|
||||
);
|
||||
|
||||
unserialize(
|
||||
file_get_contents('Tests/src/ElectionData/serialized_election_v3.2.0.txt')
|
||||
);
|
||||
}
|
||||
|
||||
public function testCloneElection(): void
|
||||
{
|
||||
$this->election1->computeResult();
|
||||
|
||||
$cloneElection = clone $this->election1;
|
||||
|
||||
self::assertNotSame($this->election1->getVotesManager(), $cloneElection->getVotesManager());
|
||||
self::assertSame($this->election1->getVotesList(), $cloneElection->getVotesList());
|
||||
|
||||
self::assertSame($this->election1->getCandidatesList(), $cloneElection->getCandidatesList());
|
||||
|
||||
self::assertNotSame($this->election1->getPairwise(), $cloneElection->getPairwise());
|
||||
self::assertEquals($this->election1->getExplicitPairwise(), $cloneElection->getExplicitPairwise());
|
||||
|
||||
self::assertNotSame($this->election1->getTimerManager(), $cloneElection->getTimerManager());
|
||||
|
||||
self::assertSame($this->election1->getVotesList()[0], $cloneElection->getVotesList()[0]);
|
||||
|
||||
self::assertTrue($cloneElection->getVotesList()[0]->haveLink($this->election1));
|
||||
self::assertTrue($cloneElection->getVotesList()[0]->haveLink($cloneElection));
|
||||
}
|
||||
|
||||
public function testPairwiseArrayAccess(): void
|
||||
{
|
||||
$this->election1->computeResult();
|
||||
|
||||
self::assertTrue($this->election1->getPairwise()->offsetExists(1));
|
||||
}
|
||||
|
||||
public function testGetCandidateObjectFromKey(): void
|
||||
{
|
||||
self::assertSame($this->candidate2, $this->election1->getCandidateObjectFromKey(1));
|
||||
|
||||
self::assertNull($this->election1->getCandidateObjectFromKey(42));
|
||||
}
|
||||
|
||||
public function testElectionState1(): never
|
||||
{
|
||||
$this->expectException(VotingHasStartedException::class);
|
||||
$this->expectExceptionMessage("The voting has started: cannot add 'candidate4'");
|
||||
|
||||
$this->election1->addCandidate('candidate4');
|
||||
}
|
||||
|
||||
public function testElectionState2(): never
|
||||
{
|
||||
$this->expectException(VotingHasStartedException::class);
|
||||
$this->expectExceptionMessage('The voting has started');
|
||||
|
||||
$this->election1->removeCandidates('candidate4');
|
||||
}
|
||||
|
||||
public function testElectionState3(): never
|
||||
{
|
||||
$this->expectException(NoCandidatesException::class);
|
||||
$this->expectExceptionMessage('You need to specify one or more candidates before voting');
|
||||
|
||||
$election = new Election;
|
||||
$election->setStateTovote();
|
||||
}
|
||||
|
||||
public function testElectionState4(): never
|
||||
{
|
||||
$this->expectException(ResultRequestedWithoutVotesException::class);
|
||||
$this->expectExceptionMessage('The result cannot be requested without votes');
|
||||
|
||||
$election = new Election;
|
||||
$election->getResult();
|
||||
}
|
||||
|
||||
public function testElectionState5(): void
|
||||
{
|
||||
$this->election1->getResult();
|
||||
|
||||
self::assertTrue($this->election1->setStateTovote());
|
||||
|
||||
self::assertSame(ElectionState::VOTES_REGISTRATION, $this->election1->getState());
|
||||
}
|
||||
|
||||
public function testAddSameVote(): never
|
||||
{
|
||||
$this->expectException(VoteException::class);
|
||||
$this->expectExceptionMessage('Problem handling vote: seats are already registered');
|
||||
|
||||
$this->election1->addVote($this->vote1);
|
||||
}
|
||||
|
||||
public function testDestroy(): void
|
||||
{
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('candidate1');
|
||||
$election->addCandidate('candidate2');
|
||||
$election->addCandidate('candidate3');
|
||||
|
||||
$election->addVote('candidate1>candidate2');
|
||||
|
||||
$weakref = \WeakReference::create($election);
|
||||
|
||||
// PHP circular reference can bug
|
||||
// \debug_zval_dump($election);
|
||||
unset($election);
|
||||
|
||||
self::assertNull($weakref->get());
|
||||
}
|
||||
|
||||
public function testRemoveCandidate(): never
|
||||
{
|
||||
$this->expectException(CandidateDoesNotExistException::class);
|
||||
$this->expectExceptionMessage('This candidate does not exist: B');
|
||||
|
||||
$election = new Election;
|
||||
|
||||
$election->addCandidate('candidate1');
|
||||
|
||||
$badCandidate = new Candidate('B');
|
||||
|
||||
$election->removeCandidates($badCandidate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider MethodsListProvider
|
||||
*/
|
||||
public function testRemoveCandidateResult(string $method): void
|
||||
{
|
||||
$votes = ' Memphis * 4
|
||||
Nashville * 3
|
||||
Chattanooga * 2
|
||||
Knoxville * 1';
|
||||
|
||||
// Ref
|
||||
$electionRef = new Election;
|
||||
|
||||
$electionRef->addCandidate('Memphis');
|
||||
$electionRef->addCandidate('Nashville');
|
||||
$electionRef->addCandidate('Knoxville');
|
||||
$electionRef->addCandidate('Chattanooga');
|
||||
|
||||
$electionRef->parseVotes($votes);
|
||||
|
||||
// Test
|
||||
$electionTest = new Election;
|
||||
|
||||
$electionTest->addCandidate('Memphis');
|
||||
$electionTest->addCandidate('BadCandidate');
|
||||
$electionTest->addCandidate('Nashville');
|
||||
$electionTest->addCandidate('Knoxville');
|
||||
$electionTest->addCandidate('Chattanooga');
|
||||
|
||||
$electionTest->removeCandidates('BadCandidate');
|
||||
|
||||
$electionTest->parseVotes($votes);
|
||||
|
||||
|
||||
self::assertSame(
|
||||
$electionRef->getResult($method)->getResultAsArray(true),
|
||||
$electionTest->getResult($method)->getResultAsArray(true)
|
||||
);
|
||||
}
|
||||
|
||||
public function MethodsListProvider(): array
|
||||
{
|
||||
$r = [];
|
||||
|
||||
foreach (Condorcet::getAuthMethods() as $method) {
|
||||
$r[] = [$method];
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
public function testAmbiguousCandidatesOnElectionSide(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid');
|
||||
|
||||
$vote = new Vote('candidate1>candidate2');
|
||||
|
||||
$election1 = new Election;
|
||||
$election2 = new Election;
|
||||
|
||||
$election1->addCandidate(new Candidate('candidate2'));
|
||||
$election2->addCandidate(new Candidate('candidate1'));
|
||||
|
||||
$election1->addVote($vote);
|
||||
$election2->addVote($vote);
|
||||
}
|
||||
|
||||
public function testAmbiguousCandidatesOnVoteSide(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: vote does not match candidate in this election');
|
||||
|
||||
$election1 = new Election;
|
||||
$election2 = new Election;
|
||||
|
||||
$election1->addCandidate(new Candidate('candidate1'));
|
||||
$election2->addCandidate(new Candidate('candidate2'));
|
||||
|
||||
$candidate3 = new Candidate('candidate3');
|
||||
$election1->addCandidate($candidate3);
|
||||
$election2->addCandidate($candidate3);
|
||||
|
||||
$vote = new Vote('candidate3');
|
||||
|
||||
$election1->addVote($vote);
|
||||
$election2->addVote($vote);
|
||||
|
||||
$election1->getResult();
|
||||
$election2->getResult();
|
||||
|
||||
try {
|
||||
$vote->setRanking('candidate1>candidate2>candidate3');
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
self::assertEmpty($election1->debugGetCalculator());
|
||||
self::assertEmpty($election2->debugGetCalculator());
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function testInvalidSeats(): never
|
||||
{
|
||||
$this->expectException(NoSeatsException::class);
|
||||
$this->expectExceptionMessage('No seats defined');
|
||||
|
||||
$this->election1->setNumberOfSeats(0);
|
||||
}
|
||||
|
||||
public function testSeats(): void
|
||||
{
|
||||
self::assertSame(100, $this->election1->getNumberOfSeats());
|
||||
|
||||
$this->election1->setNumberOfSeats(5);
|
||||
|
||||
self::assertSame(5, $this->election1->getNumberOfSeats());
|
||||
}
|
||||
}
|
334
include/Condorcet/Tests/src/ResultTest.php
Normal file
334
include/Condorcet/Tests/src/ResultTest.php
Normal file
@ -0,0 +1,334 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Algo\Methods\KemenyYoung\KemenyYoung;
|
||||
use CondorcetPHP\Condorcet\Algo\StatsVerbosity;
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election};
|
||||
use CondorcetPHP\Condorcet\Throwable\{AlgorithmException, ResultException};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ResultTest extends TestCase
|
||||
{
|
||||
private readonly Election $election1;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
}
|
||||
|
||||
public function testGetResultAsString(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->parseVotes('
|
||||
B > A > C * 7
|
||||
A > B > C * 7
|
||||
C > A > B * 2
|
||||
C > B > A * 2
|
||||
');
|
||||
|
||||
|
||||
self::assertSame(
|
||||
'A = B > C',
|
||||
$this->election1->getResult('Ranked Pairs')->getResultAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetResultAsInternalKey(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->parseVotes('
|
||||
B > A > C * 7
|
||||
A > B > C * 7
|
||||
C > A > B * 2
|
||||
C > B > A * 2
|
||||
');
|
||||
|
||||
|
||||
self::assertSame(
|
||||
[1 => [0, 1], 2 => [2]],
|
||||
$this->election1->getResult('Ranked Pairs')->getResultAsInternalKey()
|
||||
);
|
||||
}
|
||||
|
||||
public function testgetCondorcetElectionGeneratorVersion(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
self::assertSame(Condorcet::getVersion(), $this->election1->getResult('Ranked Pairs')->getCondorcetElectionGeneratorVersion());
|
||||
}
|
||||
|
||||
public function testResultClassgenerator(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
self::assertSame(\CondorcetPHP\Condorcet\Algo\Methods\RankedPairs\RankedPairsMargin::class, $this->election1->getResult('Ranked Pairs')->getClassGenerator());
|
||||
}
|
||||
|
||||
public function testMethod(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
self::assertSame('Ranked Pairs Margin', $this->election1->getResult('Ranked Pairs')->getMethod());
|
||||
}
|
||||
|
||||
public function testGetBuildTimeStamp(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
self::assertIsFloat($this->election1->getResult('Ranked Pairs')->getBuildTimeStamp());
|
||||
}
|
||||
|
||||
public function testGetWinner(): void
|
||||
{
|
||||
$this->election1->addCandidate('a');
|
||||
$this->election1->addCandidate('b');
|
||||
$this->election1->addCandidate('c');
|
||||
|
||||
$this->election1->parseVotes('
|
||||
a > c > b * 23
|
||||
b > c > a * 19
|
||||
c > b > a * 16
|
||||
c > a > b * 2
|
||||
');
|
||||
|
||||
self::assertEquals('c', $this->election1->getResult()->getWinner());
|
||||
self::assertEquals('c', $this->election1->getResult()->getCondorcetWinner());
|
||||
}
|
||||
|
||||
public function testGetLoser(): void
|
||||
{
|
||||
$this->election1->addCandidate('Memphis');
|
||||
$this->election1->addCandidate('Nashville');
|
||||
$this->election1->addCandidate('Knoxville');
|
||||
$this->election1->addCandidate('Chattanooga');
|
||||
|
||||
$this->election1->parseVotes('
|
||||
Memphis > Nashville > Chattanooga * 42
|
||||
Nashville > Chattanooga > Knoxville * 26
|
||||
Chattanooga > Knoxville > Nashville * 15
|
||||
Knoxville > Chattanooga > Nashville * 17
|
||||
');
|
||||
|
||||
self::assertEquals('Memphis', $this->election1->getResult()->getLoser());
|
||||
self::assertEquals('Memphis', $this->election1->getResult()->getCondorcetLoser());
|
||||
}
|
||||
|
||||
public function testgetOriginalResultArrayWithString(): void
|
||||
{
|
||||
$this->election1->addCandidate('a');
|
||||
$this->election1->addCandidate('b');
|
||||
$this->election1->addCandidate('c');
|
||||
|
||||
$this->election1->addVote('a > b > c');
|
||||
|
||||
self::assertEquals(
|
||||
[1 => 'a',
|
||||
2 => 'b',
|
||||
3 => 'c',
|
||||
],
|
||||
$this->election1->getResult()->getOriginalResultArrayWithString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testOffsetSet(): never
|
||||
{
|
||||
$this->expectException(ResultException::class);
|
||||
$this->expectExceptionMessage('Result cannot be changed');
|
||||
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
$result = $this->election1->getResult('Schulze');
|
||||
|
||||
$result[] = 42;
|
||||
}
|
||||
|
||||
public function testOffUnset(): never
|
||||
{
|
||||
$this->expectException(ResultException::class);
|
||||
$this->expectExceptionMessage('Result cannot be changed');
|
||||
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('C > B > A');
|
||||
|
||||
$result = $this->election1->getResult('Schulze');
|
||||
|
||||
self::assertTrue(isset($result[1]));
|
||||
|
||||
unset($result[1]);
|
||||
}
|
||||
|
||||
public function testIterator(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$vote = $this->election1->addVote('C > B > A');
|
||||
|
||||
$result = $this->election1->getResult('Schulze');
|
||||
|
||||
foreach ($result as $key => $value) {
|
||||
self::assertSame($vote->getRanking()[$key], $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testBadMethodName(): never
|
||||
{
|
||||
$this->expectException(AlgorithmException::class);
|
||||
$this->expectExceptionMessage('The voting algorithm is not available: bad method');
|
||||
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->parseVotes('A>B>C');
|
||||
|
||||
$this->election1->getResult('bad method');
|
||||
}
|
||||
|
||||
public function testResultRankOrdering(): void
|
||||
{
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
$this->election1->addCandidate('A');
|
||||
|
||||
$this->election1->addVote('C = A = B');
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['A', 'B', 'C'],
|
||||
],
|
||||
$this->election1->getResult()->getOriginalResultArrayWithString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testProportional(): void
|
||||
{
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('A');
|
||||
|
||||
$this->election1->setNumberOfSeats(2);
|
||||
|
||||
$result = $this->election1->getResult('STV');
|
||||
|
||||
self::assertSame(
|
||||
2,
|
||||
$result->getNumberOfSeats()
|
||||
);
|
||||
|
||||
self::assertTrue(
|
||||
$result->getClassGenerator()::IS_PROPORTIONAL
|
||||
);
|
||||
|
||||
self::assertTrue(
|
||||
$result->isProportional()
|
||||
);
|
||||
|
||||
$result = $this->election1->getResult('Schulze');
|
||||
|
||||
self::assertNull(
|
||||
$result->getNumberOfSeats()
|
||||
);
|
||||
|
||||
self::assertFalse(
|
||||
$result->getClassGenerator()::IS_PROPORTIONAL
|
||||
);
|
||||
|
||||
self::assertFalse(
|
||||
$result->isProportional()
|
||||
);
|
||||
}
|
||||
|
||||
public function testMethodOption(): void
|
||||
{
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('A>B>C');
|
||||
|
||||
$class = Condorcet::getMethodClass('Borda');
|
||||
|
||||
self::assertSame(1, $class::$optionStarting);
|
||||
|
||||
$b1 = $this->election1->getResult('Borda');
|
||||
$c1 = $this->election1->getResult('Copeland');
|
||||
|
||||
self::assertSame(1, $b1->getMethodOptions()['Starting']);
|
||||
|
||||
self::assertTrue($this->election1->setMethodOption('Borda Count', 'Starting', 0));
|
||||
self::assertSame(0, $class::$optionStarting);
|
||||
|
||||
self::assertSame(1, $b1->getMethodOptions()['Starting']);
|
||||
|
||||
$b2 = $this->election1->getResult('Borda');
|
||||
$c2 = $this->election1->getResult('Copeland');
|
||||
|
||||
self::assertNotSame($b1, $b2);
|
||||
self::assertSame($c1, $c2);
|
||||
|
||||
self::assertSame(0, $b2->getMethodOptions()['Starting']);
|
||||
|
||||
self::assertFalse($this->election1->setMethodOption('Unregistered method', 'Starting', 0));
|
||||
}
|
||||
|
||||
public function testVerbosityLevel(): void
|
||||
{
|
||||
$this->election1->addCandidate('A');
|
||||
$this->election1->addCandidate('B');
|
||||
$this->election1->addCandidate('C');
|
||||
|
||||
$this->election1->addVote('A>B>C');
|
||||
|
||||
$r1 = $this->election1->getResult(KemenyYoung::class);
|
||||
self::assertSame(StatsVerbosity::STD, $r1->statsVerbosity);
|
||||
|
||||
$this->election1->setStatsVerbosity(StatsVerbosity::STD);
|
||||
$r2 = $this->election1->getResult(KemenyYoung::class);
|
||||
self::assertSame($r1, $r2);
|
||||
|
||||
$this->election1->setStatsVerbosity(StatsVerbosity::FULL);
|
||||
$r3 = $this->election1->getResult(KemenyYoung::class);
|
||||
|
||||
self::assertSame(StatsVerbosity::STD, $r1->statsVerbosity);
|
||||
self::assertSame(StatsVerbosity::FULL, $r3->statsVerbosity);
|
||||
|
||||
self::assertNotSame($r1, $r3);
|
||||
self::assertArrayNotHasKey('Ranking Scores', $r1->getStats());
|
||||
self::assertArrayHasKey('Ranking Scores', $r3->getStats());
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Throwable\Internal\CondorcetInternalError;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetInternalErrorTest extends TestCase
|
||||
{
|
||||
public function testMessage(): void
|
||||
{
|
||||
$this->expectException(CondorcetInternalError::class);
|
||||
$this->expectExceptionMessage($message = 'Test message');
|
||||
|
||||
throw new CondorcetInternalError($message);
|
||||
}
|
||||
}
|
27
include/Condorcet/Tests/src/Timer/TimerTest.php
Normal file
27
include/Condorcet/Tests/src/Timer/TimerTest.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Timer;
|
||||
|
||||
use CondorcetPHP\Condorcet\Throwable\TimerException;
|
||||
use CondorcetPHP\Condorcet\Timer\{Chrono, Manager};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class TimerTest extends TestCase
|
||||
{
|
||||
public function testInvalidChrono(): never
|
||||
{
|
||||
$this->expectException(TimerException::class);
|
||||
$this->expectExceptionMessage('Only a chrono linked to this manager can be used');
|
||||
|
||||
$manager1 = new Manager;
|
||||
$manager2 = new Manager;
|
||||
|
||||
$chrono1 = new Chrono($manager1);
|
||||
$chrono2 = new Chrono($manager2);
|
||||
|
||||
$manager1->addTime($chrono1);
|
||||
$manager1->addTime($chrono2);
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
#/Candidates:A;B;C
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: false
|
||||
|
||||
A>B ^2
|
@ -0,0 +1,7 @@
|
||||
#/Candidates:A;B;C
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
#Number of Seats: 42
|
||||
|
||||
B>A ^2
|
||||
B>C
|
@ -0,0 +1,3 @@
|
||||
#/Candidates:A;B;C
|
||||
|
||||
C>B>A * 700
|
@ -0,0 +1,402 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Throwable\FileDoesNotExistException;
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class CondorcetElectionFormatTest extends TestCase
|
||||
{
|
||||
public function testCondorcetElectionFormat1_Simple(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Candidates: Richard Boháč ; Petr Němec ; Simona Slaná
|
||||
Richard Boháč>Petr Němec ^42
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
self::assertFalse($condorcetFormat->CandidatesParsedFromVotes);
|
||||
|
||||
|
||||
$election = $condorcetFormat->setDataToAnElection();
|
||||
|
||||
self::assertFalse($election->isVoteWeightAllowed());
|
||||
$election->allowsVoteWeight(true);
|
||||
self::assertTrue($election->isVoteWeightAllowed());
|
||||
|
||||
|
||||
self::assertSame(['Petr Němec', 'Richard Boháč', 'Simona Slaná'], $election->getCandidatesListAsString());
|
||||
|
||||
self::assertSame(100, $election->getNumberOfSeats());
|
||||
self::assertTrue($election->getImplicitRankingRule());
|
||||
|
||||
self::assertSame(1, $election->countVotes());
|
||||
self::assertSame('Richard Boháč > Petr Němec > Simona Slaná ^42', $election->getVotesList()[0]->getSimpleRanking(context: $election, displayWeight: true));
|
||||
self::assertSame(0, $condorcetFormat->invalidBlocksCount);
|
||||
}
|
||||
|
||||
|
||||
public function testCondorcetElectionFormat2_MultiplesErrorsAndComplications(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Candidates: A ;B;C
|
||||
#/Number of Seats: 6
|
||||
#/Implicit Ranking: false
|
||||
|
||||
A > B > C
|
||||
A > B > C * 4;tag1 || A > B > C*4 #Coucou
|
||||
# A > B > C
|
||||
A < B < C * 10
|
||||
A > E > A* 3
|
||||
D <> B
|
||||
A > B > C
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
|
||||
$election = $condorcetFormat->setDataToAnElection();
|
||||
|
||||
self::assertSame(['A', 'B', 'C'], $election->getCandidatesListAsString());
|
||||
|
||||
self::assertSame(6, $election->getNumberOfSeats());
|
||||
|
||||
self::assertFalse($election->getImplicitRankingRule());
|
||||
|
||||
self::assertSame(10, $election->countVotes());
|
||||
|
||||
self::assertSame(3, $condorcetFormat->invalidBlocksCount);
|
||||
|
||||
self::assertSame(['tag1'], $election->getVotesList()[5]->getTags());
|
||||
}
|
||||
|
||||
public function testCondorcetElectionFormat3_CustomElection1(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Candidates: Richard Boháč ; Petr Němec ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: true
|
||||
Richard Boháč>Petr Němec ^42
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(66);
|
||||
|
||||
$condorcetFormat->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(['Petr Němec', 'Richard Boháč', 'Simona Slaná'], $election->getCandidatesListAsString());
|
||||
|
||||
self::assertSame(42, $election->getNumberOfSeats());
|
||||
self::assertTrue($election->getImplicitRankingRule());
|
||||
|
||||
self::assertSame(1, $election->countVotes());
|
||||
self::assertSame('Richard Boháč > Petr Němec > Simona Slaná', $election->getVotesList()[0]->getSimpleRanking(context: $election, displayWeight: true));
|
||||
self::assertSame(0, $condorcetFormat->invalidBlocksCount);
|
||||
}
|
||||
|
||||
public function testCondorcetElectionFormat4_CustomElection2(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Candidates: Richard Boháč ; Petr Němec ; Simona Slaná
|
||||
#/Weight allowed: true
|
||||
Richard Boháč>Petr Němec ^42
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(66);
|
||||
$election->allowsVoteWeight(false);
|
||||
|
||||
$condorcetFormat->setDataToAnElection($election);
|
||||
|
||||
$election->allowsVoteWeight(true); // Must be forced by parameter
|
||||
|
||||
|
||||
self::assertSame(['Petr Němec', 'Richard Boháč', 'Simona Slaná'], $election->getCandidatesListAsString());
|
||||
|
||||
self::assertSame(66, $election->getNumberOfSeats());
|
||||
self::assertFalse($election->getImplicitRankingRule());
|
||||
|
||||
self::assertSame(1, $election->countVotes());
|
||||
self::assertSame('Richard Boháč > Petr Němec ^42', $election->getVotesList()[0]->getSimpleRanking(context: $election, displayWeight: true));
|
||||
self::assertSame(0, $condorcetFormat->invalidBlocksCount);
|
||||
}
|
||||
|
||||
public function testCondorcetElectionFormat5_UnknowParametersAndEmptyLinesAndCase(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
#/Candidates: Richard Boháč ; 郝文彦 ; Simona Slaná
|
||||
|
||||
#/AnewParameters: 7
|
||||
#/numBer of Seats: 42
|
||||
#/implicit ranking: true
|
||||
|
||||
|
||||
|
||||
Richard Boháč>郝文彦 ^42
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(66);
|
||||
|
||||
$condorcetFormat->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(['Richard Boháč', 'Simona Slaná', '郝文彦'], $election->getCandidatesListAsString());
|
||||
|
||||
self::assertSame(42, $election->getNumberOfSeats());
|
||||
self::assertTrue($election->getImplicitRankingRule());
|
||||
|
||||
self::assertSame(1, $election->countVotes());
|
||||
self::assertSame('Richard Boháč > 郝文彦 > Simona Slaná', $election->getVotesList()[0]->getSimpleRanking(context: $election, displayWeight: true));
|
||||
self::assertSame(0, $condorcetFormat->invalidBlocksCount);
|
||||
}
|
||||
|
||||
public function testOfficialSpecificationValidExamples(): void
|
||||
{
|
||||
# Example with tags and implicit ranking
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
# My beautiful election
|
||||
#/Candidates: Candidate A;Candidate B;Candidate C
|
||||
#/Implicit Ranking: true
|
||||
#/Weight allowed: true
|
||||
|
||||
# Here the votes datas:
|
||||
Candidate A > Candidate B > Candidate C * 42
|
||||
julien@condorcet.vote , signature:55073db57b0a859911 || Candidate A > Candidate B > Candidate C # Same as above, so there will be 43 votes with this ranking. And tags are registered by the software if able.
|
||||
Candidate C > Candidate A = Candidate B ^7 * 8 # 8 votes with a weight of 7.
|
||||
Candidate B = Candidate A > Candidate C
|
||||
Candidate C # Interpreted as Candidate C > Candidate A = Candidate B, because implicit ranking is true (wich is also default, but it's better to say it)
|
||||
Candidate B > Candidate C # Interpreted as Candidate B > Candidate C
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
$election = $condorcetFormat->setDataToAnElection();
|
||||
|
||||
self::assertSame(54, $election->countVotes());
|
||||
|
||||
self::assertSame(<<<'VOTES'
|
||||
Candidate C > Candidate A = Candidate B ^7 * 8
|
||||
Candidate A > Candidate B > Candidate C * 43
|
||||
Candidate A = Candidate B > Candidate C * 1
|
||||
Candidate B > Candidate C > Candidate A * 1
|
||||
Candidate C > Candidate A = Candidate B * 1
|
||||
VOTES
|
||||
, $election->getVotesListAsString());
|
||||
|
||||
|
||||
self::assertCount(1, $election->getVotesList(tags: 'signature:55073db57b0a859911', with: true));
|
||||
self::assertCount(1, $election->getVotesList(tags: 'julien@condorcet.vote', with: true));
|
||||
self::assertCount(0, $election->getVotesList(tags: 'otherTag', with: true));
|
||||
self::assertSame('Candidate A > Candidate B > Candidate C', current($election->getVotesList(tags: 'julien@condorcet.vote', with: true))->getSimpleRanking());
|
||||
|
||||
|
||||
# Example without implicit ranking as weight
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(<<<'CVOTES'
|
||||
# My beautiful election
|
||||
#/Candidates: Candidate A ; Candidate B ; Candidate C
|
||||
#/Implicit Ranking: false
|
||||
#/Weight allowed: false
|
||||
|
||||
# Here the votes datas:
|
||||
Candidate A > Candidate B > Candidate C ^7 *2 # Vote weight is disable, so ^7 is ignored. Two vote with weight of 1.
|
||||
Candidate C>Candidate B # Vote is untouched. When compute pairwise, Candidate C win again Candidate B, no one beats the candidate or achieves a draw.
|
||||
Candidate B # Vote is valid, but not have any effect on most election method, especially Condorcet methods.
|
||||
CVOTES);
|
||||
|
||||
$condorcetFormat = new CondorcetElectionFormat($file);
|
||||
$election = $condorcetFormat->setDataToAnElection();
|
||||
|
||||
self::assertSame(4, $election->countVotes());
|
||||
|
||||
self::assertSame(<<<'VOTES'
|
||||
Candidate A > Candidate B > Candidate C * 2
|
||||
Candidate B * 1
|
||||
Candidate C > Candidate B * 1
|
||||
VOTES
|
||||
, $election->getVotesListAsString());
|
||||
}
|
||||
|
||||
public function testexportElectionToCondorcetElectionFormat(): void
|
||||
{
|
||||
$input = new \SplTempFileObject;
|
||||
$input->fwrite(<<<'CVOTES'
|
||||
#/Weight allowed: true
|
||||
#/Candidates: Richard Boháč ; Petr Němec ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: true
|
||||
|
||||
Richard Boháč>Petr Němec ^7
|
||||
Richard Boháč>Petr Němec
|
||||
tag1 , tag b || Richard Boháč>Petr Němec
|
||||
Simona Slaná * 2
|
||||
Petr Němec *1
|
||||
CVOTES);
|
||||
|
||||
$election = (new CondorcetElectionFormat($input))->setDataToAnElection();
|
||||
|
||||
self::assertSame(
|
||||
$assertion1 =
|
||||
<<<'CVOTES'
|
||||
#/Candidates: Petr Němec ; Richard Boháč ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: true
|
||||
#/Weight Allowed: true
|
||||
|
||||
Richard Boháč > Petr Němec ^7 * 1
|
||||
Richard Boháč > Petr Němec * 2
|
||||
Simona Slaná * 2
|
||||
Petr Němec * 1
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election)
|
||||
);
|
||||
|
||||
self::assertStringNotContainsString('Number of Seats: 42', CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election, includeNumberOfSeats: false));
|
||||
|
||||
$election->setImplicitRanking(false);
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: Petr Němec ; Richard Boháč ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: true
|
||||
|
||||
Richard Boháč > Petr Němec ^7 * 1
|
||||
Richard Boháč > Petr Němec * 2
|
||||
Simona Slaná * 2
|
||||
Petr Němec * 1
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
<<<'CVOTES'
|
||||
#/Candidates: Petr Němec ; Richard Boháč ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: true
|
||||
|
||||
Richard Boháč > Petr Němec ^7
|
||||
Richard Boháč > Petr Němec
|
||||
tag1,tag b || Richard Boháč > Petr Němec
|
||||
Simona Slaná
|
||||
Simona Slaná
|
||||
Petr Němec
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election, aggregateVotes: false)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$assertion5 =
|
||||
<<<'CVOTES'
|
||||
#/Candidates: Petr Němec ; Richard Boháč ; Simona Slaná
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: true
|
||||
|
||||
Richard Boháč > Petr Němec ^7
|
||||
Richard Boháč > Petr Němec
|
||||
Richard Boháč > Petr Němec
|
||||
Simona Slaná
|
||||
Simona Slaná
|
||||
Petr Němec
|
||||
CVOTES,
|
||||
CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election, aggregateVotes: false, includeTags: false)
|
||||
);
|
||||
|
||||
$election->setImplicitRanking(true);
|
||||
$output = new \SplTempFileObject;
|
||||
self::assertNull(CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election, file: $output));
|
||||
$output->rewind();
|
||||
|
||||
self::assertSame(
|
||||
$assertion1,
|
||||
$output->fread(2048)
|
||||
);
|
||||
|
||||
$election->setImplicitRanking(false);
|
||||
$output = new \SplTempFileObject;
|
||||
self::assertNull(CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $election, aggregateVotes: false, includeTags: false, file: $output));
|
||||
$output->rewind();
|
||||
self::assertSame(
|
||||
$assertion5,
|
||||
$output->fread(2048)
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmptyRankingImport(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite($input = <<<'CVOTES'
|
||||
#/Candidates: A ; B ; C
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
|
||||
/EMPTY_RANKING/ * 1
|
||||
D > E * 1
|
||||
CVOTES);
|
||||
|
||||
$cef = new CondorcetElectionFormat($file);
|
||||
|
||||
$election = $cef->setDataToAnElection();
|
||||
|
||||
self::assertSame('/EMPTY_RANKING/ * 2', $election->getVotesListAsString());
|
||||
self::assertSame([], $election->getVotesList()[0]->getRanking());
|
||||
self::assertSame($input, CondorcetElectionFormat::exportElectionToCondorcetElectionFormat($election));
|
||||
}
|
||||
|
||||
public function testCandidatesFromVotes(): void
|
||||
{
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite($input = <<<'CVOTES'
|
||||
#/Number of Seats: 42
|
||||
#/Implicit Ranking: false
|
||||
#/Weight Allowed: false
|
||||
|
||||
/EMPTY_RANKING/ * 1
|
||||
D > E^7 * 2 # Comment
|
||||
|
||||
tag1, tag2 ||A= B > C = D > F
|
||||
D > F = A
|
||||
D>A>B>C>E>F
|
||||
CVOTES);
|
||||
|
||||
$cef = new CondorcetElectionFormat($file);
|
||||
|
||||
self::assertSame(['A', 'B', 'C', 'D', 'E', 'F'], $cef->candidates);
|
||||
self::assertTrue($cef->CandidatesParsedFromVotes);
|
||||
|
||||
$election = $cef->setDataToAnElection();
|
||||
|
||||
self::assertFalse($election->getImplicitRankingRule());
|
||||
self::assertSame(42, $election->getNumberOfSeats());
|
||||
|
||||
self::assertEquals(['A', 'B', 'C', 'D', 'E', 'F'], $election->getCandidatesList());
|
||||
self::assertSame('D > A > B > C > E > F', $election->getResult()->getResultAsString());
|
||||
}
|
||||
|
||||
public function testFileDoesNotExists(): void
|
||||
{
|
||||
$this->expectException(FileDoesNotExistException::class);
|
||||
|
||||
new CondorcetElectionFormat(__DIR__.'noFile.txt');
|
||||
}
|
||||
}
|
@ -0,0 +1,380 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Condorcet, Election};
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\{CondorcetElectionFormat, DavidHillFormat};
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DavidHillFormatTest extends TestCase
|
||||
{
|
||||
private static DavidHillFormat $tidemanA77;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::$tidemanA77 ?? (self::$tidemanA77 = new DavidHillFormat(__DIR__.'/TidemanData/A77.HIL'));
|
||||
}
|
||||
|
||||
public function testA77_With_Implicit(): void
|
||||
{
|
||||
$election = self::$tidemanA77->setDataToAnElection();
|
||||
|
||||
self::assertSame(213, $election->countVotes());
|
||||
self::assertSame(1, $election->getNumberOfSeats());
|
||||
|
||||
self::assertSame(
|
||||
<<<'EOD'
|
||||
3 > 1 = 2 * 39
|
||||
1 > 3 > 2 * 38
|
||||
3 > 1 > 2 * 36
|
||||
3 > 2 > 1 * 29
|
||||
1 > 2 > 3 * 28
|
||||
2 > 1 > 3 * 15
|
||||
1 > 2 = 3 * 14
|
||||
2 > 3 > 1 * 9
|
||||
2 > 1 = 3 * 5
|
||||
EOD,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testA77_With_Explicit(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
|
||||
self::$tidemanA77->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(213, $election->countVotes());
|
||||
|
||||
self::assertSame(
|
||||
<<<'EOD'
|
||||
3 * 39
|
||||
1 > 3 * 38
|
||||
3 > 1 * 36
|
||||
3 > 2 * 29
|
||||
1 > 2 * 28
|
||||
2 > 1 * 15
|
||||
1 * 14
|
||||
2 > 3 * 9
|
||||
2 * 5
|
||||
EOD,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function testA1_ForCandidatesNames(): void
|
||||
{
|
||||
$election = (new DavidHillFormat(__DIR__.'/TidemanData/A1.HIL'))->setDataToAnElection();
|
||||
|
||||
self::assertSame(380, $election->countVotes());
|
||||
self::assertSame(3, $election->getNumberOfSeats());
|
||||
|
||||
self::assertSame(
|
||||
<<<'EOD'
|
||||
Candidate 3 > Candidate 1 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 13
|
||||
Candidate 1 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 9
|
||||
Candidate 1 > Candidate 3 > Candidate 9 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 9
|
||||
Candidate 2 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 6
|
||||
Candidate 1 > Candidate 5 > Candidate 8 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 5
|
||||
Candidate 1 > Candidate 3 > Candidate 9 > Candidate 7 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 4
|
||||
Candidate 1 > Candidate 8 > Candidate 4 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 4
|
||||
Candidate 1 > Candidate 9 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 4
|
||||
Candidate 3 > Candidate 6 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 9 = Candidate 10 * 4
|
||||
Candidate 4 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 4
|
||||
Candidate 7 > Candidate 9 > Candidate 3 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 4
|
||||
Candidate 9 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 4
|
||||
Candidate 9 > Candidate 8 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 4
|
||||
Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 3 > Candidate 2 > Candidate 7 > Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 3 > Candidate 4 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 4 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 4 > Candidate 9 > Candidate 3 > Candidate 8 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 5 > Candidate 9 > Candidate 2 > Candidate 7 > Candidate 10 > Candidate 3 = Candidate 4 = Candidate 6 = Candidate 8 * 3
|
||||
Candidate 1 > Candidate 7 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 8 > Candidate 4 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 9 > Candidate 5 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 3
|
||||
Candidate 2 > Candidate 4 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 3
|
||||
Candidate 2 > Candidate 9 > Candidate 7 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 3
|
||||
Candidate 3 > Candidate 1 > Candidate 9 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 3
|
||||
Candidate 7 > Candidate 9 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 3
|
||||
Candidate 9 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 3
|
||||
Candidate 1 > Candidate 3 > Candidate 2 > Candidate 7 > Candidate 9 > Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 1 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 1 > Candidate 7 > Candidate 9 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 1 > Candidate 9 > Candidate 8 > Candidate 2 > Candidate 3 > Candidate 7 > Candidate 4 > Candidate 10 > Candidate 5 = Candidate 6 * 2
|
||||
Candidate 1 > Candidate 10 > Candidate 9 > Candidate 2 > Candidate 3 > Candidate 4 > Candidate 5 > Candidate 6 > Candidate 7 > Candidate 8 * 2
|
||||
Candidate 2 > Candidate 3 > Candidate 9 > Candidate 10 > Candidate 8 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 * 2
|
||||
Candidate 2 > Candidate 7 > Candidate 8 > Candidate 9 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 2 > Candidate 7 > Candidate 9 > Candidate 8 > Candidate 10 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 * 2
|
||||
Candidate 2 > Candidate 8 > Candidate 7 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 2 > Candidate 8 > Candidate 7 > Candidate 9 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 2 > Candidate 9 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 2
|
||||
Candidate 4 > Candidate 1 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 4 > Candidate 3 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 4 > Candidate 9 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 6 > Candidate 7 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 6 > Candidate 7 > Candidate 8 > Candidate 9 > Candidate 1 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 10 * 2
|
||||
Candidate 7 > Candidate 1 > Candidate 3 > Candidate 9 > Candidate 8 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 1 > Candidate 3 > Candidate 4 > Candidate 2 > Candidate 5 > Candidate 10 > Candidate 9 > Candidate 7 > Candidate 6 * 2
|
||||
Candidate 8 > Candidate 1 > Candidate 7 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 1 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 * 2
|
||||
Candidate 8 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 2 > Candidate 1 > Candidate 3 > Candidate 4 > Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 2 > Candidate 6 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 2 > Candidate 7 > Candidate 9 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 3 > Candidate 1 > Candidate 6 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 9 = Candidate 10 * 2
|
||||
Candidate 8 > Candidate 3 > Candidate 1 > Candidate 6 > Candidate 9 > Candidate 7 > Candidate 10 > Candidate 2 = Candidate 4 = Candidate 5 * 2
|
||||
Candidate 9 > Candidate 1 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 2 > Candidate 7 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 4 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 4 > Candidate 3 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 4 > Candidate 3 > Candidate 1 > Candidate 7 > Candidate 8 > Candidate 6 > Candidate 2 > Candidate 10 > Candidate 5 * 2
|
||||
Candidate 9 > Candidate 7 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 8 > Candidate 3 > Candidate 6 > Candidate 7 > Candidate 2 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 8 > Candidate 4 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 2
|
||||
Candidate 9 > Candidate 10 > Candidate 2 > Candidate 3 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 2
|
||||
Candidate 10 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 2
|
||||
Candidate 10 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 2
|
||||
Candidate 10 > Candidate 6 > Candidate 1 > Candidate 8 > Candidate 3 > Candidate 5 > Candidate 2 = Candidate 4 = Candidate 7 = Candidate 9 * 2
|
||||
Candidate 10 > Candidate 9 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 * 2
|
||||
Candidate 1 > Candidate 2 > Candidate 3 > Candidate 7 > Candidate 8 > Candidate 9 > Candidate 5 > Candidate 6 > Candidate 10 > Candidate 4 * 1
|
||||
Candidate 1 > Candidate 2 > Candidate 4 > Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 2 > Candidate 4 > Candidate 3 > Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 2 > Candidate 4 > Candidate 5 > Candidate 8 > Candidate 10 > Candidate 3 = Candidate 6 = Candidate 7 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 2 > Candidate 5 > Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 4 > Candidate 8 > Candidate 6 > Candidate 5 > Candidate 7 > Candidate 9 > Candidate 10 > Candidate 2 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 4 > Candidate 9 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 4 > Candidate 9 > Candidate 5 > Candidate 6 > Candidate 10 > Candidate 2 > Candidate 8 > Candidate 7 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 5 > Candidate 2 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 5 > Candidate 9 > Candidate 2 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 6 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 7 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 7 > Candidate 8 > Candidate 10 > Candidate 9 > Candidate 2 > Candidate 6 > Candidate 4 > Candidate 5 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 7 > Candidate 9 > Candidate 2 > Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 8 > Candidate 4 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 8 > Candidate 9 > Candidate 10 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 9 > Candidate 8 > Candidate 4 > Candidate 2 > Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 3 > Candidate 9 > Candidate 10 > Candidate 7 > Candidate 8 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 3 > Candidate 6 > Candidate 8 > Candidate 5 > Candidate 2 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 3 > Candidate 6 > Candidate 10 > Candidate 2 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 5 > Candidate 8 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 5 > Candidate 9 > Candidate 8 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 8 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 8 > Candidate 7 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 9 > Candidate 10 > Candidate 6 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 4 > Candidate 10 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 5 > Candidate 4 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 5 > Candidate 4 > Candidate 9 > Candidate 2 > Candidate 3 > Candidate 7 > Candidate 6 > Candidate 8 > Candidate 10 * 1
|
||||
Candidate 1 > Candidate 6 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 6 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 7 > Candidate 9 > Candidate 6 > Candidate 2 > Candidate 3 > Candidate 4 = Candidate 5 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 7 > Candidate 9 > Candidate 8 > Candidate 3 > Candidate 4 > Candidate 6 > Candidate 10 > Candidate 5 > Candidate 2 * 1
|
||||
Candidate 1 > Candidate 7 > Candidate 9 > Candidate 8 > Candidate 6 > Candidate 3 > Candidate 2 > Candidate 10 > Candidate 4 > Candidate 5 * 1
|
||||
Candidate 1 > Candidate 8 > Candidate 3 > Candidate 4 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 8 > Candidate 3 > Candidate 9 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 8 > Candidate 6 > Candidate 4 > Candidate 2 > Candidate 3 > Candidate 5 > Candidate 10 > Candidate 9 > Candidate 7 * 1
|
||||
Candidate 1 > Candidate 8 > Candidate 9 > Candidate 3 > Candidate 4 > Candidate 2 > Candidate 6 > Candidate 5 > Candidate 7 > Candidate 10 * 1
|
||||
Candidate 1 > Candidate 8 > Candidate 9 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 2 > Candidate 4 > Candidate 8 > Candidate 10 > Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 4 > Candidate 3 > Candidate 8 > Candidate 10 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 4 > Candidate 7 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 7 > Candidate 4 > Candidate 5 > Candidate 2 > Candidate 10 > Candidate 8 > Candidate 6 > Candidate 3 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 7 > Candidate 6 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 8 > Candidate 3 > Candidate 10 > Candidate 2 > Candidate 4 > Candidate 5 > Candidate 6 > Candidate 7 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 4 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 4 > Candidate 7 > Candidate 3 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 4 > Candidate 8 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 9 > Candidate 10 > Candidate 8 > Candidate 4 > Candidate 3 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 1 > Candidate 10 > Candidate 3 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 10 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 1 > Candidate 10 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 10 > Candidate 9 > Candidate 2 > Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 1 > Candidate 10 > Candidate 9 > Candidate 4 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 2 > Candidate 3 > Candidate 1 > Candidate 4 > Candidate 9 > Candidate 10 > Candidate 8 > Candidate 5 > Candidate 6 > Candidate 7 * 1
|
||||
Candidate 2 > Candidate 3 > Candidate 9 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 4 > Candidate 9 > Candidate 7 > Candidate 3 > Candidate 8 > Candidate 10 > Candidate 6 > Candidate 1 > Candidate 5 * 1
|
||||
Candidate 2 > Candidate 5 > Candidate 3 > Candidate 1 > Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 7 > Candidate 9 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 8 > Candidate 9 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 8 > Candidate 9 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 8 > Candidate 10 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 * 1
|
||||
Candidate 2 > Candidate 9 > Candidate 1 > Candidate 10 > Candidate 4 > Candidate 3 > Candidate 8 > Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 2 > Candidate 9 > Candidate 7 > Candidate 4 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 2 > Candidate 9 > Candidate 7 > Candidate 8 > Candidate 6 > Candidate 10 > Candidate 5 > Candidate 4 > Candidate 3 > Candidate 1 * 1
|
||||
Candidate 3 > Candidate 1 > Candidate 2 > Candidate 4 > Candidate 5 > Candidate 6 > Candidate 7 > Candidate 8 > Candidate 9 > Candidate 10 * 1
|
||||
Candidate 3 > Candidate 1 > Candidate 5 > Candidate 2 > Candidate 4 > Candidate 7 > Candidate 6 > Candidate 9 > Candidate 8 > Candidate 10 * 1
|
||||
Candidate 3 > Candidate 1 > Candidate 6 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 1 > Candidate 8 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 4 > Candidate 1 > Candidate 9 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 4 > Candidate 5 > Candidate 8 > Candidate 10 > Candidate 1 > Candidate 2 > Candidate 9 > Candidate 6 > Candidate 7 * 1
|
||||
Candidate 3 > Candidate 4 > Candidate 9 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 4 > Candidate 10 > Candidate 1 > Candidate 6 > Candidate 2 > Candidate 5 > Candidate 8 > Candidate 9 > Candidate 7 * 1
|
||||
Candidate 3 > Candidate 5 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 7 > Candidate 1 > Candidate 5 > Candidate 2 = Candidate 4 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 8 > Candidate 2 > Candidate 7 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 9 > Candidate 1 > Candidate 8 > Candidate 7 > Candidate 5 > Candidate 4 > Candidate 2 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 3 > Candidate 9 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 1 > Candidate 3 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 1 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 2 > Candidate 7 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 3 > Candidate 1 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 3 > Candidate 1 > Candidate 2 > Candidate 9 > Candidate 10 > Candidate 8 > Candidate 6 > Candidate 7 > Candidate 5 * 1
|
||||
Candidate 4 > Candidate 3 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 3 > Candidate 8 > Candidate 1 > Candidate 10 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 * 1
|
||||
Candidate 4 > Candidate 3 > Candidate 8 > Candidate 9 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 5 > Candidate 1 > Candidate 8 > Candidate 9 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 4 > Candidate 5 > Candidate 7 > Candidate 10 > Candidate 1 > Candidate 2 > Candidate 8 > Candidate 3 = Candidate 6 = Candidate 9 * 1
|
||||
Candidate 4 > Candidate 5 > Candidate 8 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 5 > Candidate 9 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 7 > Candidate 10 > Candidate 3 > Candidate 8 > Candidate 1 > Candidate 2 > Candidate 6 > Candidate 5 > Candidate 9 * 1
|
||||
Candidate 4 > Candidate 8 > Candidate 1 > Candidate 3 > Candidate 5 > Candidate 6 > Candidate 10 > Candidate 2 > Candidate 9 > Candidate 7 * 1
|
||||
Candidate 4 > Candidate 9 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 9 > Candidate 2 > Candidate 7 > Candidate 3 > Candidate 5 > Candidate 10 > Candidate 6 > Candidate 1 > Candidate 8 * 1
|
||||
Candidate 4 > Candidate 9 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 4 > Candidate 10 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 4 > Candidate 10 > Candidate 3 > Candidate 1 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 4 > Candidate 10 > Candidate 5 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 4 > Candidate 10 > Candidate 9 > Candidate 3 > Candidate 1 > Candidate 2 > Candidate 5 > Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 5 > Candidate 8 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 5 > Candidate 10 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 6 > Candidate 3 > Candidate 4 > Candidate 1 > Candidate 2 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 6 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 6 > Candidate 7 > Candidate 4 > Candidate 10 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 6 > Candidate 8 > Candidate 9 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 6 > Candidate 9 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 6 > Candidate 9 > Candidate 10 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 * 1
|
||||
Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 1 > Candidate 8 > Candidate 9 > Candidate 10 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 * 1
|
||||
Candidate 7 > Candidate 1 > Candidate 9 > Candidate 4 > Candidate 3 > Candidate 8 > Candidate 10 > Candidate 2 = Candidate 5 = Candidate 6 * 1
|
||||
Candidate 7 > Candidate 2 > Candidate 6 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 2 > Candidate 9 > Candidate 6 > Candidate 8 > Candidate 3 > Candidate 10 > Candidate 5 > Candidate 1 > Candidate 4 * 1
|
||||
Candidate 7 > Candidate 2 > Candidate 9 > Candidate 8 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 2 > Candidate 9 > Candidate 8 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 3 > Candidate 4 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 4 > Candidate 1 > Candidate 2 > Candidate 3 > Candidate 5 > Candidate 6 > Candidate 8 > Candidate 9 > Candidate 10 * 1
|
||||
Candidate 7 > Candidate 4 > Candidate 2 > Candidate 9 > Candidate 8 > Candidate 1 > Candidate 3 > Candidate 6 > Candidate 10 > Candidate 5 * 1
|
||||
Candidate 7 > Candidate 6 > Candidate 9 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 8 > Candidate 3 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 9 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 9 > Candidate 6 > Candidate 8 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 10 * 1
|
||||
Candidate 7 > Candidate 10 > Candidate 1 > Candidate 4 > Candidate 3 > Candidate 8 > Candidate 9 > Candidate 2 = Candidate 5 = Candidate 6 * 1
|
||||
Candidate 8 > Candidate 1 > Candidate 5 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 1 > Candidate 9 > Candidate 4 > Candidate 3 > Candidate 2 > Candidate 10 > Candidate 5 > Candidate 6 > Candidate 7 * 1
|
||||
Candidate 8 > Candidate 2 > Candidate 7 > Candidate 3 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 4 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 7 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 9 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 7 > Candidate 9 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 7 > Candidate 9 > Candidate 10 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 * 1
|
||||
Candidate 8 > Candidate 9 > Candidate 1 > Candidate 2 > Candidate 7 > Candidate 4 > Candidate 3 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 9 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 8 > Candidate 10 > Candidate 3 > Candidate 1 > Candidate 2 > Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 9 * 1
|
||||
Candidate 8 > Candidate 10 > Candidate 7 > Candidate 6 > Candidate 9 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 * 1
|
||||
Candidate 8 > Candidate 10 > Candidate 9 > Candidate 7 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 * 1
|
||||
Candidate 9 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 1 > Candidate 3 > Candidate 4 > Candidate 7 > Candidate 10 > Candidate 8 > Candidate 6 > Candidate 2 > Candidate 5 * 1
|
||||
Candidate 9 > Candidate 1 > Candidate 4 > Candidate 3 > Candidate 7 > Candidate 8 > Candidate 2 > Candidate 10 > Candidate 6 > Candidate 5 * 1
|
||||
Candidate 9 > Candidate 1 > Candidate 7 > Candidate 3 > Candidate 8 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 1 > Candidate 8 > Candidate 3 > Candidate 4 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 2 > Candidate 7 > Candidate 3 > Candidate 4 > Candidate 5 > Candidate 6 > Candidate 8 > Candidate 1 > Candidate 10 * 1
|
||||
Candidate 9 > Candidate 2 > Candidate 7 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 2 > Candidate 7 > Candidate 8 > Candidate 3 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 2 > Candidate 7 > Candidate 8 > Candidate 6 > Candidate 10 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 * 1
|
||||
Candidate 9 > Candidate 2 > Candidate 10 > Candidate 6 > Candidate 5 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 9 > Candidate 3 > Candidate 1 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 3 > Candidate 4 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 4 > Candidate 1 > Candidate 2 > Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 4 > Candidate 8 > Candidate 1 > Candidate 2 > Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 4 > Candidate 8 > Candidate 1 > Candidate 3 > Candidate 7 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 6 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 6 > Candidate 7 > Candidate 2 > Candidate 3 > Candidate 4 > Candidate 5 > Candidate 1 > Candidate 8 > Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 2 > Candidate 1 > Candidate 5 > Candidate 3 = Candidate 4 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 2 > Candidate 6 > Candidate 8 > Candidate 4 > Candidate 1 = Candidate 3 = Candidate 5 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 2 > Candidate 10 > Candidate 3 > Candidate 1 > Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 3 > Candidate 1 > Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 7 > Candidate 10 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 3 > Candidate 7 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 4 > Candidate 1 > Candidate 3 > Candidate 10 > Candidate 2 = Candidate 5 = Candidate 6 = Candidate 7 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 6 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 7 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 6 > Candidate 3 > Candidate 2 > Candidate 7 > Candidate 10 > Candidate 1 > Candidate 4 > Candidate 5 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 7 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 7 > Candidate 2 > Candidate 1 > Candidate 10 > Candidate 3 > Candidate 4 > Candidate 6 > Candidate 5 * 1
|
||||
Candidate 9 > Candidate 8 > Candidate 7 > Candidate 2 > Candidate 3 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 10 * 1
|
||||
Candidate 9 > Candidate 10 > Candidate 2 > Candidate 6 > Candidate 7 > Candidate 8 > Candidate 4 > Candidate 5 > Candidate 1 > Candidate 3 * 1
|
||||
Candidate 9 > Candidate 10 > Candidate 7 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 * 1
|
||||
Candidate 9 > Candidate 10 > Candidate 7 > Candidate 4 > Candidate 1 > Candidate 2 > Candidate 6 > Candidate 3 > Candidate 5 > Candidate 8 * 1
|
||||
Candidate 10 > Candidate 1 > Candidate 3 > Candidate 4 > Candidate 2 > Candidate 5 > Candidate 6 > Candidate 9 > Candidate 8 > Candidate 7 * 1
|
||||
Candidate 10 > Candidate 1 > Candidate 9 > Candidate 2 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 10 > Candidate 3 > Candidate 5 > Candidate 1 = Candidate 2 = Candidate 4 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 10 > Candidate 4 > Candidate 1 = Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 10 > Candidate 4 > Candidate 1 > Candidate 2 = Candidate 3 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 = Candidate 9 * 1
|
||||
Candidate 10 > Candidate 4 > Candidate 1 > Candidate 9 > Candidate 5 > Candidate 3 > Candidate 2 > Candidate 6 > Candidate 7 > Candidate 8 * 1
|
||||
Candidate 10 > Candidate 4 > Candidate 9 > Candidate 1 > Candidate 3 > Candidate 2 > Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 10 > Candidate 7 > Candidate 8 > Candidate 4 > Candidate 5 > Candidate 1 > Candidate 2 > Candidate 9 > Candidate 6 > Candidate 3 * 1
|
||||
Candidate 10 > Candidate 9 > Candidate 2 > Candidate 1 = Candidate 3 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 7 = Candidate 8 * 1
|
||||
Candidate 10 > Candidate 9 > Candidate 4 > Candidate 8 > Candidate 6 > Candidate 3 > Candidate 1 = Candidate 2 = Candidate 5 = Candidate 7 * 1
|
||||
Candidate 10 > Candidate 9 > Candidate 7 > Candidate 3 > Candidate 2 > Candidate 1 = Candidate 4 = Candidate 5 = Candidate 6 = Candidate 8 * 1
|
||||
EOD,
|
||||
$election->getVotesListAsString()
|
||||
);
|
||||
|
||||
self::assertSame('Candidate 1 > Candidate 9 > Candidate 8', $election->getResult('STV')->getResultAsString());
|
||||
}
|
||||
|
||||
public function testBugDavidHillRandomOrderAndStatsRound(): void
|
||||
{
|
||||
$hil = new DavidHillFormat(__DIR__.'/TidemanData/A60.HIL');
|
||||
|
||||
self::assertEquals([0=>'1', 1=>'2', 2=>'3', 3=>'4', 4=>'5', 5=>'6'], $hil->candidates); # Candidates are object, AssertEquals compare __toString
|
||||
|
||||
$implicitElectionFromHill = $hil->setDataToAnElection();
|
||||
|
||||
// Without aggregate vote
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $implicitElectionFromHill, aggregateVotes: false));
|
||||
$implicitElectionFromCondorcetElection = (new CondorcetElectionFormat($file))->setDataToAnElection();
|
||||
|
||||
self::assertEquals($implicitElectionFromHill->getCandidatesListAsString(), $implicitElectionFromCondorcetElection->getCandidatesListAsString());
|
||||
|
||||
foreach (Condorcet::getAuthMethods() as $method) {
|
||||
// Stats
|
||||
self::assertSame($implicitElectionFromHill->getResult($method)->getStats(), $implicitElectionFromCondorcetElection->getResult($method)->getStats(), 'Method: '.$method);
|
||||
|
||||
// Result
|
||||
self::assertSame($implicitElectionFromHill->getResult($method)->getResultAsString(), $implicitElectionFromCondorcetElection->getResult($method)->getResultAsString(), 'Method: '.$method);
|
||||
}
|
||||
|
||||
|
||||
// With aggregate vote
|
||||
$file = new \SplTempFileObject;
|
||||
$file->fwrite(CondorcetElectionFormat::exportElectionToCondorcetElectionFormat(election: $implicitElectionFromHill, aggregateVotes: true));
|
||||
$implicitElectionFromCondorcetElection = (new CondorcetElectionFormat($file))->setDataToAnElection();
|
||||
|
||||
self::assertEquals($implicitElectionFromHill->getCandidatesListAsString(), $implicitElectionFromCondorcetElection->getCandidatesListAsString());
|
||||
|
||||
foreach (Condorcet::getAuthMethods() as $method) {
|
||||
// Stats
|
||||
self::assertEqualsWithDelta(
|
||||
$implicitElectionFromHill->getResult($method)->getStats(),
|
||||
$implicitElectionFromCondorcetElection->getResult($method)->getStats(),
|
||||
1 / (0.1 ** Condorcet::getMethodClass($method)::DECIMAL_PRECISION),
|
||||
'Method: '.$method
|
||||
);
|
||||
|
||||
// Result
|
||||
self::assertSame($implicitElectionFromHill->getResult($method)->getResultAsString(), $implicitElectionFromCondorcetElection->getResult($method)->getResultAsString(), 'Method: '.$method);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,445 @@
|
||||
|
||||
Tally Sheet for the votes cast.
|
||||
|
||||
The format is:
|
||||
"V: vote MD5SUM"
|
||||
You may locate the MD5SUM corresponding to a debian login ID,
|
||||
given the associated secret token returned with the ack,
|
||||
by simply running md5sum. Forexample, for login ID srivasta, and
|
||||
the secret token 0123456789ABCDE, the following invocation works:
|
||||
% echo "srivasta 0123456789ABCDE" | md5sum
|
||||
The vote block represents the ranking given to each of the
|
||||
candidates by the voter.
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
Option 1--------->: Jeroen van Wolffelaar
|
||||
/ Option 2-------->: Ari Pollak
|
||||
|/ Option 3------->: Steve McIntyre
|
||||
||/ Option 4------>: Anthony Towns
|
||||
|||/ Option 5----->: Andreas Schuldei
|
||||
||||/ Option 6---->: Jonathan aka Ted Walther
|
||||
|||||/ Option 7--->: Bill Allombert
|
||||
||||||/ Option 8-->: None of the Above
|
||||
|||||||/
|
||||
V: 57213846 1d7ba886e62a2cf64379a5c8f8032cc2
|
||||
V: 3-311-56 5983810b34693310479f3b26eda85177
|
||||
V: 16313857 1ccb15e79dc5734b217fb8e3fb296b9d
|
||||
V: 47125863 52b444e0fb8778d31d52efb6b6e88401
|
||||
V: 2-1----3 b2c77c75a0747fc1b6019ca54d76aa42
|
||||
V: -------1 21acf319d1a9185b36fa065c649ca1da
|
||||
V: --21---- 5778a0e6c4c15de35a92c85c66e1ecff
|
||||
V: 47321856 9b76679e424a887ccf80f506ab8ba81c
|
||||
V: 26145837 fdab256bb874774d3a67547f88f23ffc
|
||||
V: 1-423-5- b71d5f0a6e58b4e6ec2d81bce6160799
|
||||
V: 43516728 29a8468f09b317cea6b6c3defdccb513
|
||||
V: 38214756 b13ae01b3143d7287e099f3746e80211
|
||||
V: 4-123-4- 321ab097081bea5d4ee967f670fe9998
|
||||
V: 18234756 df985c5e22db36646fd9e6ceb594cefc
|
||||
V: --1----2 0ffef79d2a2f58928e677160ffa6eaaf
|
||||
V: 31323735 64fe866fc009aa01fddff32268b6d0fe
|
||||
V: 47134826 205d5eea98ef53d8fdc77c04a5a55a08
|
||||
V: 36124857 cc9da13d222a4e987f3dcc1286e86827
|
||||
V: 63472815 0c7f3ca5b9d12d159428aaa3c28b319c
|
||||
V: 36172845 38957e1d01d3bd1798f21d8ede7570f2
|
||||
V: 56314827 15251ab0ced1f920959a4fe6edcc4bc4
|
||||
V: 47135826 69b76a672ecc2038ff585f19129330dd
|
||||
V: --213--- 618ae0bdab9d6c79a9fdb01636c579b2
|
||||
V: 16432735 be3d804ecf4b6d120b05acf9a51410b5
|
||||
V: ----2--1 7aa0f0fb4f7c64ae913ab0e56066d4cd
|
||||
V: 17244826 25f689d866a88ee2a9759568fd3fe005
|
||||
V: 36213837 5cdaab4305428a8ca58a3cbfe59b95b3
|
||||
V: 48213756 06d4fb088c5f5ab2f64c18a34431b745
|
||||
V: 25331746 e365550e0d6b3b06e7ee847cadf96d76
|
||||
V: 68456837 def821da56979f9a5343e8794c7357ee
|
||||
V: --21---3 d5ec4a853775b7fa030c6b75145d03b3
|
||||
V: 45213867 215d5062f2fcf07a9d59c35dcdda3a0d
|
||||
V: 3-12---4 edb43166e6c262a6ac65d292187449d4
|
||||
V: 27413856 a0cb8268f78214afec42e6553ee02d2e
|
||||
V: 26314857 4ce63b670a52419f8049c5e8f48f2374
|
||||
V: 33313332 6a8df1962f5c4e3366670b09cf584e49
|
||||
V: 16341857 652d3d17e3f31a54c6cac6bccc7bc88f
|
||||
V: 12437746 0fdfbdf716e0ad87f34c8dc36f0dd787
|
||||
V: ------1- add8d5d6a42dd64dabda529e5f1164a1
|
||||
V: 35182764 34364576fff96cc923019d044992dc4f
|
||||
V: 25143867 572294825056c43dd29e7ceec5527807
|
||||
V: 37142856 a05bdb2c64d2cb6c815da770610dcf5a
|
||||
V: 26434415 1df47bf79ec9072715c1f02becca192a
|
||||
V: 17172776 6be1de6c656087ef4e3cddec0ca4f721
|
||||
V: 22111423 11c02dd825a181522f347b6f01f3d8cd
|
||||
V: 34313-45 5cac77e9526f23ce4a1a16abb26db617
|
||||
V: 17722877 8cab4abee238fa92f915cad6c207d015
|
||||
V: -1-2---3 8e7d53af5d79a4f02e3b953ddf6a90a7
|
||||
V: 2512143- 9b8e13faa9eee964c4d036d6d2026cd8
|
||||
V: 23222514 4da78e380dd0348cc23b08d202b06b07
|
||||
V: 35176824 04941b0b82c4ad0ecaa0bd3fabb99747
|
||||
V: 17245836 40436efc84e638cb88ed622cf391ac95
|
||||
V: 3-21465- c20db1801a0ce83d3a1708284fbf7d41
|
||||
V: 26143857 79da07c69774e5c02f4e965acfa12659
|
||||
V: 56125847 13466aa166e8bd33ecdd22225732b46f
|
||||
V: 37124856 6ef35eb5863c7622f262b63762b06785
|
||||
V: 35124876 51eebd2937a95059c8f412ec1f65d37a
|
||||
V: 34217888 64b30ef5c9727a7a5eb97188e853cce7
|
||||
V: 36214857 3486cec2aa47163e4c31cbfdd3cd8c18
|
||||
V: 32143615 4d559753e30e204760c1173e07bc12bc
|
||||
V: 47113865 b72b0c7346dfb180fe295b9c983b8e06
|
||||
V: 51426837 d0bfe4b03c6987e34cab3b1f88d38d68
|
||||
V: 35187624 11747aa6d4fbdd0bc1c502abd5cc0420
|
||||
V: 17365824 39c0873fb3ea788c2e784b7a59de432e
|
||||
V: 27314756 6c0e7bb7ed471b66889ae35209a0f65c
|
||||
V: -------1 2fcb54e96e72615d584d25a764bb5bdf
|
||||
V: 57241836 a59dd95cdf8f9320fb4316a0bd302b12
|
||||
V: 16235874 bcf0c7f540325d0565c55d2bc46e7d00
|
||||
V: 57463841 c7f910e0cdc01d325af5b4250154829a
|
||||
V: 33351432 0c2c1c6a578b0d200e4043e51db02810
|
||||
V: --21---- 2e7d77538990c1e31d13b741940a4d02
|
||||
V: 53412756 943d20eb0ed12484d06d2d021b7d459f
|
||||
V: 84516732 f658fcba86c86801db4ad3ea978b7761
|
||||
V: 62417853 d8ec1af3f585b8406f61540f0e66d04c
|
||||
V: 67854123 f5e5faa5d9b53a8dab2adcdc0986e179
|
||||
V: 13131312 94d43e38f7c76a6d5524d247a2f45656
|
||||
V: 52466813 348339ee1016d2f9411784048cba11f9
|
||||
V: 36214857 9885e78df0246087d547089844cc9e8a
|
||||
V: 1--12--- dd6b581b2a8f63cdd34653d489356195
|
||||
V: --213--- 0ae4501dc5ce4048066354d5c3d4af7d
|
||||
V: 18321854 69edd0c955e9bc8fa84ac20a77e20e20
|
||||
V: -1-23-4- 262face2bb4273375e9fd76c6a2509e5
|
||||
V: 38214627 1b3a3bdbd0a179980483e416e0795baa
|
||||
V: --2---13 46bc6540158fc0daec9c70cf5bd82d84
|
||||
V: 17263845 f176ab1b4ae7b5e58dac00e245e03d48
|
||||
V: 13212534 bbe25dc3ce2685837c519f081ea64b2f
|
||||
V: 25413768 c8a8f8868387fe1c329d3ae032db683f
|
||||
V: 16323837 c1f1fe56c798749ee68b66cbefe622fe
|
||||
V: ------1- f243ecb479123642450e3dbda3206fbf
|
||||
V: 36217854 fd6d9b3830630169e825007f13ebe8bf
|
||||
V: 1312243- d981046fdf12bc06d3323f4818b4ecf8
|
||||
V: 56123748 526319ee2e62ce669f3c423d19db5253
|
||||
V: ----1--2 b612cf7fa381d20e570a6ffe96c69c1f
|
||||
V: 36215847 ce1ce9b1c098572142b1e14267f7119d
|
||||
V: 63571824 2b78c2b02dd6ef88c3cbf08bf34b6ba9
|
||||
V: --213--4 2e6cf5d0919e44bab5da343986d4bdaa
|
||||
V: 47312658 84ae6893f6d9ac51da736a8fd218d5ee
|
||||
V: 68324751 89cdcd02e654e8a01c3bc22339b25c2a
|
||||
V: 18327564 203b053779120f7f124741e55d4b6b29
|
||||
V: 27145863 9b780b86648711a1a6c88ed6062ebe58
|
||||
V: 27222816 2c8f95554a9870c50b5cf3efb76ce7d7
|
||||
V: 35231654 ffd9b278ed3fc7fa8c4035f36b37bb6a
|
||||
V: 53764812 930472fe08a877860f3bd36f9732866d
|
||||
V: 76281543 a47a0563c7c4bc859513d9ec77b0984c
|
||||
V: --31--24 34d620519358d03577e5f4ecfa085193
|
||||
V: 1--23--- 89273c0a7ef50e10c75bac6225f3bca5
|
||||
V: 36214758 7d7a168f75df077736c4c8b5b16bbf8a
|
||||
V: ---1--23 0566a2deea82f48a34909f42ae9c1d2f
|
||||
V: 37241856 bd91b538b63952989e69a4e741d267f3
|
||||
V: 37862415 141aa11e71c9d7f13fd8581d6d121683
|
||||
V: 35126847 87cd81732ba07d494b1ad21c416e3c53
|
||||
V: 66555847 fed9917aad1b843920ab9e0fb6a76432
|
||||
V: -------1 a0d57e402df787ea900f5eeece60f3e8
|
||||
V: 56283817 699d933ac9270b5c0899393464e23445
|
||||
V: ---21--3 a92e12939d92e230cc4dcd7ac3b7500f
|
||||
V: ----1--2 393df9cd1a4acd036136e1fc18a0c202
|
||||
V: 47213856 1b3e06fed30a0d10951c3bd6e23e684b
|
||||
V: 27314865 075af50b08f18d3fe215f462a8c40186
|
||||
V: 23212423 443fd55c64badfef00ebfda88060560c
|
||||
V: 2-15---- bb4f3af2fab5aebe4040ca0b744d8bc6
|
||||
V: --1---23 93326e4606370bcce0447aa5ce18ba26
|
||||
V: 14325867 2e2226b7b3b0149cb44cc35b8197240c
|
||||
V: 48213756 75859a51ce1826198d24cd3ff31e3405
|
||||
V: 54137826 7ebf1d0373d3e34891dfcc755b965b10
|
||||
V: 57123846 13bb5bb80516771d4ae60dd1a16124bb
|
||||
V: 3-2-4-15 340999c0ec581eddc1d6acba03f969a4
|
||||
V: 1-121-2- b6952712bcfc67e75d9c782d96843e07
|
||||
V: 54312678 58e6eeed6d3a00cb716cc87b7db3cbfb
|
||||
V: 56281743 ba1699941ee575f6e854e62ec5007945
|
||||
V: 3651246- 290a2e2c02659c0ec9ab08a2d228bd50
|
||||
V: ---1---2 de1f95854235d0483efc9ba459e2d155
|
||||
V: 47214836 74898729967bb36fd06baa6c5dbbf901
|
||||
V: 37214856 c92e606be125ec4d1d5348223c021933
|
||||
V: 35271846 481a1776d8ec86ec99298e18464ae19d
|
||||
V: 47235816 66956aa6b91cc91bbce99a525643a438
|
||||
V: 26143857 d4ca50a32d95adcbe73d15b846e5a63a
|
||||
V: 36512847 774848bf48af2111487fb965a3be58d6
|
||||
V: 12576834 2551e91a8e7668cbb0f482ccc10f32ed
|
||||
V: 57214836 a0f24ccf79099b4bac8832749743f2be
|
||||
V: 47123658 4d0c9446881c4754e30bc6b3bb3fad0b
|
||||
V: 46132857 d0d775364c3a7da51432c79ec8387bf1
|
||||
V: 35512554 b64c8d26c985b4703b63f55221828d2e
|
||||
V: 75261843 3eaba62f35ffa84dfe02ed2e90370ba3
|
||||
V: 4-123-56 71255bd645f2f58654624ead16febd52
|
||||
V: 3651364- eb77b4378a3ffb30e767d6e6f0b41509
|
||||
V: 17235846 04c2bd919aabbc157d74dda7e91b6bdd
|
||||
V: 37125846 00711d1fbb56afd0595c77ff5dcfd988
|
||||
V: 17245836 4a12429299445d2bf6fd5436910f75f5
|
||||
V: 34172856 37af528b7e9a225e32477d730bdcfe59
|
||||
V: 45212867 587fa0665ae596a95d7ece13e2ce22cc
|
||||
V: 1--32--4 3d51934b51002a07f91417cf34d2c554
|
||||
V: 56314827 0f761b0ce435d6ce62d64b3e22aba016
|
||||
V: 1------2 16c3c50d7d6b5328531543a784d54aae
|
||||
V: 37124856 7cef1bfed93d560db0f7e586c036d63e
|
||||
V: 36214758 9bc3d5b8ab15177cf1faacda4dd2f426
|
||||
V: 47312865 fed32a2c4312d80a1435f0c87413d924
|
||||
V: 34213645 f1475c21940d4e495f12a3627d81c640
|
||||
V: --2-1--- 8612593f5f075ad538bebb8165af866f
|
||||
V: 47123856 0c3e2026ceeaf3bb82ecc8b83f1b5441
|
||||
V: 36415872 684beceb9005f15e19ed8c95a6af19f8
|
||||
V: 27154836 622a15b70c1d7ea1e7025072a2a7e2cd
|
||||
V: 14121113 561b5f127729b6e0e562218fbb540e37
|
||||
V: 2---1--- 354690c06e2ee7233cdcd8cab7dbcef0
|
||||
V: 4351267- 0efe4848150319dfe4b4524d9f35dd74
|
||||
V: 3----2-- aab4b685acc5e43beb6f8d98169a10f2
|
||||
V: 65173842 1ae6b329601fbff1b14a8b51f0729238
|
||||
V: 25361-74 722e6a02a32db6af4d96f2d5d78b5c10
|
||||
V: 36174258 9572bca2548943135baf0cebea660970
|
||||
V: 21222827 d4d735f042dec1bd930e08049675cba6
|
||||
V: 18234756 d993813864820064f475cde6cff78bb0
|
||||
V: 1--32--4 4dfad67ff5f70d006506079f9cda1498
|
||||
V: 24121513 b2a922593853e7dde04ec157b5eb2a22
|
||||
V: 3714265- 505ad37f22f3aeacb75e1c80ad4e98a2
|
||||
V: 18311876 3f34c5e7b1f8aea7c21ff1d9791dea70
|
||||
V: 58261734 9eafa3d8c4420ad1128cb4f092e85d0d
|
||||
V: -------1 5fd942211bf7a1bc00e25baedd68337d
|
||||
V: 2-1-3--4 1d970b99347c3280a291c795349be841
|
||||
V: 32313534 551853e032d3af216766cf5ce628b048
|
||||
V: 33313332 af6f53e4eecb7025fc1a2aaf56bbc8ea
|
||||
V: 47213856 6b5b8478d87ea4cccb5d8bb47598c7fc
|
||||
V: 76372851 e9c7cbd222a7208679e79883f086c980
|
||||
V: 67435812 77f7d77ae0c49c073bd10ca29972341f
|
||||
V: 2634175- 2dde0c5c869860ab65fbf9a1989a4fae
|
||||
V: 15342746 04d00c5ac8f72303e41ce4aed80031de
|
||||
V: 77182883 e51f673ed77a5eeb528ca6fcf9d8ccf6
|
||||
V: ---12-3- 3e634a2cd14108e31728ec7297633408
|
||||
V: 1111111- a2ddcdf092cf246bb6eebb19d49b735d
|
||||
V: 28211756 7fcb58961f970342e55ada51e4ecdf3f
|
||||
V: 26315748 5e3ec904295fbd5630c752f0de8cd691
|
||||
V: 22222321 da73a4f7b6d4a13ce0c3d05588bb236a
|
||||
V: 3--21--- 606507e3764d93396765c376d9da1742
|
||||
V: 45263718 383bf17a69d06d7a5a21f54aac301802
|
||||
V: 46132857 e23ca002e58c630692b28dffa1ca297a
|
||||
V: 56214837 20069e176e4483f8da1e51a0b6123867
|
||||
V: 21233837 e414567128a8f008ab77e198e1cc3f29
|
||||
V: 3--1-2-- 02330a44c97af838a81d6292573b4eda
|
||||
V: 47312756 c8c545e83d619d2114c0fbccd7b2958d
|
||||
V: 16243857 81a34863eddb1ace447f03e0ee8c5ed5
|
||||
V: 3321142- 471075a14f0204d43966bc7ed1836380
|
||||
V: 27124856 1f090b828641f58f23077ed9e63dfb9a
|
||||
V: 15252436 cdcce2c16bb4f2c65e021adf8189ca54
|
||||
V: 13542756 c282080f91976a8fe8705e95304dbaae
|
||||
V: 24316857 6f3d994c2b76ad7a3394bc780d7773f9
|
||||
V: 46315827 1a6ce57f379a856ae765619df2d11c9e
|
||||
V: 16213754 bb36796a34d9d3018d43c00f5521877b
|
||||
V: 43412546 8710ae17f79d0f7ca6f5867d6aa5cf1b
|
||||
V: 14121413 76f747f526e28529b540f767b3d7ae86
|
||||
V: 37122856 181472faa895b41286461d7547d71b66
|
||||
V: 3---1-2- a8d023d434d82734f3a5a80d04a1940c
|
||||
V: 46132785 36b8cae2b98fc3db9eaf959f44311cad
|
||||
V: 45123716 5f9a087e69c3bc94d0aaa7346dfa4785
|
||||
V: 57218634 1a1a17ae3c0c5e477cc7bb9a49460610
|
||||
V: 2-134--- a43c376a51775634062ca0d3e6fb94ea
|
||||
V: 25553514 260e30bedea0c52b1bbb0a2815e6816d
|
||||
V: 32313534 b91f1cd1a266f0b83a19773de41a57b2
|
||||
V: --34321- ba73f9b8cd0b382e601b0af0628ef9c7
|
||||
V: 45132768 a533eb573a0c666ebeaa75520fd8a0ad
|
||||
V: 13211423 85447b4a780d6cb76155430f94ba2fc3
|
||||
V: 12232827 cea1a6ed78c00e4f6766f26d5680bc0b
|
||||
V: 37114865 521f0599b9293761a8c6d5c4c9331b27
|
||||
V: 17243856 dc2f98656a8658910368c59f0dd29d64
|
||||
V: 2-314--- 73f124f4951b7fa4be929348f4f69893
|
||||
V: 2---1-3- a4f78f197aebe3725b28ad6cd81ee791
|
||||
V: 27354861 833ec1a121582f4862b3918f3c217648
|
||||
V: 3542155- 28ca97fcaa707b3da1fdbc9ff16e9dd9
|
||||
V: 27314856 551578fff90d4efa1a448ae18662b966
|
||||
V: 58213647 ee72bed75ddee0ab99928a1ec84be049
|
||||
V: 37213845 7ecd14e14664e97b71ed6fd6ae9e3289
|
||||
V: --13---- 91fdfe530a9b91bb007556beb10bff1f
|
||||
V: 3-213--- 68565639059e4fc6b990d804f9233fa5
|
||||
V: -412--35 b97c6eede494b947bb16ccb17ceeb69b
|
||||
V: 16342857 06d98fd115fe376920e2d2ac512aa2ca
|
||||
V: --111--- 8a82b70816aaad1d467758c5812d58ef
|
||||
V: 15132645 66848b8170c2db2f2abe6b25d1e5c9c0
|
||||
V: --12---- 3f065a7957d7f390a3e061b7900c6f96
|
||||
V: 25783812 29cfdb2a407276bfbe3b15b376c3011e
|
||||
V: 4-352-16 d2660f925cdf7652cd288a335c36c087
|
||||
V: 46135827 f682962b778365ed60bb1c5689922ddc
|
||||
V: 18243657 baaa4948103cdcfd22a35bab497498c8
|
||||
V: 35426817 ab8689d544892cd98a8934d8177071e0
|
||||
V: 37213546 1efbf206b794d5fb465fb09e03963969
|
||||
V: 48617352 3aaeacf14b78212fc8fa472c8f4cf291
|
||||
V: 46125837 df78f6e49831939364f72a3b240b9445
|
||||
V: 27163845 0b0b628b347f4e8b1eacb899b3af83c8
|
||||
V: 46123857 b4b1a3fbd7496fec1aec1b05d975ce4e
|
||||
V: 16432857 267a89c4fb685ae9469a29d520501c9e
|
||||
V: 2-321--- de972272af8ce405a6d182a9fd720bed
|
||||
V: 36412-57 38bc1b80864acc40b59a5f3a87693a82
|
||||
V: 67241538 8509328895c9bcbcb30aaf4d77caf046
|
||||
V: 26241-35 f2a9a4977ed875007ebd63fdbbdf9c16
|
||||
V: 1642735- 2bdd09c10af28c9a7db48531e5055746
|
||||
V: 2---1-3- bc60c46c4d479dd14d2cc82aeb76ae47
|
||||
V: 58162347 f5751d54419ec48b51a3aa539c2a06f2
|
||||
V: 26431758 48e4faceb12114a34875fb10c515c822
|
||||
V: 44321325 b5e89830a69176124166c80f0b73d943
|
||||
V: 46531827 2fa36fb883943603b77ef6bf7134650a
|
||||
V: 2-31---- edbce0a99d07f4a9fb0cc89c5a721adf
|
||||
V: 46413827 e62a26583df4a6e9cf8327504ee1c440
|
||||
V: 64312758 0af4d0d55a6e24603b8cc2c6d171e3d8
|
||||
V: 46321857 beb78a9a14abd6efcf872f3d3eb2595a
|
||||
V: 25333614 e40a9c140998105c697a3ffc81b2b18e
|
||||
V: 47213856 47a15efec113b8dbcd8ea622e8ec3aa7
|
||||
V: 2222122- b01b57e2760c298b03c10098b8667bf7
|
||||
V: 34412645 c0214391f78a07db85d9a510b3088a12
|
||||
V: ---1---2 b62553d8cda24607d9dbe18d2e796636
|
||||
V: 37251846 f3ff3af00d333aa9fd7984a25ea0ea4a
|
||||
V: 37241856 ef27166a1513ed44afa951b0d6aad90b
|
||||
V: 4731286- c86ee3b3bf804b13420b7114d04ffd83
|
||||
V: ---1---- d89199800cbeefe076ea5e42d0d6338e
|
||||
V: --32--1- a5689afcb25e65fe5558cb0f5f22699d
|
||||
V: 54612738 b63567bab3d8fd1d73f39085391ac1c7
|
||||
V: 15221634 7f27ce42b144eae453bb61a6679623b1
|
||||
V: 4-124-35 9046bb5a0c4fed095c518dd8ea647cea
|
||||
V: ---12435 7cb8db4791e5c0b553d0da00e8184616
|
||||
V: 36245817 89480e5e36bc818d11ad4da244c3c805
|
||||
V: 57143628 3081e523fa72f996c616dd249737d60d
|
||||
V: 37241756 800a4c20e9e64739289bf4e806378988
|
||||
V: 11111817 039cfc7b5204fa3bbc8ed947957b277d
|
||||
V: 2713477- d951b48292a445b1e19c1c3d167b7c78
|
||||
V: 7718287- 6444ff6d1f40b53c4cae53de0439bb92
|
||||
V: ---1---- a367913ddf67262c843a076f1ec663a8
|
||||
V: 34313334 08a9efef2a901bfa6d1cf0ece23943fb
|
||||
V: ---1---- 18c3d5e7bce1aa7fd7e660db6e252bcd
|
||||
V: 1------- 1b1aa1f2cc3e5f80232808ec00291fc7
|
||||
V: 31264876 555b6a094b7aa7955193ed50b8871719
|
||||
V: 26621668 114f8d914a5df96a3ae6689301f6af20
|
||||
V: 4-3125-6 3e022fc2787ac2bb6d663bc94c27cf0e
|
||||
V: 57216843 0cfe14ad878eff2ab4614834bb9fd5c7
|
||||
V: 85237416 9828017e89e92b41ee082bb845663625
|
||||
V: 12111413 7b431d7d3418db13aa16e20da8a417fe
|
||||
V: 45683712 ab0ecb700d02967f06c555fe36ecd42c
|
||||
V: 56217834 cd4deb457556d9f90f4c8d19ab91f880
|
||||
V: --213--4 9e8ccce13ca29b67e0e2f7d4a5313444
|
||||
V: --13---4 b20a8c621150cb660bf724d9e655aaff
|
||||
V: 15324-55 9e9268214073491f5471592b8d289cf2
|
||||
V: 37141856 2a0ca8001e353f88c40571d996f32bb3
|
||||
V: 53214867 c830ac007ae86215f5e3e421f8b05c8c
|
||||
V: 25313534 9e0616daa64466947d9a786dc367e397
|
||||
V: 22221223 15ac14e7afb0425ca30b3594ec2e6d81
|
||||
V: 15312-48 9f7562106c9e7aca42589dceff287c0c
|
||||
V: 14212845 880fcfe863faa4ce8dd22bb97387351f
|
||||
V: 143-2--5 d8074543780301c50b56615e7007e6c9
|
||||
V: 26456731 bc5d66627de5e5fa2c3f22483fbd9ae0
|
||||
V: 26145837 9b4d5196c5861f43f84eb5a90d386732
|
||||
V: 3-21---- 6392474f4a775a992cb2506ed288ab40
|
||||
V: --12--3- 5cdf7d656bca6562e10328de20f0ed69
|
||||
V: 3-123--- b27d3f0640a314d33bc6ad346b98b0e4
|
||||
V: 1-3-2--4 411f9f37f6f24b3c7b673f3648aeaacf
|
||||
V: 45673812 32a2ff36efed47b5f45498c8acbb21d2
|
||||
V: 24134815 df5cc376c3ecba2825adc9947f20757a
|
||||
V: 14231-35 80209162b8c7b1ba2ad71877e8d51153
|
||||
V: 14122434 9ffe0ca817cb02a9eaabebe53e824b4f
|
||||
V: 45431642 56bce963ba4cd5f28860358950998828
|
||||
V: 25153554 cc3185d62934d4bd50e6edd9754b37c3
|
||||
V: 23845716 fa1b8ba74186465d36c7e7434c5784f5
|
||||
V: 37261854 e2326f5bd39399b9d28eb7be7d1823a7
|
||||
V: ---12--- 2121b9021124043d7349c32e2f858d22
|
||||
V: 68215734 fa16b6b9af98e29380a86a6fedcf0f00
|
||||
V: 15221634 33abe04e778991d8de766861d39324d5
|
||||
V: 84158263 c71db3061b853baeb3f9b6ad5e4fb4d3
|
||||
V: 37215864 240a1d5f7fc9227051d43d7f642bfc32
|
||||
V: 23865714 cdde362f02085d20f8912b6dec5470ed
|
||||
V: 25112-34 b49af1186dbb0b248b8212e54b570f89
|
||||
V: 47412857 aa1333bb4777ab1561aa462433af27a1
|
||||
V: 48344836 aaa073ff487e6fa9f2cde048a420d1ed
|
||||
V: 33213534 080b246a2cb565fe85393ddf1830ad79
|
||||
V: 28612617 1a307458ea414869b8e6d2a056f7819b
|
||||
V: 57314682 fcef91d6f8104aba23e9033fa5a2e7a9
|
||||
V: 24146827 14be0f2cf36f0f77f921234203fe51d9
|
||||
V: 35164827 85c37d57cee1b7f9e31fdc1e34024b99
|
||||
V: 2--1---- 59d43bd00cc40321e33f961d34403d73
|
||||
V: 26312745 ea5c635a481beb24051676e2d426935d
|
||||
V: 36124758 09d4bb9d0ace04fd0a9e67dbdc980a81
|
||||
V: --12---- 555df6c79e30b20a85b258744015a460
|
||||
V: --1----- 664aaae907754c218eac78449302f107
|
||||
V: 25241857 d789918d625bdc8ae57a87f0705620ed
|
||||
V: 23312867 d7d14ed77eabdba10e897fbaf2508e70
|
||||
V: 48125763 d6e4dcdfcfd41c24c1de5b894c9702d7
|
||||
V: 64125837 1abd54f13f8097d2a939e213e859600c
|
||||
V: 27341856 dd25c2f04bd766b0427e3de9ba9a6e95
|
||||
V: 48213657 28de4db63bb2206140a978135ffe3d61
|
||||
V: 33232534 20487b8523ed033494835b1c09ebf88c
|
||||
V: 1-234-56 f7c3b8576bc0f154a8f22b148bee01e6
|
||||
V: 46325871 893ec7e08d3f0a4b55b9e5af1c018571
|
||||
V: 88224416 142ef6f2613c2c7a4c9f65f51f274f22
|
||||
V: 76354812 e992b4e6302811b0dacc8289bb937da8
|
||||
V: 15126734 1af31da3d1e8c52683b8bbb1454d0602
|
||||
V: 77521876 61a4382c2834aeb1b8de6db72539a121
|
||||
V: 13122534 c337202ec1ddd673ad1d71a41fffe614
|
||||
V: --12---3 acf1a7f99572aeca10950b8f4ee88bc2
|
||||
V: 35213524 88e1f5b9709fa6f5c2080ad5da7f87df
|
||||
V: 37124658 0172f801214d54119c7320e04cb59ad7
|
||||
V: -------1 b2d836dc52f53c12697de54978316b00
|
||||
V: 35212634 5fef8b71aa06f647c9a52a7ead8bbfce
|
||||
V: ---1---- 319f2f745f8282276b6a2af328eeffda
|
||||
V: 37421856 f9579c15d964b1a777aed3162173866f
|
||||
V: -------1 c23ba38e315a59cfd72d02a8276989de
|
||||
V: 28341756 039d5c78c555881a2db18baad15f6086
|
||||
V: --4213-- 74c86a247f9a38a56fb06204b4da00b1
|
||||
V: 35214867 a661b740a120439c99dab3592bd05dcc
|
||||
V: 34312333 ef39e11380318138a04cde2f0b0577b8
|
||||
V: --123--- 13408a29aa3f41d950ced5fa5e89a307
|
||||
V: 15238478 7eb1177e865f30c3f9a72a4a9f722d03
|
||||
V: 47123658 7dd94fc57a410a4d1c874cbb185f4b4f
|
||||
V: 48321675 0b7ba5275881a9304c9616f9d7174095
|
||||
V: 46382715 8ae29c87282779a1ff916ef08cfd85bd
|
||||
V: 37214-56 dcfbc0e94ee6f3e1a32ede7176501b64
|
||||
V: 27135846 99c1e35449f51f788bfbf950d5261ceb
|
||||
V: 24113635 a8ae3bffdd433278f62ac6ad06daa43f
|
||||
V: 15223534 9a3e83ef7a2582aa568c341e68823554
|
||||
V: 55334518 e0b11ad010d1d899e1f4a2c0b78cb5a1
|
||||
V: 28415736 aab8a4cf861fd4849b53eb06e100b165
|
||||
V: ---1-3-2 23ce463064353d726caea161a0abc3e4
|
||||
V: 2-431--- 04acdb573b3b20aa0746a6b0b499bd89
|
||||
V: 67152834 45757642be8c7fe6b2c99dc3433af51c
|
||||
V: 57214736 dd71fe62536a3125f7e1a8c33fedcd81
|
||||
V: 26315-47 fc636c8e3c7845d365814f3b69ea2fb1
|
||||
V: 45126837 bb79a341d25da6da950b6a7da21ee856
|
||||
V: 3-123-45 8e8b4a402102c9ce44033364e4b33322
|
||||
V: 36213745 9df7140f924e1aba6d7022604a60db5c
|
||||
V: 2513474- e79947e2ef56bbc2e402589447c016f2
|
||||
V: 76275854 9bfc20fbf724f484d785f413124458d7
|
||||
V: 83712645 a7137d5e63595dc3abd876e227bd3d74
|
||||
V: 56124837 ee28b414256ed28d559c699519d0bdab
|
||||
V: 16234758 dbc3b2ae38b6586b001983934b6a1dc8
|
||||
V: 2311232- 0b47129f951218caf8b1bf35f1fd0cc9
|
||||
V: 46123857 57d7997f3990f03a8d15d5192ca81830
|
||||
V: 35134726 d549175168c301e2c826ac5c00b45c3e
|
||||
V: 57216834 9b8898579f751d6abfbc9b4b591b914f
|
||||
V: 16324857 01299188960b4b3239a0cad2d4c42c5e
|
||||
V: 25134867 174c2e9763e3269e5f62119e56671c30
|
||||
V: 17252846 286076c0ce373a2037e3d4fb50f3f2da
|
||||
V: 57324816 e28c6ab23da73f62876fad302d2f5950
|
||||
V: 54312876 0bb9a47e90f076aa0242d26857cf733c
|
||||
V: 54125736 a77e6c989eb7a4c4d5b19fedcef8705e
|
||||
V: 22123856 8e7dd62b11322a6e742b2bbe8f2ef16d
|
||||
V: 35213634 95e58cd7c48aea7e1a0cbab5c9ca608b
|
||||
V: 36123745 d292ee2b1542abec738eaea6a7c35f51
|
||||
V: 2-21--43 6bc4bed870490203fe2def3874706a8c
|
||||
V: 76312845 84c82862270ca5c33895c5a7edd0fba1
|
||||
V: 38158824 f9ded889c2208134f80b6f3ad150738f
|
||||
V: --123--4 2fa85770cdc7a7e320f2fdc20b93e5b9
|
||||
V: 42444413 e3adcc29425fcbc749d7731ac264d691
|
||||
V: 2-31--45 fcdf69793004c8b7a09b6f0be12d53c4
|
||||
V: 14231634 30863ace9b616d8a4a697e9a029df9a4
|
||||
V: 57314826 8dd85a4c80afca93265d58cf1b37758d
|
||||
V: 35176824 3dafd70470d24f4249c7da00b6301317
|
||||
V: 2222122- 62d875af374ae6b616b439767b517f79
|
||||
V: 3-22132- 931d0912646dae05376667f24d2d5b10
|
||||
V: 8812288- 1641b004e994796ee4667fa8b8b2c4a1
|
||||
V: ---1-32- e3e90e7d278a0399b0c2668dae4abeb3
|
||||
V: 14523--6 c613606c0e07b2900ad7d0532228e1a7
|
||||
V: 67341852 2e46d7dbdd4a0e31fecfd9d26d97a836
|
||||
V: 23211423 d5ea3a2298070dd799f20a00ce8febed
|
||||
V: 23417865 d2d1a54dba89b27b56559a2ab3e2ba80
|
||||
V: 28314675 d13925332cc5d4ada191a5df1ea404db
|
||||
V: 17243658 191ed8bf19c5cb6d6871d7782eced295
|
||||
V: 2-31---- f504e2dd66052cd618b2619f21afd3f6
|
||||
V: 26114735 aead9fe58962a052073c3eba978ce3e0
|
||||
V: 27134865 d4a556f9a1d5712704424e39c69bd139
|
||||
V: 3--1-2-- 47c90820c612b4b9288405afa3ec8dfa
|
@ -0,0 +1,507 @@
|
||||
|
||||
Tally Sheet for the votes cast.
|
||||
|
||||
The format is:
|
||||
"V: vote MD5SUM"
|
||||
You may locate the MD5SUM corresponding to a debian login ID,
|
||||
given the associated secret token returned with the ack,
|
||||
by simply running md5sum. Forexample, for login ID srivasta, and
|
||||
the secret token 0123456789ABCDE, the following invocation works:
|
||||
% echo "srivasta 0123456789ABCDE" | md5sum
|
||||
The vote block represents the ranking given to each of the
|
||||
candidates by the voter.
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
Option 1---------->: Wouter Verhelst
|
||||
/ Option 2--------->: Aigars Mahinovs
|
||||
|/ Option 3-------->: Gustavo Franco
|
||||
||/ Option 4------->: Sam Hocevar
|
||||
|||/ Option 5------>: Steve McIntyre
|
||||
||||/ Option 6----->: Rapha<68>l Hertzog
|
||||
|||||/ Option 7---->: Anthony Towns
|
||||
||||||/ Option 8--->: Simon Richter
|
||||
|||||||/ Option 9-->: None Of The Above
|
||||
||||||||/
|
||||
V: 111111312 5de2d9bdec162e7ad7d475f7a3a912e0
|
||||
V: 296153487 82779753e0665892a0168183b4d03db6
|
||||
V: 222142443 8fc3f20b27697bbc84c5d14782ce29cb
|
||||
V: ---321--- 85a74c0916cb5df9b7c33fa49230ce73
|
||||
V: ----21--- ec0aeebf04b664751df5a3113cdba64b
|
||||
V: ---31-245 3bc131481a5f0ac8d07748b93e275f0c
|
||||
V: 344412645 4e58d78db380234727c3170416c9720d
|
||||
V: 392156478 737552a1b770c84bf44b12990d0344fc
|
||||
V: 72135648- 5b6ecb7d1eff7fd31097659d49f7f9e7
|
||||
V: 263754189 0b946ed4c6fb3f3751e0886822eb7871
|
||||
V: 16421553- c6fa84467050016ffaf55542b74fbb8b
|
||||
V: -----21-3 c93cc619a255967030ffab7df2ef66d3
|
||||
V: 483125576 9897dfb2d83c8aa480ece204e81e2254
|
||||
V: 355196924 00115bf3d3b02e3449305ebb7dfe375c
|
||||
V: 885214893 5cca377bbf7b08de0245764a31300820
|
||||
V: --------1 f71e69ff5942550e11505ef6896a0612
|
||||
V: 163724865 5e3bd536aaec6eb14614b2a33d55b855
|
||||
V: 372451689 a995aeb8bcb4b412ec7e795dfad9164b
|
||||
V: 5--2413-6 2931ffdcf2d0e5e76131053141afbb28
|
||||
V: ---1--2-- 16fb70036d9ef9054ee5e18490e65ffa
|
||||
V: 34641425- fcd1442e37dcd5b93e80630452beba06
|
||||
V: 183624579 570a5ee57b184758b7101bef1376512c
|
||||
V: ---1----- 58a680be2eba20a5c56e0136c755e46c
|
||||
V: 185324769 8b4c2ac7df2dc0520d2dfc324f0938f4
|
||||
V: 566213254 9faa59f85f4ef321bd3b7b1eb95a962c
|
||||
V: ----231-- 6fd0574788f5e39d2f3ef5f419ff45d7
|
||||
V: 287134695 3e4019943e1c2a06086b8fa9b7f26b13
|
||||
V: 165324978 7f12cd29047b33dbbd39f1baf299b2d6
|
||||
V: 714365289 b5164cdf1389b949b2e9c9bcef97bfe0
|
||||
V: 1---2-3-- 883b71a74f1dafdbabe41b7e9bd282dc
|
||||
V: 562155643 6cede7d373127b3f776572492f2013df
|
||||
V: 492163785 c57f0d386ac109a968890e96494c7d19
|
||||
V: 581342766 e2f6b90c93ada18c05c4577f432b8249
|
||||
V: 991999992 c8e99a4c0bce7b29dd319d798d917808
|
||||
V: 2---5413- 9f8220bf2318e743aedba861ea728594
|
||||
V: 296331478 b75d57ab25da0dd20ba763e25a1e2f8e
|
||||
V: 471325376 38dd111235919341e256ca0beae75233
|
||||
V: 352188839 2e12a634b4335369041e17192818ea4f
|
||||
V: 6241-5-37 3951ed0cce057646f9cd78208b87c5f4
|
||||
V: 543815297 c8875690b94b5698d52a48e068928d98
|
||||
V: 492361587 e205db0ec3a7fc454c6f4050e47aa992
|
||||
V: --21----- 6dbff1a985e92da42f3fcec7a19307a0
|
||||
V: 199299993 23101224c5d0d377cef8f5e4c2e45045
|
||||
V: 187324695 1eaaa132079955ea5589485e843646eb
|
||||
V: 583171964 a2a6d73a291f23663332156edc849cf5
|
||||
V: 491365782 88ea4569c43c1736b4c505603916a859
|
||||
V: 144332543 90d3b334e399882da35d69bc72726027
|
||||
V: --------1 cf3b91dea6391a8a3331d13eddd10b59
|
||||
V: 465155623 e0dd82a30b72c1fa483215469f1b6972
|
||||
V: 274138956 d7dab11af00b8028015098df5a1d3cb6
|
||||
V: ------1-- 43b414518d6603d5345ec4bfd08c7a53
|
||||
V: 48561327- b4b6417a49c0b1f38aa73adf0fde98fb
|
||||
V: ----2-1-- 16dafaa67afe1f28ad17f007e1eafb85
|
||||
V: ----1-2-3 864d806937c7b6ee21e381f6e8b6d699
|
||||
V: 25341355- abab795f67d507315e39b28884ee1247
|
||||
V: ------1-2 1435df948819103e326dd285a870d7be
|
||||
V: 4-212-4-5 9a71f50326a4cc423e78b705efba39bc
|
||||
V: 195264873 3d0d30383706da28452caee427ad520f
|
||||
V: 377815264 6595f5ab403c46ae3e5ebee012b5b439
|
||||
V: ---1-1--2 3d0e67d584384018f0dd6960a604665e
|
||||
V: 537412176 45f67677e48ce5733169537737c8e461
|
||||
V: ----321-4 62866e67f4dce3a01f3d970befc95175
|
||||
V: 45551325- b73343c1560d714e065e72a8565036f3
|
||||
V: 278514396 97a23e6b79f7ee634d2521fbb1808ace
|
||||
V: 78261524- 402b4bd1a358667dd1e695f510948f0a
|
||||
V: 476123589 9008efe86a4ccaf437bf00c126f2a81c
|
||||
V: 5-61423-7 072cc65cd6b7e037301594be54a56afa
|
||||
V: 443122635 f8c7983399cfc9acb1e38054d970f9ed
|
||||
V: 372144576 3458172b1523f8ea96785bc156581a31
|
||||
V: 191122938 2e78f4e0c2f641934c56fc7f8910b066
|
||||
V: 2----13-3 7c747a75c8a8afe77d20f0949b3aaa83
|
||||
V: ---1----2 f5fcaf54dce30ace7adc8688d2ba8aab
|
||||
V: 34441214- 8b433ccb9ae7e3b131f703d1a271edeb
|
||||
V: 56412378- 875dbffdbe89c5dbd8e832e6b892712f
|
||||
V: 4-31-2--- 1def3be27460b7c59799672e535beef5
|
||||
V: 372165498 59b6c624b34091e14cc3ca2c490b3719
|
||||
V: 582168997 fb92a33b945d36f3f8051c0049a96646
|
||||
V: 377914265 3a0053ac583871542503eb0e8dba7fee
|
||||
V: 387415296 0bbf5448890cfcf57a0fed19efa324cd
|
||||
V: 111111111 e7db684ce9919802b57a0a3b55468098
|
||||
V: 586432197 f39d939d8095f8e539388aa988c0713c
|
||||
V: 571242776 44d42fde51290d065e8efeb787eeacc7
|
||||
V: 233331134 a42d1851a9bbd882d354c2caabef93df
|
||||
V: 496512378 035fd8c2be571cf93a1632554513f8cc
|
||||
V: 895132476 030e90534cb75b16ea78229227fb81c8
|
||||
V: 487921365 b2bbee806824f770133b7aa3af04bf27
|
||||
V: ----2-1-- 8d2aaa61f2b975ca1de55236c2c9a36c
|
||||
V: 862183968 c8ff3b650fcd6dc86d5337961f30d55c
|
||||
V: 456728931 e99a33058dcf1248134f26daf9d9167c
|
||||
V: 642187935 6feefc11d1ba5bbd386a5cbe2cc54c7e
|
||||
V: 26713548- 4c8e050da3f0d40830aa649c7e7eef41
|
||||
V: 6-51432-7 f45968e0d9b48d70e9f19016d2e6a3bd
|
||||
V: 465932178 94d47901ffa8a4cbc53abdbb7440bf77
|
||||
V: 487532169 a143468aa15a1fac903dad4bc7af7356
|
||||
V: 256143978 8388d60c8a8500ae717f3d47417a985e
|
||||
V: 197236854 50bd4fd15d40600ffe7dd0812ec7d487
|
||||
V: 295613487 d60ebd8b7797248e8004fee92e1dc707
|
||||
V: ------1-2 f31d5f580cfa6b93b359d4250dfcccbb
|
||||
V: ----1-2-- 9e56fde5c2185837f240f02771659a7b
|
||||
V: 2--5431-6 1fc8967dfc0c77a494b799309ab589af
|
||||
V: 547231968 9368b647e156b39acfb14c4862fc8ddf
|
||||
V: 111111212 7a4c4f1b8f580c452f80b0e593376072
|
||||
V: 4--3152-6 26940b24a7153e4da66d8a52f8c66220
|
||||
V: 987165432 84b093a44ffc6d107ad7b469e127fe8f
|
||||
V: 683142579 70aebffad84baefadee4ec11a6b10ee9
|
||||
V: 173244665 940ea2aff5130d4c31a871681bc6eb80
|
||||
V: 486313547 e283a692d7c5e21f3e5a06620e761753
|
||||
V: 6-53214-7 ed9c42f95476d5bd9aa25c322dfa2abb
|
||||
V: ------1-2 3db6fc96af0bed387e7767d885d15129
|
||||
V: 189732654 401e66df6743eef21ac0a9521d03ba1e
|
||||
V: 583924176 6a2f93593aa6209a0d2ed1033c8d0cea
|
||||
V: ------1-- 30cc4fa4575d8924b52b7bd22938ccd5
|
||||
V: 355523134 8e290f67b1359e2b42030d0f4b3b14fe
|
||||
V: 662135547 b81159450b1dbf5e247f6699978a3771
|
||||
V: 3-21-3--- e35a7bcac43b3c7f49865a65d170efe0
|
||||
V: -----1--2 f2d740fc3d33021470ad78feb1787295
|
||||
V: 487163259 a8f3dbec826cecf4654d28cb7e006750
|
||||
V: 574362189 36c1c8a5adacaee09ec26e74e5098de3
|
||||
V: 18652437- 84a54ab0641b9672ed1e1c01ee747e3e
|
||||
V: 582168997 dce81c3b9ecfbf1b1577c3f3ebf7637e
|
||||
V: 377231465 d3e512c9b0b9475517276aa35e19b57f
|
||||
V: 3---142-- e04c48b370b8ec4f3d2a6fe55104d45d
|
||||
V: ------21- 7deb96af26706c3e7faaecd287f6f9a7
|
||||
V: 344134245 067301f57174bdc1a190047ca71d8d28
|
||||
V: 1---3-245 b93c1808abc7145a2fb50fd805702b98
|
||||
V: -----1--- 4f2512ecc8efddc9978f9f3b4645097b
|
||||
V: 385126479 1de2591052e74e0f671172e880a358ab
|
||||
V: 567312489 0e4617eea72f2a15fb4e98e84b1000d0
|
||||
V: 124873139 c72d232fd42efce75e8b49c00458659a
|
||||
V: --12111-- 4889813b13967043023bfd00795b41f2
|
||||
V: 444144243 cd594cd6d4b3a85bdd1dedfdd3149231
|
||||
V: 762584139 ec51b658d6c78a199790d601c5e4cfa4
|
||||
V: 598123476 67cf31ba28bb7dceb57ee8f68b4a311a
|
||||
V: ---1-32-- 7e36458326b532e5fbdace7230536504
|
||||
V: 876543129 fd041dbe5623c65f56351d3d4b929456
|
||||
V: 586413297 4d58d5cf2f37d1440b2a07fab7151f54
|
||||
V: --------1 b09ed6026229caa68d66e730fb8a4a8b
|
||||
V: 2-22-3--- 02d3929e6d994cb541659531e10dd7aa
|
||||
V: 266513164 4c5ab909158a181c387fa45034e609ee
|
||||
V: 23332214- a71096e3aada5291d8c20019760ef560
|
||||
V: 651243897 a01ea206af27afcbe5264456be6348c7
|
||||
V: ---1----2 ce7e62d5da29d0823d96ca6e026d3dc4
|
||||
V: 1---32--- 35fea1c47efd4f97d02b482a001aa6be
|
||||
V: 346815279 9b1fc26351bca7560c19d6e3990d5f2a
|
||||
V: 576312477 144afb1c547f39986811fd947dec72a2
|
||||
V: 592134687 6098c043773d4fb0710e15c0a8b71231
|
||||
V: 574216389 a782449c23cf84a322be471a9c452cdf
|
||||
V: 287146953 56506a20b0acefd21d9a6e354fdc36fd
|
||||
V: 385621497 458b63db0a1dc0ec93adf00be7abc8f2
|
||||
V: --3331139 c46e4526db436392ed366f88a5d9d496
|
||||
V: 265431978 f871c7777a9e4012481323c57d89bcb7
|
||||
V: ---1----2 080d2758523efa3ccebbe873f6ef197c
|
||||
V: 2--41-3-5 71496d6e09335081ac4e49a8c506e40c
|
||||
V: 3-412-3-- d943b69cf304d61feda9e36c8c4b3c00
|
||||
V: --35412-6 fdb2b8c51eb9739f9eca1138eab195f0
|
||||
V: 45214354- 4df1e71f298c322bc241fc3c94996b64
|
||||
V: 244361745 2e6c1b374f54014bdb31a41e5b9919dd
|
||||
V: 554134255 10cdc8478283ac2642a3fd78d353935e
|
||||
V: 583162974 b87266251cfc78a497895e4dc71208dd
|
||||
V: 596231487 ff06deda5f6815ea89c5b43de59af03c
|
||||
V: 111111112 2aacea3dacd4d5f4d05571faa1138a12
|
||||
V: 154116732 8b0caf9a0a525c75f012189dff836d36
|
||||
V: 5--4231-6 b75cde399f6e1d6be9706d6c16ae8f37
|
||||
V: 222222221 ae449dfeff4775355b9ca663e30a4fab
|
||||
V: 47352618- 2f58a9c394d01d254755ec3bc9acc29a
|
||||
V: ---1-2--3 e9a2552055e05d8261082c09d2d10e86
|
||||
V: 4--12---3 59b3cc4f7d1ef6c906101ca6bfdc6e77
|
||||
V: 296143798 de294802bfd760bcdfde37d1949ab495
|
||||
V: 287643159 7f1b781af70c0a2565851ad537c3aa59
|
||||
V: 465213357 e87f371d4979e1e96d10f4410516c9a2
|
||||
V: --------1 1d596053c880a9e08bd0e4e6375244ea
|
||||
V: 535551255 3ab4be2a34d570562d6101145e7829bd
|
||||
V: 3--132--4 0582f1ee87127997455fb714808a4a32
|
||||
V: 267418953 a4fbd4c9df212fcc42a6a556c1095454
|
||||
V: 554125356 480de81efc20be2b13db3df1c10c28cc
|
||||
V: ---1-2--3 c431f05de380f86bffa3eff6dbf55910
|
||||
V: 3---12--- 76c519562f2b6ece724663f9057bfec6
|
||||
V: 774325176 eabd71100caacd9886ac112755b9c80a
|
||||
V: 564323157 8677b137910cd002ae49b912effc89c6
|
||||
V: 482153769 c15eaa53b3868422a7491e4cee1e468b
|
||||
V: 385924176 3eb456075d86629034f72794d01d77ec
|
||||
V: 333332134 63bcbbf01456a69ed0dc1148a8fd7999
|
||||
V: ---12---3 f269f96fc40edf20bee614999098e2db
|
||||
V: 663324165 07280de9e2136d41e3abba5df1eafc2d
|
||||
V: ----1-324 5a3aedc715ab8b5a71d0af8d0f3cee7a
|
||||
V: 153312545 f7c8d103b7493a94de336d5bfedfdea9
|
||||
V: 1--42-3-5 a4056d79e458ba9b240937109c5c961f
|
||||
V: 586342179 88545fcc0c659eac3e994d9c80be08ab
|
||||
V: 888284889 52bbdf64b4d6045954fdc56688ef66fa
|
||||
V: 365271864 747a037ddc920c6d131ae249173ed0d0
|
||||
V: 999991999 dd7c59a028b7d3dd0bcfa56701d40bf6
|
||||
V: 753196962 f2d58336c99b6b56b96fe1bd70fcb506
|
||||
V: 197235864 f1a36539afe221432a673fddfacd84e9
|
||||
V: 566623164 be5c2112e5bd09fe9771dd7cba3c80c5
|
||||
V: ----231-- f3de32932dfe8c46bf9af8368ddea379
|
||||
V: 562178943 018c4083746f12acae080ac80441d5ba
|
||||
V: 498321576 b1b6ccdfc44a7489a0f530c19f83c935
|
||||
V: 4---312-- 210d724ac9d0af7aeb53d86a93bc501f
|
||||
V: 246381957 493f32eb0149a3778cc9248bd7b1b623
|
||||
V: 293949157 53e63d6e4958e51e99d0bcb5f566fb6c
|
||||
V: 576132489 eb34f24957923357cc0e4e1fa2e6a840
|
||||
V: 694521897 4561d375465b5cc82ba5b7da0647ca8a
|
||||
V: 3---1-2-- 00ffe84df2b1202dfdc005900fc11f5c
|
||||
V: 382144789 02ee19e06db684d192fd1e833b21287e
|
||||
V: ----1--23 98f1438393ae5a3e6dccd71a34f3f88e
|
||||
V: 15433245- bdfb1dc25bcf3d9b8bf8edf095fb59ef
|
||||
V: 225222134 cb6919843f9fb2e1bafefb6a413afd8a
|
||||
V: 111111111 8844e5b2800219ada59963f2b54fdab5
|
||||
V: ---1432-5 86d8197150520a659727c56b269c6b2c
|
||||
V: 4314-4-42 6014b669eaaf068938c4bd76fc0c6503
|
||||
V: 444442413 3984cf2163162502529cb13d78956780
|
||||
V: 396257841 98177070aac46939e188e030e3d62496
|
||||
V: 4---123-5 6d467c6f4cedf79ce0c4e9d8f4408ed8
|
||||
V: 382174965 49012c3bdd90f1745b8d16df135a5571
|
||||
V: ---1----2 0c08ea573d54ea48a8763efaa6d17337
|
||||
V: 361342457 296887cb5532784f210a1c7caa48db27
|
||||
V: 333133932 dab3b11f08a9e01169d6cdfd1cec9e47
|
||||
V: -----123- f58b879a15f04ff62a942cb69d0fad16
|
||||
V: 673524189 39126fb06601fdfc55c10d7470a0e764
|
||||
V: 596142387 32a1fcb031835d8de9eba04ef66c8b22
|
||||
V: 385214376 6223e697bbeaa08d50cc4937e16196a9
|
||||
V: 187425369 a85b88c2163821431424202c3509bb74
|
||||
V: 244443145 513d840e74cc85a997055c4118844cbc
|
||||
V: ------1-2 acda34550cf3809cb8752ce647109d78
|
||||
V: ---21-3-4 2e74a63c4d6b9e1a4eca6c8da108097f
|
||||
V: 2-22-1--- fc31b6fe22604434cf3e425fc3ffe475
|
||||
V: 664193952 02d0f4e29ce8b6c12c39098673eb50eb
|
||||
V: 3-21----- 83e3167965de09ca3cded63c7dcb8e8c
|
||||
V: ----1---- 5321943134fdaac12c2571361e3209c2
|
||||
V: 273165846 5ea27f991311bef0452ff35feeae5f1a
|
||||
V: 35214343- 3a7bf3609002ea58d4357ebc5a17a691
|
||||
V: 514523637 a2c5fa69b9bc838371d7f3bb230bdde7
|
||||
V: 265413457 70f7918a20744aae8c73a3c7d09efeaa
|
||||
V: 3---12--- 93596e6dd5046fec39b84360d73237b2
|
||||
V: --21-3--4 22dfa2efcfe4ce437a5896b2521424b5
|
||||
V: 255322154 c3079709aa5e629e38f289c9179eb487
|
||||
V: 355524155 852c672036e2c380fd3b72c1fcd3820a
|
||||
V: 522184866 da7b8095312ae94fa3c3ec1c58f230af
|
||||
V: 26-154-37 dcdd3b22679d894baf2dfdf578abeca6
|
||||
V: 565215364 aefc7247dc28f1e1f741258306679c4d
|
||||
V: 295314768 ae3901f16520b90f7aa52ba483dd40ca
|
||||
V: 2---13--- 8047f51cee67e205bbacaa777348e469
|
||||
V: --------1 372bd24e089a9d7726756e056802735b
|
||||
V: 473132356 8ae4163bfa6a1b0bf41ce4c37b911506
|
||||
V: 5--3214-6 763173424abf54ffb1736849a11ff871
|
||||
V: 343132645 258a5db24ad7f2ecaec5e42a9d4705d7
|
||||
V: 164235789 51ee8107224ef5a0621e57733cc0d8d5
|
||||
V: 675142398 e4cf8161965f37b27645edc0c2ad4af2
|
||||
V: 498132567 94ea66e5524ad103fd2a4e825e80e5be
|
||||
V: 275513476 d90bacaf87ee54e879d6916b9007638f
|
||||
V: 344525154 3dc49a068780f6485d0af621b5b8e911
|
||||
V: 643271965 31cf29e73d41b93fdf933a091a5e3b22
|
||||
V: 333313234 4d398272cc170b83d1d4bb38e046b231
|
||||
V: 341241145 66a5fd284dd053f97f856ee85c064206
|
||||
V: 4---231-5 f6d23c2a3aa9a7b241bb6a4f1b9cd157
|
||||
V: 169854327 f5032d096a80595a75c731f0db8f9ac5
|
||||
V: 152142554 451d02c778b4afcdc4ce933e6b6e4cdb
|
||||
V: 574412376 2f3ebbed8bc9ded4a725d93ce1c4973c
|
||||
V: 682145983 8be65a7c019f5cc303ade7d1d3f607d4
|
||||
V: 2---1-1-3 d644146add46155ca62cb86ee7b1626d
|
||||
V: 244155643 1dd2140c3af1fb9bbc08a46cfdbcad0d
|
||||
V: 255123456 84a85cc820ae48b691b69f9ff507b878
|
||||
V: 265311546 1ec1989a8abac2bca278edad96c8f0ab
|
||||
V: 394122885 d83c3ddd0ab56881474bae3be7adc135
|
||||
V: 3--142--5 f49c6238d3620d159421dc3c0c51e5ea
|
||||
V: 355125456 742bc19e1efd4ea4529403ac053fe1ac
|
||||
V: 586134792 a1d8322a946514463c0a47f2391e59ca
|
||||
V: --------1 e3f5d8bdb0547e74aedb0e067def31e2
|
||||
V: 654123879 7b04ca30a2af51a6389ba498a7efbe7b
|
||||
V: 295615384 ee8968ac72017b229193e8f2e775916a
|
||||
V: 197234586 e571ea4a611d3982521507b44422f9cb
|
||||
V: 2----1--3 bd4b6e615fa5c8154f0a7c92298d5e37
|
||||
V: 233251554 a656f68b43f6a033893898d9e59f5591
|
||||
V: 2-----1-- 27eba01b3562e3b6276fbeb2d77775cd
|
||||
V: 286621269 f03249c241b60383117b06fcdd94cb13
|
||||
V: 752186943 667913ce66544f3c55ea195672a54ea3
|
||||
V: 474144826 3f87280c40b2088ab06d8a46be823698
|
||||
V: 376542189 bf2ce69341e0fe56af28e6c601e151d4
|
||||
V: 492142687 c85dec9e5ccb61ed8e6676fc02478fdb
|
||||
V: 2---3-1-- 960d0f72870bafad41b2519819370285
|
||||
V: 355162647 56327ec0402144a7af744a7da21be341
|
||||
V: 276134675 e19b33e179295b1cde6f2c888ffe4720
|
||||
V: 465423157 01f1ba9478f9c851737cabdedb2918b7
|
||||
V: 555213554 06c43c5f70b81389c0f940c0e83811ce
|
||||
V: 58632417- 75992f292891b0aafc6e2f5c6a0ba054
|
||||
V: 111111-12 f1983b48853dcba93afda7f745e9d724
|
||||
V: --------1 aa9ddaef3c62aec7e66552179a27f613
|
||||
V: 355113354 5ce16651123c955d0c75ea4416759586
|
||||
V: --31-2--4 e677ea5d9d11e73d5740d9dd98e80cc0
|
||||
V: 2--221--9 11704a4fd006ce5fe2dd8c7219b6b1ee
|
||||
V: 4---2-1-3 2018f2fb975f57cbcad50930f27d9f92
|
||||
V: 375914286 8bc0c1a4347c03ade54ef74480c7f0b8
|
||||
V: 4---32--1 91c3356f3a8be093e9a439206742130b
|
||||
V: --------1 44300321087cf840cdba98efa91e0d5c
|
||||
V: 974523186 911309d8774584421cb2207b6688f6c8
|
||||
V: 2--543167 534dc18fa8968c8d6afbe6e7bb1bb4ab
|
||||
V: 162376948 27b493deda85a020b32d87f2a866140c
|
||||
V: ----1-2-3 eb59e40399d66c00c246325bdfb6dfea
|
||||
V: 133378924 7fcc00f3a13c0ad091fba88aaba22878
|
||||
V: 483127956 097a5794e1fb240f5526780034d80156
|
||||
V: 436125276 b5308be450ff392d904ae96e23074a08
|
||||
V: 578314296 a1b4a901e1c09daaaf14499fe2ee0660
|
||||
V: 4-3326--- 750c674329b6075fb8274dfdbcf4d9c5
|
||||
V: ------1-- 448873ddcd452b462cf4c5dd0ffb82b6
|
||||
V: 398726154 3948e05c633c5791fcd756d1ccd76392
|
||||
V: 355321254 1a13f53484c844bda94aa55636aff06b
|
||||
V: 166324753 747164c51703185ac5ec34ebc70db2df
|
||||
V: ---34215- 97872544e77cc4c586d827660254e426
|
||||
V: 366612465 04a7bf5b89fb416de7a3a1e87fe0583b
|
||||
V: 4---213-5 0396ea3ecdbe8ddc983c9b8ade292b32
|
||||
V: ----231-- 8931ea4448a7a7c42160a2fbd3b2a2c0
|
||||
V: 175372476 b0aa48e827229ff7b892d83101b40a4a
|
||||
V: 46512738- 3ba3a82e8832bf7b8a0026227927807b
|
||||
V: 189723645 7c85d2372017f0ee0fb704ed172eb683
|
||||
V: --------1 156186b54bff4c7907b5df6464d8feed
|
||||
V: 526943991 b3231587079f02856a593300acadbbf5
|
||||
V: 888819283 7fb70747a0d5320877d28d97b770920b
|
||||
V: 3---1-2-4 e26de25d1a566a20401ae8057f545102
|
||||
V: 496512378 764f8e7a378d3f6c76ac132e57108cde
|
||||
V: 264123335 fd2b183c89c1fd2f05d3359d678caf89
|
||||
V: 456782193 7234ee67b6ca1902ab2e00ef7d720df2
|
||||
V: 355134256 1c0e8c39dbb2b38a75a4c3f19ac9259f
|
||||
V: 354513267 aca0c504d4bd9914379976fe1d18b275
|
||||
V: 476532168 e0764d62ddad54b8b6e98fb089a17fe3
|
||||
V: 466412375 9769a406a06a0235a504476dd27df65b
|
||||
V: 1-------2 e24806bcab753eb0ba0a3645ceab0539
|
||||
V: 111111111 44be34c4339cbd9e9518dd50174ae944
|
||||
V: 374281956 4500e4f45a2f577bd8143c772d67f5c1
|
||||
V: 365187924 a25a9bb597997a98ae0f32aeb41955ee
|
||||
V: 194372856 cad4db5728398cf2f58caa33c919cb3e
|
||||
V: 596416287 4cbc67bce81623d5f6dbf5b689855ecb
|
||||
V: 381254976 e3799870d31e15c5fc2602f337564757
|
||||
V: --31-2--4 05e3025d083f1c723df5f62ff1a9f2d6
|
||||
V: 3--321--- 75c92f1fe4b33daf63318c3443d6eeb8
|
||||
V: 785342169 8f5b77fe9bb0791771c04c3bec9cf71c
|
||||
V: 23232114- 608fd99471a69c86da4fd9b2d65e4041
|
||||
V: 121133524 3792a22312edbe0119f58f0429208ea0
|
||||
V: 195324768 fd7444f48ce4680da423975408624084
|
||||
V: 254731689 7bb119c375699411e19265067c0d488d
|
||||
V: 374152698 65f8f21944b9a1cf3b5aafacb1595a19
|
||||
V: 4---251-3 fcd68ade4a0848e838425841f1f6e173
|
||||
V: 456789123 5ae533c50c1040e84e4e4c67889e6cf4
|
||||
V: --------1 d8d3bf624b18531382e159cd2beecef5
|
||||
V: 896115792 6c811386473a4cd9689934c381a2e223
|
||||
V: --------1 702f6278c262559addeab19aa451d47d
|
||||
V: --421-3-5 163467838b8b0a764368392812d20cf0
|
||||
V: 589137642 872bb1d79a6c6efbfedd09fa4144b98d
|
||||
V: ------1-2 838574ea391956187d09cef22818cca3
|
||||
V: -----21-- ce617eff7e6139505741b9395fafe735
|
||||
V: 273156984 5a48e39939f7eccc20f36e873cece388
|
||||
V: 199931498 4127f49f613bd079a5c61bfaf27f9fb8
|
||||
V: 952184763 18669f7a2e8fd42eb615471c7a24988d
|
||||
V: 444211243 8ea420445c49abc20903ad72e0115f01
|
||||
V: 156723984 cea35d528fb437c707a4f3da25e8ee04
|
||||
V: 394152678 cb1b0ff1dc395c3629f4d27db93c35be
|
||||
V: 495124478 958f9f64e3fec695230fa900dd9d58f9
|
||||
V: 76-1-438- eca2dce469616c429cb8ecb5050f3940
|
||||
V: 4---231-5 731c3fbc78d38d309c49ee6012bcea39
|
||||
V: 3---122-- 5ca9803e8d3b2752f96c95cb2f3f9af1
|
||||
V: 475143286 58f0a8ba4dd1b1606b58057f565a30fd
|
||||
V: 4-5-231-6 5f38bdb077a31e32187baa761e7cc636
|
||||
V: 562175834 a466b5b91e43b9a61af656da6d530627
|
||||
V: --21----3 8b3755dc6ef27e43a346c9a9403e27ed
|
||||
V: 1-------2 30c4333004e45f08bb7b8d84f4de638b
|
||||
V: 2--33-2-1 62f3466069f39f60b3910e8d32edc347
|
||||
V: 2-----1-- 013cae7d31d7a577bbca3c9e2bb498d8
|
||||
V: 399142498 6daae1c6289aedde583e1e967615e82c
|
||||
V: 495932199 91df45e7019d8976f0dd31f2c8dbcce8
|
||||
V: -22131--4 a505bedf414f1415bd751b6ae28804b5
|
||||
V: 274414379 96fcdcb871e4abe1af7547e0c231331c
|
||||
V: 798314265 ea0bce5bb1aff2deeab387c4e4ed9c3a
|
||||
V: 597321468 3ad68bd9961a5c5744f52647e2f2504e
|
||||
V: 255414553 917ce5f81938ef83a4f3db51ae6178bd
|
||||
V: 174293958 976ffc2fe7dc2d4cad3a8f07f68339c4
|
||||
V: 366324165 bdde81ba338ddcb33001f359c5214c90
|
||||
V: 555314259 95f8d0bd38affe6ae9c3d71d2199ac42
|
||||
V: 478613295 50b490bb14d6fed354dbab130f07da2e
|
||||
V: 14537682- eac404717952d119d722f2f15fd3cd00
|
||||
V: 239814567 2d5ea2b98b818352b34e4344a91f1fc1
|
||||
V: 333331332 5c1a7e3719bf2ce986c1d39d18548f34
|
||||
V: --------1 bd66e05d62ac660c5c74ee274107628e
|
||||
V: 2---51436 6b78eb57b435fbf29633bf1abe9a27c3
|
||||
V: 392164587 24d7edbaee90b8e5fb8d800ed2ddf351
|
||||
V: 173642589 868b4a0cf7ac9e47f64659670b7c247d
|
||||
V: 37514268- 8c40da82b9b3ab4983d5326de87c781b
|
||||
V: 345617289 dfe43345c1dc20f29c8750eb06067da1
|
||||
V: 285912457 82b5dfb5c8756f3902cb2553309ac0d3
|
||||
V: 222222221 c5b28d9d485fb3841d31e82438e42ac2
|
||||
V: 477215376 175d997dcbc410c4386c00e826b51273
|
||||
V: 342164645 d91be484ccc0cbaf2ebbb274b14f71e7
|
||||
V: ---1-2--3 e5f837e3b0a4408b9a201a0014a43f07
|
||||
V: 999299199 452ee865caf3d481994da4d869701f76
|
||||
V: 1--2233-4 ae95067b3585cd16a60ac24685b2a0c4
|
||||
V: 2---1-3-- e98d8eded90d2fec8bb9c3eaa5de2fcb
|
||||
V: 794316285 a3e5a1018c069d7e9c86668465ce0a32
|
||||
V: 498726153 ae9aad17831770e8909ee41908a8f2dd
|
||||
V: ---31-2-4 8573c551f716d78cad467d17a1df1121
|
||||
V: 233241645 1352574fa909e3b2eb1667a250596344
|
||||
V: 46226---8 4bac6c66bd4a909a4ba0bf446640aaa0
|
||||
V: 163284957 847d6aeab5fbb1a3849b7e44e6dea116
|
||||
V: 1-------2 04d3d08aae2a5406a086129a5a8281b3
|
||||
V: 23331213- a00acc5da9cdae31356f3e4446d83487
|
||||
V: 371243856 bec3edbf12bb2f0cff96073fb638b078
|
||||
V: 195726348 073499ac9d86f36aa314e3a0fdd6d41b
|
||||
V: 3-21-2--- 25cd17899934e7aec5c36d412b143fa1
|
||||
V: 367524189 36432746596bd9078c342e86b4803786
|
||||
V: 387425169 8b8c6575aedff7a0ce8363ad23de6965
|
||||
V: ----21234 c46c4edbb67cc243051f483fad0b27d9
|
||||
V: 675132466 9639e14905858627e4069e1362be836d
|
||||
V: 1---7-8-- 2dd0cd8630c080193e998b85a9c6b343
|
||||
V: 583153986 e722c36ade585eeb09e41475fd6b2645
|
||||
V: 3-15-24-- 9598237dcc4e6c2d69ae1386004cf2ab
|
||||
V: 567432189 5a550769adc0cd30c8c143b008536098
|
||||
V: ---31-2-- df42a1a9e276a8f937aaa517f9989a63
|
||||
V: 3--5241-6 2cc98e3ff1202694eaf23af0203dcbe7
|
||||
V: 454513256 aa11975d8353c88727b59a6a65eec05e
|
||||
V: 472135869 973b9384b33e21e06b79676b6132982e
|
||||
V: 876542913 0b768ad1c7eba0d6af8ce4f9013d3067
|
||||
V: 583421967 a3ebcb8830c373594a6949bbab3ef605
|
||||
V: 473562189 fcdb1e90e4e87f0b313fa3c4ed30daa1
|
||||
V: 492135687 8270767ec9af8ff30163c1ba11219d57
|
||||
V: 473152986 c863b36f1e9bb6a2e0689b07c7cec405
|
||||
V: 34321215- 2048937296216731b4942f13234732c7
|
||||
V: 234615337 c722315d845bf3b8900873f01a1b6d80
|
||||
V: 894125376 1c74a47b123bf2fff4df65a6a82ba0d7
|
||||
V: ------1-- b513e43d27e8ef8fbab1397c1ef0177c
|
||||
V: 378214596 2e60fd12c3c8b523560d212c0f8a520e
|
||||
V: 466236165 ed7047447d8c83123d10ce83371b048f
|
||||
V: ---3-12-4 06a00e033e301fed22a75c8eed28c2b6
|
||||
V: 465213265 e57783d1b8b193db6d2b0cca96f0907d
|
||||
V: 663314165 c9e848ed71b49de37adb3729c610981f
|
||||
V: 494613278 104644f9f0daa43db0ecba9a425b7552
|
||||
V: 184536924 7d05d0a4355829223b4bcaaf18e0292c
|
||||
V: 695421378 aa785047e901d85ceaddb8d39ac8fbb9
|
||||
V: 196724853 673220b63776cf4cdba842d83802a29f
|
||||
V: 2--11-1-3 cfca0279d8f7a4c7a75288e05c3d7c23
|
||||
V: ------1-2 e26b476320b331b4f47d01807dce2e1f
|
||||
V: 173244536 9091a67166331b5b8a0af81dcaebc1c7
|
||||
V: 441244443 a25d9aef343ebfcc2fd8eff632042e68
|
||||
V: 3---142-- 26e7e3c411611e9dfa6cb5e12041091a
|
||||
V: 388824189 2be1f033b4144e56b1e29b207a014de3
|
||||
V: 583246197 a127843a35f49ec7900797879d5582aa
|
||||
V: 883312497 ef7cbe1df6a2e3f9c18c0236739a4469
|
||||
V: 164612435 c0141e6786e1d7fa0ec6f14ab42af5db
|
||||
V: 587321496 9880d041dcc6b49ad32ae1b87d20874e
|
||||
V: 483257169 5a5536130285fa1f49e59b12f284bfb4
|
||||
V: 47216358- 36cddfe1a10d5d4ec18789f68652cce0
|
||||
V: 781243569 e81b6f4d2d685a1f0f7199fc6602e78f
|
||||
V: 682143597 b47401bedd3e9c14d3083857473a2e0a
|
||||
V: 2---413-5 38552e43c001aac5248885ded1cdb116
|
||||
V: 575121673 d85a7e66322100d2efcbc8ca51ce86f1
|
||||
V: 273451896 a3875fe4e1af9d07cf9efc661954e838
|
||||
V: 193991499 646a655c6c6b8ff073cb74cb8abdfdf0
|
||||
V: ----1---- 434d6c54c6ee22d9838c17dcde1e8714
|
||||
V: 111111111 db0ba98892501139afd8e3590c2388ef
|
||||
V: 14112234- c96fd6283ac8460dde8b4ef281ec6f03
|
||||
V: 173242856 af7339fc519870f144e700dfd1366b98
|
||||
V: 3-11-29-- 9054f0443ce90b42d1d5d8915e6670a7
|
||||
V: ---1----2 fdbd02faf74cf40038c7f81887c5b1e1
|
||||
V: 372135574 ecd69fce4975cfe9f7291bbeb992bd24
|
||||
V: 471326589 6dc06d9ae7f4482b0f54b52fe8b71bf4
|
||||
V: 79518789- 307439b033a02f983be37e6b0dec868e
|
||||
V: 273155467 196cc4e7fca7d16acb693b92d6513e40
|
||||
V: 613254978 73d1b0b63a1d17919b20b8c0bea1f0a6
|
||||
V: 265134466 cb63ad319b5aa1a7c7aed178ddda311b
|
||||
V: 372156574 21d94a46a5a9162b906f4c4f985131c2
|
||||
V: 696174-97 f077e7bd35a3194915b3002853a9e374
|
||||
V: --41-32-- c93781659b330e3322699299d7b0263f
|
||||
V: 4-----1-5 92a18fedc75e10f238b593a1068cdb2e
|
||||
V: 582167943 9fb47f93ec4ad670378899f259e1cd2c
|
||||
V: 185274936 0dd48de8586a03bc634d5b7f88f2ad09
|
||||
V: 794523186 6461f50716c1241c1e94c44d01b9d223
|
||||
V: 444241443 61b0198899c64e3f3893662524afbd13
|
||||
V: 2---1---- bfa429a7aa1dd33851efb4deb1a182db
|
||||
V: 166146965 8be478fdc7fc4f6c5f5ec767c26b7070
|
||||
V: 361289754 9ebf1d644affd657f6c8aacb7893ad70
|
||||
V: 222222123 a6ebe2e8cad2d93c0034ea8a1f800a36
|
||||
V: 45123245- 6524617fc241314119683ac3aa923033
|
||||
V: 442134365 8f663a21f0cbff38bd59272657674974
|
||||
V: 455512359 56947a39e87ec487c5587de1974d2266
|
||||
V: 23331414- 774b5d5acbfd0c28486987b6e2858ff2
|
||||
V: 672185943 7ad3a7548af383e4c6e556f064821e87
|
@ -0,0 +1,359 @@
|
||||
|
||||
Tally Sheet for the votes cast.
|
||||
|
||||
The format is:
|
||||
"V: vote HMAC_SHA256_HEX"
|
||||
You may locate the HMAC_SHA256_HEX corresponding to a debian login ID,
|
||||
given the associated secret token returned with the ack,
|
||||
by running the sha256 hmac function. For example, for login ID srivasta, and
|
||||
the secret token 0123456789ABCDE, the following invocation works:
|
||||
% echo -n "srivasta" | openssl dgst -hmac 0123456789ABCDE -sha256
|
||||
The vote block represents the ranking given to each of the
|
||||
candidates by the voter.
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
|
||||
|
||||
Option 1----->: Jonathan Carter
|
||||
/ Option 2---->: Sruthi Chandran
|
||||
|/ Option 3--->: Brian Gupta
|
||||
||/ Option 4-->: None Of The Above
|
||||
|||/
|
||||
V: 2313 00230fd5e1d4c86edfefc517d88a8a6421826b429fd2eb50ba9671c127897e6a
|
||||
V: 1234 00a38267cbca56da01221dc49c7e8a0d5c0c92ac6943736c47301b76f07fee55
|
||||
V: 1234 0104ae27ece19d7ec3c44235f5cf3d7f261da7199b90517045bfd1a9f9e2815b
|
||||
V: 122- 01615815a269fe2204dba1f2ed62646b2c88406f3de4b4a6146360e1636b17fc
|
||||
V: 1243 017d19eb2a0ec8f22b4f0da0903679e2a029a6ffd6fe7ac97247bb0ce7cd308b
|
||||
V: 1123 02b68510f34e9dd4001b022630c1db0963d2dc5b631ecee71640c0d6d620b8cf
|
||||
V: 1324 03587b33eddc978bfb281892a55551b723f72871791cfb3713f697dda46ce303
|
||||
V: 1324 03ddd8e7530ad80a89a0e8ae3bc09fb8d136b565a478dc506521c097cdccc39e
|
||||
V: 1342 045f85c8bc3ae81c942f50e0683a31a2bbe34d3fde4adb6f211879aa87542e4f
|
||||
V: 1423 0553d6b166e9cdcfc40b02a8d616fb0595b0c0365d4dae15355410b123169aac
|
||||
V: 1234 05b31a059b06d5bfccba09fdb392cffb7e27451eb0b8a3cef66fa9ad99313a40
|
||||
V: 122- 05de119d845c3db2dc4f32cdf997408da48fc73f8a8de783ac7999c16c4fb466
|
||||
V: 2314 062c6f02a8458937f0f462010854b2292527a09f38d9fa82df990c0934ad8f03
|
||||
V: 132- 06b5c7c8f84fb0c88ad55c734c2523873029ff932e4d49b4f0fb5f95648da397
|
||||
V: 1--2 07b7623628d5dde1d3ced9ad560639940578dfaccf3739e50e4e7058111afa53
|
||||
V: 21-3 085dce24b409845a4deb8460237634ae3fc239a27b69ec08b6eb15b4f276efbc
|
||||
V: 1243 087d057b2e69670448fd5f60d428f2b93cd3ae3f2cad1dc18bcb8daf85c5bff2
|
||||
V: 1243 08ba708a7bcd34d0a08dbff732ad6ab00349b77504507681514c993c1f8d3545
|
||||
V: 132- 0ba19a57a9598d8a755ce61da4a55acb4131a924c0491db78333b1649f72ec0d
|
||||
V: 1132 0bab6662fd04a87d3a456da6ee1e965268a50301d2edb835c58d28daa863b4da
|
||||
V: 1143 0bdb370e94eec3d92784bc19826c2e6221835c90660b8264e62bf14d68245e9f
|
||||
V: 1--2 0cec914c29299b7a40084cb19207869baeb3f135bbcc86259802b85c8c2de03c
|
||||
V: 1342 0d24800b8d57e28b571546ee17f184870bfcc4cef7cc8faf8b3ed1debc5d3c13
|
||||
V: 213- 0dc034010b256c0b1b72fa96d0ab7beba78d90a4d708d32d2a4495c453824e65
|
||||
V: 1243 0e5ab2229dfc9666e94a6c21f266744030383e4aa6c590f56e7236b447920fc6
|
||||
V: 1423 0ea1e5a3edec6da8fbf88ed662a19e6caf5891460f2fcec767f625e0134a4249
|
||||
V: 1432 0f3a6fd53289be2a20764c36f4a9ddb6b6561505b449d12d44f246ca3880cd77
|
||||
V: 12-- 1051b91e22d54b50e70ec2ec9eb90a7ebbb55f4795784d84bd60fa06d27baf3a
|
||||
V: 1324 13bbd22d648f39b52e28e39324efbed56c107030187f9fb836828eb72b47cc5e
|
||||
V: 2-13 1453adb5e5cb9adb37fb879054672c81466d37795b01e2163a6de88832623927
|
||||
V: 132- 14dc579f84696e02c6da84960ff5057d101ab52612caebf1bf82079b6035455f
|
||||
V: 2134 151130777ad486910fcdaf47d71340d7bc97885e9e445551cbbf3965cbc4153b
|
||||
V: 1432 161e7cca0fc2ed16289b488734a1743d85d66bbd548a10200dad251abe20c745
|
||||
V: 1432 186217749f7512384f01aae7e3b02f5b48387b8ea72b46bfcb112b446cfdf0d6
|
||||
V: 1234 18d533341ce06a37e6328fd7bf557b03e09ace5556d2e671c9eb1b976acddfca
|
||||
V: 1234 1a096393a22ed2bfdb6cf02b59d9ba83057a50b6f339439a7d16e4da17c9e0bc
|
||||
V: 1112 1a0ded7512e931634e34a6bd70079e7ba5dd8ce8dfd5e632850ce3ef17f14722
|
||||
V: 2143 1a126954cec275899d8ee55beebc50648d7ac4e7585890073152e69f107ba689
|
||||
V: 1332 1acf0431d98eb0d6888afd5f94713552d2118ee2a70f77a3618f9b584192ec30
|
||||
V: 123- 1b3bf8eebc3b4ae959f844f7ea40cf538f5cc04bdd231c5113f98be72f6d8912
|
||||
V: 1132 1eb417dd3c44eb7f69625af204d89c232c4b0e620fae9ec3f1b93d2b9844a416
|
||||
V: --12 1edc3a57f6b9919d80de8befecc9435ef9cd93ea52d52e445cacee0acdea213c
|
||||
V: 13-- 1eeea04ed2aa31e13e343cd124cb96fda976ef90d533d6fac2415ba23c187482
|
||||
V: 231- 1f0b97ea0043978b4095ea3a58fd02fee5cde226a24b8c1b84d498df2c1a6620
|
||||
V: 21-- 1f38b144ef16134d85c49c34b5baa25cb541125c39e8d77ab1ff840e3ac4a0ab
|
||||
V: 1-1- 1fd42b5fbb1400cb2b8815e9d595fb4a8de78336e3ae2c32fe7b972a08cde8bb
|
||||
V: 1234 2069c55c2c2a39879251ee28085ea7fcafd474c0a9adf71a7cf05710a5c09db5
|
||||
V: 1243 216c76dcfd63d942e1453951d5ec89ce43e5f1e579a99bf5b232cae308915694
|
||||
V: 1423 21e9f11aa81008acb5ed4651cde7444e988f535929ee2bf48509f9f5a02a574a
|
||||
V: 123- 23117fe84f1e2e4438d1637961f6eeac605b931477fcf8b41656b97f32032c89
|
||||
V: 1432 23b10cd32ba0ff66b69720d5dbeca6c4c93139a826d240825d808a91f2a64d28
|
||||
V: 1234 23ce2496abaa5eea4c66d1a93937b6062eb0449cef6262036279e5bc74267936
|
||||
V: 1234 2501bd56f7321c5658adad5bf40e62fe833e81f6eaf8573ed9db03ede7e29572
|
||||
V: 1243 260d9f85b8f240eade7ac80b4129b2e422cd76b3c965c61766671d7e5ff87fbb
|
||||
V: -213 26620d1f5308853e02685ec9fa36185eca36d7e2c9183b037ebdc2ca28e62472
|
||||
V: 132- 26db6a1d63640b11d2c0f5a44e09c746aa506ad049d5cc5508bc1e2309a7d914
|
||||
V: 1243 284834e16622976c9ba3feae7caab326255bc937b547e4cb0a5db9b641847fa7
|
||||
V: ---1 292ba49a9d13ac6688dde6c06284b1f8e9a122ca974b6e64bdfb8a5a8ef16792
|
||||
V: 132- 29ddd123d7c1d7228b8f04a7c357b8bd525b0b985d1164e0666b6ab624e121d8
|
||||
V: 2143 2bc79ff7b56ba1b5f973e2d686cf0fe8284ed02192e56b336aff541a2f9cfaac
|
||||
V: 1324 2c19f12a63d779d18bb786ac528ad8703e3d273fa766f9572de7c5d92c076d87
|
||||
V: 1243 2c309b4c136043e04cf5956a6c9bb8b730572112d1abc4898ef48d4b49dcdfea
|
||||
V: 1324 2c4cbc9fa4f9ea291ffc2d22598a7f0425524824d39adc4424a91ffea815b4dd
|
||||
V: -214 2d1a15cde460e780bbab7864858e05bf946229909053ca74c1c740b358d4bd2d
|
||||
V: 1234 2eba3f1a686253d92f5b87c05946bba17bf3ef377cc99549416300ffe68bd119
|
||||
V: ---1 2ec9d0c0596db6bdb00c776f8f5a984946af44a2d223e99f03495e8d97e2a9bd
|
||||
V: 3142 3090dc887814dca97535dd715044fb156ac3924beb40e278c9604ec3b094c73c
|
||||
V: 1234 3173f1d70ffa85e2f68a7c8ef19d4cd7f51cc1a361a89dac928800d195027b9f
|
||||
V: 1243 3184d63ca3cf69e8ab4b6065786da9675325ab781462f052a82e3903d68a3273
|
||||
V: 1243 33ee6bed02afa4a2b68099485168b759bd05ba9265f88f139b71cec1c7a3ba24
|
||||
V: 132- 37ad76134fdb50a50a2ec09baab6e0bb3e1c94c0055e8a0b2ac2e53659f01121
|
||||
V: 1432 37c2766c4d7c94ce4f3645656d814ac1b91d802740d159af0c6d623f9bc58789
|
||||
V: 1223 381b844d8cb7f3e4422b8a41e6a370416eff97d58040ef9d68ffa212beb47f84
|
||||
V: 1--2 39181f9cb392f8827ec6156b704a5c625c0eafc59356042ab9adbfe636ea4a61
|
||||
V: 1243 395bd339c374ce48ccb2c25626345d63286354c4e65bdc50390884fd860e8a26
|
||||
V: 1--- 3ad0fc89ce243ce38d98b6cc68df05ba7593f1a71dfd4986b1861d11f0b8454b
|
||||
V: 1324 3b9d015bc558b6b18d66b1fe1d0fc6a2476b0612e051462653ac24d300a59537
|
||||
V: 132- 3bdbc10ffc8965aaa8364978c47e6c939bf3ed6dc6ccd2f76fddc116dfb35aff
|
||||
V: 3142 3dea431f16502a73772a3d92d86e321a2a33d8f0477f0c1ae627012844d052b6
|
||||
V: 2143 3e7cb35db49524a7bdb03497210ea62402fd77ba6e7d50ef0ac9ab19faa5ccc0
|
||||
V: 132- 3f376d5d675041d3cf20c7ae80409363a26a2474d1b9182f44fd5537d7738a7b
|
||||
V: 2134 3f831cbb195e8130e3d4d7b430703598e2e1d1280232b5e798c164017cdd79dd
|
||||
V: 321- 3fdb669d233eac37cd3b4814f2492b1db3b00d9b7d58633a5901e19849d56d30
|
||||
V: 1243 3fffa918e99d969287ecb666e02d1ed0d94ed05d42554434f62044d1a151c1e8
|
||||
V: 3142 400458b4cb458c603567dac49b656a878c3fc92ad12e806e89d6f8c009e3b1ce
|
||||
V: 3134 41dd69104f361489e952a4dd09cfe48e53db931769329e2bd0b0ea8ddbb06a40
|
||||
V: 122- 41ee96f092b29cb1c0ca37e5e35b468470b9895656650a375b4d6904082be689
|
||||
V: 1332 41f26f6bfc07601b29a5b37c5ee991cf64cd25b2aed7b48bfcf8a10e9684cb7a
|
||||
V: 1223 43036914deeaca5a3192703254620fc558953937b86289681ad1443fee066e43
|
||||
V: 1224 44b7f1a5b9808acf6349f218abf41c6ffbc7c89e9a12d4dd2f1420dee05ba7cb
|
||||
V: 1234 4512c7af3d347c0ac67661a0b7b118f129147b814bed56c99d1253c2fad1ba8e
|
||||
V: 1224 477d6b7e8b19ff5ce5a992a6cdf2ad237d96304ade46c2c81ecfc99158e1d4e5
|
||||
V: 2134 47857bc01cfcc6e4650335007de8bc071b806ea92a2fd023ab566d0e89aa5464
|
||||
V: 1324 4912aa46d364ea1c951b35f95155bce5a8f2fd7510fe5310b898b80c54e317ae
|
||||
V: 1324 491b838d26c32c9fa15b6a7f79c428cbcca0b4cdc9bbb8c5602b0471bcc82e46
|
||||
V: 1223 49d8a2109ccf6f4f0337a0675d866c7b9fc1eb8f8d603d57424ec7999c2c2141
|
||||
V: 321- 4a8af63961802228c24ca6c12ce8e9314ac2e47704133286c1534f76d85ce8c5
|
||||
V: 1243 4b2aac61a4d2fe9c81a3c4dce5b447d15f092cb348d8ba41311dfcdd28db2256
|
||||
V: 2143 4db60fead16f807ad0179aafca04ccd016b467451c5f7d69b0ac9c66cfa9be17
|
||||
V: 1223 4e9c0fce8c1d0a7135de0385d6bce3e96426477e4c3603ba426477e9d37b9f69
|
||||
V: 231- 4f7c1ced6a867a03ef9930f976d24877bbe8967d93e04df5f5a5d0019960d802
|
||||
V: 3412 4feaaa2111dd4e68de721ffa3d38d73efda5dffa4a1f6b1e5db373bef286d9a4
|
||||
V: 1--- 50704d439bb5fb104218313f34ab8af85e33bf2cde0d5c9e1d265297af6df010
|
||||
V: 12-- 509dd76a0698daad30c206b70dc20fad0b8e0b257a1b4fc0ef4c22870de3cb33
|
||||
V: 3142 50e8b2b548e000c6c799e9c5ccb8e695d307e4b939036837f19a0e3543c6669d
|
||||
V: 1324 51635961ab65280f91b5dffa400d40ac4be172f79992b9854b196f764810fd79
|
||||
V: 1243 516f46fb19c7f540b47920f89d016b20ef0bd9ce109fb9e3560e6148aeaf80ba
|
||||
V: 1324 518bb1cfb457acc983e07c75c225e6c580227e5b7eb58d15c2a4951fa3b24eff
|
||||
V: 1342 51eed5a592fe0f6b602cd1b930744bbdf3c2acbba1b713cceeb0a47b41a61bfa
|
||||
V: 1324 52072e9dfaa3e288ac7c6c4e996d9d213191a3b7e1ce41f35cba0f26c278a39a
|
||||
V: 2143 5221af94b2dd98c45448b21f3fa1d647f06dbff91b3c2f5bb670e863406656e4
|
||||
V: 122- 524776b066a0246ea93c565f1124db9712c24295ae372040f6bf117b9c128c47
|
||||
V: 2431 5448422e27b967db46fe1025488ede682b1861069c2dda98657d400e6e0831a3
|
||||
V: ---1 547fb0314fe14791b18accfbfc2c565dfeffa209c16d9fe8bc4e1adadba54d20
|
||||
V: 1243 55fcc1800eb8048ba76308cb27ef8c04012a661a192f56f49eeaa18201a62dda
|
||||
V: 1234 564245f302908cd54b512d64f179090fd31a8503b8773abbfea9d8e9e02cdcbf
|
||||
V: 213- 575afc0d3ba0ca08d6586d010dc1c359fe9367ceec56103293385fdca96f959c
|
||||
V: 1234 58ddb039c66074ac1690358db20491c6f50623d47fcc828c3dec927e4d621fb7
|
||||
V: 1111 591cb1fdc78455e36cd85e2f8bcddb74736def1f5ae7ad477fedef1e1fd8b3d8
|
||||
V: 1243 5a1175ca0601f5c174484f13d1236881612dfd5fbf322e72d6e2a1b511149616
|
||||
V: 1--- 5af419c1c3716030574ed08c976752e861f386e62e61fa7d3a5de889f527f745
|
||||
V: 1423 5b3b2777c80f107e3e7aa44b96dc8a3eb8499ca77c2bc8c3f84910d89c02d0f0
|
||||
V: 2143 5b6250931b5f647bd4cfa5509ffb998b42c6675797ac3abd0aa1da567f7a695d
|
||||
V: 1324 5be337340d15c2d240e38fb5c71185e32bab25eb937a95cbc38bd904aef11d4a
|
||||
V: 1243 5c39a41afe845b06980019ef07aace6e9c64352eeb77a071b532b81a66f32f5e
|
||||
V: 1234 5cc6847c1882bc189c1885132781e4a48326d88feb2f58245e7cce405f4592ce
|
||||
V: 3142 5d656881e0c3159be593b204c7ea776f44e0848b4923eb3f486e165609771608
|
||||
V: 123- 5db083f1f2e5b1e9c2744a103b87dc3821b7b1e1c04366f9316f39f387fdfeca
|
||||
V: 2143 5ddb66fa11786f5e4c5310d62830f2207449b14f5c9e3fa2483c172d179cd17d
|
||||
V: 312- 5e66c5958e186f66966ccedef22cc44c4f951c6b9370d4981318809b5353a258
|
||||
V: 1324 5f5656e1f7eb9f716682473619da394ceab35a2f057b6b710038e641e68c9364
|
||||
V: -1-- 5f995e23ffc5d0472a8c9c47e31d0d89b616619026af164cf9a825d8bc0ba316
|
||||
V: 1--- 60df9c45703d3070b2478958f39d1920e5f8ab47132bf166127d1b02cf1dc3d0
|
||||
V: 1432 60fd60a3e86b21489df394bd077a9c2ae852f7eda146e4854a3e979484cf7325
|
||||
V: 3441 611be55bcd57fc89c016bae02331ddba792f218ad1d8a19434f374e5ddedd6b3
|
||||
V: 12-- 6122856a4782805b2e6344f0b46b02303f630fcf48e051103e24ee1c742b0e0a
|
||||
V: 1--- 61a109bf6db7dd040e3321cd335c4ead5d479901a51cc58de3c408272d722310
|
||||
V: 1234 638ff677bb694b99a45da3187b45146660b7c48a796a24add68188ead7d729b4
|
||||
V: 1342 641bcca8c7a20e1668dc94658f01c85c40e068d66e4f386d359b5e7191cf8fc5
|
||||
V: 3421 642682889d4ad50f32e25ee327d181bf04a17396a1763efed6a709672eb81a60
|
||||
V: 1423 64b2289a6d4be7c4bd71dbe24332e7cc998d7402f7eb2ec83f52353892f5794c
|
||||
V: 2413 64f36c07e169e52fe1194e3a579e2572eb76ae2e4f6ef5f43e0b5b4d8f42e3ab
|
||||
V: 2134 6567d243a933775e2ed9295b6119b3d0c7f7083621e3345aa231eb44d1d74327
|
||||
V: 12-3 65727b46046d08cc287a31437d1151926d633c56a59aa6c739d9504746302fae
|
||||
V: 3132 65782607cad77a18d407affd55b7598698cb538aec207e461384ecd9fa907108
|
||||
V: 1234 665c01ea8f42470faea4865677c8e6f907fd2d7263f5f41c3af967c65b7ac87f
|
||||
V: 2134 66651c00d9cdf52c46d3d38fb19970f605d1b352aa21fd8ee69ac3e8d7bb338a
|
||||
V: 1243 668fa18d7a1d0dd597365487faf797bdfb83f8871290bcb35c240b2cb5de7d52
|
||||
V: 1324 670842dc2ea834a83df2179525537054e5f99c483ba1f3279b5ea2e77f75bf2d
|
||||
V: 3214 675bbed303062069bb8e1484b551ffc198a723f4fd735f49515c964545bcfefa
|
||||
V: 1234 67a766ddbce1a86891a9f15d4a01b5190da02ee9258368bb71d4e8bff0f70aa3
|
||||
V: 1134 67f771b1156d5a82b59187c4e4a490d8d4d5e88f383f9995067828ae91919333
|
||||
V: 1243 68f436c1a53db55420d006a73e9777ed2cad57b7fe9bddf0c3400014f0b309fb
|
||||
V: 132- 693fd519a6ea39a355d655b1d985ebdad5dba4c5fb8806dfe84de5c09492316f
|
||||
V: 4321 695317bcaa6cde855e4f2c47ec690e8c95e737ef4df95337e886c8b5acab27eb
|
||||
V: 3-1- 69a8ef1bfb1a6f8ad9c26f5647e646e722d8d99f645a8651cb83823c2573a77b
|
||||
V: 231- 69eeec23bc5161193d250ee139c8813d20a81ba524cfa783df1db781a22af54c
|
||||
V: 132- 6a76e47a0e3f9868345e1fb532009514439407361fd48fa24cf4634ea2622120
|
||||
V: 2314 6b281305b6bf76b1f7edd6a6f26718b058990d09057bfa9abed1b2927bcd4aab
|
||||
V: 1123 6bf7daa3756b8cbc45f65571bee50bc2b5f7c86c69d7d3da4e6cef1771736e95
|
||||
V: 123- 6bfa769a65845ee681a42d48cebd8c61697c2eaeec5def8091b96b63ed6b184d
|
||||
V: 1243 6c4fd1bde48da1ab15e570dc4978c605c287440bea8b1031869f17d709265a9f
|
||||
V: 1234 6e38c35452e2468af44eb307c96bc04f4306db04285706332fddce6284943049
|
||||
V: 1243 6e533b84daf0ac9b80a21249d00cc31b6e5b8b16ed2d5291975365f782ce9e8d
|
||||
V: --12 6f3128090510e3b3a749a3da3718a347690b17515e472287c00424693a6c94f4
|
||||
V: 2331 6fce63ac5677b2432e969dfad5cd27369c163f2f8dea4bf9c28434b888104441
|
||||
V: 3421 710dc7db44eb6af16776c9e32155f45568a5132c1cf29f4298e453115e25456d
|
||||
V: 1234 72392dc6cbdf61b2d0c35c654e1fc7c0f3a6821b5ef821942483eb620b438744
|
||||
V: 1243 725540f8ffde4cba4f5a77efb11154a68d42d8d1a17a953b8cf11340120aa7d8
|
||||
V: 1332 74c31d4c0ca6fc37392e93076f999398112c795c5d765455499a7559631ab47c
|
||||
V: 1234 7777671d528f4c7acdb7857c3ea933a0504a9a08d9b24c6b8f500efc51fea4fb
|
||||
V: 1324 7b59a47801e9b0852184c6521151992f8be634e272d2f7e53864e8de1ea87afe
|
||||
V: 1--2 7b75c039d6aba1b5a61556bd4bcdba732a4c4922336b51340ab5f1154cbfc370
|
||||
V: ---1 7cfe95f01abb22402733c37c9654f19f3baf90233f515390eea05a2aea4fb9c6
|
||||
V: 1324 7d36731d43b81ef1a40193be3d227cc2c2f8e3137b8f383d011914e9c97e3a0f
|
||||
V: 122- 7de6b2b78e6f33ee68a83885ec411e052c07f2a22e7a4c54fa103a716615694a
|
||||
V: 321- 7e7da318d8ee61ddc5be7ab6ea5f16e8066ce1c60d40b78f7a58061370aacbb3
|
||||
V: 1442 7e94db0e97920f35e5616f635d18f7e3cb2d3c19fb4929c3419abd62c3fb161c
|
||||
V: 341- 7ea7456c3b1b212f6754b9cc99a395d4256e81148d1e95ee930fb8b05b6f70ac
|
||||
V: 1423 8033bfc957830b6f1e8d739736b19fe0db88dc159ca2ae6d7d3652fd27d40a44
|
||||
V: 1234 821d21fa4ef2127d73d1d9f1c3006d5a0dd51db4d0d687a1303ff4dadbb12dbd
|
||||
V: 2331 82b981f25f52c7269dfa90351113c063db8aac32b8857c1ae8feaf27b0539683
|
||||
V: 1234 82e5a90d81c2846febd1674c8c2dfa46b9a677b1a6e6cae56d33cd2ca0c331e5
|
||||
V: 213- 83190b8340ed97e2e24862865c0ceef1a8231a8c57256909aa879fb62615f507
|
||||
V: 1234 83ec9391805a79332864d6ff4d6d7b541a6b36fd2c185e00594125e601672c6a
|
||||
V: 4313 84f851c39fdfa82eb08b62fb6d881d50d20f226fdf5c77d00241aa0a876430b4
|
||||
V: 123- 8598965da7900f506c7385a33ca24cd9c321606e383b16f86031fd1c395ef616
|
||||
V: 111- 85ee8de9db19c908d4107d0fe81a43bd685ac2d56280354006b11ce3c4ad6372
|
||||
V: 1234 861f87d31834385501ff9e5a452443878c02fd7385c7b9e8cdce92c2dacf40e7
|
||||
V: 1234 866c240c9c28f0e2d31f11d925aab7d183eb724c4d0aeb83be07c05cd1d332d8
|
||||
V: ---1 86d1fc4713fbcca183523391c7f5497cfc4be98a5b2dd11aa6b727e1dbd5492f
|
||||
V: 2314 86fdf98bf698febeb33300bc0e36942618f9e21b1885d5c77a0239898009748f
|
||||
V: 1223 8931a8b26a2fcf6e39aee320db7ed3b15aaeb2c6c28fa41d642359001ac9ec0e
|
||||
V: 1423 895443c7eeb83d121711181194ba5b8ec69eb5a97532e8b4839e9693b205071f
|
||||
V: 2314 89c4b0f8625d54c44fe6d0d7b5d28606dafd36cdc0fe10bf77080e6b5b65233b
|
||||
V: 1233 8a3d51b9c0a1249f5a4f42de84079e946b50a5a553cf6e575166d83685421086
|
||||
V: 1324 8a850f90b5282c48474e15f91b5503888c8d806ad07f6e75fee314c47f37ceb1
|
||||
V: 3124 8c07321c8a9c9247976f8179082a1fc5adc87201fbec0e327e89864bdf8a6ad4
|
||||
V: 3214 8fb98206cf3b14222eaac4b25c94a238236fab634ed0784bf0af1f7b7040f60a
|
||||
V: 1324 900018d3dd3d39d7c592411ed5b483921e936a02901da2720f0062765ed70e53
|
||||
V: 1324 937c6eb3e558e859d4021507cc44e8bc8a0a8df7db2bea30bb141ea4f8c72b57
|
||||
V: 1--4 945705fa99e567f0f695c204737f76de576254d659f1e34e5042fb8a1da79117
|
||||
V: 213- 94c4e731e175fb1ddf4836cc9cc78c1ce93a953ee6888bc9a1438bfcb4574eaa
|
||||
V: 1--2 95299541aff780d727f9b4014ca7d85b36e5fc822df919dac720408527cac2d2
|
||||
V: 1332 9619afb74f4bd92c8a8fd73bd89fa0cec98e555bb6621da1318e572b6372a4fa
|
||||
V: 1324 9628e21866b0e71806d52d43f31716867d22320b88189203749ee4419757ad23
|
||||
V: 1234 9658c14a9d998f97728e9ac84bc6928e4efb6889d0a5c43e378bb3022b760e24
|
||||
V: --1- 966920501d6f5f38a7e8a5a1d9fb52339b72e6fd30263c63a95ed892b4713287
|
||||
V: 1342 974dbdc06aa63fa6a578f5a53811b3c176fd96c1c00691ed4aff0329a5e880e7
|
||||
V: 2221 9872b34803c05770209bde3a060f1f292e1e7cb88b44dffeddad41b0085783fa
|
||||
V: 1234 99547a1d62c9268b50d18055e16547756960c6eedb1e0dca8457090de3d27d55
|
||||
V: 1432 995a9465cefdca35c49cf15e5ebb3cb9e8b28921aa87486a56cfbf0b991b0fd8
|
||||
V: 1223 995c49eafc96472d28dd64c0ce12ee2b95e17bbc4cfd50c5f4a3b7598e83c272
|
||||
V: 1--2 9a7722ac85e84660801705efc6435dafdb3ae761c261ac90c4cc4f30a9304e14
|
||||
V: 1234 9b0838f5891eeef1df87f1dd5971dbd32a42573927292fd4fb0c60258225199f
|
||||
V: 231- 9d2ad16596a2fd273d94f3c44197ecc2ecd84317e7aed88dc40fa9615c7ff5df
|
||||
V: 1233 9dbcd73dd95c769e47b95cdb7c09f199959775143529b113edcb904ca1413532
|
||||
V: 1132 9de1c25d174edd05d7c30535517226a1bc52a498d126c4468fe690fa6f524729
|
||||
V: 2143 9f18109633b37d11dca369c31ae3c41a0f82f102ae33ac609e10e96db53cb9ef
|
||||
V: 123- 9fa2683057f83695a190663fc0e2f38fef669e0f74bbb5904d99b64aa8287d6d
|
||||
V: 132- 9ff7950887b5103d5d8d251623ab7e887c153c7de4eaa15602d1ffb962873afb
|
||||
V: 3312 a0a8965e15509244e9b4a87f5b05750dc92366561899f8fb5af3b1b1a5d29436
|
||||
V: 2143 a18fdad5c8c4dee869e3f8aba9d53dcf03dd32476d088a3ee6b0f33054a75deb
|
||||
V: 1324 a209cf013669c8a13f31b2cfb23f0889d55f89f7ca8701c3dc0fa5d4536f1ced
|
||||
V: 12-- a241c88b992936b69ea99a1de315440ec715a9bc1a05fb8580a503e7885cf912
|
||||
V: 2331 a2488cc3e9e4a8e927173650d665c62f414ba90819fe2d9af5877ff454afe305
|
||||
V: 3132 a4ab151cad3197e7b9e80b60732f2283c2f8b0d4e3a3fa716f54fac325d2f30c
|
||||
V: 1243 a4f4c16e3d740d1be9bfdea40f6678813b157d7d91b61e8bdbf8f3812be9f291
|
||||
V: 1243 a63f9d3a23b6159fabf45874c00bbe178c0d5bdbcd726c19a09b816a3eeabdc1
|
||||
V: 132- a79eef235c0530dccab92913cc6bdc8ae62dd1a27e9c5f753d25a25865daee67
|
||||
V: 2431 a7e963cc242119d8583d541830fb3e6b5de7d0c28175e0a402793332fe7c74b5
|
||||
V: 2413 a8293b1c65fbed212bcdd2199c95ed1b323792dba3be913df45e29bffdf3fba3
|
||||
V: 132- aa40bab0f832f3c0b6f8e3bec2c08a7dedc48ae527d6063dd1d7c72bf07b5f45
|
||||
V: 4444 aabd62acd6c8ca258a0a716b3c9fa9ca24cd3e3c4b8c77404da2d3883fb81e12
|
||||
V: 1423 abddd5dc2e3cfa1acddb5f386992f4a73316d758337d99053df21ae1fcf19ddc
|
||||
V: 1234 acd0ff84b59571e14b98fe995697060303c8279e3e58d4269a2ab0cbeb040b4f
|
||||
V: 1-2- af0789d52fa246a8133df11e17bd4b60710dc3a3c70313fdb7b8b4f037f8bd48
|
||||
V: 1243 b028e3bc08d2c8fd5374b8ec5b65587cf501bff569c3bfb3c7088db54c581829
|
||||
V: 2314 b0bf1709ce7a978839d463c9e354ee0ae8e5b099c522baa1d083668e21dbb350
|
||||
V: 1243 b17d9dd78a6d16650581746d56331a67e9e9d5a8790b1068e930d17b0c85ca16
|
||||
V: 2134 b1ff74d6019227f860cfe394d33112090bc0fc8ab525e424f0ac393d2ed4477a
|
||||
V: 2134 b2118cff55fc5c3c40fc1f35a718e87bf0ce4326bb01287c4a840feaf1266084
|
||||
V: -1-2 b2647fdbf96a8f9d5ba0722e1fc0575951f61e8e39f3360ec238b2bec4f31f43
|
||||
V: 1324 b2ad4279d784eeeb41cfbaed5396fc412421361cfcfe9d8f7a39773f2e47aeb4
|
||||
V: 1234 b2b8f07e2a6eb4e60e76eb00f86c721f0d52a7cd3ad9687893fd1697a7b0ec32
|
||||
V: 1332 b3282e1ace028119fb12431daca45c798ab54916a986d55c92b8106c9fa5b90c
|
||||
V: 1234 b50c1b62fce7ce8befc477d9781ad6f036f2d281ad8d5424a94e03f7d5ca7d84
|
||||
V: 1324 b521fc2e8281a53bf3694c66d2a6394547bb9dfe1c838790053ba5282abcaeed
|
||||
V: 1234 b55b7afeb537fa892f93996fb4b69a72ba07ec6c82529006b91faf931560af28
|
||||
V: 132- b57abea86a397f16384d0c86d1049feadb7f1b639fd4c96f7454e44c70b64d0f
|
||||
V: 1342 b7d63d41965da9e483d6660806f44084f60cf6d9d3ea91a687bd85e19e8e9f3d
|
||||
V: 1-2- b82f85d10f4ff97f0542815b64cf1c8884694adb1414b76b9db77e8ffdf784bf
|
||||
V: 1324 b94990cb249ad507a294da3da2301e6741cf697f9ebb61a2b2698a75ac18ba38
|
||||
V: 1223 b9c6ab7341fe79f71bb68ede0b97bd58280187f71199522bc294ecf93a81ec24
|
||||
V: 123- ba3c715b7f3b714394e82092c2a21cfb43e1af1c087f9c5cd4198bbfcb0c457d
|
||||
V: 1324 badbdd9cc1f2cc99e903193ea3d6cd81a00195a3d1d243247621b3122497d70d
|
||||
V: 1332 bb8a5f01bc35cbd83f156c2310699bd7f9fe6438855af3742a94977fe01305bc
|
||||
V: 3124 bc815b156abac6bed6bbc8560fd33e8df18097b097b8d2752a17ffcc73bf0e92
|
||||
V: 1312 bd20e4e7057b9ddf916da20b67a64fef4307b3e8b5e6ed1fa2d3eb83cbb2eff8
|
||||
V: 1-2- be58de50429f21fb6f069cb6191349a50567cb9f48eb0fa190db668280df79df
|
||||
V: 2134 bef8ffb42ba8cf0973962d2320ae055e1f420e5f5e36aadb3bb15c1e28deb18d
|
||||
V: 2341 c007d9c20bc7e5b1a97948315dd815ef95d0825ab755725b217e5c8350d342c3
|
||||
V: 1243 c06f5f8b93020633dba0dc34fcd4ce9e1bb82add3f59248f227c0dd20a157acf
|
||||
V: 1--2 c15d433a517bc451df1d3b5e72371c11998657244593fe3df192d129e3b837f3
|
||||
V: 3-14 c2b77edc07f3af06a1e158ce55ae36ba0f3dfaa6e55f6071f7ee6b4eb381fefb
|
||||
V: 1243 c3134402f85fe8ef5abebefb70654a0ff3bc4b7ed8d567b3f927189e33df6716
|
||||
V: 2--1 c55768b26d1e5a6b48442fc898fab4b2bf7777046b03cc663415c8fcf46dab84
|
||||
V: 1342 c6f41abafe4e8977af77d294a40b57ae3b931c716b11cfde884c7662a71b9645
|
||||
V: 1332 c7817348270724eb35c3a76de22498161d509359d95e4f160be337bb393f1c63
|
||||
V: 122- c838f17d30d8b2b957cf49775a468cee64f3e13974577710fed81041741ff3f2
|
||||
V: 123- cabfc096aa5ecf42e23a1391b3a236a50ced3da47c93a2e8bf8cdd67ef87ecab
|
||||
V: 1--- cae83e3c79fcee59017aa741439df1b6f8192f57e0aa527ad3ad626b049da031
|
||||
V: 1224 cccd5b5f7310307167c51806e0989a134c91a3a593779f4e4534afb5b62cdc2c
|
||||
V: 2134 cd0c5ae8ab69cc44596d24a7c7300e9fdf1cb4e4f9b8f07440146c4096045440
|
||||
V: 1324 cf056bfbb7436ea53e6ac51517f1ec5e75736b81b98e7b87b5ecc110b643e65b
|
||||
V: 1432 cf1bbd2e9ed2306307631135af81e850739483890ce405ab9a0a0c655b8fe738
|
||||
V: 12-3 d018469cb6a8ec6c80b6ff436279907e97ed5500944e9688fd62d039581e406d
|
||||
V: 123- d109ca02ebf28bb1f45a55b47c5ce4febbc2d74e4609528bb8e0894bc2762aef
|
||||
V: -1-2 d1ad0078098f332d54243a6eb45897aaf24c7c8398001638c96a243cd127bd93
|
||||
V: 1243 d33ad007842ddb9a16a13b5b8042d267134553e700b59eef9febf109180e69d8
|
||||
V: 1234 d453d3a6732b845fae67430993f354acd5aa442a45f3fc57aa3a6004c45d1f10
|
||||
V: 1342 d46078625095fb5238c79e7015caa7e452d336458161def6a3ff0efafbd65b1e
|
||||
V: 1423 d53e129f0e8de61631867d85c4f0e340bbc3bda995fe6f7174bf52ae3ab4a818
|
||||
V: 2143 d607c68d0baf141c404266193f73cf16a7b7d7ed3b4e7bd96c3f4fb1d9cdcc86
|
||||
V: 1--- d6612fd623b2aa5dc1c74dcea2b25eea828695a0c929fff8a5c191801167aaa7
|
||||
V: 143- d742a7a26ab23a4302d6f6a1538aea3d7a4a533bd8288f18623858d0f75d6b47
|
||||
V: 1123 d76800ee67faed96e04fc79fee0d277c477989055bfb583c4472ec22d1e16fef
|
||||
V: 2143 d7eddb6bc259a081e6f260855ff203f377d520cfbb62acfa691059fb787aad16
|
||||
V: 1243 d808a6229a41c31a17fe17e4bf4eca2bb754ce45c825b29a8d1c5fe2a009a84b
|
||||
V: 1234 d882c5a434b340dcfa9b4b1ab418d9248bed5ce5e3b47899b36e86de615c691c
|
||||
V: 1243 d9cc4807186147d165e8502076dae5c0d6c34e8c81f3206b950cefd80bd06358
|
||||
V: 1243 db07d43c82af5e797695293a78398712c0a1015e14a74dfd438faaa69b8b9920
|
||||
V: 2134 db4417cafae7cf1fd8961b7d4722e116c583496183cb8b5b9ff54aaffd6d5011
|
||||
V: 1324 db66a3144ca4164b78d755e5e1d12c69b727c76117200c83433ca37056a64c8e
|
||||
V: 1123 dba989d730342e8f9187a40724a9db2b51fb6d4f8829f676f2da1ff514f54b3a
|
||||
V: 1324 ddd015d992805d78b0763837e13f6b12ed2ce98af64192cfcb0b4f7403e7ff77
|
||||
V: 1234 de0b883f0c62ab73d4b4cf51a02036828f3e50b828f419576d0f7de78163af9f
|
||||
V: 1243 dee08b1cad06eed24ea5fa8296b3517c2d4e49e7509d7ccc70cee8f9baf767b6
|
||||
V: 1234 df7b23c1e82ab9ef09f4f160624a62bd31ed66254f384b379a7dc25197c0deb8
|
||||
V: 1223 df942ed4951f6e2c44063ef5bfc2948e9e5c60f8e7228ca41b47f5d2d293cf50
|
||||
V: 231- e05b0c0307eb24eef7e3ad3246e3bb3a564688addcf03e26ec5b5bc89ebf8b4a
|
||||
V: 1324 e0fe58087a6be3fba15bca5d426c758bf64482089d0ef1b7e7f88ccff26e2bab
|
||||
V: 1324 e13eefeb5a11fa820951493620925cddb1f0b43fe32d57dc3620b0b0d0f5a965
|
||||
V: 1243 e2c239f9dfb960af46c10d63c0382c3b34a69324caef0f0dc198c81e40fb3d2a
|
||||
V: 1332 e3031b38717fab10a755fda6a8c1afe8327f0cb56cb7f5bdec4f66417565d599
|
||||
V: 1423 e3786f46aec93a7d0d4833805fca583c6b3adc30535e7b6a6fd7f9914d091304
|
||||
V: 231- e3c40e28c6ecd3496a9d0727c627ea82bb2cd473531dd343fefd20d051a21efd
|
||||
V: 1442 e3d83ca355450bc9ef01d9ecd4cc524df6d26d3e1952a34d0e8cf6fadb0ce273
|
||||
V: 2143 e4f7c618fd859a049309344bce6dbb1ac82d026994da31dbcdead954343e0bb3
|
||||
V: 1324 e645b42cd8df792e993298820401e1dc1608bfe5aeb0c3197f1a5056312332b1
|
||||
V: 1--- e6dd2e7a9026ae00224333bf733f012aa8ca9a62abe942749235bd20d5732c67
|
||||
V: 1243 e6ea5d80ace12a22759ab3a522df6efa2a1cd8b65e651fc6c5aa148683613b43
|
||||
V: 2143 e71eced655b7e055c1fa964d4f59a0a0d45469e6aedaed95ef6eeae89eb16162
|
||||
V: 1324 e7c84202b6389bb8a00c3a1560712ab3944a9e5ea197264ba034a79d1dcbefd6
|
||||
V: 1332 e9510ca600935ac70c5cf34f833bbc79b30ada9578050e878835bcffaeb711fe
|
||||
V: 2134 e993930a9d4138d33e2d035f2cf200346b232fcc211d520d057b020b741f7241
|
||||
V: 1234 eb5039de58c0f0822ae1325a4098e84b2ee7d9c7dade967daea76ddf9665fa84
|
||||
V: 2134 eb990ffe5423e829f3c574c70ea2dd85afc54fab693c6f56a516de0cce7e73bf
|
||||
V: 2413 ec8450663968fa79c74d718f8fd297508f0a9a61fa20986d60923029e0140245
|
||||
V: 1342 ed09fb58f17d81ec1445759c591947a1f3c3020cb94e1da95b1c24d3d43edf8d
|
||||
V: 4231 ed814e84f97eeef24ed75d4e378ebe94e7989dbd556ad49e2d10969a110d8896
|
||||
V: 122- ee831b442ffe9f78fabd636db19a3971fdbc6fc7492c35f8751332486e8da4b8
|
||||
V: 132- eeaa12e828b2adc09d2153a9af5f3c9d65b67e7c2c9dce28a0818bbde1eb56b0
|
||||
V: 12-3 f0292d5ddfb3b59c6614f781096d4287e1080a42b64b7eb0cec0fd1a28c15f6c
|
||||
V: 2314 f1038f35b8a74878b31a2fbca061b284be5ab60e685c538215f8f02ed859260a
|
||||
V: 1432 f1b88d5505eb7886a7a6c307ca283f24bfd4ac6f347ef79b16b9446e690600a7
|
||||
V: 132- f2fafb29cc8b773ff4e8eca280b80c4025e48ffbfbc35c754d865b21ab8581a3
|
||||
V: 1324 f39a4e391326f31e8eef0e1edcf606478b5860a7d2e68684d106966706abeae5
|
||||
V: 1324 f4f5af10cc6750cbe27630ee0102e6d650e8a8da75b3adc439dc86faf8e39970
|
||||
V: 123- f69965dba3253f4cae3de1e910981d04e4c215af4257d58e231b9919f7cdc398
|
||||
V: 1123 f6fef1d957364983901f9fd70cd1784ee91c9944ce5403f6db2261f53a2449cb
|
||||
V: 1223 f7d9f266a8860da5cae2f3f1985d0ec40ef8ba2646a7320eba6dcdf80e5ce8fc
|
||||
V: 2143 f7f4751708682d25f8926bbb5e3225456ac39256cf37a66320890513008875bf
|
||||
V: 2143 f9fda8051473bb5c506fa8cb3bf18019939003f85391f95252f5d3fefe613c65
|
||||
V: 1--2 fac6dbd7d23e398c32b281e7549f1cec2bc2afe057f22b112f2228ff70942cff
|
||||
V: 1243 fc0d80e20c401136bf89eff2f55714179ca1d78e30eb33dee4a63258edab60f9
|
||||
V: 1242 fc11eaee428c4a0f42c77994c72efd96f25a79db17f250adca5b1e7847caed40
|
||||
V: 12-- fce80a45bb9ec929c592dd441baa7d89ec08c6c511faead56fe35fcb454dec8c
|
||||
V: 1324 feb645c3d70b34a37ac206a023afbbe9947fa9ef0b03695927c52a1a8499446d
|
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\Election;
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\DebianFormat;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class DebianFormatTest extends TestCase
|
||||
{
|
||||
private static DebianFormat $debian2020;
|
||||
private static DebianFormat $debian2007;
|
||||
private static DebianFormat $debian2006;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
self::$debian2020 ?? (self::$debian2020 = new DebianFormat(__DIR__.'/DebianData/leader2020_tally.txt'));
|
||||
self::$debian2007 ?? (self::$debian2007 = new DebianFormat(__DIR__.'/DebianData/leader2007_tally.txt'));
|
||||
self::$debian2006 ?? (self::$debian2006 = new DebianFormat(__DIR__.'/DebianData/leader2006_tally.txt'));
|
||||
}
|
||||
|
||||
public function test2020_Implicit(): void
|
||||
{
|
||||
$election = self::$debian2020->setDataToAnElection();
|
||||
|
||||
self::assertSame(339, $election->countVotes());
|
||||
self::assertSame(1, $election->getNumberOfSeats());
|
||||
|
||||
self::assertSame(
|
||||
'Jonathan Carter > Sruthi Chandran > Brian Gupta > None Of The Above',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
unserialize('a:4:{s:15:"Jonathan Carter";a:3:{s:15:"Sruthi Chandran";i:201;s:11:"Brian Gupta";i:241;s:17:"None Of The Above";i:267;}s:15:"Sruthi Chandran";a:3:{s:15:"Jonathan Carter";i:0;s:11:"Brian Gupta";i:49;s:17:"None Of The Above";i:168;}s:11:"Brian Gupta";a:3:{s:15:"Jonathan Carter";i:0;s:15:"Sruthi Chandran";i:0;s:17:"None Of The Above";i:69;}s:17:"None Of The Above";a:3:{s:15:"Jonathan Carter";i:0;s:15:"Sruthi Chandran";i:0;s:11:"Brian Gupta";i:0;}}'),
|
||||
$election->getResult('Schulze Margin')->getStats()
|
||||
);
|
||||
}
|
||||
|
||||
public function test2020_Explicit(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(1);
|
||||
|
||||
self::$debian2020->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(339, $election->countVotes());
|
||||
|
||||
self::assertSame(
|
||||
'Jonathan Carter > Sruthi Chandran > Brian Gupta > None Of The Above',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function test2007_Implicit(): void
|
||||
{
|
||||
$election = self::$debian2007->setDataToAnElection();
|
||||
|
||||
self::assertSame(482, $election->countVotes());
|
||||
self::assertSame(1, $election->getNumberOfSeats());
|
||||
|
||||
self::assertSame(
|
||||
'Sam Hocevar > Steve McIntyre > Raphaël Hertzog > Wouter Verhelst > Anthony Towns > Gustavo Franco > None Of The Above > Simon Richter > Aigars Mahinovs',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function test2007_Explicit(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(1);
|
||||
|
||||
self::$debian2007->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(482, $election->countVotes());
|
||||
|
||||
self::assertSame(
|
||||
'Sam Hocevar > Steve McIntyre > Raphaël Hertzog > Wouter Verhelst > Anthony Towns > Gustavo Franco > None Of The Above > Simon Richter > Aigars Mahinovs',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function test2006_Implicit(): void
|
||||
{
|
||||
$election = self::$debian2006->setDataToAnElection();
|
||||
|
||||
self::assertSame(421, $election->countVotes());
|
||||
self::assertSame(1, $election->getNumberOfSeats());
|
||||
|
||||
self::assertSame(
|
||||
'Anthony Towns > Steve McIntyre > Andreas Schuldei = Jeroen van Wolffelaar > Bill Allombert > None of the Above > Ari Pollak > Jonathan aka Ted Walther',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
}
|
||||
|
||||
public function test2006_Explicit(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->setImplicitRanking(false);
|
||||
$election->setNumberOfSeats(1);
|
||||
|
||||
self::$debian2006->setDataToAnElection($election);
|
||||
|
||||
self::assertSame(421, $election->countVotes());
|
||||
|
||||
self::assertSame(
|
||||
'Steve McIntyre > Anthony Towns > Jeroen van Wolffelaar > Andreas Schuldei > Bill Allombert > None of the Above > Ari Pollak > Jonathan aka Ted Walther',
|
||||
$election->getResult('Schulze Margin')->getResultAsString()
|
||||
);
|
||||
}
|
||||
}
|
384
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A1.HIL
Normal file
384
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A1.HIL
Normal file
@ -0,0 +1,384 @@
|
||||
10 3
|
||||
1 2 9 7 0
|
||||
1 2 7 9 0
|
||||
1 2 9 7 0
|
||||
1 2 9 7 0
|
||||
1 1 2 5 0
|
||||
1 7 2 6 0
|
||||
1 9 8 7 2 3 0
|
||||
1 9 4 1 0
|
||||
1 9 10 2 6 7 8 4 5 1 0
|
||||
1 9 7 2 0
|
||||
1 9 7 8 0
|
||||
1 9 8 0
|
||||
1 9 6 7 2 3 4 5 1 8 0
|
||||
1 9 8 7 2 1 10 3 4 6 0
|
||||
1 9 8 7 0
|
||||
1 9 8 7 0
|
||||
1 9 8 7 0
|
||||
1 9 1 3 4 7 10 8 6 2 0
|
||||
1 9 7 2 1 5 0
|
||||
1 9 6 0
|
||||
1 9 8 7 0
|
||||
1 9 8 0
|
||||
1 9 10 2 3 0
|
||||
1 9 10 2 3 0
|
||||
1 9 3 4 7 0
|
||||
1 9 0
|
||||
1 9 6 7 0
|
||||
1 9 8 1 0
|
||||
1 9 7 2 6 8 4 0
|
||||
1 9 7 10 0
|
||||
1 9 1 4 3 7 8 2 10 6 0
|
||||
1 9 1 3 0
|
||||
1 9 8 6 0
|
||||
1 9 8 3 7 0
|
||||
1 9 1 3 0
|
||||
1 9 0
|
||||
1 9 1 7 3 8 0
|
||||
1 9 2 10 6 5 0
|
||||
1 9 7 0
|
||||
1 9 4 3 0
|
||||
1 9 8 4 1 3 10 0
|
||||
1 9 2 7 8 0
|
||||
1 9 8 3 6 7 2 0
|
||||
1 9 0
|
||||
1 9 8 3 6 7 2 0
|
||||
1 9 8 7 1 0
|
||||
1 9 10 7 4 1 2 6 3 5 0
|
||||
1 9 3 1 0
|
||||
1 9 10 7 1 0
|
||||
1 9 4 1 2 0
|
||||
1 9 2 7 8 3 0
|
||||
1 9 4 8 1 2 0
|
||||
1 9 7 2 10 3 1 0
|
||||
1 9 4 3 1 7 8 6 2 10 0
|
||||
1 9 4 3 1 7 8 6 2 10 0
|
||||
1 9 8 0
|
||||
1 9 1 0
|
||||
1 9 4 8 1 3 7 0
|
||||
1 9 4 1 0
|
||||
1 9 8 6 3 2 7 10 1 4 0
|
||||
1 9 8 4 0
|
||||
1 9 7 8 0
|
||||
1 9 8 4 0
|
||||
1 9 0
|
||||
1 9 1 8 3 4 0
|
||||
1 9 2 7 8 0
|
||||
1 9 2 7 3 4 5 6 8 1 0
|
||||
1 9 2 7 4 0
|
||||
1 9 2 7 8 6 10 0
|
||||
1 9 4 3 0
|
||||
1 9 7 3 1 0
|
||||
1 1 9 2 4 8 10 0
|
||||
1 1 9 10 4 8 0
|
||||
1 1 9 10 0
|
||||
1 1 9 7 4 5 2 10 8 6 0
|
||||
1 1 9 3 0
|
||||
1 1 9 7 6 3 0
|
||||
1 1 9 10 3 0
|
||||
1 1 9 4 3 8 10 0
|
||||
1 1 9 4 7 0
|
||||
1 1 9 8 2 3 7 4 10 0
|
||||
1 1 9 8 2 3 7 4 10 0
|
||||
1 1 9 3 0
|
||||
1 1 9 3 0
|
||||
1 1 9 3 0
|
||||
1 1 9 10 8 4 3 0
|
||||
1 1 9 5 3 0
|
||||
1 1 9 5 3 0
|
||||
1 1 9 5 3 0
|
||||
1 1 9 8 3 10 2 4 5 6 0
|
||||
1 1 9 10 4 0
|
||||
1 1 9 10 4 7 3 0
|
||||
1 6 9 2 0
|
||||
1 6 9 10 8 0
|
||||
1 1 5 9 2 7 10 0
|
||||
1 1 5 9 2 7 10 0
|
||||
1 1 5 9 2 7 10 0
|
||||
1 1 10 9 4 0
|
||||
1 1 10 9 0
|
||||
1 1 10 9 2 3 4 5 6 7 0
|
||||
1 1 10 9 2 0
|
||||
1 1 10 9 2 3 4 5 6 7 0
|
||||
1 10 9 7 3 2 0
|
||||
1 10 9 4 8 6 3 0
|
||||
1 10 1 9 0
|
||||
1 10 9 8 0
|
||||
1 10 9 8 0
|
||||
1 10 9 2 0
|
||||
1 1 7 9 8 3 4 6 10 5 0
|
||||
1 1 7 9 8 6 3 2 10 4 0
|
||||
1 1 7 9 3 0
|
||||
1 1 7 9 0
|
||||
1 1 7 9 0
|
||||
1 1 7 9 0
|
||||
1 1 7 9 6 2 3 0
|
||||
1 1 7 9 3 0
|
||||
1 7 6 9 0
|
||||
1 7 9 2 0
|
||||
1 7 9 8 0
|
||||
1 7 9 8 0
|
||||
1 7 1 9 4 3 8 10 0
|
||||
1 7 9 3 0
|
||||
1 7 9 3 0
|
||||
1 7 9 3 0
|
||||
1 7 9 3 0
|
||||
1 7 9 8 0
|
||||
1 7 9 6 8 0
|
||||
1 4 8 1 3 5 6 10 2 9 0
|
||||
1 4 5 7 10 1 2 8 0
|
||||
1 4 5 8 1 0
|
||||
1 7 4 2 9 8 1 3 6 10 0
|
||||
1 2 9 7 4 8 0
|
||||
1 2 4 8 0
|
||||
1 2 4 8 0
|
||||
1 2 4 8 0
|
||||
1 7 0
|
||||
1 6 7 0
|
||||
1 1 10 5 0
|
||||
1 10 1 0
|
||||
1 10 1 0
|
||||
1 10 0
|
||||
1 10 0
|
||||
1 5 10 0
|
||||
1 1 5 0
|
||||
1 1 5 0
|
||||
1 1 6 5 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 4 9 10 6 0
|
||||
1 1 4 10 5 0
|
||||
1 1 4 0
|
||||
1 1 4 0
|
||||
1 1 4 0
|
||||
1 1 4 5 0
|
||||
1 1 5 4 0
|
||||
1 1 2 4 0
|
||||
1 4 9 1 0
|
||||
1 4 10 1 0
|
||||
1 4 9 6 0
|
||||
1 4 9 6 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 2 7 0
|
||||
1 4 9 7 0
|
||||
1 4 1 9 0
|
||||
1 4 1 9 0
|
||||
1 4 10 5 0
|
||||
1 4 5 9 1 0
|
||||
1 4 1 5 0
|
||||
1 4 0
|
||||
1 6 7 4 10 0
|
||||
1 10 4 0
|
||||
1 10 4 1 0
|
||||
1 2 4 0
|
||||
1 1 4 3 6 10 0
|
||||
1 1 4 9 3 8 0
|
||||
1 1 4 9 3 8 0
|
||||
1 1 4 9 3 8 0
|
||||
1 1 4 3 6 8 5 0
|
||||
1 1 5 4 9 2 3 7 6 8 0
|
||||
1 1 2 4 3 0
|
||||
1 1 4 5 8 10 0
|
||||
1 1 4 8 7 0
|
||||
1 1 4 5 9 8 0
|
||||
1 1 4 8 0
|
||||
1 1 2 4 5 8 10 0
|
||||
1 8 9 2 0
|
||||
1 8 3 1 6 0
|
||||
1 8 10 3 1 2 0
|
||||
1 8 2 6 0
|
||||
1 8 2 1 3 4 0
|
||||
1 8 2 1 3 4 0
|
||||
1 8 2 0
|
||||
1 8 2 0
|
||||
1 8 2 6 0
|
||||
1 8 2 7 9 0
|
||||
1 8 3 1 6 0
|
||||
1 8 1 9 4 3 2 10 5 6 0
|
||||
1 8 2 7 3 0
|
||||
1 8 1 5 0
|
||||
1 8 7 0
|
||||
1 8 9 1 2 7 4 0
|
||||
1 8 1 7 9 0
|
||||
1 8 10 7 6 9 0
|
||||
1 8 10 9 7 6 0
|
||||
1 8 7 9 10 6 0
|
||||
1 8 1 7 9 0
|
||||
1 8 4 2 0
|
||||
1 8 7 9 0
|
||||
1 8 7 1 0
|
||||
1 8 1 3 4 2 5 10 9 7 0
|
||||
1 8 1 3 4 2 5 10 9 7 0
|
||||
1 8 2 7 9 0
|
||||
1 8 3 1 6 9 7 10 0
|
||||
1 8 3 1 6 9 7 10 0
|
||||
1 8 1 10 0
|
||||
1 8 1 10 0
|
||||
1 1 8 4 0
|
||||
1 1 8 6 4 2 3 5 10 9 0
|
||||
1 1 8 3 4 0
|
||||
1 1 8 9 3 4 2 6 5 7 0
|
||||
1 1 8 4 0
|
||||
1 1 8 9 10 0
|
||||
1 1 8 4 9 0
|
||||
1 1 8 4 9 0
|
||||
1 1 8 4 9 0
|
||||
1 1 8 3 9 0
|
||||
1 1 8 4 0
|
||||
1 1 8 4 0
|
||||
1 5 8 1 0
|
||||
1 6 8 9 0
|
||||
1 1 5 8 0
|
||||
1 1 5 8 0
|
||||
1 1 5 8 0
|
||||
1 1 5 8 0
|
||||
1 1 5 8 0
|
||||
1 10 6 1 8 3 5 0
|
||||
1 10 6 1 8 3 5 0
|
||||
1 7 1 8 9 10 0
|
||||
1 7 8 3 0
|
||||
1 10 7 8 4 5 1 2 9 6 0
|
||||
1 6 7 8 9 1 3 0
|
||||
1 6 7 8 9 1 3 0
|
||||
1 6 7 8 0
|
||||
1 6 7 8 0
|
||||
1 2 8 10 0
|
||||
1 2 8 7 9 4 0
|
||||
1 2 8 7 9 4 0
|
||||
1 2 8 0
|
||||
1 2 8 0
|
||||
1 2 8 7 0
|
||||
1 2 8 7 0
|
||||
1 2 7 8 9 0
|
||||
1 2 8 9 4 0
|
||||
1 2 7 8 9 0
|
||||
1 2 8 0
|
||||
1 2 8 0
|
||||
1 2 8 9 0
|
||||
1 2 8 0
|
||||
1 2 8 0
|
||||
1 2 9 8 0
|
||||
1 2 9 7 8 6 10 5 4 3 0
|
||||
1 2 7 9 8 10 0
|
||||
1 2 7 9 8 10 0
|
||||
1 2 9 8 0
|
||||
1 7 2 9 8 0
|
||||
1 7 2 9 6 8 3 10 5 1 0
|
||||
1 7 2 9 8 4 0
|
||||
1 4 3 6 0
|
||||
1 4 5 1 8 9 10 0
|
||||
1 4 3 8 0
|
||||
1 4 3 1 0
|
||||
1 4 3 6 0
|
||||
1 4 3 1 2 9 10 8 6 7 0
|
||||
1 4 9 2 7 3 5 10 6 1 0
|
||||
1 4 10 3 1 0
|
||||
1 4 1 3 0
|
||||
1 4 3 8 9 0
|
||||
1 4 10 9 3 1 2 5 0
|
||||
1 4 7 10 3 8 1 2 6 5 0
|
||||
1 4 3 8 1 10 0
|
||||
1 7 10 1 4 3 8 9 0
|
||||
1 7 4 1 2 3 5 6 8 9 0
|
||||
1 10 4 1 9 5 3 2 6 7 0
|
||||
1 10 4 9 1 3 2 0
|
||||
1 2 9 1 10 4 3 8 0
|
||||
1 2 4 9 7 3 8 10 6 1 0
|
||||
1 3 6 8 0
|
||||
1 3 6 8 0
|
||||
1 3 6 8 0
|
||||
1 3 6 8 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 8 0
|
||||
1 3 4 1 9 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 2 4 5 6 7 8 9 0
|
||||
1 3 1 6 0
|
||||
1 3 9 8 0
|
||||
1 3 7 1 5 0
|
||||
1 3 4 10 1 6 2 5 8 9 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 4 9 7 0
|
||||
1 3 5 8 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 9 0
|
||||
1 3 1 9 0
|
||||
1 3 1 9 0
|
||||
1 3 4 5 8 10 1 2 9 6 0
|
||||
1 3 6 0
|
||||
1 3 9 1 8 7 5 4 0
|
||||
1 3 1 5 2 4 7 6 9 8 0
|
||||
1 3 8 2 7 0
|
||||
1 1 2 3 7 8 9 5 6 10 0
|
||||
1 2 3 9 0
|
||||
1 2 3 9 10 8 0
|
||||
1 2 5 3 1 0
|
||||
1 2 3 1 4 9 10 8 5 6 0
|
||||
1 2 3 9 10 8 0
|
||||
1 1 3 9 8 4 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 4 9 5 6 10 2 8 0
|
||||
1 1 3 4 8 6 5 7 9 10 0
|
||||
1 1 3 0
|
||||
1 1 3 8 9 10 0
|
||||
1 1 3 4 0
|
||||
1 1 3 9 0
|
||||
1 1 3 0
|
||||
1 1 3 9 7 0
|
||||
1 1 3 9 7 0
|
||||
1 1 3 6 0
|
||||
1 1 3 7 8 10 9 2 6 4 0
|
||||
1 1 3 7 9 2 0
|
||||
1 1 3 2 7 9 0
|
||||
1 1 3 2 7 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 7 0
|
||||
1 1 3 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 0
|
||||
1 1 3 9 10 7 8 0
|
||||
1 1 3 5 9 0
|
||||
1 1 3 2 7 0
|
||||
1 1 3 2 7 0
|
||||
1 1 3 2 7 0
|
||||
1 1 3 9 7 0
|
||||
1 1 3 8 4 0
|
||||
1 1 3 4 0
|
||||
1 1 3 0
|
||||
1 1 3 5 0
|
||||
1 1 3 0
|
||||
1 1 3 9 0
|
||||
1 1 3 7 0
|
||||
1 1 3 4 9 0
|
||||
1 1 3 4 0
|
||||
1 6 3 4 1 0
|
||||
1 1 6 3 0
|
||||
1 1 10 3 0
|
||||
1 10 3 5 0
|
||||
1 10 1 3 4 2 5 6 9 8 0
|
||||
1 7 1 3 9 8 0
|
||||
1 7 1 3 9 8 0
|
||||
1 7 3 4 0
|
||||
0
|
||||
"Candidate 1" "Candidate 2" "Candidate 3" "Candidate 4" "Candidate 5" "Candidate 6" "Candidate 7" "Candidate 8" "Candidate 9" "Candidate 10" "a1"
|
||||
|
992
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A3.HIL
Normal file
992
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A3.HIL
Normal file
@ -0,0 +1,992 @@
|
||||
15 7
|
||||
1 0
|
||||
1 8 0
|
||||
1 8 0
|
||||
1 8 6 0
|
||||
1 8 6 0
|
||||
1 8 6 0
|
||||
1 8 0
|
||||
1 8 6 0
|
||||
1 8 0
|
||||
1 8 6 0
|
||||
1 8 0
|
||||
1 5 11 8 0
|
||||
1 5 11 6 8 1 0
|
||||
1 5 8 6 14 0
|
||||
1 4 11 14 0
|
||||
1 4 6 8 14 11 0
|
||||
1 4 6 11 1 13 15 14 7 5 3 2 12 8 9 0
|
||||
1 4 6 11 8 5 0
|
||||
1 4 6 0
|
||||
1 4 9 12 14 0
|
||||
1 4 8 0
|
||||
1 4 3 13 0
|
||||
1 4 6 10 7 11 14 12 0
|
||||
1 4 8 6 1 14 11 0
|
||||
1 4 11 0
|
||||
1 4 6 5 0
|
||||
1 4 6 0
|
||||
1 4 8 5 0
|
||||
1 4 8 6 0
|
||||
1 4 5 3 0
|
||||
1 4 5 3 0
|
||||
1 4 6 5 11 7 10 12 13 8 9 14 15 0
|
||||
1 4 11 3 6 0
|
||||
1 4 11 6 5 14 0
|
||||
1 4 5 6 11 14 0
|
||||
1 4 13 3 5 7 10 11 14 0
|
||||
1 4 8 14 1 0
|
||||
1 4 6 1 11 0
|
||||
1 4 11 0
|
||||
1 4 5 6 7 11 14 0
|
||||
1 4 2 7 8 5 13 14 9 10 3 1 6 15 11 0
|
||||
1 4 8 3 6 11 9 14 15 2 1 5 13 7 12 0
|
||||
1 4 0
|
||||
1 4 14 11 0
|
||||
1 4 6 12 0
|
||||
1 4 6 5 2 1 13 12 11 7 3 8 9 10 14 0
|
||||
1 4 8 3 5 11 14 0
|
||||
1 4 6 5 0
|
||||
1 4 6 5 0
|
||||
1 4 5 6 8 3 11 0
|
||||
1 4 11 6 10 15 0
|
||||
1 4 5 7 11 0
|
||||
1 4 0
|
||||
1 4 6 8 0
|
||||
1 4 6 3 0
|
||||
1 4 11 8 6 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 13 3 0
|
||||
1 4 5 0
|
||||
1 4 6 11 0
|
||||
1 4 6 3 0
|
||||
1 4 6 11 8 7 1 0
|
||||
1 1 8 4 11 0
|
||||
1 4 8 6 0
|
||||
1 4 6 11 10 0
|
||||
1 4 6 7 10 14 11 3 5 8 9 12 13 15 1 0
|
||||
1 4 1 6 11 0
|
||||
1 4 8 6 5 11 14 0
|
||||
1 4 6 8 11 0
|
||||
1 4 1 6 11 2 8 0
|
||||
1 4 11 8 5 6 3 7 14 15 13 12 10 9 0
|
||||
1 4 1 5 0
|
||||
1 4 6 2 0
|
||||
1 3 1 7 13 15 0
|
||||
1 3 4 12 13 11 8 9 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 6 4 1 0
|
||||
1 3 4 10 0
|
||||
1 3 11 6 10 14 0
|
||||
1 3 11 8 0
|
||||
1 3 8 6 0
|
||||
1 3 2 7 15 13 0
|
||||
1 3 14 5 10 13 0
|
||||
1 3 0
|
||||
1 3 6 7 0
|
||||
1 3 2 7 15 0
|
||||
1 3 13 1 7 15 2 9 10 0
|
||||
1 3 13 0
|
||||
1 3 8 0
|
||||
1 3 6 4 0
|
||||
1 3 6 11 0
|
||||
1 3 8 0
|
||||
1 3 4 10 14 0
|
||||
1 3 7 11 0
|
||||
1 3 1 0
|
||||
1 3 14 6 8 0
|
||||
1 3 0
|
||||
1 1 0
|
||||
1 1 13 2 3 7 0
|
||||
1 1 4 6 13 11 14 0
|
||||
1 1 3 10 0
|
||||
1 1 3 2 15 6 0
|
||||
1 1 5 0
|
||||
1 1 10 2 3 7 0
|
||||
1 1 13 3 0
|
||||
1 1 2 3 6 10 0
|
||||
1 4 0
|
||||
1 4 6 1 11 3 5 0
|
||||
1 4 6 11 1 3 0
|
||||
1 4 5 6 11 12 15 0
|
||||
1 4 0
|
||||
1 4 11 14 8 0
|
||||
1 4 0
|
||||
1 4 8 11 0
|
||||
1 4 6 10 0
|
||||
1 4 11 8 0
|
||||
1 4 11 6 0
|
||||
1 4 6 11 1 8 13 2 14 0
|
||||
1 4 14 11 8 0
|
||||
1 4 11 5 14 6 0
|
||||
1 4 3 1 5 0
|
||||
1 4 6 11 0
|
||||
1 4 5 6 11 0
|
||||
1 4 5 6 13 14 0
|
||||
1 4 5 11 0
|
||||
1 4 3 5 8 14 0
|
||||
1 4 5 8 3 11 0
|
||||
1 4 6 10 11 5 12 8 0
|
||||
1 4 11 8 6 5 0
|
||||
1 4 5 6 8 11 14 15 13 12 3 1 2 7 9 0
|
||||
1 4 6 11 10 13 12 14 0
|
||||
1 4 7 9 15 0
|
||||
1 4 6 10 12 0
|
||||
1 4 3 6 8 11 0
|
||||
1 4 6 11 7 10 12 14 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 6 1 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 6 5 11 0
|
||||
1 4 6 8 0
|
||||
1 4 12 6 1 3 13 0
|
||||
1 4 12 5 0
|
||||
1 4 8 6 11 0
|
||||
1 4 12 8 5 11 0
|
||||
1 4 13 5 1 11 3 8 0
|
||||
1 4 9 15 1 3 2 5 7 0
|
||||
1 4 6 11 14 0
|
||||
1 4 14 11 0
|
||||
1 4 6 11 1 7 0
|
||||
1 4 5 14 0
|
||||
1 4 8 2 7 0
|
||||
1 4 11 15 8 6 5 3 10 0
|
||||
1 4 6 8 11 14 0
|
||||
1 4 6 11 5 10 12 14 0
|
||||
1 4 5 6 11 14 12 8 7 15 3 10 0
|
||||
1 4 0
|
||||
1 4 6 11 12 14 10 8 5 13 7 15 3 2 1 0
|
||||
1 4 6 8 11 12 13 3 5 14 0
|
||||
1 4 8 1 0
|
||||
1 1 4 6 11 12 13 15 8 14 7 5 2 9 10 0
|
||||
1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0
|
||||
1 2 0
|
||||
1 2 7 9 0
|
||||
1 2 7 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 9 10 0
|
||||
1 2 1 0
|
||||
1 2 13 9 10 7 0
|
||||
1 2 1 4 0
|
||||
1 2 0
|
||||
1 2 7 1 3 10 13 0
|
||||
1 2 6 10 0
|
||||
1 2 13 6 3 8 0
|
||||
1 2 1 7 15 0
|
||||
1 2 7 0
|
||||
1 2 7 1 6 10 15 0
|
||||
1 2 7 9 13 10 0
|
||||
1 2 0
|
||||
1 2 9 6 0
|
||||
1 2 5 10 0
|
||||
1 2 5 10 0
|
||||
1 2 1 7 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 7 9 0
|
||||
1 2 10 7 9 0
|
||||
1 2 1 0
|
||||
1 2 9 10 0
|
||||
1 2 7 0
|
||||
1 2 0
|
||||
1 2 10 9 0
|
||||
1 2 8 6 0
|
||||
1 2 13 7 0
|
||||
1 2 7 12 13 9 10 6 0
|
||||
1 2 7 10 9 8 0
|
||||
1 2 7 9 0
|
||||
1 4 8 12 0
|
||||
1 4 6 8 13 15 5 10 0
|
||||
1 4 6 11 13 0
|
||||
1 4 11 12 0
|
||||
1 4 6 1 8 0
|
||||
1 4 8 11 0
|
||||
1 4 6 8 1 0
|
||||
1 4 6 7 5 11 0
|
||||
1 4 1 6 9 11 3 5 2 7 10 12 14 15 13 0
|
||||
1 4 8 11 14 12 13 3 0
|
||||
1 4 8 14 3 0
|
||||
1 4 6 8 0
|
||||
1 8 5 0
|
||||
1 8 4 12 14 15 3 6 5 1 2 7 9 10 11 0
|
||||
1 8 9 5 11 0
|
||||
1 8 5 6 0
|
||||
1 8 11 5 0
|
||||
1 8 11 0
|
||||
1 8 5 2 6 7 9 10 0
|
||||
1 8 9 5 0
|
||||
1 8 12 0
|
||||
1 8 4 5 11 14 0
|
||||
1 8 5 0
|
||||
1 8 5 6 11 0
|
||||
1 8 6 11 9 0
|
||||
1 8 2 7 10 9 0
|
||||
1 1 14 15 11 0
|
||||
1 1 7 15 0
|
||||
1 1 3 13 0
|
||||
1 1 6 2 15 11 7 3 10 0
|
||||
1 1 3 5 13 7 11 0
|
||||
1 1 6 0
|
||||
1 1 7 0
|
||||
1 1 3 7 0
|
||||
1 1 4 6 0
|
||||
1 1 6 8 9 15 0
|
||||
1 1 9 10 13 3 5 0
|
||||
1 1 8 5 0
|
||||
1 1 6 4 11 0
|
||||
1 1 13 3 0
|
||||
1 1 0
|
||||
1 1 6 0
|
||||
1 1 2 3 7 8 15 10 13 0
|
||||
1 4 6 12 13 0
|
||||
1 1 9 2 3 6 5 0
|
||||
1 1 3 14 0
|
||||
1 1 2 7 0
|
||||
1 1 0
|
||||
1 1 11 13 0
|
||||
1 1 2 7 0
|
||||
1 1 15 4 6 7 8 3 2 9 10 13 11 14 12 0
|
||||
1 1 3 13 0
|
||||
1 1 3 13 4 0
|
||||
1 1 2 15 9 0
|
||||
1 1 3 15 0
|
||||
1 1 13 5 4 6 0
|
||||
1 1 4 5 13 0
|
||||
1 1 4 6 0
|
||||
1 1 8 12 0
|
||||
1 1 10 2 8 0
|
||||
1 1 3 13 0
|
||||
1 1 3 13 0
|
||||
1 8 11 2 0
|
||||
1 8 5 4 6 1 11 14 7 10 3 9 15 0
|
||||
1 8 5 0
|
||||
1 8 3 13 10 0
|
||||
1 8 11 5 9 6 0
|
||||
1 8 7 11 0
|
||||
1 2 0
|
||||
1 2 7 10 9 13 3 8 6 0
|
||||
1 2 6 7 10 9 0
|
||||
1 2 6 0
|
||||
1 2 3 1 7 8 9 13 5 12 15 10 14 4 11 0
|
||||
1 2 3 5 11 0
|
||||
1 2 10 9 0
|
||||
1 2 6 7 10 0
|
||||
1 2 7 9 1 3 0
|
||||
1 2 6 7 10 1 13 3 0
|
||||
1 2 1 4 13 0
|
||||
1 2 7 0
|
||||
1 2 10 6 0
|
||||
1 2 7 0
|
||||
1 2 13 0
|
||||
1 2 8 15 11 0
|
||||
1 2 0
|
||||
1 2 3 1 13 0
|
||||
1 2 1 10 0
|
||||
1 2 8 0
|
||||
1 2 0
|
||||
1 2 7 5 1 3 10 9 0
|
||||
1 2 1 0
|
||||
1 2 7 0
|
||||
1 8 12 0
|
||||
1 8 5 9 11 0
|
||||
1 8 2 3 6 0
|
||||
1 8 3 10 13 1 0
|
||||
1 8 11 0
|
||||
1 8 5 11 9 0
|
||||
1 8 14 5 0
|
||||
1 8 11 5 0
|
||||
1 8 7 6 0
|
||||
1 8 14 4 0
|
||||
1 8 6 15 0
|
||||
1 8 4 3 6 1 2 5 7 13 11 10 15 14 9 0
|
||||
1 8 3 7 0
|
||||
1 8 12 3 0
|
||||
1 8 11 5 9 0
|
||||
1 8 11 10 0
|
||||
1 8 14 10 0
|
||||
1 8 5 9 3 11 0
|
||||
1 8 12 0
|
||||
1 8 12 6 0
|
||||
1 5 6 8 0
|
||||
1 5 6 4 11 8 0
|
||||
1 5 8 0
|
||||
1 5 11 15 14 8 0
|
||||
1 5 8 7 10 3 11 0
|
||||
1 5 11 8 0
|
||||
1 5 9 11 0
|
||||
1 5 8 11 2 6 14 0
|
||||
1 5 6 0
|
||||
1 5 8 12 11 0
|
||||
1 5 6 15 8 11 0
|
||||
1 5 4 6 11 13 1 3 8 0
|
||||
1 5 11 4 0
|
||||
1 5 4 3 0
|
||||
1 5 14 4 0
|
||||
1 5 8 0
|
||||
1 5 8 1 0
|
||||
1 5 8 1 11 12 13 9 2 3 14 7 10 4 6 0
|
||||
1 5 6 11 0
|
||||
1 5 11 4 0
|
||||
1 5 8 11 0
|
||||
1 8 14 0
|
||||
1 8 6 4 0
|
||||
1 8 14 0
|
||||
1 8 5 11 0
|
||||
1 8 14 0
|
||||
1 8 6 11 0
|
||||
1 8 5 14 0
|
||||
1 8 11 5 0
|
||||
1 8 5 6 11 0
|
||||
1 8 11 14 12 0
|
||||
1 8 11 0
|
||||
1 8 6 12 0
|
||||
1 8 6 14 0
|
||||
1 8 6 14 0
|
||||
1 8 5 6 4 11 12 10 13 0
|
||||
1 8 7 2 1 15 11 0
|
||||
1 8 3 12 0
|
||||
1 8 5 3 4 9 11 14 0
|
||||
1 8 6 5 0
|
||||
1 8 11 3 14 0
|
||||
1 8 11 9 5 0
|
||||
1 8 5 9 11 0
|
||||
1 8 11 0
|
||||
1 8 5 11 9 6 0
|
||||
1 8 11 6 12 0
|
||||
1 8 11 5 4 6 9 14 15 0
|
||||
1 8 4 11 5 6 12 14 15 9 0
|
||||
1 8 6 4 3 0
|
||||
1 8 6 5 0
|
||||
1 5 12 9 2 1 15 8 6 7 13 10 3 14 4 0
|
||||
1 5 11 15 0
|
||||
1 5 0
|
||||
1 5 11 0
|
||||
1 5 8 11 14 7 6 0
|
||||
1 5 8 14 1 11 0
|
||||
1 5 4 11 15 0
|
||||
1 5 0
|
||||
1 5 7 11 0
|
||||
1 5 6 1 7 8 15 13 11 12 4 3 9 14 2 0
|
||||
1 5 6 8 0
|
||||
1 5 0
|
||||
1 5 14 4 6 15 8 11 12 3 0
|
||||
1 5 11 0
|
||||
1 5 7 8 11 14 13 4 1 15 12 6 3 9 10 0
|
||||
1 5 11 6 0
|
||||
1 5 6 11 0
|
||||
1 5 6 3 11 12 0
|
||||
1 5 0
|
||||
1 5 6 14 0
|
||||
1 5 6 11 12 0
|
||||
1 5 11 8 14 0
|
||||
1 5 6 11 4 14 8 0
|
||||
1 5 14 8 0
|
||||
1 5 8 11 12 0
|
||||
1 5 6 14 8 7 0
|
||||
1 5 8 11 13 6 15 1 7 3 0
|
||||
1 6 9 7 13 15 14 8 0
|
||||
1 5 4 8 1 0
|
||||
1 5 7 2 0
|
||||
1 5 6 14 11 12 8 0
|
||||
1 5 11 4 13 6 0
|
||||
1 5 8 9 0
|
||||
1 5 6 8 0
|
||||
1 5 6 14 0
|
||||
1 5 11 8 6 1 7 2 4 3 9 10 14 15 13 0
|
||||
1 5 11 8 4 3 0
|
||||
1 5 6 8 14 0
|
||||
1 5 11 6 0
|
||||
1 5 11 8 4 6 0
|
||||
1 5 8 13 0
|
||||
1 5 8 11 6 12 0
|
||||
1 8 5 9 11 0
|
||||
1 8 5 11 13 6 1 0
|
||||
1 8 11 5 9 0
|
||||
1 8 1 4 0
|
||||
1 8 14 11 0
|
||||
1 8 5 11 0
|
||||
1 8 5 11 12 0
|
||||
1 8 9 11 5 6 0
|
||||
1 8 6 11 14 0
|
||||
1 7 6 2 5 4 8 14 0
|
||||
1 7 6 12 8 0
|
||||
1 7 13 6 0
|
||||
1 7 10 8 0
|
||||
1 8 1 3 0
|
||||
1 8 4 6 14 15 0
|
||||
1 8 6 14 0
|
||||
1 8 6 11 0
|
||||
1 8 6 11 0
|
||||
1 8 11 14 0
|
||||
1 8 6 5 9 0
|
||||
1 8 11 0
|
||||
1 8 6 0
|
||||
1 8 5 11 14 0
|
||||
1 8 0
|
||||
1 8 5 9 6 4 14 0
|
||||
1 8 11 0
|
||||
1 8 5 11 9 0
|
||||
1 8 0
|
||||
1 8 11 0
|
||||
1 8 1 6 0
|
||||
1 8 11 6 0
|
||||
1 8 5 11 4 12 14 0
|
||||
1 8 9 12 0
|
||||
1 8 5 11 9 0
|
||||
1 8 0
|
||||
1 8 11 4 0
|
||||
1 8 10 12 0
|
||||
1 8 6 5 14 0
|
||||
1 7 4 8 6 5 0
|
||||
1 7 10 6 0
|
||||
1 7 10 6 0
|
||||
1 7 10 4 2 13 3 0
|
||||
1 7 2 8 10 0
|
||||
1 7 0
|
||||
1 7 8 12 0
|
||||
1 7 11 14 0
|
||||
1 7 0
|
||||
1 7 1 4 0
|
||||
1 7 6 0
|
||||
1 7 5 12 0
|
||||
1 7 8 15 0
|
||||
1 7 4 3 1 6 13 14 15 5 2 8 9 10 12 0
|
||||
1 7 6 10 11 1 0
|
||||
1 7 1 3 2 6 13 15 0
|
||||
1 7 11 12 3 4 6 5 8 0
|
||||
1 10 2 6 0
|
||||
1 10 14 6 11 4 0
|
||||
1 10 14 7 6 4 12 11 0
|
||||
1 10 0
|
||||
1 10 0
|
||||
1 10 9 11 0
|
||||
1 10 2 7 9 0
|
||||
1 10 8 7 0
|
||||
1 10 5 6 0
|
||||
1 10 14 6 0
|
||||
1 10 7 2 0
|
||||
1 10 11 14 0
|
||||
1 9 8 6 4 0
|
||||
1 9 14 8 0
|
||||
1 9 12 6 8 2 0
|
||||
1 9 10 12 6 14 13 1 0
|
||||
1 9 0
|
||||
1 9 10 2 0
|
||||
1 9 0
|
||||
1 9 10 8 2 0
|
||||
1 9 8 12 0
|
||||
1 9 0
|
||||
1 9 10 12 6 14 13 1 0
|
||||
1 9 8 11 14 3 4 10 0
|
||||
1 9 8 11 14 3 4 0
|
||||
1 9 8 11 13 3 4 10 0
|
||||
1 9 6 12 14 8 0
|
||||
1 9 12 6 0
|
||||
1 9 6 12 0
|
||||
1 7 2 3 1 13 15 0
|
||||
1 7 1 2 0
|
||||
1 7 15 3 1 2 0
|
||||
1 7 6 1 0
|
||||
1 7 4 2 0
|
||||
1 7 1 3 15 13 6 2 0
|
||||
1 7 10 6 4 0
|
||||
1 7 15 3 0
|
||||
1 7 15 1 3 13 0
|
||||
1 7 4 6 10 15 14 11 13 8 3 12 1 5 2 0
|
||||
1 7 9 10 0
|
||||
1 7 8 2 13 6 3 0
|
||||
1 7 2 9 0
|
||||
1 7 0
|
||||
1 7 1 2 3 10 9 0
|
||||
1 7 15 5 0
|
||||
1 7 2 6 0
|
||||
1 7 2 0
|
||||
1 7 2 13 0
|
||||
1 7 8 5 0
|
||||
1 7 5 8 0
|
||||
1 7 1 2 8 3 0
|
||||
1 11 6 5 8 0
|
||||
1 11 7 15 0
|
||||
1 11 13 12 6 14 0
|
||||
1 11 15 6 0
|
||||
1 11 9 7 4 3 14 12 0
|
||||
1 11 7 0
|
||||
1 11 4 1 0
|
||||
1 11 5 3 0
|
||||
1 11 8 6 0
|
||||
1 11 10 7 2 6 14 15 12 13 9 1 8 5 3 0
|
||||
1 11 4 6 0
|
||||
1 11 4 5 12 0
|
||||
1 11 6 8 0
|
||||
1 11 8 12 0
|
||||
1 11 5 6 4 8 3 13 14 0
|
||||
1 11 6 5 14 0
|
||||
1 11 6 8 3 4 13 14 15 12 7 2 1 9 10 0
|
||||
1 11 12 14 0
|
||||
1 11 8 0
|
||||
1 11 14 6 5 8 0
|
||||
1 11 8 10 0
|
||||
1 11 5 12 14 0
|
||||
1 11 6 10 0
|
||||
1 11 4 14 7 8 3 0
|
||||
1 11 6 5 0
|
||||
1 11 4 14 7 8 3 0
|
||||
1 11 6 5 0
|
||||
1 11 6 4 0
|
||||
1 11 6 13 12 8 14 1 0
|
||||
1 11 6 5 8 0
|
||||
1 11 14 4 0
|
||||
1 11 5 6 8 0
|
||||
1 11 6 4 0
|
||||
1 11 5 6 0
|
||||
1 11 4 6 1 7 10 5 14 0
|
||||
1 11 8 6 10 12 0
|
||||
1 11 4 6 0
|
||||
1 11 13 12 2 14 0
|
||||
1 11 14 6 0
|
||||
1 11 6 12 0
|
||||
1 11 8 3 5 4 6 0
|
||||
1 11 6 4 0
|
||||
1 11 14 6 0
|
||||
1 11 4 8 0
|
||||
1 11 6 0
|
||||
1 11 4 14 6 0
|
||||
1 11 14 5 0
|
||||
1 11 8 0
|
||||
1 11 8 15 14 3 6 0
|
||||
1 10 14 15 11 9 4 5 6 7 12 13 0
|
||||
1 10 6 4 11 12 0
|
||||
1 10 14 4 5 7 6 8 11 0
|
||||
1 11 7 0
|
||||
1 11 5 0
|
||||
1 11 2 6 0
|
||||
1 11 0
|
||||
1 11 8 4 3 5 0
|
||||
1 11 1 4 2 0
|
||||
1 11 5 6 14 0
|
||||
1 11 4 6 3 14 0
|
||||
1 11 4 13 14 12 0
|
||||
1 11 4 8 0
|
||||
1 11 14 6 5 8 4 0
|
||||
1 11 0
|
||||
1 11 14 6 12 0
|
||||
1 11 0
|
||||
1 11 12 14 0
|
||||
1 11 8 5 0
|
||||
1 11 15 14 12 8 6 0
|
||||
1 11 4 5 6 14 3 12 0
|
||||
1 11 6 12 14 1 3 4 7 13 0
|
||||
1 11 3 8 0
|
||||
1 11 14 0
|
||||
1 11 4 6 8 0
|
||||
1 11 3 5 0
|
||||
1 11 12 8 6 0
|
||||
1 11 5 14 4 0
|
||||
1 11 5 8 0
|
||||
1 11 5 6 14 0
|
||||
1 11 12 6 0
|
||||
1 11 6 7 14 0
|
||||
1 11 8 5 6 14 12 1 4 0
|
||||
1 11 14 8 6 3 10 12 0
|
||||
1 11 5 4 6 0
|
||||
1 11 6 14 0
|
||||
1 11 8 2 0
|
||||
1 11 14 6 0
|
||||
1 11 8 6 0
|
||||
1 11 5 8 3 4 14 0
|
||||
1 11 12 5 6 15 0
|
||||
1 11 8 5 6 0
|
||||
1 11 6 12 0
|
||||
1 11 5 3 0
|
||||
1 11 5 6 0
|
||||
1 11 0
|
||||
1 11 6 4 8 0
|
||||
1 11 0
|
||||
1 11 14 8 0
|
||||
1 11 14 9 0
|
||||
1 11 6 8 3 4 5 13 14 0
|
||||
1 11 6 4 3 0
|
||||
1 11 1 4 7 5 8 9 12 10 3 2 14 15 6 0
|
||||
1 3 9 13 0
|
||||
1 0
|
||||
1 5 0
|
||||
1 6 0
|
||||
1 0
|
||||
1 0
|
||||
1 8 5 11 12 0
|
||||
1 8 4 0
|
||||
1 8 12 0
|
||||
1 8 6 14 0
|
||||
1 8 11 6 14 0
|
||||
1 8 11 4 14 5 9 3 0
|
||||
1 8 1 0
|
||||
1 8 5 4 0
|
||||
1 8 11 10 4 0
|
||||
1 8 9 11 5 0
|
||||
1 8 5 11 9 0
|
||||
1 8 14 13 6 0
|
||||
1 8 0
|
||||
1 8 6 5 14 11 12 15 0
|
||||
1 12 14 0
|
||||
1 12 8 6 0
|
||||
1 12 0
|
||||
1 12 3 4 6 13 0
|
||||
1 12 0
|
||||
1 11 9 0
|
||||
1 12 6 1 0
|
||||
1 12 11 8 6 4 0
|
||||
1 12 8 13 0
|
||||
1 12 14 0
|
||||
1 12 8 0
|
||||
1 12 6 1 8 0
|
||||
1 12 0
|
||||
1 12 6 5 4 11 7 10 13 8 9 14 15 0
|
||||
1 8 6 12 0
|
||||
1 8 9 11 0
|
||||
1 8 5 11 9 0
|
||||
1 8 11 5 0
|
||||
1 8 4 5 0
|
||||
1 8 11 0
|
||||
1 8 0
|
||||
1 8 11 14 0
|
||||
1 8 11 5 9 0
|
||||
1 8 6 14 3 4 0
|
||||
1 8 12 0
|
||||
1 8 5 12 0
|
||||
1 8 5 11 12 6 4 0
|
||||
1 8 11 5 6 0
|
||||
1 8 5 4 11 6 0
|
||||
1 8 0
|
||||
1 8 11 9 5 0
|
||||
1 8 11 6 5 14 3 15 12 0
|
||||
1 8 7 1 0
|
||||
1 8 13 15 0
|
||||
1 8 6 12 0
|
||||
1 8 4 11 0
|
||||
1 8 0
|
||||
1 8 12 15 6 14 0
|
||||
1 8 6 2 0
|
||||
1 8 11 5 0
|
||||
1 8 6 14 12 0
|
||||
1 8 6 1 0
|
||||
1 8 9 12 0
|
||||
1 8 5 12 4 6 0
|
||||
1 8 5 11 9 0
|
||||
1 8 0
|
||||
1 8 11 6 3 4 14 0
|
||||
1 8 14 5 0
|
||||
1 8 6 4 11 5 1 15 14 13 12 10 9 2 3 0
|
||||
1 8 6 3 11 14 0
|
||||
1 0
|
||||
1 0
|
||||
1 0
|
||||
1 0
|
||||
1 14 1 11 6 8 10 0
|
||||
1 14 4 6 0
|
||||
1 14 6 8 0
|
||||
1 14 6 11 15 8 7 4 12 5 13 9 0
|
||||
1 14 12 8 6 1 10 0
|
||||
1 14 6 8 0
|
||||
1 14 6 10 0
|
||||
1 14 11 6 0
|
||||
1 14 5 0
|
||||
1 14 12 0
|
||||
1 15 7 2 0
|
||||
1 15 3 13 7 10 0
|
||||
1 15 12 6 0
|
||||
1 15 7 14 0
|
||||
1 15 12 11 0
|
||||
1 15 11 4 2 6 8 14 13 12 1 3 5 7 10 0
|
||||
1 15 14 0
|
||||
1 15 8 6 0
|
||||
1 15 3 2 1 0
|
||||
1 15 11 0
|
||||
1 15 7 0
|
||||
1 15 6 7 0
|
||||
1 15 14 11 3 4 0
|
||||
1 15 7 2 11 10 0
|
||||
1 13 11 1 6 8 5 10 0
|
||||
1 13 8 0
|
||||
1 13 1 3 7 15 2 0
|
||||
1 13 3 7 15 1 9 0
|
||||
1 13 1 6 0
|
||||
1 13 12 4 0
|
||||
1 13 6 3 0
|
||||
1 13 7 6 0
|
||||
1 13 11 6 5 0
|
||||
1 13 11 6 15 0
|
||||
1 13 8 4 6 1 0
|
||||
1 12 2 6 0
|
||||
1 12 5 8 4 0
|
||||
1 12 9 8 0
|
||||
1 12 11 5 0
|
||||
1 12 8 0
|
||||
1 12 0
|
||||
1 12 9 0
|
||||
1 12 8 6 11 5 0
|
||||
1 12 6 0
|
||||
1 12 6 8 0
|
||||
1 12 14 6 0
|
||||
1 12 8 4 0
|
||||
1 12 6 3 0
|
||||
1 12 3 8 0
|
||||
1 12 4 13 0
|
||||
1 6 11 0
|
||||
1 6 5 4 13 0
|
||||
1 6 0
|
||||
1 6 1 3 0
|
||||
1 6 10 14 8 0
|
||||
1 6 5 11 7 4 10 12 13 8 9 14 15 0
|
||||
1 6 13 12 11 9 15 0
|
||||
1 6 8 12 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 11 10 5 12 13 14 15 7 9 8 0
|
||||
1 6 8 14 0
|
||||
1 6 13 4 3 5 0
|
||||
1 14 6 8 11 4 3 0
|
||||
1 14 8 11 3 4 6 0
|
||||
1 14 4 0
|
||||
1 14 0
|
||||
1 14 0
|
||||
1 14 8 10 0
|
||||
1 14 0
|
||||
1 14 5 11 0
|
||||
1 14 6 11 0
|
||||
1 14 6 8 5 4 11 3 12 0
|
||||
1 14 11 4 5 13 0
|
||||
1 14 8 10 6 0
|
||||
1 14 11 4 0
|
||||
1 14 6 4 3 0
|
||||
1 14 4 5 0
|
||||
1 14 5 0
|
||||
1 14 11 6 0
|
||||
1 14 0
|
||||
1 14 6 7 0
|
||||
1 14 8 0
|
||||
1 14 3 8 10 13 0
|
||||
1 14 4 6 0
|
||||
1 14 10 8 0
|
||||
1 14 6 10 0
|
||||
1 14 15 6 11 10 5 0
|
||||
1 14 0
|
||||
1 14 10 11 0
|
||||
1 14 11 8 12 0
|
||||
1 14 8 6 2 0
|
||||
1 14 6 4 11 10 5 8 1 0
|
||||
1 14 12 8 11 10 0
|
||||
1 14 8 0
|
||||
1 14 8 0
|
||||
1 14 11 4 7 2 0
|
||||
1 14 11 4 5 8 0
|
||||
1 14 12 15 4 8 7 13 10 1 3 6 5 2 11 0
|
||||
1 14 0
|
||||
1 14 11 12 0
|
||||
1 14 6 0
|
||||
1 6 4 10 14 7 5 8 11 0
|
||||
1 6 0
|
||||
1 6 12 8 3 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 11 4 14 12 0
|
||||
1 6 1 7 5 0
|
||||
1 6 8 4 0
|
||||
1 6 5 11 0
|
||||
1 6 7 10 3 12 2 1 0
|
||||
1 6 2 5 0
|
||||
1 6 5 11 2 10 3 7 13 4 1 0
|
||||
1 6 8 9 10 0
|
||||
1 6 11 4 10 14 5 0
|
||||
1 6 11 1 0
|
||||
1 6 13 0
|
||||
1 6 8 11 0
|
||||
1 6 5 8 11 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 8 15 0
|
||||
1 6 11 2 1 13 3 0
|
||||
1 6 8 0
|
||||
1 6 10 2 11 7 14 12 13 0
|
||||
1 6 4 5 11 14 8 15 12 0
|
||||
1 6 12 0
|
||||
1 6 11 2 13 15 8 0
|
||||
1 6 5 11 8 4 0
|
||||
1 6 0
|
||||
1 6 3 5 9 10 4 7 8 11 13 15 14 2 12 0
|
||||
1 6 8 0
|
||||
1 6 8 14 0
|
||||
1 6 3 8 0
|
||||
1 6 8 14 0
|
||||
1 6 5 11 12 14 13 4 15 0
|
||||
1 6 10 2 9 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 8 0
|
||||
1 6 5 8 11 14 0
|
||||
1 6 8 4 14 11 0
|
||||
1 6 8 11 0
|
||||
1 6 2 3 5 4 8 1 7 13 0
|
||||
1 6 4 12 0
|
||||
1 6 4 8 11 12 13 10 5 7 14 15 1 9 2 0
|
||||
1 6 3 4 0
|
||||
1 6 8 11 0
|
||||
1 6 11 4 0
|
||||
1 6 4 11 0
|
||||
1 6 11 3 12 7 0
|
||||
1 6 11 13 4 14 8 0
|
||||
1 6 4 8 12 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 8 11 4 3 13 14 12 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 3 8 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 15 0
|
||||
1 6 12 0
|
||||
1 6 8 4 3 11 14 0
|
||||
1 6 8 4 14 12 5 11 15 9 7 0
|
||||
1 6 12 8 4 11 14 0
|
||||
1 6 0
|
||||
1 13 6 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 15 0
|
||||
1 6 5 8 9 12 11 13 0
|
||||
1 6 8 12 0
|
||||
1 6 4 8 11 14 0
|
||||
1 6 11 14 0
|
||||
1 6 4 3 1 13 0
|
||||
1 6 5 4 11 7 3 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 2 13 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 1 3 4 8 15 0
|
||||
1 6 5 8 4 11 0
|
||||
1 6 8 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 14 0
|
||||
1 6 4 8 5 11 12 14 15 0
|
||||
1 6 4 1 13 0
|
||||
1 6 4 2 7 11 13 14 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 10 2 0
|
||||
1 6 8 14 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 8 0
|
||||
1 6 11 5 15 0
|
||||
1 6 5 4 14 7 10 12 13 8 9 11 15 0
|
||||
1 6 5 4 14 7 10 12 13 8 9 11 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 8 14 0
|
||||
1 6 8 4 11 0
|
||||
1 6 4 12 11 13 0
|
||||
1 6 5 4 11 8 12 0
|
||||
1 6 5 8 4 0
|
||||
1 6 5 4 8 11 0
|
||||
1 6 4 8 7 5 3 14 15 0
|
||||
1 6 4 14 11 0
|
||||
1 6 4 12 0
|
||||
1 6 11 0
|
||||
1 6 11 0
|
||||
1 6 8 14 4 0
|
||||
1 6 14 11 1 0
|
||||
1 6 5 3 4 8 13 0
|
||||
1 6 0
|
||||
1 6 5 4 11 7 10 12 13 8 0
|
||||
1 6 8 12 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 14 12 10 8 9 11 1 4 13 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 8 0
|
||||
1 6 11 14 0
|
||||
1 6 11 5 0
|
||||
1 6 4 3 1 7 8 5 9 14 12 10 11 0
|
||||
1 6 4 13 14 0
|
||||
1 6 8 12 0
|
||||
1 6 4 11 7 0
|
||||
1 6 5 8 9 3 2 0
|
||||
1 6 8 12 11 0
|
||||
1 6 8 1 0
|
||||
1 6 14 0
|
||||
1 6 8 14 0
|
||||
1 6 4 11 5 12 8 10 0
|
||||
1 6 14 9 0
|
||||
1 6 3 10 4 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 3 0
|
||||
1 6 0
|
||||
1 6 7 11 10 2 13 3 1 9 0
|
||||
1 6 5 8 3 13 7 15 14 12 1 11 9 10 4 0
|
||||
1 6 11 12 0
|
||||
1 6 7 2 10 9 0
|
||||
1 6 9 10 3 4 1 7 11 13 8 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 5 0
|
||||
1 6 5 4 11 7 10 12 13 14 9 8 15 0
|
||||
1 6 11 8 12 5 4 1 13 14 0
|
||||
1 6 5 4 8 9 10 11 0
|
||||
1 6 3 5 0
|
||||
1 6 11 14 0
|
||||
1 6 0
|
||||
1 6 8 4 0
|
||||
1 6 4 11 12 8 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 8 4 11 13 0
|
||||
1 6 5 3 8 13 9 14 10 7 1 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 8 11 5 0
|
||||
1 6 5 11 0
|
||||
1 6 5 8 11 14 15 9 4 0
|
||||
1 6 1 7 0
|
||||
1 6 7 2 9 10 15 1 3 12 14 13 4 11 5 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 10 14 7 5 8 11 0
|
||||
1 6 5 8 11 0
|
||||
1 6 8 4 0
|
||||
1 6 13 5 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 8 0
|
||||
1 6 4 10 11 7 0
|
||||
1 6 4 8 11 7 5 14 10 3 0
|
||||
1 6 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 1 8 2 5 3 4 7 9 12 15 13 10 11 0
|
||||
1 6 8 9 5 11 0
|
||||
1 6 7 3 4 0
|
||||
1 6 8 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 5 3 14 0
|
||||
1 6 4 11 7 10 12 13 8 9 14 0
|
||||
1 6 4 8 12 11 14 3 5 13 0
|
||||
1 6 4 8 12 11 14 3 5 13 0
|
||||
1 6 4 11 5 12 14 15 13 0
|
||||
1 6 4 11 0
|
||||
1 6 8 0
|
||||
1 6 13 12 11 0
|
||||
1 6 7 10 12 13 3 4 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 14 8 0
|
||||
1 6 7 4 3 5 2 14 8 1 15 0
|
||||
1 6 4 11 3 12 13 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 14 11 0
|
||||
1 6 3 5 0
|
||||
1 6 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 11 12 0
|
||||
1 6 12 8 0
|
||||
1 6 2 0
|
||||
1 6 1 0
|
||||
1 6 0
|
||||
1 6 5 4 11 7 10 12 13 8 9 14 15 0
|
||||
1 6 4 11 0
|
||||
1 6 8 11 0
|
||||
1 6 5 1 4 11 2 0
|
||||
0
|
||||
"1" "2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14" "15" "a3"
|
200
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A60.HIL
Normal file
200
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A60.HIL
Normal file
@ -0,0 +1,200 @@
|
||||
6 1
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 4 3 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 4 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 0
|
||||
1 4 3 5 0
|
||||
1 4 5 2 0
|
||||
1 3 5 0
|
||||
1 3 5 2 0
|
||||
1 5 3 4 0
|
||||
1 5 0
|
||||
1 5 4 3 0
|
||||
1 5 0
|
||||
1 5 2 4 0
|
||||
1 5 4 3 0
|
||||
1 5 4 3 0
|
||||
1 4 5 6 0
|
||||
1 5 6 0
|
||||
1 5 6 1 4 3 0
|
||||
1 5 6 0
|
||||
1 5 4 6 3 1 0
|
||||
1 5 6 2 1 4 0
|
||||
1 5 6 0
|
||||
1 5 4 6 1 2 0
|
||||
1 5 6 0
|
||||
1 5 3 2 4 6 0
|
||||
1 5 4 6 3 1 0
|
||||
1 5 6 0
|
||||
1 3 5 6 0
|
||||
1 3 2 5 4 6 0
|
||||
1 6 5 4 0
|
||||
1 6 4 1 0
|
||||
1 6 0
|
||||
1 6 2 4 0
|
||||
1 6 0
|
||||
1 6 2 3 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 1 4 2 3 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 5 3 0
|
||||
1 6 0
|
||||
1 6 4 5 3 1 0
|
||||
1 6 1 3 0
|
||||
1 6 0
|
||||
1 6 5 0
|
||||
1 6 1 3 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 1 3 0
|
||||
1 6 4 5 3 2 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 5 4 1 2 0
|
||||
1 6 4 0
|
||||
1 6 5 2 3 1 0
|
||||
1 6 5 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 2 3 1 4 0
|
||||
1 6 3 2 4 5 0
|
||||
1 6 0
|
||||
1 6 4 3 5 1 0
|
||||
1 6 5 4 0
|
||||
1 6 5 1 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 0
|
||||
1 6 5 1 0
|
||||
1 3 6 5 0
|
||||
1 3 6 0
|
||||
1 3 6 4 0
|
||||
1 3 6 4 0
|
||||
1 2 4 6 0
|
||||
1 4 6 3 0
|
||||
1 4 6 1 2 3 0
|
||||
1 4 3 6 0
|
||||
1 4 3 2 6 1 0
|
||||
1 4 2 6 3 1 0
|
||||
1 4 6 0
|
||||
1 4 5 1 0
|
||||
1 3 4 5 2 1 0
|
||||
1 5 1 6 2 3 0
|
||||
1 5 1 4 0
|
||||
1 5 1 0
|
||||
1 5 4 1 0
|
||||
1 5 1 0
|
||||
1 5 1 3 6 2 0
|
||||
1 5 1 0
|
||||
1 5 1 4 0
|
||||
1 5 1 0
|
||||
1 5 1 3 4 2 0
|
||||
1 1 4 3 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 2 3 6 5 0
|
||||
1 1 4 2 3 5 0
|
||||
1 1 4 6 0
|
||||
1 1 5 4 3 0
|
||||
1 1 4 3 0
|
||||
1 1 5 6 0
|
||||
1 1 6 4 0
|
||||
1 1 3 4 0
|
||||
1 1 2 6 3 4 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 5 0
|
||||
1 1 0
|
||||
1 1 4 3 0
|
||||
1 1 6 2 4 3 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 3 6 5 2 0
|
||||
1 1 6 2 3 4 0
|
||||
1 1 0
|
||||
1 1 6 5 3 4 0
|
||||
1 1 0
|
||||
1 1 6 0
|
||||
1 1 2 3 0
|
||||
1 1 6 3 5 4 0
|
||||
1 1 4 2 3 6 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 5 2 3 6 0
|
||||
1 1 3 4 0
|
||||
1 1 4 5 6 3 0
|
||||
1 1 3 0
|
||||
1 1 3 2 4 6 0
|
||||
1 1 0
|
||||
1 1 3 5 0
|
||||
1 1 0
|
||||
1 1 6 0
|
||||
1 1 5 6 3 2 0
|
||||
1 1 2 4 0
|
||||
1 1 5 3 4 6 0
|
||||
1 1 3 2 4 6 0
|
||||
1 1 0
|
||||
1 1 5 2 6 3 0
|
||||
1 1 4 6 2 3 0
|
||||
1 1 3 0
|
||||
1 1 5 4 3 2 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 3 2 5 4 0
|
||||
1 1 5 0
|
||||
1 1 5 0
|
||||
1 1 5 0
|
||||
1 1 2 5 0
|
||||
1 1 3 4 0
|
||||
1 1 3 4 6 2 0
|
||||
1 1 2 6 4 5 0
|
||||
1 1 6 0
|
||||
1 1 5 4 3 0
|
||||
1 1 0
|
||||
1 1 4 3 0
|
||||
1 1 5 4 0
|
||||
1 1 2 5 0
|
||||
1 1 6 0
|
||||
1 2 1 3 4 5 0
|
||||
1 2 1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 5 6 2 0
|
||||
1 3 1 5 0
|
||||
1 3 1 5 0
|
||||
1 3 1 4 0
|
||||
1 3 1 5 0
|
||||
1 3 1 4 0
|
||||
1 3 4 1 0
|
||||
1 4 1 6 5 3 0
|
||||
1 4 2 1 0
|
||||
1 4 1 5 6 2 0
|
||||
1 4 1 6 2 5 0
|
||||
1 4 1 3 2 6 0
|
||||
1 4 1 6 0
|
||||
0
|
||||
"1" "2" "3" "4" "5" "6" "f:a60"
|
216
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A77.HIL
Normal file
216
include/Condorcet/Tests/src/Tools/Converters/TidemanData/A77.HIL
Normal file
@ -0,0 +1,216 @@
|
||||
3 1
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 2 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 3 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 2 1 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 2 0
|
||||
1 1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
1 3 1 0
|
||||
1 3 0
|
||||
1 3 2 0
|
||||
1 3 2 0
|
||||
1 3 0
|
||||
1 3 0
|
||||
1 3 1 0
|
||||
0
|
||||
"1" "2" "3" "f:a77"
|
190
include/Condorcet/Tests/src/Utils/VoteEntryParserTest.php
Normal file
190
include/Condorcet/Tests/src/Utils/VoteEntryParserTest.php
Normal file
@ -0,0 +1,190 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Utils;
|
||||
|
||||
use CondorcetPHP\Condorcet\Throwable\VoteInvalidFormatException;
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use CondorcetPHP\Condorcet\Utils\VoteEntryParser;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VoteEntryParserTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider voteBadNumericValueProvider()
|
||||
*/
|
||||
public function testBadNumericValue(string $entry, string $message): void
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage($message);
|
||||
|
||||
new VoteEntryParser($entry);
|
||||
}
|
||||
|
||||
public function voteBadNumericValueProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
'entry' => 'A>B ^g',
|
||||
'message' => "the value 'g' is not an integer.",
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'A>B ^a*b',
|
||||
'message' => "the value 'b' is not an integer.",
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'A>B*b',
|
||||
'message' => "the value 'b' is not an integer.",
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'A>B ^4Y ',
|
||||
'message' => "the value '4Y' is not an integer.",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider voteEntriesProvider()
|
||||
*/
|
||||
public function testVotesEntries(string $entry, array $expected): void
|
||||
{
|
||||
$parser = new VoteEntryParser($entry);
|
||||
|
||||
self::assertSame($entry, $parser->originalEntry);
|
||||
|
||||
self::assertSame($expected['comment'], $parser->comment);
|
||||
self::assertSame($expected['multiple'], $parser->multiple);
|
||||
self::assertSame($expected['ranking'], $parser->ranking);
|
||||
self::assertSame($expected['tags'], $parser->tags);
|
||||
self::assertSame($expected['weight'], $parser->weight);
|
||||
}
|
||||
|
||||
public function voteEntriesProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
'entry' => 'A >B = C>D',
|
||||
'expected' => [
|
||||
'comment' => null,
|
||||
'multiple' => 1,
|
||||
'ranking' => [
|
||||
['A'],
|
||||
['B', 'C'],
|
||||
['D'],
|
||||
],
|
||||
'tags' => null,
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'tag1, tag2 || A >B = C>D ^ 7 * 42 # One Comment',
|
||||
'expected' => [
|
||||
'comment' => 'One Comment',
|
||||
'multiple' => 42,
|
||||
'ranking' => [
|
||||
['A'],
|
||||
['B', 'C'],
|
||||
['D'],
|
||||
],
|
||||
'tags' => ['tag1', 'tag2'],
|
||||
'weight' => 7,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'A >B = C>D *42#One Comment',
|
||||
'expected' => [
|
||||
'comment' => 'One Comment',
|
||||
'multiple' => 42,
|
||||
'ranking' => [
|
||||
['A'],
|
||||
['B', 'C'],
|
||||
['D'],
|
||||
],
|
||||
'tags' => null,
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'A^ 7#',
|
||||
'expected' => [
|
||||
'comment' => '',
|
||||
'multiple' => 1,
|
||||
'ranking' => [
|
||||
['A'],
|
||||
],
|
||||
'tags' => null,
|
||||
'weight' => 7,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => ' ',
|
||||
'expected' => [
|
||||
'comment' => null,
|
||||
'multiple' => 1,
|
||||
'ranking' => null,
|
||||
'tags' => null,
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => ' tag1,tag2|| ',
|
||||
'expected' => [
|
||||
'comment' => null,
|
||||
'multiple' => 1,
|
||||
'ranking' => null,
|
||||
'tags' => ['tag1', 'tag2'],
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => '^7*4 ',
|
||||
'expected' => [
|
||||
'comment' => null,
|
||||
'multiple' => 4,
|
||||
'ranking' => null,
|
||||
'tags' => null,
|
||||
'weight' => 7,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => ' #One Comment',
|
||||
'expected' => [
|
||||
'comment' => 'One Comment',
|
||||
'multiple' => 1,
|
||||
'ranking' => null,
|
||||
'tags' => null,
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => 'tag1,tag2||'.CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING.'^7*42#FeteDuDindon',
|
||||
'expected' => [
|
||||
'comment' => 'FeteDuDindon',
|
||||
'multiple' => 42,
|
||||
'ranking' => [],
|
||||
'tags' => ['tag1', 'tag2'],
|
||||
'weight' => 7,
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'entry' => ' '.CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING.' ',
|
||||
'expected' => [
|
||||
'comment' => null,
|
||||
'multiple' => 1,
|
||||
'ranking' => [],
|
||||
'tags' => null,
|
||||
'weight' => 1,
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
77
include/Condorcet/Tests/src/Utils/VoteUtilTest.php
Normal file
77
include/Condorcet/Tests/src/Utils/VoteUtilTest.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests\Utils;
|
||||
|
||||
use CondorcetPHP\Condorcet\Utils\VoteUtil;
|
||||
use CondorcetPHP\Condorcet\Throwable\VoteInvalidFormatException;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VoteUtilTest extends TestCase
|
||||
{
|
||||
public function testTypeMismatchTagsThrowAnException(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: every tag must be of type string, array given');
|
||||
VoteUtil::tagsConvert(['not', 'a', 'string:', []]);
|
||||
}
|
||||
|
||||
public function testEmptyTagsThrowAnException(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: found empty tag');
|
||||
VoteUtil::tagsConvert('an , empty, tag , , in, the, middle');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider tagsProvider()
|
||||
*/
|
||||
public function testTagsGetConverted($tags, $expected): void
|
||||
{
|
||||
$this->assertSame($expected, VoteUtil::tagsConvert($tags));
|
||||
}
|
||||
|
||||
public function testGetRankingAsString(): void
|
||||
{
|
||||
// Empty ranking
|
||||
$this->assertEquals('', VoteUtil::getRankingAsString([]));
|
||||
|
||||
// String ranking
|
||||
$this->assertEquals('A > B > C', VoteUtil::getRankingAsString(['A', 'B', 'C']));
|
||||
|
||||
// Array ranking
|
||||
$this->assertEquals('A = B > C', VoteUtil::getRankingAsString([['A', 'B'], 'C']));
|
||||
|
||||
// Unsorted array ranking
|
||||
$this->assertEquals('A = B > C', VoteUtil::getRankingAsString([['B', 'A'], 'C']));
|
||||
}
|
||||
|
||||
public function tagsProvider(): iterable
|
||||
{
|
||||
yield 'null tags' => [
|
||||
'tags' => null,
|
||||
'expected' => null,
|
||||
];
|
||||
|
||||
yield 'empty string' => [
|
||||
'tags' => '',
|
||||
'expected' => null,
|
||||
];
|
||||
|
||||
yield 'empty array' => [
|
||||
'tags' => [],
|
||||
'expected' => null,
|
||||
];
|
||||
|
||||
yield 'tags as string' => [
|
||||
'tags' => 'these, are, some , tags',
|
||||
'expected' => ['these', 'are', 'some', 'tags'],
|
||||
];
|
||||
|
||||
yield 'tags as array' => [
|
||||
'tags' => ['these', 'are', 'some', 'more', 'tags'],
|
||||
'expected' => ['these', 'are', 'some', 'more', 'tags'],
|
||||
];
|
||||
}
|
||||
}
|
814
include/Condorcet/Tests/src/VoteTest.php
Normal file
814
include/Condorcet/Tests/src/VoteTest.php
Normal file
@ -0,0 +1,814 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CondorcetPHP\Condorcet\Tests;
|
||||
|
||||
use CondorcetPHP\Condorcet\{Candidate, Election, Vote};
|
||||
use CondorcetPHP\Condorcet\Throwable\{CandidateDoesNotExistException, VoteInvalidFormatException, VoteNotLinkedException};
|
||||
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
|
||||
use CondorcetPHP\Condorcet\Utils\CondorcetUtil;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class VoteTest extends TestCase
|
||||
{
|
||||
private readonly Election $election1;
|
||||
|
||||
private readonly Candidate $candidate1;
|
||||
private readonly Candidate $candidate2;
|
||||
private readonly Candidate $candidate3;
|
||||
private readonly Candidate $candidate4;
|
||||
private readonly Candidate $candidate5;
|
||||
private readonly Candidate $candidate6;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->election1 = new Election;
|
||||
|
||||
$this->candidate1 = $this->election1->addCandidate('candidate1');
|
||||
$this->candidate2 = $this->election1->addCandidate('candidate2');
|
||||
$this->candidate3 = $this->election1->addCandidate('candidate3');
|
||||
$this->candidate4 = new Candidate('candidate4');
|
||||
$this->candidate5 = new Candidate('candidate5');
|
||||
$this->candidate6 = new Candidate('candidate6');
|
||||
}
|
||||
|
||||
public function testTimestamp(): void
|
||||
{
|
||||
$vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
|
||||
self::assertEquals($vote1->getCreateTimestamp(), $vote1->getTimestamp());
|
||||
|
||||
$vote1->setRanking([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
|
||||
self::assertLessThan($vote1->getTimestamp(), $vote1->getCreateTimestamp());
|
||||
}
|
||||
|
||||
public function testDifferentRanking(): never
|
||||
{
|
||||
$this->expectException(VoteNotLinkedException::class);
|
||||
$this->expectExceptionMessage('The vote is not linked to an election');
|
||||
|
||||
// Ranking 1
|
||||
$vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
|
||||
$newRanking1 = $vote1->getRanking();
|
||||
|
||||
// Ranking 2
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
[$this->candidate1, $this->candidate2, $this->candidate3]
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getRanking()
|
||||
);
|
||||
|
||||
// Ranking 3
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
[4=> $this->candidate1, 6=> $this->candidate2, 14 => $this->candidate3]
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getRanking()
|
||||
);
|
||||
|
||||
// Add vote into an election
|
||||
self::assertSame(
|
||||
$this->election1->addVote($vote1),
|
||||
$vote1
|
||||
);
|
||||
|
||||
// Ranking 4
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
[$this->candidate1, $this->candidate2]
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
self::assertCount(
|
||||
2,
|
||||
$vote1->getRanking()
|
||||
);
|
||||
|
||||
// Ranking 5
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
['candidate1', 'candidate2']
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
// Ranking 6
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
[42 => 'candidate2', 142=> 'candidate1']
|
||||
)
|
||||
);
|
||||
|
||||
self::assertNotSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
// Ranking 7
|
||||
self::assertTrue(
|
||||
$vote1->setRanking(
|
||||
'candidate1>Kim Jong>candidate2>Trump'
|
||||
)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
|
||||
// Ranking 8
|
||||
self::assertTrue(
|
||||
$vote1->setRanking([
|
||||
2=> $this->candidate2,
|
||||
1=> $this->candidate1,
|
||||
3=> $this->candidate3,
|
||||
])
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
|
||||
// Ranking 9
|
||||
|
||||
$vote = new Vote('candidate4 > candidate3 = candidate1 > candidate2');
|
||||
|
||||
self::assertSame(
|
||||
CondorcetUtil::format($vote->getRanking()),
|
||||
[
|
||||
1 => 'candidate4',
|
||||
2 => ['candidate1', 'candidate3'],
|
||||
3 => 'candidate2',
|
||||
]
|
||||
);
|
||||
|
||||
$election = new Election;
|
||||
$election->parseCandidates('candidate2;candidate3;candidate4;candidate1');
|
||||
$election->addVote($vote);
|
||||
|
||||
self::assertSame(
|
||||
CondorcetUtil::format($vote->getContextualRanking($election)),
|
||||
[
|
||||
1 => 'candidate4',
|
||||
2 => ['candidate1', 'candidate3'],
|
||||
3 => 'candidate2',
|
||||
]
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
$election->getResult()->getResultAsArray(true),
|
||||
[
|
||||
1 => 'candidate4',
|
||||
2 => ['candidate1', 'candidate3'],
|
||||
3 => 'candidate2',
|
||||
]
|
||||
);
|
||||
|
||||
// Contextual Ranking Fail
|
||||
|
||||
$unexpectedElection = new Election;
|
||||
|
||||
$vote1->getContextualRanking($unexpectedElection);
|
||||
}
|
||||
|
||||
public function testSimpleRanking(): void
|
||||
{
|
||||
// Ranking 1
|
||||
$vote1 = new Vote('candidate1 > candidate3 = candidate2 > candidate4');
|
||||
|
||||
self::assertSame($vote1->getSimpleRanking(), 'candidate1 > candidate2 = candidate3 > candidate4');
|
||||
|
||||
$this->election1->addVote($vote1);
|
||||
|
||||
self::assertSame($vote1->getSimpleRanking($this->election1), 'candidate1 > candidate2 = candidate3');
|
||||
}
|
||||
|
||||
public function testProvisionalCandidateObject(): void
|
||||
{
|
||||
// Ranking 1
|
||||
$vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
$newRanking1 = $vote1->getRanking();
|
||||
$this->election1->addVote($vote1);
|
||||
|
||||
// I
|
||||
self::assertTrue(
|
||||
$vote1->setRanking([
|
||||
new Candidate('candidate1'),
|
||||
$this->candidate2,
|
||||
$this->candidate3,
|
||||
])
|
||||
);
|
||||
|
||||
self::assertNotSame(
|
||||
$newRanking1,
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => [$this->candidate2],
|
||||
2 => [$this->candidate3],
|
||||
3 => [$this->candidate1], ],
|
||||
$vote1->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'candidate2',
|
||||
2 => 'candidate3',
|
||||
3 => 'candidate1', ],
|
||||
$vote1->getContextualRankingAsString($this->election1)
|
||||
);
|
||||
|
||||
// II
|
||||
$vote2 = new Vote('candidate1>candidate2');
|
||||
|
||||
self::assertTrue($vote2->getRanking()[1][0]->getProvisionalState());
|
||||
$vote2_firstRanking = $vote2->getRanking();
|
||||
|
||||
$this->election1->addVote($vote2);
|
||||
|
||||
self::assertFalse($vote2->getRanking()[1][0]->getProvisionalState());
|
||||
|
||||
self::assertSame(
|
||||
[1 => [$this->candidate1],
|
||||
2 => [$this->candidate2],
|
||||
3 => [$this->candidate3], ],
|
||||
$vote2->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
self::assertNotEquals(
|
||||
$vote2_firstRanking,
|
||||
$vote2->getRanking()
|
||||
);
|
||||
|
||||
|
||||
// III
|
||||
$otherCandidate1 = new candidate('candidate1');
|
||||
$otherCandidate2 = new candidate('candidate2');
|
||||
|
||||
$vote3 = new Vote([$otherCandidate1, $otherCandidate2, $this->candidate3]);
|
||||
|
||||
self::assertFalse($vote3->getRanking()[1][0]->getProvisionalState());
|
||||
$vote3_firstRanking = $vote3->getRanking();
|
||||
|
||||
$this->election1->addVote($vote3);
|
||||
|
||||
self::assertFalse($vote2->getRanking()[1][0]->getProvisionalState());
|
||||
|
||||
self::assertSame(
|
||||
[1 => [$this->candidate3],
|
||||
2 => [$this->candidate1, $this->candidate2], ],
|
||||
$vote3->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[1 => 'candidate3',
|
||||
2 => ['candidate1', 'candidate2'], ],
|
||||
$vote3->getContextualRankingAsString($this->election1)
|
||||
);
|
||||
|
||||
self::assertEquals(
|
||||
$vote3_firstRanking,
|
||||
$vote3->getRanking()
|
||||
);
|
||||
}
|
||||
|
||||
public function testDifferentElection(): void
|
||||
{
|
||||
$election1 = $this->election1;
|
||||
|
||||
$election2 = new Election;
|
||||
$election2->addCandidate($this->candidate1);
|
||||
$election2->addCandidate($this->candidate2);
|
||||
$election2->addCandidate($this->candidate4);
|
||||
|
||||
$vote1 = new Vote([
|
||||
$this->candidate1,
|
||||
$this->candidate2,
|
||||
$this->candidate3,
|
||||
$this->candidate4,
|
||||
]);
|
||||
$vote1_originalRanking = $vote1->getRanking();
|
||||
|
||||
$election1->addVote($vote1);
|
||||
$election2->addVote($vote1);
|
||||
|
||||
self::assertSame($vote1_originalRanking, $vote1->getRanking());
|
||||
self::assertSame(
|
||||
[1=>[$this->candidate1], 2=>[$this->candidate2], 3=>[$this->candidate3]],
|
||||
$vote1->getContextualRanking($election1)
|
||||
);
|
||||
self::assertSame(
|
||||
[1=>[$this->candidate1], 2=>[$this->candidate2], 3=>[$this->candidate4]],
|
||||
$vote1->getContextualRanking($election2)
|
||||
);
|
||||
self::assertNotSame($vote1->getRanking(), $vote1->getContextualRanking($election2));
|
||||
|
||||
self::assertTrue($vote1->setRanking([
|
||||
[$this->candidate5, $this->candidate2],
|
||||
$this->candidate3,
|
||||
]));
|
||||
|
||||
self::assertSame(
|
||||
[1=>[$this->candidate2], 2=>[$this->candidate3], 3=>[$this->candidate1]],
|
||||
$vote1->getContextualRanking($election1)
|
||||
);
|
||||
self::assertSame(
|
||||
[1=>[$this->candidate2], 2=>[$this->candidate1, $this->candidate4]],
|
||||
$vote1->getContextualRanking($election2)
|
||||
);
|
||||
}
|
||||
|
||||
public function testValidTags(): void
|
||||
{
|
||||
$vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
|
||||
$targetTags = ['tag1', 'tag2', 'tag3'];
|
||||
|
||||
self::assertTrue($vote1->addTags(
|
||||
'tag1,tag2,tag3'
|
||||
));
|
||||
|
||||
self::assertSame(
|
||||
$targetTags,
|
||||
array_values($vote1->getTags())
|
||||
);
|
||||
|
||||
self::assertTrue($vote1->removeAllTags());
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote1->getTags()
|
||||
);
|
||||
|
||||
self::assertTrue($vote1->addTags(
|
||||
['tag1', 'tag2', 'tag3']
|
||||
));
|
||||
|
||||
self::assertSame(
|
||||
$targetTags,
|
||||
array_values($vote1->getTags())
|
||||
);
|
||||
|
||||
self::assertEquals(['tag2'], $vote1->removeTags('tag2'));
|
||||
|
||||
self::assertEquals(
|
||||
['tag1', 'tag3'],
|
||||
array_values($vote1->getTags())
|
||||
);
|
||||
|
||||
self::assertTrue($vote1->removeAllTags());
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote1->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
public function testBadTagInput1(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: every tag must be of type string, integer given');
|
||||
|
||||
$vote = new Vote('A');
|
||||
$vote->addTags(['tag1', 42]);
|
||||
}
|
||||
|
||||
public function testBadTagInput2(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: found empty tag');
|
||||
|
||||
$vote = new Vote('A');
|
||||
$vote->addTags(
|
||||
['tag1 ', ' tag2', ' tag3 ', ' ']
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote->getTags()
|
||||
);
|
||||
|
||||
self::assertTrue($vote->removeAllTags());
|
||||
}
|
||||
|
||||
public function testBadTagInput3(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: found empty tag');
|
||||
|
||||
$vote = new Vote('A');
|
||||
$vote->addTags(
|
||||
' tag1,tag2 , tag3 ,'
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote->getTags()
|
||||
);
|
||||
|
||||
self::assertTrue($vote->removeAllTags());
|
||||
}
|
||||
|
||||
public function testBadTagInput4(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: every tag must be of type string, NULL given');
|
||||
|
||||
$vote = new Vote('A');
|
||||
$vote->addTags(
|
||||
[null]
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
public function testBadTagInput5(): void
|
||||
{
|
||||
$vote = new Vote('A');
|
||||
$vote->addTags(
|
||||
[]
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
public function testAddRemoveTags(): void
|
||||
{
|
||||
$vote1 = new Vote([$this->candidate1, $this->candidate2, $this->candidate3]);
|
||||
|
||||
$vote1->addTags('tag1');
|
||||
$vote1->addTags(['tag2', 'tag3']);
|
||||
self::assertTrue($vote1->addTags('tag4,tag5'));
|
||||
|
||||
self::assertSame(
|
||||
['tag1', 'tag2', 'tag3', 'tag4', 'tag5'],
|
||||
$vote1->getTags()
|
||||
);
|
||||
|
||||
self::assertsame([], $vote1->removeTags(''));
|
||||
$vote1->removeTags('tag1');
|
||||
$vote1->removeTags(['tag2', 'tag3']);
|
||||
self::assertsame($vote1->removeTags('tag4,tag5,tag42'), ['tag4', 'tag5']);
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote1->getTags()
|
||||
);
|
||||
|
||||
self::assertTrue($vote1->addTags('tag4,tag5'));
|
||||
self::assertTrue($vote1->removeAllTags());
|
||||
|
||||
self::assertSame(
|
||||
[],
|
||||
$vote1->getTags()
|
||||
);
|
||||
}
|
||||
|
||||
public function testTagsOnConstructorByStringInput(): void
|
||||
{
|
||||
$vote1 = new Vote('tag1,tag2 ||A > B >C', 'tag3,tag4');
|
||||
|
||||
self::assertSame(['tag3', 'tag4', 'tag1', 'tag2'], $vote1->getTags());
|
||||
|
||||
self::assertSame('A > B > C', $vote1->getSimpleRanking());
|
||||
|
||||
$vote2 = new Vote((string) $vote1);
|
||||
|
||||
self::assertSame((string) $vote1, (string) $vote2);
|
||||
}
|
||||
|
||||
public function testCloneVote(): void
|
||||
{
|
||||
// Ranking 1
|
||||
$vote1 = new Vote('candidate1 > candidate3 = candidate2 > candidate4');
|
||||
|
||||
$this->election1->addVote($vote1);
|
||||
|
||||
$vote2 = clone $vote1;
|
||||
|
||||
self::assertSame(0, $vote2->countLinks());
|
||||
self::assertSame(1, $vote1->countLinks());
|
||||
}
|
||||
|
||||
public function testIterator(): void
|
||||
{
|
||||
$vote = new Vote('C > B > A');
|
||||
|
||||
foreach ($vote as $key => $value) {
|
||||
self::assertSame($vote->getRanking()[$key], $value);
|
||||
}
|
||||
}
|
||||
|
||||
public function testWeight(): never
|
||||
{
|
||||
$vote = new Vote('A>B>C^42');
|
||||
|
||||
self::assertsame(42, $vote->getWeight());
|
||||
self::assertsame(2, $vote->setWeight(2));
|
||||
self::assertsame(2, $vote->getWeight());
|
||||
self::assertsame(1, $vote->getWeight($this->election1));
|
||||
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage("The format of the vote is invalid: the value 'a' is not an integer.");
|
||||
|
||||
$vote = new Vote('A>B>C^a');
|
||||
}
|
||||
|
||||
public function testCustomTimestamp(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: Timestamp format of vote is not correct');
|
||||
|
||||
$vote = new Vote(
|
||||
'A>B>C',
|
||||
null,
|
||||
$createTimestamp = microtime(true) - (3600 * 1000)
|
||||
);
|
||||
|
||||
self::assertSame($createTimestamp, $vote->getTimestamp());
|
||||
|
||||
$vote->setRanking('B>C>A', $ranking2Timestamp = microtime(true) - (60 * 1000));
|
||||
|
||||
self::assertSame($ranking2Timestamp, $vote->getTimestamp());
|
||||
|
||||
self::assertSame($createTimestamp, $vote->getCreateTimestamp());
|
||||
|
||||
self::assertSame($createTimestamp, $vote->getHistory()[0]['timestamp']);
|
||||
|
||||
self::assertSame($ranking2Timestamp, $vote->getHistory()[1]['timestamp']);
|
||||
|
||||
$vote->setRanking('A', 1);
|
||||
}
|
||||
|
||||
public function testHashCode(): void
|
||||
{
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
$hashCode[1] = $vote->getHashCode();
|
||||
|
||||
$vote->addTags('tag1');
|
||||
|
||||
$hashCode[2] = $vote->getHashCode();
|
||||
|
||||
$vote->setRanking('C>A>B');
|
||||
|
||||
$hashCode[3] = $vote->getHashCode();
|
||||
|
||||
$vote->setRanking('C>A>B');
|
||||
|
||||
$hashCode[4] = $vote->getHashCode();
|
||||
|
||||
self::assertNotsame($hashCode[2], $hashCode[1]);
|
||||
self::assertNotsame($hashCode[3], $hashCode[2]);
|
||||
self::assertNotSame($hashCode[4], $hashCode[3]);
|
||||
}
|
||||
|
||||
public function testCountRankingCandidates(): void
|
||||
{
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
self::assertsame(3, $vote->countRankingCandidates());
|
||||
}
|
||||
|
||||
public function testInvalidWeight(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid: the vote weight can not be less than 1');
|
||||
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
$vote->setWeight(0);
|
||||
}
|
||||
|
||||
public function testInvalidTag1(): never
|
||||
{
|
||||
$this->expectException(\TypeError::class);
|
||||
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
$vote->addTags(true);
|
||||
}
|
||||
|
||||
public function testInvalidTag2(): never
|
||||
{
|
||||
$this->expectException(\TypeError::class);
|
||||
|
||||
$vote = new Vote('A>B>C');
|
||||
|
||||
$vote->addTags(42);
|
||||
}
|
||||
|
||||
public function testRemoveCandidate(): never
|
||||
{
|
||||
$vote1 = new Vote('candidate1 > candidate2 > candidate3 ^ 42');
|
||||
|
||||
$this->election1->addVote($vote1);
|
||||
|
||||
self::assertSame('candidate1 > candidate2 > candidate3', $this->election1->getResult()->getResultAsString());
|
||||
|
||||
$vote1->removeCandidate('candidate2');
|
||||
|
||||
self::assertSame('candidate1 > candidate3 ^42', $vote1->getSimpleRanking());
|
||||
|
||||
self::assertSame('candidate1 > candidate3 > candidate2', $this->election1->getResult()->getResultAsString());
|
||||
|
||||
$vote1->removeCandidate($this->candidate3);
|
||||
|
||||
self::assertSame('candidate1 > candidate2 = candidate3', $this->election1->getResult()->getResultAsString());
|
||||
|
||||
$this->expectException(CandidateDoesNotExistException::class);
|
||||
$this->expectExceptionMessage('This candidate does not exist: candidate4');
|
||||
|
||||
$vote1->removeCandidate($this->candidate4);
|
||||
}
|
||||
|
||||
public function testRemoveCandidateInvalidInput(): never
|
||||
{
|
||||
$vote1 = new Vote('candidate1 > candidate2 > candidate3 ^ 42');
|
||||
|
||||
$this->expectException(\TypeError::class);
|
||||
|
||||
$vote1->removeCandidate([]);
|
||||
}
|
||||
|
||||
public function testVoteHistory(): void
|
||||
{
|
||||
$this->election1->addCandidate($this->candidate4);
|
||||
$this->election1->addCandidate($this->candidate5);
|
||||
$this->election1->addCandidate($this->candidate6);
|
||||
|
||||
|
||||
$vote1 = $this->election1->addVote(['candidate1', 'candidate2']);
|
||||
|
||||
self::assertCount(1, $vote1->getHistory());
|
||||
|
||||
// -------
|
||||
|
||||
$vote2 = $this->election1->addVote('candidate1 > candidate2');
|
||||
|
||||
self::assertCount(1, $vote2->getHistory());
|
||||
|
||||
// -------
|
||||
|
||||
$vote3 = new Vote(['candidate1', 'candidate2']);
|
||||
|
||||
$this->election1->addVote($vote3);
|
||||
|
||||
self::assertCount(2, $vote3);
|
||||
|
||||
// -------
|
||||
|
||||
$this->election1->parseVotes('voterParsed || candidate1 > candidate2');
|
||||
|
||||
$votes_lists = $this->election1->getVotesListGenerator('voterParsed', true);
|
||||
$vote4 = $votes_lists->current();
|
||||
|
||||
self::assertCount(1, $vote4->getHistory());
|
||||
|
||||
// -------
|
||||
|
||||
$vote5 = new Vote([$this->candidate5, $this->candidate6]);
|
||||
|
||||
$this->election1->addVote($vote5);
|
||||
|
||||
self::assertCount(1, $vote5->getHistory());
|
||||
|
||||
// -------
|
||||
|
||||
$vote6 = new Vote([$this->candidate5, 'candidate6']);
|
||||
|
||||
$this->election1->addVote($vote6);
|
||||
|
||||
self::assertCount(2, $vote6->getHistory());
|
||||
|
||||
// -------
|
||||
|
||||
$vote7 = new Vote([$this->candidate6, 'candidate8']);
|
||||
|
||||
$candidate8 = $vote7->getAllCandidates()[1];
|
||||
|
||||
self::assertsame('candidate8', $candidate8->getName());
|
||||
|
||||
self::assertTrue($candidate8->getProvisionalState());
|
||||
|
||||
$this->election1->addVote($vote7);
|
||||
|
||||
self::assertTrue($candidate8->getProvisionalState());
|
||||
|
||||
self::assertCount(1, $vote7->getHistory());
|
||||
}
|
||||
|
||||
public function testBadRankingInput1(): never
|
||||
{
|
||||
$this->expectException(\TypeError::class);
|
||||
|
||||
$vote = new Vote(42);
|
||||
}
|
||||
|
||||
public function testBadRankingInput2(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid');
|
||||
|
||||
$candidate = new Candidate('A');
|
||||
|
||||
$vote = new Vote([$candidate, $candidate]);
|
||||
}
|
||||
|
||||
public function testEmptyVoteContextualInRanking(): void
|
||||
{
|
||||
$vote = $this->election1->addVote('candidate4 > candidate5');
|
||||
|
||||
self::assertSame(
|
||||
[1 => [$this->candidate1, $this->candidate2, $this->candidate3]],
|
||||
$vote->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
$cr = $vote->getContextualRankingAsString($this->election1);
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['candidate1', 'candidate2', 'candidate3']],
|
||||
$cr
|
||||
);
|
||||
}
|
||||
|
||||
public function testNonEmptyVoteContextualInRanking(): void
|
||||
{
|
||||
$vote = $this->election1->addVote('candidate1 = candidate2 = candidate3');
|
||||
|
||||
self::assertSame(
|
||||
[1 => [$this->candidate1, $this->candidate2, $this->candidate3]],
|
||||
$vote->getContextualRanking($this->election1)
|
||||
);
|
||||
|
||||
$cr = $vote->getContextualRankingAsString($this->election1);
|
||||
|
||||
self::assertSame(
|
||||
[1 => ['candidate1', 'candidate2', 'candidate3']],
|
||||
$cr
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// https://github.com/julien-boudry/Condorcet/issues/32
|
||||
public function testDuplicateCandidates1(): never
|
||||
{
|
||||
$this->expectException(VoteInvalidFormatException::class);
|
||||
$this->expectExceptionMessage('The format of the vote is invalid');
|
||||
|
||||
new Vote('Spain>Japan>France>Netherlands>Australia>France');
|
||||
}
|
||||
|
||||
|
||||
// https://github.com/julien-boudry/Condorcet/issues/32
|
||||
public function testDuplicateCandidates2(): void
|
||||
{
|
||||
$election = new Election;
|
||||
$election->parseCandidates('Spain;Japan;France;Netherlands;Australia');
|
||||
|
||||
$vote = $election->addVote('Spain>Japan>France>Netherlands>Australia>france');
|
||||
|
||||
self::assertSame(
|
||||
'Spain > Japan > France > Netherlands > Australia',
|
||||
$vote->getSimpleRanking($election)
|
||||
);
|
||||
}
|
||||
|
||||
public function testEmptySpecialKeyWord(): void
|
||||
{
|
||||
$vote1 = new Vote(CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING);
|
||||
$vote2 = new Vote(' '.CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING.' ');
|
||||
|
||||
self::assertSame([], $vote1->getRanking());
|
||||
self::assertSame([], $vote2->getRanking());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user