Closed phplicengine closed 3 years ago
Now I believe there is bug with getName()
, It happens when more than one candidate gets rank 1.
Hi, See the documentation for getWinner() here : https://github.com/julien-boudry/Condorcet/blob/master/Documentation/Election%20Class/public%20Election--getWinner.md
If you use an advanced method instead of Natural, you can get an array with multiples winners.
Here, Schulze's method certainly produces a tie for first place, which may be normal, depending on the input votes. getWinner therefore returns an array.
please give a sample code how to use advance method? @julien-boudry
Do you mean this?
Election->getWinner('advanced')
?
Election->getWinner() is always an advanced method. Default is 'Schulze Winning' method. Most of the advanced methods can produce a tie on rank, including top rank.
If you want the Natural Condorcet computation, the Marquis de Condorcet Winner. You must use Election->getCondorcetWinner() method. But be careful, the result can be NULL. The advanced methods almost always gives results, not the original Condorcet method. https://github.com/julien-boudry/Condorcet/blob/master/Documentation/Election%20Class/public%20Election--getCondorcetWinner.md
Here is my full source. If in form you choose the same number for more than one item, it gets error for getName()
on getWinner()
. What wrong I did as it is Schulze as you said.
use CondorcetPHP\Condorcet\Condorcet;
use CondorcetPHP\Condorcet\Election;
use CondorcetPHP\Condorcet\Candidate;
use CondorcetPHP\Condorcet\CondorcetUtil;
use CondorcetPHP\Condorcet\Vote;
if (isset($_POST) && $_POST != "") {
Condorcet::setDefaultMethod('Schulze');
$election = new Election ();
print("<pre>");
print_r($_POST['item']);
// To get Candidates by Category via Doctrine orm
$category = $em->getRepository('Entities\Category')->findOneBy(['id' => 1]);
$candidates = $category->getCandidates();
$total_items = 0;
foreach ($candidates as $candidate) {
$candidate = $candidate->getCandidate();
$election->addCandidate(new Candidate($candidate));
++$total_items;
}
$votes = array();
foreach ($_POST['item'] as $item => $ranking) {
$vote_factor = 1 + $total_items - $ranking;
if (isset($votes[$vote_factor])) {
$votes[$vote_factor] = (array) $votes[$vote_factor];
$votes[$vote_factor][] = $item;
} else {
$votes[$vote_factor] = $item;
}
}
$result = $election->addVote(new Vote($votes));
print("<br />");
foreach ($election->getResult('Schulze') as $rank => $candidates) :
echo 'Rank ' . $rank . ': ';
echo implode(', ', $candidates);
echo '<br />';
endforeach;
print_r($result->getSimpleRanking()); // To be saved in db.
echo 'Schulze winner is : ' . $election->getWinner('Schulze')->getName() . '<br />';
}
?>
<html>
<body>
<form method="post">
Wingspan: <select name="item[Wingspan]" id="Wingspan">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select><br />
Scythe: <select name="item[Scythe]" id="Scythe">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select><br />
Spirit Island: <select name="item[Spirit Island]" id="Spirit Island">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select><br />
Everdell: <select name="item[Everdell]" id="Everdell">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select><br />
<input type="submit" name="submit" value="submit">
</form>
</body>
</html>
I think you meant:
foreach ($election->getWinner('Schulze') as $winner) {
print($winner->getName()."<br />");
}
Is it correct? But it gives nothing if there is only one candidate. How do I know if there are only one or more than one winner(s) to fix this problem?
Please see my source, it seems it is working well, just for sure I want you to look at the source to see if everything is correct or any improvements you can suggest?
It seems
if (isset($_POST) && $_POST != "") {
is not working and for first run when there is nothing posted yet, I get these notices:
Notice: Undefined index: item on line 19
Notice: Undefined index: item on line 34
Warning: Invalid argument supplied for foreach() on line 34.
Why I am getting these errors?
And is there any way to combine both foreach()
as one and how to generate form items field from items fetched from db rather than hardcoding them?
I know these are not directly related to Condorcet, but I highly appreciate your help.
Hi @phplicengine,
Two ways.
1.
$winners = $election->getWinner('Schulze');
if (is_array($winners) {
foreach ($winners as $oneWinner) {
echo($oneWinner->getName()."<br />");
}
}
else {
echo($winners->getName());
}
2.
// On getResult, the ranks are always arrays.
foreach ($election->getResult('Schulze')[1] as $oneWinner) {
echo($oneWinner->getName()."<br />");
}
About your problem with the $_POST
in your code. I suppose that $_POST
is always set (so your isset is useless) and is never an empty string. So, your condition is always true.
Look with empty()
or count()
or isset($_POST['item'])
Here is my code I am using: https://github.com/julien-boudry/Condorcet/issues/42#issuecomment-831346042 I want to add a blank select option, that my users if they don't want to have some candidates in voting just use the blank select option and don't be forced to select a ranking number from the drop down menu. How to omit blank options completely from listing and voting? @julien-boudry
Beside my another question regarding
=
in my another issue, I have another problem too:If I have only one $vote, it works fine, but if I have both vote as above, I get this error:
Fatal error: Uncaught Error: Call to a member function getName() on array
Isn't it a bug? or I did a mistake?