<?php
class Util_ngREMACS extends JRCMSAPI {
function millitime() {
$microtime = microtime();
$comps = explode(' ', $microtime);
// Note: Using a string here to prevent loss of precision
// in case of "overflow" (PHP converts it to a double)
return sprintf('%d%03d', $comps[1], $comps[0] * 1000);
}
function rightMenuItem($item, $script) {
return '<li id="'.$item.'" class="menuopened"><span class="menu"
>.$script.'"; return false;">'.$item.'</span></li>';
}
function arrayValuesMulti(array $array, $index = null) {
$output = array();
foreach ($array as $key => $value) {
if (is_array($value)) {
$output = array_merge($output, array_values_multi($value, $index));
} elseif (is_null($index) || (is_string($index) && $key == $index) || (is_array($index) && in_array($key, $index))) {
$output[] = $value;
}
}
return $output;
}
public function requestParameter($param, $defaultValue=NULL) {
switch($_SERVER['REQUEST_METHOD']){
case 'GET': return isset($_GET[$param])?$_GET[$param]:$defaultValue; break;
case 'POST': return isset($_POST[$param])?$_POST[$param]:$defaultValue; break;
default:
}
}
public function parameterStorageJsonParse($data, $mode = 'decode', $storage='') {
$datas = array();
if( $mode == 'decode' AND !empty($data) AND is_string($data) ) {
$data = json_decode($data,true);
$datas = array();
if( is_array($data) and !empty($data) ) {
// specific return structure
switch ($storage) {
case 'example':
foreach($data as $key=>$element) {
$datas[] = array('id'=>0,'key'=>$key,'storageValue'=>$element);
}
break;
default:
$datas = $data;
}
}
}
if( $mode == 'encode' ) {
$datas = json_encode($data);
}
return $datas;
}
public function rennId($regId, $nummer) {
return ($regId*100).$nummer;
}
public function uniqueCashId($regId) {
$date = new DateTime();
return ($regId*100).'_'.$date->getTimestamp();
}
// public function rennNoFromRennId($regId, $rennId) {
// return substr($rennId,strlen((string)$regId*100));
// }
// public function getRennenSpec($spezifikation) {
// $spec = explode(' ', $spezifikation);
// return $spec;
// }
public function raceContestPointsStd($place) {
return (7 - $place);
}
public function raceContestPointsExtra($place, $noOfTeams=Null) {
$points = 7 - $place;
$points = $points >= 0 ? $points : 0;
if(isset($noOfTeams)) {
// reciprocal value of teams as basic value
return $noOfTeams > 0 ? (float)($points/$noOfTeams): 0;
}
return $points;
}
private static $masterRelations = Array (
//bootsClass
'1x' => Array( 'A' => 0.0
,'B' => 2.0
,'C' => 4.5
,'D' => 7.0
,'E' => 6.5
,'F' => 7.5
,'G' => 9.0
,'H' => 10.0
,'I' => 11.0
,'J' => 13.0
)
,'2-' => Array( 'A' => 0.0
,'B' => 2.0
,'C' => 4.5
,'D' => 7.0
,'E' => 6.5
,'F' => 7.5
,'G' => 9.0
,'H' => 10.0
,'I' => 11.0
,'J' => 13.0
)
,'2x' => Array('A' => 0
,'B' => 2.0
,'C' => 4.0
,'D' => 6.0
,'E' => 5.5
,'F' => 6.5
,'G' => 8.0
,'H' => 9.0
,'I' => 10.0
,'J' => 12.0
)
,'4+' => Array('A' => 0
,'B' => 2.0
,'C' => 4.0
,'D' => 6.0
,'E' => 5.5
,'F' => 6.5
,'G' => 8.0
,'H' => 9.0
,'I' => 10.0
,'J' => 12.0
)
,'4' => Array('A' => 0
,'B' => 2.0
,'C' => 4.0
,'D' => 6.0
,'E' => 5.5
,'F' => 6.5
,'G' => 8.0
,'H' => 9.0
,'I' => 10.0
,'J' => 12.0
)
,'4-' => Array('A' => 0
,'B' => 2.0
,'C' => 4.0
,'D' => 6.0
,'E' => 5.5
,'F' => 6.5
,'G' => 8.0
,'H' => 9.0
,'I' => 10.0
,'J' => 12.0
)
,'4x' => Array('A' => 0
,'B' => 2.0
,'C' => 4.0
,'D' => 6.0
,'E' => 5.5
,'F' => 6.5
,'G' => 8.0
,'H' => 9.0
,'I' => 10.0
,'J' => 12.0
)
,'4x-' => Array('A' => 0
,'B' => 2.0
,'C' => 3.0
,'D' => 5.5
,'E' => 5.0
,'F' => 6.0
,'G' => 7.0
,'H' => 8.0
,'I' => 9.0
,'J' => 10.0
)
,'8+' => Array('A' => 0
,'B' => 2.0
,'C' => 3.0
,'D' => 5.5
,'E' => 5.0
,'F' => 6.0
,'G' => 7.0
,'H' => 8.0
,'I' => 9.0
,'J' => 10.0
)
);
public static $weightClasses = Array (
'single' => Array( 'JM A' => 67.5 //Einzelgewicht
,'JF A' => 57.5
,'JM B' => 65.0
,'JF B' => 55.0
,'SM' => 72.5
,'SF' => 59.0
)
,'average' => Array('JM A' => 65.0 //Durchschnittgewicht
,'JF A' => 55.0
,'JM B' => 62.5
,'JF B' => 52.5
,'SM' => 70.0
,'SF' => 57.0
)
,'stm' => Array( 'M' => 55.0 //Stm: Maenner, Junioren
,'F' => 50.0 //Stm: Frauen, Juniorinnen, Mixed
)
);
public function getMasterRelationsTime($bootsclass, $baseAk, $diffAK) {
$relationTime = 0;
reset(self::$masterRelations[$bootsclass]);
$_key = key(self::$masterRelations[$bootsclass]);
//step to baskAk
while(isset($_key) && $_key !== $baseAk) {
next(self::$masterRelations[$bootsclass]);
$_key = key(self::$masterRelations[$bootsclass]);
}
//one step ahead
next(self::$masterRelations[$bootsclass]);
$_key = key(self::$masterRelations[$bootsclass]);
while(isset($_key) && $_key <= $diffAK) {
$relationTime+= self::$masterRelations[$bootsclass][$_key];
next(self::$masterRelations[$bootsclass]);
$_key = key(self::$masterRelations[$bootsclass]);
}
return $relationTime;
}
public function masterAK($age){
$age = (int)$age;
return ($age < 36 ? 'A' :
($age < 43 ? 'B' :
($age < 50 ? 'C' :
($age < 55 ? 'D' :
($age < 60 ? 'E' :
($age < 65 ? 'F' :
($age < 70 ? 'G' : 'H')))))));
}
public function masterAge($letter){
return ($letter=='A' ? 27 :
($letter=='B' ? 36 :
($letter=='C' ? 43 :
($letter=='D' ? 50 :
($letter=='E' ? 55 :
($letter=='F' ? 60 :
($letter=='G' ? 65 :
($letter=='H' ? 70 : 99))))))));
}
public function getRennenBootstyp($spezifikation, $classOnly=True) {
if(preg_match("/[0-9x+]+/",$spezifikation,$match))
return $classOnly ? str_replace('x','',$match[0]): $match[0];
else
return Null;
}
public function getSpezificationProperties($spezifikation) {
$response = Array(
'spezifikation' => $spezifikation
,'parameterFilter' => NULL
,'parameterTitelFilter' => Null
);
$rest = '';
// if(count(preg_split("/[\s,]+/", $spezifikation, 3))>2)
// list($response['ak'], $response['boot'], $rest) = preg_split("/[\s,]+/", $spezifikation, 3);
// else
// list($response['ak'], $response['boot']) = preg_split("/[\s,]+/", $spezifikation, 3);
//try to catch PAUSE/MITTAGSPAUSE
$spezifikation = trim($spezifikation);
if(count(preg_split("/[\s,]+/", $spezifikation, 3))>2) {
list($response['ak'], $response['boot'], $rest) = preg_split("/[\s,]+/", $spezifikation, 3);
} elseif(count(preg_split("/[\s,]+/", $spezifikation, 3))>1) {
list($response['ak'], $response['boot']) = preg_split("/[\s,]+/", $spezifikation, 2);
}
if(isset($response['ak'])) {
$property = !empty($rest)?preg_split("/[-\/u]+/", trim($rest)):Null;
$response['bootstyp'] = $this->getRennenBootstyp($spezifikation);
$response['bootsClass'] = $this->getRennenBootstyp($spezifikation, False);
$response['athletenNo'] = preg_match("/[1-8]/",$response['bootstyp'],$match);
$response['athletenNo'] = $match[0];
$response['withStm'] = (boolean)preg_match("/[+]/",$response['bootstyp'],$match);
$response['LG'] = (boolean)preg_match("/LG/",$spezifikation,$match);
switch($response['ak']){
case 'Jung/Mäd':
$response['geschlecht'] = 'mix';
case 'Jung':
case 'Mäd':
if(!empty($property)) {
preg_match("/1[0-4]/",$property[0],$aage);
$response['aalter'] = $aage[0];
if(isset($property[1])){
preg_match("/1[0-4]/",$property[1],$eage);
$response['ealter'] = $eage[0];
} else {
$response['ealter'] = $aage[0];
}
} else {
$response['aalter'] = 10;
$response['ealter'] = 15;
}
break;
case 'JM':
case 'JF':
$response['aalter'] = 14;
$response['ealter'] = (!empty($property)&&(substr($property[0],0,1)=='B')?16:18);
if(preg_match("/I+/", $rest)) {
$response['lk'] = substr($rest, strpos($rest, 'I'));
$response['parameterFilter'] = 'Leistungsgruppe';
$response['parameterTitelFilter'] = 'Leistungsgruppe';
}
if($response['withStm']) {
$response['stmWeight'] = ($response['ak']=='JM'?self::$weightClasses['stm']['M']:self::$weightClasses['stm']['F']);
}
if($response['LG']) {
$response['singleWeight'] = !empty($property)&&(substr($property[0],0,1)=='A')
? self::$weightClasses['single']['J'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M').' A']
: self::$weightClasses['single']['J'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M').' B'];
$response['averageWeight'] = !empty($property)&&$property[0]=='A'
? self::$weightClasses['average']['J'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M').' A']
: self::$weightClasses['average']['J'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M').' B'];
}
break;
case 'SM':
case 'SF':
$response['aalter'] = 16;
$response['ealter'] = (!empty($property)&&(substr($property[0],0,1)=='B')?22:27);
if(preg_match("/I+/", $rest)) {
$response['lk'] = substr($rest, strpos($rest, 'I'));
$response['parameterFilter'] = 'Leistungsgruppe';
$response['parameterTitelFilter'] = 'Leistungsgruppe';
}
if($response['withStm']) {
$response['stmWeight'] = ($response['ak']=='SM'?self::$weightClasses['stm']['M']:self::$weightClasses['stm']['F']);
}
if($response['LG']) {
$response['singleWeight'] = self::$weightClasses['single']['S'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M')];
$response['averageWeight'] = self::$weightClasses['average']['S'.((boolean)preg_match("/F/",$response['ak'],$match)?'F':'M')];
}
break;
case 'MM/W':
$response['geschlecht'] = 'mix';
//break;
case 'MM':
case 'MW':
$response['aalter'] = $this->masterAge(!empty($property)?$property[0]:'A');
$response['ealter'] = 99;
$response['parameterFilter'] = 'Altersklasse';
$response['parameterTitelFilter'] = 'Altersklasse';
if($response['withStm']) {
$response['stmWeight'] = ($response['ak']=='MM'?self::$weightClasses['stm']['M']:self::$weightClasses['stm']['F']);
}
break;
case 'OFF':
$response['aalter'] = 18;
$response['ealter'] = 99;
$response['geschlecht'] = 'mix';
$response['parameterFilter'] = 'Altersklasse';
$response['parameterTitelFilter'] = 'Altersklasse';
break;
default:
break;
}
$response['geschlecht'] = !isset($response['geschlecht'])
? (boolean)preg_match("/Jung|JM|SM|MM/",$response['ak'])? 'm': sportler_female_sign
: $response['geschlecht'];
}
//return as object to be more flexible
return json_decode(json_encode($response));
}
public function checkProperties($obj, $ctrl){
switch($ctrl){
case 'LKrequired':
return (preg_match('/JM|JF|SM|SF/',$obj->spezifikation) && preg_match('/I/',$obj->spezifikation));
break;
case 'AKrequired':
return (preg_match('/MM|MW|MM\/M/',$obj->spezifikation) && preg_match('/[-\/]/',$obj->spezifikation));
break;
default:
return false;
break;
}
}
public function rennenDefaultLength($nummer, $spezifikation) {
$_raceLengtJMJF = (int)$this->requestParameter('regmtn_raceLengtJMJF', ngremacsCONFIG::$defaultRaceLengtJMJF);
$_regExpRaceLengtShortNo = (string)$this->requestParameter('regmtn_regExpRaceLengtShortNo', ngremacsCONFIG::$regExpRaceLengtShortNo);
$_raceLengtShort = (int)$this->requestParameter('regmtn_raceLengtShort', ngremacsCONFIG::$defaultRaceLengtShort);
$_regExpRaceLengtLongNo = (string)$this->requestParameter('regmtn_regExpRaceLengtLongNo', ngremacsCONFIG::$regExpRaceLengtLongNo);
$_raceLengtLong = (int)$this->requestParameter('regmtn_raceLengtLong', ngremacsCONFIG::$defaultRaceLengtLong);
$_defaultRaceLengt = (int)$this->requestParameter('regmtn_defaultRaceLengt', ngremacsCONFIG::$defaultRaceLengt);
if(preg_match('/JM|JF/',$spezifikation)) {
return $_raceLengtJMJF;
} elseif(preg_match($_regExpRaceLengtShortNo, $nummer)) {
return $_raceLengtShort;
} elseif(preg_match($_regExpRaceLengtLongNo, $nummer)) {
return $_raceLengtLong;
}
return $_defaultRaceLengt;
}
/**
* Define structure of an Abteilung for internal processing
*
* control could be
* - none no addition processing steps
* - previousStartTime same start time as previous set
* but move them to other rennen
* @param integer $aid
* @param string $startzeit
* @param integer $strecke
* @param array $meldungen
* @param string $control
*/
public function abteilungStructure( $aid, $startzeit, $strecke, $meldungen, $control='none', $leichtgewicht=False, $relations=False) {
return Array(
'startzeit' => $startzeit
,'aid' => $aid
,'nummer' => Null //Abteilung number
,'control' => $control //used control further processing
,'strecke' => $strecke //distance of Rennen
,'LG' => $leichtgewicht
,'relations' => $relations
,'subset' => $meldungen
);
}
/**
* For easier processing (debugging) the SQl result is re-organized
* by this function in a multidim data set of
*
* <parameter|0> =>
* <array> => // abteilung(en)
* 0 => startzeit
* aid
* <subSet> => SQL_dataSet
*
* @param array $dataSet
* @param integer $strecke
*/
public function splitSQLDataSetForDrawing(array &$dataSet, $strecke, $leichtgewicht=false) {
$resultSet = Array();
$subSet = Array();
$ctrlParameter = NULL;
//correct missing Bootnr
$title = '';
$bootnr = 1;
reset($dataSet);
do {
$actKey = key($dataSet);
if($title == $dataSet[$actKey]['titel']) {
$bootnr++;
$dataSet[$actKey]['_bootnr'] = $dataSet[$actKey]['_bootnr'] == 1 ? $bootnr : $dataSet[$actKey]['_bootnr'];
} else {
$title = $dataSet[$actKey]['titel'];
$bootnr = 1;
if(isset($lastKey) && $dataSet[$lastKey]['_bootnr'] == 1 ) {
$dataSet[$lastKey]['_bootnr'] = 0;
}
}
$lastKey = $actKey;
} while(next($dataSet) !== false);
foreach($dataSet AS $key => $value) {
// //correct missing Bootnr
// if($title == $value['titel']) {
// $bootnr++;
// $value['_bootnr'] = $value['_bootnr'] == 1 ? $bootnr : $value['_bootnr'];
// } else {
// $title = $value['titel'];
// $bootnr = 1;
// }
$value['LG'] = $leichtgewicht?1:0;
if(!isset($ctrlParameter) || $ctrlParameter == $value['parameter']) {
$subSet[] = $value;
$ctrlParameter = $value['parameter'];
} else {
$resultSet[$ctrlParameter] = Array( 0 =>
$this->abteilungStructure($subSet[0]['aid'], $subSet[0]['startzeit'], $strecke, $subSet, NULL, $leichtgewicht));
$subSet = Array();
$subSet[] = $value;
$ctrlParameter = $value['parameter'];
}
}
if(!empty($subSet)) {
//catch the last subset or subset without parameter
$ctrlParameter = isset($ctrlParameter)?$ctrlParameter:0;
$resultSet[$ctrlParameter] = Array( 0 =>
$this->abteilungStructure($subSet[0]['aid'], $subSet[0]['startzeit'], $strecke, $subSet, NULL, $leichtgewicht));
} elseif(empty($resultSet) && !empty($dataSet)) {
throw new MyException("splitSQLDataSetForDrawing Processing failure!");
}
$dataSet = $resultSet;
return;
}
/**
* This function combine subSets of parameter types.
* The function merge toplevel in case the sublevel array consist
* of one element only.
* For merged elments a key consisting of old identifier separated
* by a comma is assigned.
* The parameter maxCombines control the number of singel sublevels
* merged together.
* The Masters relation flag depend on the type and flag to check
* for relations
*
* e.g.
* Array( 'A' => Array( 0 => Array ( 'typ' => 'A0') )
* ,'B' => Array( 0 => Array ( 'typ' => 'B0')
* ,1 => Array ( 'typ' => 'B1') )
* is combined in
* Array( 'A,B' => Array( 0 => Array ( 'typ' => 'A0')
* ,1 => Array ( 'typ' => 'B0')
* ,2 => Array ( 'typ' => 'B1') )
*
* @param array $dataSet
* @param integer $maxCombines
* @param boolean $relations
*/
public function combineParameterDataSet(array &$dataSet, $maxCombines=6, $relations=False) {
ksort($dataSet);
reset($dataSet);
if(count($dataSet) > 1) {
$firstKey = key($dataSet);
while(next($dataSet) !== false) {
$nextKey = key($dataSet);
if(((count($dataSet[$firstKey][0]['subset']) == 1) ||
(count($dataSet[$nextKey][0]['subset']) == 1) ||
//special case, already merged
(preg_match("/,/",$firstKey) && count($dataSet[$nextKey][0]['subset']) == 1)) &&
(preg_match_all("/,/",$firstKey,$notused) < $maxCombines-1))
{
$dataSet[$firstKey.','.$nextKey] = Array( 0 =>
$this->abteilungStructure($dataSet[$firstKey][0]['aid']
,$dataSet[$firstKey][0]['startzeit']
,$dataSet[$firstKey][0]['strecke']
,array_merge($dataSet[$firstKey][0]['subset'], $dataSet[$nextKey][0]['subset'])
,NULL
,$dataSet[$firstKey][0]['LG']
//MASTERS RELATION, at least one merge
,$dataSet[$firstKey][0]['relations'] || $relations
));
unset($dataSet[$firstKey]);
unset($dataSet[$nextKey]);
return $this->combineParameterDataSet($dataSet, $maxCombines);
}
$firstKey = $nextKey;
}
}
return;
}
/**
* This function logical puts to Abteilung together by using the
* same StartTime as the previous one. The goal is to combine
* different AKs to one more callenging race.
*
* e.g.
* Array( 'A,B' => Array( 0 => Array ( 'typ' => 'A0')
* ,1 => Array ( 'typ' => 'B0') )
* Array( 'C,D' => Array( 0 => Array ( 'typ' => 'C0')
* ,1 => Array ( 'typ' => 'D0') )
*
* will have the same StartTime
*
* @param array $dataSet
* @param integer $maxSubEl
*/
public function mastersParameterdataSet(array &$dataSet, $maxSubEl=6, $zrrAbtOpt=False) {
ksort($dataSet);
reset($dataSet);
if(count($dataSet) > 1) {
$firstKey = key($dataSet);
// while(next($dataSet) !== false) {
// $nextKey = key($dataSet);
// if((count($dataSet[$firstKey][0]['subset'])+count($dataSet[$nextKey][0]['subset'])) <= $maxSubEl) {
// $dataSet[$nextKey][0]['control'] = 'previousStartTime';
// $dataSet[$nextKey][0]['relations'] = $dataSet[$nextKey][0]['relations'] || $dataSet[$firstKey][0]['relations'];
// next($dataSet);
// $nextKey = key($dataSet);
// }
// $firstKey = $nextKey;
// }
while(next($dataSet) !== false) {
$nextKey = key($dataSet);
if((count($dataSet[$firstKey][0]['subset'])+count($dataSet[$nextKey][0]['subset'])) <= $maxSubEl &&
preg_match("/,/",$firstKey))
{
$dataSet[$firstKey.','.$nextKey] = Array( 0 =>
$this->abteilungStructure($dataSet[$firstKey][0]['aid']
,$dataSet[$firstKey][0]['startzeit']
,$dataSet[$firstKey][0]['strecke']
,array_merge($dataSet[$firstKey][0]['subset'], $dataSet[$nextKey][0]['subset'])
,NULL
,$dataSet[$firstKey][0]['LG']
//MASTERS RELATION, there was at least one merge
,$dataSet[$firstKey][0]['relations']
));
unset($dataSet[$firstKey]);
unset($dataSet[$nextKey]);
//start again, but do not use recursive function
ksort($dataSet);
reset($dataSet);
$nextKey = key($dataSet);
} elseif((count($dataSet[$firstKey][0]['subset'])+count($dataSet[$nextKey][0]['subset'])) <= $maxSubEl && $zrrAbtOpt) {
$dataSet[$nextKey][0]['control'] = 'previousStartTime';
$dataSet[$nextKey][0]['relations'] = $dataSet[$nextKey][0]['relations'] || $dataSet[$firstKey][0]['relations'];
next($dataSet);
$nextKey = key($dataSet);
}
$firstKey = $nextKey;
}
}
return;
}
/**
* determine ZRR (Masters Time Relation Races)
*
* @param array $dataSet
* @param string $bootsClass
* @param real $relationsFactor
*/
public function mastersRelationsRace(array &$dataSet, $bootsClass, $relationsFactor=1) {
foreach($dataSet as $akgroup => &$abteilungen) {
$akList = explode(',', $akgroup );
if(count($akList) > 1) {
//build timediff list
reset($akList);
$firstKey = key($akList);
$timeDiffList = Array($akList[$firstKey] => 0);
while(next($akList) !== false) {
$nextKey = key($akList);
$timeDiffList[$akList[$nextKey]] = $this->getMasterRelationsTime($bootsClass, $akList[$firstKey], $akList[$nextKey])*$relationsFactor;
$firstKey = $nextKey;
}
//build startTime list
reset($akList);
end($akList);
$firstKey = key($akList);
$startTimeDiff = 0;
$startTimeDiffList = Array($akList[$firstKey] => $startTimeDiff);
while(prev($akList) !== false) {
$nextKey = key($akList);
$startTimeDiff+= $this->getMasterRelationsTime($bootsClass, $akList[$nextKey], $akList[$firstKey])*$relationsFactor;
$startTimeDiffList[$akList[$nextKey]] = $startTimeDiff;
$firstKey = $nextKey;
}
//assign diff times
foreach($abteilungen as $abtNo => &$abteilung) {
if($abteilung['relations']) {
$ak = Array();
//=== sort by AK and assign time diff ===
foreach ($abteilung['subset'] as $key => &$row) {
$ak[$key] = $row['parameter'];
$row['_timeCredit'] = $timeDiffList[$row['parameter']];
$row['_startTimeDelay'] = $startTimeDiffList[$row['parameter']];
}
array_multisort($ak, SORT_ASC, $abteilung['subset']);
}
}
}
}
}
}
?>