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/Utils/VoteEntryParser.php
2022-09-21 14:01:45 +02:00

143 lines
4.2 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\Utils;
use CondorcetPHP\Condorcet\Dev\CondorcetDocumentationGenerator\CondorcetDocAttributes\Throws;
use CondorcetPHP\Condorcet\Throwable\VoteInvalidFormatException;
use CondorcetPHP\Condorcet\Tools\Converters\CondorcetElectionFormat;
// Base Condorcet class
class VoteEntryParser
{
public readonly string $originalEntry;
public readonly ?string $comment;
public readonly int $multiple;
public readonly ?array $ranking;
public readonly ?array $tags;
public readonly int $weight;
public function __construct(string $entry)
{
$this->originalEntry = $entry;
// Disallow < and "
if (preg_match('/<|"/mi', $entry) === 1) {
throw new VoteInvalidFormatException("found '<' or '|' in " . $entry);
}
$this->comment = $this->getComment($entry, true);
$this->multiple = self::parseIntValueFromVoteStringOffset('*', $entry, true);
$this->weight = self::parseIntValueFromVoteStringOffset('^', $entry, true);
$this->tags = $this->convertTagsFromVoteString($entry, true);
$this->ranking = self::convertRankingFromString($entry);
}
// From a string like 'A>B=C=H>G=T>Q'
public static function convertRankingFromString(string $formula): ?array
{
$formula = trim($formula);
// Condorcet Election Format special string
if (empty($formula)) {
return null;
} elseif ($formula === CondorcetElectionFormat::SPECIAL_KEYWORD_EMPTY_RANKING) {
return [];
} else {
$ranking = explode('>', $formula);
foreach ($ranking as &$rank_vote) {
$rank_vote = explode('=', $rank_vote);
$rank_vote = array_filter($rank_vote);
// Del space at start and end
foreach ($rank_vote as &$value) {
$value = trim($value);
}
}
return array_filter($ranking);
}
}
public static function convertTagsFromVoteString(string &$voteString, bool $cut = false): ?array
{
$offset = mb_strpos($voteString, '||');
if (\is_int($offset)) {
$tagsPart = mb_substr($voteString, 0, $offset);
$tags = explode(',', $tagsPart);
array_walk($tags, static function (string &$value): void {
$value = trim($value);
});
$cut && $voteString = mb_substr($voteString, $offset + 2);
return $tags;
} else {
return null;
}
}
public static function getComment(string &$voteString, bool $cut = false): ?string
{
$offset = mb_strpos($voteString, '#');
if (\is_int($offset)) {
$comment = trim(mb_substr($voteString, $offset + 1));
$cut && $voteString = mb_substr($voteString, 0, $offset);
return $comment;
} else {
return null;
}
}
#[Throws(VoteInvalidFormatException::class)]
public static function parseIntValueFromVoteStringOffset(string $character, string &$entry, bool $cut = false): int
{
$offset = mb_strpos($entry, $character);
if (\is_int($offset)) {
$input = trim(mb_substr($entry, $offset + 1));
$value = '';
foreach (mb_str_split($input) as $char) {
if (!\in_array($char, ['#', '^', '*', "\n"], true)) {
$value .= $char;
} else {
break;
}
}
// Errors
if (!is_numeric($value)) {
throw new VoteInvalidFormatException("the value '{$value}' is not an integer.");
}
$cut && $entry = mb_substr($entry, 0, $offset);
$value = \intval($value);
return ($value > 0) ? $value : 1;
} else {
return 1;
}
}
}