Копипаста:Метод Шульце
Перейти к навигации
Перейти к поиску
<?php
use Silex\Application;
use Symfony\Component\HttpFoundation\Request;
class Schulze
{
private $app;
private $request;
private $candidates;
private $paths;
public function __construct(Application $app, Request $request)
{
$this->app = $app;
$this->request = $request;
}
public function mainReturn()
{
$votes = $this->request->get('votes');
if(!$this->getCandidates($this->request) || !$votes)
{
return $this->returnError();
}
$votes_arr = explode('|', $votes);
foreach ($votes_arr as $vote)
{
$names = explode(',', $vote);
foreach ($names as $i)
{
$is_next = false;
$f_i = htmlspecialchars($i);
foreach ($names as $j)
{
$f_j = htmlspecialchars($j);
if ($is_next && array_key_exists($f_i, $this->candidates) && array_key_exists($f_j, $this->candidates[$f_i]))
{
$this->candidates[$f_i][$f_j] += 1;
}
if ($f_i == $f_j)
{
$is_next = true;
}
}
}
}
foreach ($this->candidates as $i => $v)
{
foreach ($this->candidates as $j => $v)
{
if ($i !== $j)
{
if ($this->candidates[$i][$j] > $this->candidates[$j][$i])
{
$this->paths[$i][$j] = $this->candidates[$i][$j];
}
else
{
$this->paths[$i][$j] = 0;
}
}
}
}
foreach ($this->candidates as $i => $v)
{
foreach ($this->candidates as $j => $v)
{
if ($i !== $j) {
foreach ($this->candidates as $k => $v)
{
if ($i !== $k && $j !== $k)
{
$this->paths[$j][$k] = max( $this->paths[$j][$k], min( $this->paths[$j][$i], $this->paths[$i][$k] ) );
}
}
}
}
}
$table = $this->htmlTable();
return $this->app['twig']->render('base.twig', array( 'title' => 'Выборы по Шульце', 'content' => $table ));
}
private function returnError ()
{
return $this->app['twig']->render('base.twig', array( 'title' => 'Ошибка', 'content' => 'Никаких данных не передано' ));
}
private function getCandidates (Request $request)
{
$dataset = $request->get('dataset');
if(!$dataset)
{
return false;
}
$candidates = explode('|', $dataset);
foreach ($candidates as $c)
{
$f_c = htmlspecialchars($c);
$this->candidates[$f_c] = array();
$this->paths[$f_c] = array();
foreach ($candidates as $k)
{
$f_k = htmlspecialchars($k);
if ($f_c !== $f_k)
{
$this->candidates[$f_c][$f_k] = 0;
$this->paths[$f_c][$f_k] = 0;
}
}
}
return true;
}
private function htmlTable()
{
$asort = array();
foreach ($this->paths as $k => $v)
{
$asort[$k] = 0;
foreach ($this->paths as $j => $v)
{
if($k !== $j) {
if ($this->paths[$k][$j] > $this->paths[$j][$k])
{
$asort[$k] += 2;
}
if ($this->paths[$k][$j] === $this->paths[$j][$k])
{
$asort[$k] += 1;
}
}
}
}
arsort($asort);
$c = "<div class=\"subheader\" style=\"padding-top:1.75em\">Попарные победы</div>\n<table class=\"maintable\">\n<tr><th><!--empty--></th> ";
$t = "<div class=\"subheader\" style=\"padding-top:0.5em\">Сильнейший путь</div>\n<table class=\"maintable\">\n<tr><th><!--empty--></th> ";
foreach ($asort as $k => $v)
{
$line = sprintf("<th title=\"%s\">%s</th> ", $k, substr($k, 0, 3));
$t .= $line;
$c .= $line;
}
$t .= "</tr>\n";
$c .= "</tr>\n";
foreach ($asort as $k => $v)
{
$line = sprintf("<tr><td>%s</td> ", $k, substr($k, 0, 3));
$t .= $line;
$c .= $line;
foreach ($asort as $j => $v)
{
if($k === $j)
{
$p = '';
$z = '';
$p_class = 'blank';
$z_class = 'blank';
}
else
{
$p = $this->paths[$k][$j];
$z = $this->candidates[$k][$j];
if ($this->paths[$k][$j] === $this->paths[$j][$k])
{
$p_class = 'white';
}
if ($this->candidates[$k][$j] === $this->candidates[$j][$k])
{
$z_class = 'white';
}
if ($this->paths[$k][$j] > $this->paths[$j][$k])
{
$p_class = 'green';
}
if ($this->candidates[$k][$j] > $this->candidates[$j][$k])
{
$z_class = 'green';
}
if ($this->paths[$k][$j] < $this->paths[$j][$k])
{
$p_class = 'red';
}
if ($this->candidates[$k][$j] < $this->candidates[$j][$k])
{
$z_class = 'red';
}
}
$t .= sprintf("<td class=\"%s\">%d</td> ", $p_class, $p);
$c .= sprintf("<td class=\"%s\">%d</td> ", $z_class, $z);
}
$t .= "</tr>\n";
$c .= "</tr>\n";
}
$t .= "</table>\n";
$c .= "</table>\n";
return $t . $c;
}
}