1
0
This repository has been archived on 2023-11-30. You can view files and clone it, but cannot push or open issues or pull requests.
Files
dtux__serveur-vote-lalis/include/condorcet/src/DataManager/VotesManager.php
2022-09-21 14:01:45 +02:00

272 lines
7.9 KiB
PHP

<?php
/*
Condorcet PHP - Election manager and results calculator.
Designed for the Condorcet method. Integrating a large number of algorithms extending Condorcet. Expandable for all types of voting systems.
By Julien Boudry and contributors - MIT LICENSE (Please read LICENSE.txt)
https://github.com/julien-boudry/Condorcet
*/
declare(strict_types=1);
namespace CondorcetPHP\Condorcet\DataManager;
use CondorcetPHP\Condorcet\{Vote};
use CondorcetPHP\Condorcet\Dev\CondorcetDocumentationGenerator\CondorcetDocAttributes\{Throws};
use CondorcetPHP\Condorcet\ElectionProcess\ElectionState;
use CondorcetPHP\Condorcet\Throwable\VoteManagerException;
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
class VotesManager extends ArrayManager
{
/////////// Data CallBack for external drivers ///////////
protected function decodeOneEntity(string $data): Vote
{
$vote = new Vote($data);
$vote->registerLink($this->getElection());
$vote->notUpdate = true;
$this->getElection()->checkVoteCandidate($vote);
$vote->notUpdate = false;
return $vote;
}
protected function encodeOneEntity(Vote $data): string
{
$data->destroyLink($this->getElection());
return str_replace([' > ', ' = '], ['>', '='], (string) $data);
}
protected function preDeletedTask(Vote $object): void
{
$object->destroyLink($this->getElection());
}
/////////// Array Access - Specials improvements ///////////
public function offsetGet(mixed $offset): Vote
{
return parent::offsetGet($offset);
}
#[Throws(VoteManagerException::class)]
public function offsetSet(mixed $offset, mixed $value): void
{
if ($value instanceof Vote) {
parent::offsetSet((\is_int($offset) ? $offset : null), $value);
$this->UpdateAndResetComputing(key: $this->maxKey, type: 1);
} else {
throw new VoteManagerException;
}
$this->checkRegularize();
}
public function offsetUnset(mixed $offset): void
{
$this->UpdateAndResetComputing(key: $offset, type: 2);
parent::offsetUnset($offset);
}
/////////// Internal Election related methods ///////////
public function UpdateAndResetComputing(int $key, int $type): void
{
$election = $this->getElection();
if ($election->getState() === ElectionState::VOTES_REGISTRATION) {
if ($type === 1) {
$election->getPairwise()->addNewVote($key);
} elseif ($type === 2) {
$election->getPairwise()->removeVote($key);
}
$election->cleanupCalculator();
} else {
$election->setStateToVote();
}
}
/////////// Get Votes Methods ///////////
public function getVoteKey(Vote $vote): ?int
{
($r = array_search(needle: $vote, haystack: $this->Container, strict: true)) !== false || ($r = array_search(needle: $vote, haystack: $this->Cache, strict: true));
return ($r !== false) ? $r : null;
}
protected function getFullVotesListGenerator(): \Generator
{
foreach ($this as $voteKey => $vote) {
yield $voteKey => $vote;
}
}
protected function getPartialVotesListGenerator(array $tags, bool $with): \Generator
{
foreach ($this as $voteKey => $vote) {
$noOne = true;
foreach ($tags as $oneTag) {
if (($oneTag === $voteKey) || \in_array(needle: $oneTag, haystack: $vote->getTags(), strict: true)) {
if ($with) {
yield $voteKey => $vote;
break;
} else {
$noOne = false;
}
}
}
if (!$with && $noOne) {
yield $voteKey => $vote;
}
}
}
// Get the votes list
public function getVotesList(?array $tags = null, bool $with = true): array
{
if ($tags === null) {
return $this->getFullDataSet();
} else {
$search = [];
foreach ($this->getPartialVotesListGenerator($tags, $with) as $voteKey => $vote) {
$search[$voteKey] = $vote;
}
return $search;
}
}
// Get the votes list as a generator object
public function getVotesListGenerator(?array $tags = null, bool $with = true): \Generator
{
if ($tags === null) {
return $this->getFullVotesListGenerator();
} else {
return $this->getPartialVotesListGenerator($tags, $with);
}
}
public function getVotesValidUnderConstraintGenerator(?array $tags = null, bool $with = true): \Generator
{
$election = $this->getElection();
$generator = ($tags === null) ? $this->getFullVotesListGenerator() : $this->getPartialVotesListGenerator($tags, $with);
foreach ($generator as $voteKey => $oneVote) {
if (!$election->testIfVoteIsValidUnderElectionConstraints($oneVote)) {
continue;
}
yield $voteKey => $oneVote;
}
}
public function getVotesListAsString(bool $withContext): string
{
$election = $this->getElection();
$simpleList = '';
$weight = [];
$nb = [];
foreach ($this as $oneVote) {
$oneVoteString = $oneVote->getSimpleRanking($withContext ? $election : null);
if (!\array_key_exists(key: $oneVoteString, array: $weight)) {
$weight[$oneVoteString] = 0;
}
if (!\array_key_exists(key: $oneVoteString, array: $nb)) {
$nb[$oneVoteString] = 0;
}
if ($election->isVoteWeightAllowed()) {
$weight[$oneVoteString] += $oneVote->getWeight();
} else {
$weight[$oneVoteString]++;
}
$nb[$oneVoteString]++;
}
ksort($weight, \SORT_NATURAL);
arsort($weight);
$isFirst = true;
foreach ($weight as $key => $value) {
if (!$isFirst) {
$simpleList .= "\n";
}
$voteString = ($key === '') ? CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING : $key;
$simpleList .= $voteString.' * '.$nb[$key];
$isFirst = false;
}
return $simpleList;
}
public function countVotes(?array $tag, bool $with): int
{
if ($tag === null) {
return \count($this);
} else {
$count = 0;
foreach ($this as $key => $value) {
$noOne = true;
foreach ($tag as $oneTag) {
if (($oneTag === $key) || \in_array(needle: $oneTag, haystack: $value->getTags(), strict: true)) {
if ($with) {
$count++;
break;
} else {
$noOne = false;
}
}
}
if (!$with && $noOne) {
$count++;
}
}
return $count;
}
}
public function countInvalidVoteWithConstraints(): int
{
$election = $this->getElection();
$count = 0;
foreach ($this as $oneVote) {
if (!$election->testIfVoteIsValidUnderElectionConstraints($oneVote)) {
$count++;
}
}
return $count;
}
public function sumVotesWeight(bool $constraint = false): int
{
$election = $this->getElection();
$sum = 0;
foreach ($this as $oneVote) {
if (!$constraint || $election->testIfVoteIsValidUnderElectionConstraints($oneVote)) {
$sum += $election->isVoteWeightAllowed() ? $oneVote->getWeight() : 1;
}
}
return $sum;
}
}