<?php
// тестовое окружение не перезагружает строковые функции!!!
/* ЗАДАЧА 1
*
* Дано:
* - Текст из *.csv файла
* Необходимо:
* 1. Распарсить текст, подготовить данные к работе (элемент = тип Объект)
* 2. Отсортировать данные по дате затем КБК и вывести в таблице, таким образом, что если существует несколько записей на одну дату с одним КБК, то в поле %% считать среднее, а в скобках вывести кол-во елементов.
*
* Пример Табл.:
* | ДАТА | КБК | Адрес | %% |
* | 11.01.2013 | 1-01-001 | Спб, Восстания, 1 | 84% (2) |
*
*/
$data = "
02-01-2013;1-01-001;Спб, Восстания, 1;95
05-01-2013;1-02-011;Спб, Савушкина, 106;87
01-01-2013;1-01-003;Спб, Обводный канал, 12 ;92
06-02-2013;2-05-245;Ростов-на-Дону, Стачек, 41;79
12-01-2012;5-10-002;Новосибирск, Ленина, 105;75
01-01-2013;1-01-003;Спб, Обводный канал, 12 ;98
03-01-2013;6-30-855;Сочи, Коммунистическая, 2;84
05-01-2013;2-04-015;Ростов-на-Дону, Пушкинская, 102;71
07-01-2013;6-01-010;Сочи, Приморская, 26;62
05-01-2013;1-02-011;Спб, Савушкина, 106;89
01-01-2013;1-01-003;Спб, Обводный канал, 12 ;57
";
class Element {
public $date;
public $kbk;
public $addres;
public $oth;
public $kbkNum;
public function __construct($csvtxt) {
if ($csvtxt) {
$ar=str_getcsv($csvtxt, ';');
if (sizeof($ar)==4) {
if ($dt=DateTime::createFromFormat('d-m-Y', $ar[0])) {
$this->date=$dt->getTimeStamp();
$this->kbk=trim($ar[1]);
$this->kbkNum=intval(str_replace('-', '', $this->kbk));
$this->addres=trim($ar[2]);
$this->oth=$ar[3];
} else {
throw new \Exception('Некорректная дата.');
}
} else {
throw new \Exception('Некорректная строка.');
}
}
}
public function getKbkNum() { return $this->kbkNum; }
public function getDate() { return $this->date; }
public function getKbk() { return $this->kbk; }
public function getAddres() { return $this->addres; }
public function getOth() { return $this->oth; }
public function compare(Element $e) { // сравнение элментов
if ($this->getDate()>$e->getDate()) {
return 1;
} elseif ($this->getDate()<$e->getDate()) {
return -1;
} else { // даты равны - сравнение кбк
if ($this->getKbkNum()==$e->getKbkNum()) return 0;// равны
if ($this->getKbkNum()>$e->getKbkNum()) return 1;// больше
if ($this->getKbkNum()<$e->getKbkNum()) return -1;// меньше
}
} // end compare
} // end Element
class Elements {
protected $ar=array();
protected $maxSize=array('addrres'=>5, 'kbk'=>3);
public function __construct($text) {
$p=0;
$size=strlen($text);
do {
$f=strpos($text, "\n", $p);
if ($f!==false) {
if ($f>0 && substr($text, $f-1, 1)=="\r") {
$line=substr($text, $p, $f-1-$p);
} else {
$line=substr($text, $p, $f-$p);
}
$p=$f+1;
} elseif ($p<$size) {
$line=substr($text, $p);
$p=false;
}
if ($line) {
try {
$e=new Element($line);
$this->maxSize['addres']=max($this->maxSize['addres'], strlen($e->getAddres()));
$this->maxSize['kbk']=max($this->maxSize['kbk'], strlen($e->getKbk()));
$this->ar[]=$e;
} catch (\Exception $e) {} // ошибка формата
}
} while ($p!==false && $p<$size);
} // end
public function count() {
return sizeof($this->ar);
}
public function sort() {
if (sizeof($this->ar)>0) {
usort($this->ar, function ($a, $b) {
return $a->compare($b);
});
}
} // end sort
public function __toString() {
if (sizeof($this->ar)>0) {
$printMask="| %-10s | %-".$this->maxSize['kbk']."s | %-".$this->maxSize['addres']."s | %-8s |\n";
$s=vsprintf($printMask, array('ДАТА', 'КБК', 'АДРЕС', '%%'));
$counter=0;
$sum=0;
$print=false;
$prev=false;
$count=sizeof($this->ar);
for ($i=0; $i<$count; $i++) {
$next=( $i+1<$count ? $this->ar[$i+1] : false);
$curr=$this->ar[$i];
$counter++;
$sum+=$curr->getOth();
if ($next) {
if ($curr->getKbkNum()!=$next->getKbkNum() || $curr->getDate()!=$next->getDate()) {
$print=true;
}
} else { // последняя строка данных
$print=true;
}
if ($print) {
$forPrint=array(
date('d-m-Y', $curr->getDate()),
$curr->getKbk(),
$curr->getAddres()
);
if ($counter>1) {
$forPrint[]=round($sum/$counter, 0).'% ('.$counter.')';
} else {
$forPrint[]=$sum.'%';
}
$s.=vsprintf($printMask, $forPrint);
$counter=0;
$sum=0;
$print=false;
}
} // end for
return $s;
}
return '';
} // end toString
} // end Elements
$c=new Elements($data);
$c->sort();
echo $c;