class interpolators { //////////////////////////////////////////////////////////////// /// /// some statistical functons. /// //////////////////////////////////////////////////////////////// function stat_mean ($data) { // calculates mean return (array_sum($data) / count($data)); } function stat_median ($data) { // calculates median sort ($data); $elements = count ($data); if (($elements % 2) == 0) { $i = $elements / 2; return (($data[$i - 1] + $data[$i]) / 2); } else { $i = ($elements - 1) / 2; return $data[$i]; } } function stat_range ($data) { // calculates range return (max($data) - min($data)); } function stat_var ($data) { // calculates sample variance $n = count ($data); $mean = stat_mean ($data); $sum = 0; foreach ($data as $element) { $sum += pow (($element - $mean), 2); } return ($sum / ($n - 1)); } function stat_varp ($data) { // calculates population variance $n = count ($data); $mean = stat_mean ($data); $sum = 0; foreach ($data as $element) { $sum += pow (($element - $mean), 2); } return ($sum / $n); } function stat_stdev ($data) { // calculates sample standard deviation return sqrt (stat_var($data)); } function stat_stdevp ($data) { // calculates population standard deviation return sqrt (stat_varp($data)); } /////////////////////////end statistical functions/////////////////////////// /////////////should make it in seperate class, i think/////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// //function which returns year and month according to: //if it is the first day on the month, it returns the current year and month, //otherwise it returns next month with according year ///////////////////////////////////////////////////////////////////////////// function firstFullYearMonth($dateString) { try { $firstDate = new DateTime($dateString); } catch (Exception $e) { echo $e->getMessage(); exit(1); } $firstDate= new DateTime($dateString); $currentDay=(int) $firstDate->format('d'); $currentMonth=(int) $firstDate->format('m'); $currentYear=(int) $firstDate->format('y'); $prevMonth = (int) date("m", mktime(0, 0, 0, $currentMonth, $currentDay-1, $currentYear)); if ($currentMonth>$prevMonth) { $firstDay=date("Y-m", mktime(0, 0, 0, $currentMonth, $currentDay, $currentYear)); } else { $firstDay = date("Y-m", mktime(0, 0, 0, $currentMonth+1, 1, $currentYear)); } return $firstDay; } ///////////////////////////////////////////////////////////////////////////// //function which returns year and month according to: //if the date consists of the last day on the month, it returns the current year and month, //otherwise it returns previous month with according year ///////////////////////////////////////////////////////////////////////////// function lastFullYearMonth($dateString) { try { $firstDate = new DateTime($dateString); } catch (Exception $e) { echo $e->getMessage(); exit(1); } $firstDate= new DateTime($dateString); $currentDay=(int) $firstDate->format('d'); $currentMonth=(int) $firstDate->format('m'); $currentYear=(int) $firstDate->format('y'); $nextMonth = (int) date("m", mktime(0, 0, 0, $currentMonth, $currentDay+1, $currentYear)); if ($currentMonth<$nextMonth) { $lastDay = date("Y-m", mktime(0, 0, 0, $currentMonth, $currentDay, $currentYear)); } else { $lastDay = date("Y-m", mktime(0, 0, 0, $currentMonth, 0, $currentYear)); // 0tā diena - iepriekšējā mēneša pēdējā diena. } return $lastDay; } ///////////////////////////////////////////////////////////////////////////// //Function interpolates values from 2d array where measurement date is in the first //dimension and measured value in the second dimension. //Function returns 2d array with interpolated values for each date between measurements ///////////////////////////////////////////////////////////////////////////// function interpolate($arrays) { $oldDate=$this->firstValDate($arrays); $oldVal=$this->firstValVal($arrays); next($arrays); foreach ($arrays as $key=>$tmpArray) { $ii=0; foreach ($tmpArray as $value) { $keys= new DateTime($key); //try different date formats $keys=$keys->format("Y-m-d"); //compare with standart if ($keys!=$oldDate) { $datums=$keys; $vertiba=$value; $datetimeOld = new DateTime($oldDate); $datetimeCurrent = new DateTime($datums); $lastForInt = strtotime($oldDate); $firstForInt = strtotime($datums); $intervals = round(($firstForInt-$lastForInt)/60/60/24); if ($intervals<0) { echo "Nākošais datums ir senāks par iepriekšējo.\nLaiks parasti iet uz priekšu un nenāk atpakaļ."; die; } //echo $intervals; $delta=$vertiba-$oldVal; $increment = $delta/$intervals; if ($intervals>1) { for ($i=1;$i<=$intervals;$i++) { $datetimeOld->modify('+1 day'); //vecajam datumam pieliek vienu dienu klāt $currentDay=$datetimeOld->format('Y-m-d'); //pārtaisa datumobjektu uz string $interpValue=round($oldVal+$increment*$i,2); //aprēķina patreizējās dienas vērtību pēc formulas //vecā vērtība plus esošais solis reiz soļa lielums $interpBoolText=(($i!=$intervals)?"\ti":""); //visos soļos atrastajai vērtībai galā būs strings "i", //tas ļauj uzskatāmi redzēt, ka tieši šī vērtība ir interpolēta $interpArray[$currentDay][$ii]=$interpValue; $ii++; } $oldDate=$datums; //definējam nākošo "iepriekšējo" datumu un vērtību $oldVal=$vertiba; } else { $interpArray[$datums][$ii]=$vertiba; $oldDate=$datums; $oldVal=$vertiba; $ii++; } } else { $interpArray[$key][$ii]=$value; $ii++; } } } //print_r ($interpArray); return $interpArray; } ///////////////////////////////////////////////////////////////////////////// //Returns first key - date value from 2 dimensional associative key array. // // ///////////////////////////////////////////////////////////////////////////// function firstValDate($arrays) { foreach ($arrays as $key=>$tempArray) { return $key; break; } } ///////////////////////////////////////////////////////////////////////////// //Returns last key - date value from 2 dimensional associative key array. // //are there direct way how to get the last key of associative array? //such loop seems kind of stupid... ///////////////////////////////////////////////////////////////////////////// function lastValDate($arrays) { $i=1; foreach ($arrays as $key=>$tempArray) { if ($i==count($arrays)) { return $key; break; } $i++; } } ///////////////////////////////////////////////////////////////////////////// //Returns first key - date value from 2 dimensional associative key array. // // ///////////////////////////////////////////////////////////////////////////// function firstValVal($arrays) { return $arrays[$oldDate=$this->firstValDate($arrays)][0]; } ///////////////////////////////////////////////////////////////////////////// //Function checks element first two symbols (are they tabs), checks, if the value //is null or empty and deletes such element. // ///////////////////////////////////////////////////////////////////////////// function unsetEmpty($arrays) { $i=0; foreach($arrays as $key=>$value) { $rest = substr($value, 0, 2); if(!(is_null($value) || $value=="" || $rest=="\t\t")) { $arrayNew[$i]=$value; $i++; } } return $arrayNew; } ///////////////////////////////////////////////////////////////////////////// //Function makes 2 dimensional array from string which is formatted by default //as "date (tab) value". // //should make possibility to divide string in parts and define them (seperator, etc) //by giving optional parameters. ///////////////////////////////////////////////////////////////////////////// function make2dArrayFromDateValueString($dateValueString) { $text = str_replace("\r", "", $dateValueString); $text = str_replace("\n", "+", $text); $text = str_replace(",",".",$text); $arrtext = explode("+", $text); $arrtext=$this->unsetEmpty($arrtext); $i=0; foreach($arrtext as $key=>$value) { $bothValues= explode ("\t",$value); $datums=$bothValues[0]; $vertiba=$bothValues[1]; $masivs2d[$datums][$i]=$vertiba; $i++; } return $masivs2d; } ///////////////////////////////////////////////////////////////////////////// //Function cuts the months which has unfilled daily mesaured values // // ///////////////////////////////////////////////////////////////////////////// function cutInterpolated($arrays) { $FirstDateFrom2dArray=$this->firstValDate($arrays); $LastDateFrom2dArray=$this->lastValDate($arrays); $FirstFullYearMonth=$this->firstFullYearMonth($FirstDateFrom2dArray); $LastFullYearMonth=$this->lastFullYearMonth($LastDateFrom2dArray); $validDayCount=round((strtotime($LastFullYearMonth."-2")-strtotime($FirstFullYearMonth."-01"))/60/60/24)+1; //echo $validDayCount; //echo $FirstFullYearMonth; //$LastDateFrom2dArray if ($validDayCount>0) { $i=0; foreach ($arrays as $key=>$tmpArray) { foreach ($tmpArray as $value) { if (($key>=$FirstFullYearMonth) and ($key<=$LastFullYearMonth)) { $array[$key][$i]=$value; $i++; } } } } return $array; } ///////////////////////////////////////////////////////////////////////////// //create 2d array with year and month in first dimension and respective //daily data valuesin seceond ///////////////////////////////////////////////////////////////////////////// function createByYearMonth($arrays) { $k=0; foreach ($arrays as $key=>$tmpArray) { foreach ($tmpArray as $value) { $currDate=new datetime($key."-01"); $Months=(int)$currDate->format("m"); if (($oldmonth<$Months) or (($oldmonth==12) and ($Months==1))) //skatamies, ja nākamais mēnesis, tad ieliekam iekš masīva { $k=0; $gadsMenesis=$currDate->format("Y-").$oldmonth; $paMenesiem[$currDate->format("Y-m")][$k]=$value; //izdala gadu un pareizo mēnesi masīvam $k++; } else { //echo $value; $paMenesiem[$currDate->format("Y-m")][$k]=$value; $k++; } $oldmonth=$Months; } } //print_r ($paMenesiem); return $paMenesiem; } ///////////////////////////////////////////////////////////////////////////// //create 2d array with year and month in first dimension and statistical values //for respective monthly data in second. //0 - count //1 - min //2 - max //3 - sum //4 - average //5 - median //6 - variance (for sample) //7 - variance (for population) //8 - standart deviation (for sample) //9 - standart deviation (for population) ///////////////////////////////////////////////////////////////////////////// function getStatistics($arrays) { foreach ($arrays as $key=>$tempone) { $array[$key]["count"]=count($tempone); $array[$key]["min"]=min($tempone); $array[$key]["max"]=max($tempone); $array[$key]["sum"]=array_sum($tempone); $array[$key]["average"]=stat_mean($tempone); $array[$key]["median"]=stat_median($tempone); $array[$key]["variance"]=stat_var($tempone); $array[$key]["variancep"]=stat_varp($tempone); $array[$key]["stdev"]=stat_stdev($tempone); $array[$key]["stdevp"]=stat_stdevp($tempone); } return $array; } } $interpolators = new interpolators(); //create interpolator object $masivStrings=$_POST['tabula']; //get some data (date\tvalue\n(\r)) format $arrays2d= $interpolators->make2dArrayFromDateValueString($masivStrings); //create from gathered data 2dimensional array $interpolatedArray = $interpolators->interpolate($arrays2d); //interpolate it daily $cuttedArray=$interpolators->cutInterpolated($interpolatedArray); //cut end and last month, if it is not started/lasted from beginning/till end $paMenesiem=$interpolators->createByYearMonth($cuttedArray); //sepereate values for each month $statistika=$interpolators->getStatistics($paMenesiem); //get some monthly statistics