0) {$tippTendenz=1;} if ($tippTendenz < 0) {$tippTendenz=-1;} $gameTendenz = $score1 - $score2; if ($gameTendenz<0) {$gameTendenz=-1;} if ($gameTendenz>0) {$gameTendenz=1;} if ($tippTendenz!=$gameTendenz || $score1 ==-1 || $score2==-1 || $tipp1 == -1 || $tipp2==-1) { return ""; } $styling='background-color:grey;'; if ( ($tipp1 == $score1) && ($tipp2 == $score2) ) { $styling='background-color:orange;'; if ($joker) { $styling='background-color:red'; } } return $styling; } // get tendency Color public static function getCol($user_id,$game_id) { $tipp = Tipp::getTipp($user_id,$game_id); $game = Game::where('id',$tipp->game_id)->first(); $tippTendenz = $tipp->score1 - $tipp->score2; if ($tippTendenz > 0) {$tippTendenz=1;} if ($tippTendenz < 0) {$tippTendenz=-1;} $gameTendenz = $game->score1 - $game->score2; if ($gameTendenz<0) {$gameTendenz=-1;} if ($gameTendenz>0) {$gameTendenz=1;} if ($tippTendenz!=$gameTendenz || $game->score1 ==-1 || $game->score2==-1 || $tipp->score1 == -1 || $tipp->score2==-1) { return ""; } $styling='background-color:grey;'; if ( ($tipp->score1 == $game->score1) && ($tipp->score2 == $game->score2) ) { $styling='background-color:orange;'; if ($tipp->joker==true) { $styling='background-color:red'; } } return $styling; } public static function getTipp( $user_id,$game_id) { //Log::info("getTipp for game_id, user_id = ".$game_id.",".$user_id); return DB::table('tipps')->where([ ['user_id','=',$user_id], ['game_id','=',$game_id] ])->first(); } public static function getScoreLocal($goals1, $goals2, $tipp1, $tipp2, $joker) { $score=0; $tippTendenz = $tipp1 - $tipp2; if ($tippTendenz > 0) {$tippTendenz=1;} if ($tippTendenz < 0) {$tippTendenz=-1;} $gameTendenz = $goals1 - $goals2; if ($gameTendenz<0) {$gameTendenz=-1;} if ($gameTendenz>0) {$gameTendenz=1;} if ($tippTendenz==$gameTendenz) { $score=1; } if ( ($tipp1 == $goals1) && ($tipp2 == $goals2) ) { $bonus = max(0,$goals1 + $goals2 - 3); $score= 2 + $bonus; } if ($joker==true) { $score = $score * 2; } if ($tipp1==-1||$tipp2==-1||$goals1==-1||$goals2==-1) { $score=0; } return $score; } // Bei Tagessieg gilt nur wer am meisten genau richtig getippt hat, // Bei Gleichstand wer den höchsten Jokersieg hat ( Jokersieg mit mehr Toren zählt mehr) // Bei Gleichstand gilt die Summe aller Rankscores, deshalb wird sie auch im Ergebnis gespeichert // Fürs Dayscore-Bewerten ist rankscore allerdings irrelevant. Mit Rank nur fürs Sortieren, um die Auswahl einzugrenzen. public static function getDayScoreLocal($goals1, $goals2, $tipp1, $tipp2, $joker, $rankScore=0) { if ($tipp1==-1||$tipp2==-1||$goals1==-1||$goals2==-1) { return 0; } // Ungetippt oder Spiel hat noch kein Ergebnis if ( ($tipp1 != $goals1) || ($tipp2 != $goals2) ) return 0; $jokerValue=0; if ($joker) { $jokerValue = max(0, $goals1 + $goals2 - 3) + 1; } return 1000 + $jokerValue * 100 + $rankScore; } public static function getTippScore($user_id,$game_id, $team=0) { //Log::info("Getting tippstring for game_id=". $game_id .", user_id=" . $user_id.", $team=".$team); $tipp=Tipp::getTipp($user_id,$game_id); if (!$tipp) { //Log::info("not found !"); return "x"; } $tippScore=""; if ($team==0) { $tippScore= $tipp->score1;} else { $tippScore=$tipp->score2; } if ($tippScore==-1) { /*Log::info("untipped!");*/$tippScore="x";} //Log::info("Returning: ". $tippScore); return $tippScore; } public static function getScore($tipp_id) { $tipp = Tipp::where('id',$tipp_id)->first(); $game = Game::where('id',$tipp->game_id)->first(); $bonus = max(0,$game->score1 + $game->score2 - 3); $tippTendenz = $tipp->score1 - $tipp->score2; if ($tippTendenz > 0) {$tippTendenz=1;} if ($tippTendenz < 0) {$tippTendenz=-1;} $gameTendenz = $game->score1 - $game->score2; if ($gameTendenz<0) {$gameTendenz=-1;} if ($gameTendenz>0) {$gameTendenz=1;} $score=0; if ($tippTendenz == $gameTendenz) { $score=1; } if ( ($tipp->score1 == $game->score1) && ($tipp->score2 == $game->score2) ) { $score=2 + $bonus; } if ($tipp->joker==true) { $score = $score *2; } if ($game->score1 == -1) { $score=0; } if ($tipp->score1==-1 || $tipp->score2==-1) {$score=0;} return $score; } public static function resultString($tipp_id) { $tipp = Tipp::where('id',$tipp_id)->first(); $rStr="Ungetippt"; if ($tipp->score1 > -1) $rStr= $tipp->score1 . " : " . $tipp->score2; return $rStr; } public static function createTipps($user_id) { $activeSeason = Season::getCurrent(); $rounds = Round::all()->where('season_id', '=', $activeSeason->id); foreach($rounds as $round) { $games=Game::all()->where('round_id','=',$round->id); foreach($games as $game) { // Tipp erzeugen wenn noch nicht vorhanden $tipp = DB::table('tipps')->where([ ['game_id','=',$game->id], ['user_id','=',$user_id]] )->first(); if (! $tipp) { $tipp=Tipp::create([ 'user_id' => $user_id, 'game_id'=> $game->id, 'score1'=> -1, 'score2'=> -1, 'joker'=> false ]); $tipp->save(); } } } } public static function createAllTips() { $users = DB::table('users')->where('deleted',null)->get(); foreach($users as $user) { Log::info("Creating tipps for userid ".$user->id); Tipp::createTipps($user->id); } } // Struktur: gameval * 1000 + jokerValue * 100 + rankscore public static function addDayScoreValues($val1, $val2) { $gameVal1 = intdiv($val1 , 1000); $gameVal2 = intdiv( $val2, 1000); $jokerVal1 = intdiv(($val1 - $gameVal1*1000),100); $jokerVal2 = intdiv(($val2 - $gameVal2*1000),100); if ( $gameVal1 ==0 ) { $jokerVal1=0; $rankVal1=0; } if ( $gameVal2 ==0 ) { $jokerVal2=0; $rankVal2=0; } $rankVal1 = $val1 - $gameVal1*1000 - $jokerVal1*100; $rankVal2 = $val2 - $gameVal2*1000 - $jokerVal2*100; // Minimaler Brainfuck, da $rankVal1 und $rankVal2 immer gleich sein sollten $result = ($gameVal1 + $gameVal2) * 1000 + max($jokerVal1, $jokerVal2) * 100 + max ($rankVal1, $rankVal2); return $result; } public static function getDayScoreWithoutRankScore($val) { $gameVal = intdiv($val , 1000); $jokerVal = intdiv(($val - $gameVal*1000),100); if ($gameVal==0) return 0; return $gameVal * 1000 + $jokerVal * 100; } // TODO: Implement partial caching public static function getRoundTipps($max_round_id=-1, $seasonId=-1) { $currentSeason=null; if ($seasonId==null) { $currentSeason = Season::getCurrent(); } else { $currentSeason = Season::where('id','=', $seasonId)->first(); } $startTime = microtime(true); $currentSeason = Season::getCurrent(); if ($seasonId!=-1) { $currentSeason=Season::where('id','=',$seasonId)->first(); }; error_log("SeasonId=".$currentSeason->id); // Hier werden _alle_ Tipps der aktuellen Saison ausgerechnet, die $round_id Begrenzung wird erst später ausgewertet. // TODO: Nur die Runden durchrechnen, die aktuell sind, oder round_incomplete, alle anderen Runden (bis zur ersten unvollständigen) sollen in eine Cachetabelle gespeichert werden. $sql = "select users.id as user_id, users.name as user_name, "; $sql = $sql . "rounds.id as round_id, rounds.name as round_name, "; $sql = $sql . "games.id as game_id, games.team1, games.team2, games.score1 as game_score1, games.score2 as game_score2, games.kickoff as game_kickoff, "; $sql = $sql . "tipps.id as tipp_id, tipps.score1 as tipp_score1, tipps.score2 as tipp_score2, tipps.joker "; $sql = $sql . "from users,rounds,games,tipps,payments "; $sql = $sql . "where rounds.season_id=".$currentSeason->id." "; $sql = $sql . "and games.round_id=rounds.id and tipps.game_id=games.id and users.id = tipps.user_id "; $sql = $sql . "and payments.season_id=".$currentSeason->id." and payments.user_id = users.id "; $sql = $sql . "and payments.paid_date is not null "; $sql = $sql . "and users.deleted is null "; $sql = $sql . "order by rounds.id, games.id, users.id;"; $result=DB::select($sql); $roundtipps = array(); $roundData = array(); $user_ids=array(); $round_ids=array(); // Write sql result to roundtipps (score per round & user) if ($max_round_id==-1) { $max_round_id=Round::getLastCompleteRoundId($currentSeason->id); } foreach ($result as $entry) { $round_id = $entry->round_id; if ($max_round_id >-1 && $round_id>$max_round_id) break; if (!in_array($entry->user_id,$user_ids)) { array_push($user_ids,$entry->user_id); } if (!in_array($entry->round_id,$round_ids)) { array_push($round_ids,$entry->round_id); } if (!in_array($round_id,$roundData)) { $roundData[$round_id]=array(); } $user_id = $entry->user_id; $key = $round_id."_".$user_id; if (!array_key_exists($key,$roundtipps)) { $roundtipps[$key]=array(); $roundtipps[$key]['tipps']=array(); $roundtipps[$key]['results']=array(); $roundtipps[$key]['joker']=array(); $roundtipps[$key]['round_completed']=true; $roundtipps[$key]['user_name'] = $entry->user_name; $roundtipps[$key]['user_id'] = $entry->user_id; $roundtipps[$key]['rankscore']=0; $roundtipps[$key]['payout']=0; $roundtipps[$key]['earliest_kickoff']=$entry->game_kickoff; $roundtipps[$key]['hits']=0; // Wenigstens Tendenz getroffen. Wenn 4, dann 2 Punkte Bonus auf rankscore $roundtipps[$key]['is_dayscorewinner']=0; $roundtipps[$key]["ranking_payout"]=0; // Existiert nur in der letzten Runde } if (!array_key_exists('is_completed',$roundData[$round_id])) { $roundData[$round_id]['is_completed'] = true; } $game_value=Tipp::getScoreLocal($entry->game_score1,$entry->game_score2,$entry->tipp_score1,$entry->tipp_score2,$entry->joker); // Für alle 4 Spiele $roundtipps[$key]['rankscore']+=$game_value; if($game_value>0) { $roundtipps[$key]['hits']+=1;} if ($roundtipps[$key]['hits']==4) {$roundtipps[$key]['rankscore']+=2;} // Wenn alle 4 Spiele mind. Tendenz, dann 2 Punkte Bonus if ($entry->game_score1==-1 || $entry->game_score2==-1) { $roundtipps[$key]['round_completed'] = false; // TODO: Remove it, its succeeded by roundData['is_completed'] $rounds[$round_id]['is_completed'] = false; } array_push($roundtipps[$key]['tipps'],$entry->tipp_score1); array_push($roundtipps[$key]['tipps'],$entry->tipp_score2); array_push($roundtipps[$key]['results'],$entry->game_score1); array_push($roundtipps[$key]['results'],$entry->game_score2); array_push($roundtipps[$key]['joker'],$entry->joker); if ( $entry->game_kickoff < $roundtipps[$key]['earliest_kickoff'] ) { $roundtipps[$key]['earliest_kickoff'] = $entry->game_kickoff; } } // NOW ALL KEYS FOR ROUNDTIPPS (ROUND & USER) EXIST // CALCULATION OF SCORES, RANKS, ETC. (COMPUTE AGGREGATED VALUES) $highestDayscores=array(); foreach($user_ids as $user_id) { $totalRankScore=0; foreach($round_ids as $round_id) { $key=$round_id."_".$user_id; // Compute Dayscore values $dayScore1WithRankScore = Tipp::getDayScoreLocal($roundtipps[$key]['results'][0],$roundtipps[$key]['results'][1],$roundtipps[$key]['tipps'][0],$roundtipps[$key]['tipps'][1],$roundtipps[$key]['joker'][0],$roundtipps[$key]['rankscore']); $dayScore2WithRankScore = Tipp::getDayScoreLocal($roundtipps[$key]['results'][2],$roundtipps[$key]['results'][3],$roundtipps[$key]['tipps'][2],$roundtipps[$key]['tipps'][3],$roundtipps[$key]['joker'][1],$roundtipps[$key]['rankscore']); $dayScore3WithRankScore = Tipp::getDayScoreLocal($roundtipps[$key]['results'][4],$roundtipps[$key]['results'][5],$roundtipps[$key]['tipps'][4],$roundtipps[$key]['tipps'][5],$roundtipps[$key]['joker'][2],$roundtipps[$key]['rankscore']); $dayScore4WithRankScore = Tipp::getDayScoreLocal($roundtipps[$key]['results'][6],$roundtipps[$key]['results'][7],$roundtipps[$key]['tipps'][6],$roundtipps[$key]['tipps'][7],$roundtipps[$key]['joker'][3],$roundtipps[$key]['rankscore']); $totalDayScoreWithRankScore = Tipp::addDayScoreValues($dayScore1WithRankScore,$dayScore2WithRankScore); $totalDayScoreWithRankScore = Tipp::addDayScoreValues($totalDayScoreWithRankScore,$dayScore3WithRankScore); $totalDayScoreWithRankScore = Tipp::addDayScoreValues($totalDayScoreWithRankScore,$dayScore4WithRankScore); $roundtipps[$key]['dayScoreWithRankScore'] = $totalDayScoreWithRankScore; $roundtipps[$key]['dayscore'] = Tipp::getDayScoreWithoutRankScore($totalDayScoreWithRankScore); if (!array_key_exists($round_id,$highestDayscores)) { $highestDayscores[$round_id] = 0;} if ($highestDayscores[$round_id] < $roundtipps[$key]['dayscore'] ) { $highestDayscores[$round_id]=$roundtipps[$key]['dayscore'];} $totalRankScore += $roundtipps[$key]["rankscore"]; $roundtipps[$key]['totalRankScore'] = $totalRankScore; } } //////////////////////////////////////////////////////// // Sortier-Array nach Rang (nur für max_round_id) $userRankings = array(); foreach ($user_ids as $user_id) { $key = $max_round_id."_".$user_id; //error_log("Pushing:". $user_id." => ".$key); array_push($userRankings, [$user_id , $roundtipps[$key]['totalRankScore']]); } usort($userRankings, array('App\Tipp','cmpRank')); // Ranknr identifizieren, inkl, geteilter Rankplatzierungen nur für max_round_id notwendig, da der Rest ja gar nicht angezeigt wird $lastScore=-1; $lastrank=0; $current_list_position=0; foreach($userRankings as $userRank) { $user_id=$userRank[0]; $totalRankScore=$userRank[1]; $key=$max_round_id."_".$user_id; $current_list_position+=1; if ($roundtipps[$key]["totalRankScore"]==$lastScore) { $roundtipps[$key]["rank"] = $lastrank; } else { $lastrank = $current_list_position; $roundtipps[$key]["rank"] = $current_list_position; $lastScore = $totalRankScore; } } ////////////////////////////// // START OF HURTFUL 6 PLACE RESTRICTION IF DAYSCORE WIN (exception: completely even scores) // If more than 6 DayScoreWinners: Restrict by dayscore (rank) // Compute highest dayscore // Addition: no dayscorewinner && round_completed: Payout goes to next round $payouts = Quota::getPayouts($currentSeason->id); $totalDayWinPayout = 0; $round_count=0; foreach ($round_ids as $round_id) { $round_count += 1; $totalDayWinPayout += $payouts["tagessieg"]; $highestDayScore = $highestDayscores[$round_id]; $usersWithHighestDayScore = array(); $round_completed = false; foreach ($user_ids as $user_id) { $key = $round_id . "_" . $user_id; if ($roundtipps[$key]['dayscore'] == $highestDayScore && $roundtipps[$key]['round_completed'] && $highestDayScore > 0) { array_push($usersWithHighestDayScore, [$user_id, $roundtipps[$key]['dayScoreWithRankScore']]); } } $dayScoreWinnersIds = array(); // Bei >6 Tagessiegern über rankscore reduzieren if (sizeof($usersWithHighestDayScore) > 6) { usort($usersWithHighestDayScore, array('App\Tipp', 'cmpDayWin')); $count = 0; $cutOffScore = 0; foreach ($usersWithHighestDayScore as $user) { // Feld0: user_id, dayScoreWithRankScore $key = $max_round_id . "_" . $user[0]; // Hier: $user[0] = user_id, $user[1] = dayScore WithRankScore $rankscore = $user[1]; $count += 1; if ($count == 1) { $cutOffScore = $rankscore; } if ($rankscore < $cutOffScore) { break; } array_push($dayScoreWinnersIds, $user[0]); $key = $round_id . "_" . $user[0]; $roundtipps[$key]['is_dayscorewinner'] = true; } } // Bei bis zu 6 Gewinnern normal als Sieger klassifizieren else { foreach ($usersWithHighestDayScore as $user) { array_push($dayScoreWinnersIds, $user[0]); $key = $round_id . "_" . $user[0]; $roundtipps[$key]['is_dayscorewinner'] = true; } } // Compute Dayscorewin payout (Tagessieg) $winnerCount = sizeof($dayScoreWinnersIds); $single_payout=0; if ($winnerCount > 0) { $single_payout = $totalDayWinPayout / $winnerCount; $single_payout = number_format((float)$single_payout, 2, '.', ''); $single_payout = str_replace(".", ",", $single_payout); $totalDayWinPayout=0; } foreach ($user_ids as $user_id) { $key = $round_id . "_" . $user_id; if ($roundtipps[$key]['is_dayscorewinner']) { $roundtipps[$key]['payout'] = $single_payout; } else { $roundtipps[$key]['payout'] = ''; } } } $quotas=Quota::getQuotas($currentSeason->id); if ($round_count==$quotas["Runden"]) { // Ranking Payout ausschütten $payout_groups =array(); $lastRoundId= array_values(array_slice($round_ids,-1))[0]; foreach($user_ids as $user_id) { $key = $lastRoundId."_".$user_id; $rank = $roundtipps[$key]["rank"]; //Log::info("Setting ranking_payout for user_id ".$user_id); //TODO: Do it for any number of rank payouts if ($rank<11) { if (!array_key_exists($rank,$payout_groups)) { $payout_groups[$rank]=array(); } array_push($payout_groups[$rank],$user_id); } } // platz0= unsused, just for getting place equal to rank position. $rank_names=['platz0','platz1','platz2','platz3','platz4','platz5','platz6','platz7','platz8','platz9','platz10']; // Ausschüttungsgruppen für Platzierung bilden foreach([1,2,3,4,5,6,7,8,9,10] as $rank) { // Jedes Payout, das verteilt werden muss $current_rank = $rank; $rankPayout=$payouts[$rank_names[$rank]]; while($current_rank) { while (!array_key_exists($current_rank, $payout_groups)) { $current_rank -=1; } $groupsize = sizeof($payout_groups[$current_rank]); $single_payout = $rankPayout / $groupsize; foreach($payout_groups[$current_rank] as $user_id) { $key = $round_count."_".$user_id; $roundtipps[$key]["ranking_payout"] += $single_payout; } $current_rank=0; } } } //////////////////// END OF ROUNDTIPPS CREATION /////////////////// $response = array(); $response['roundtipps'] = $roundtipps; $response['roundData'] = $roundData; $response['user_ids'] = $user_ids; $response['round_ids'] = $round_ids; Log::info("Tipp::getRoundTipps: ExecutionTime: " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n"); return $response; } // Used by getRoundTipps method public static function cmpRank($rank1, $rank2) { return ($rank1[1] < $rank2[1]); //Feld0: user_id, Feld1: rank } // Used by getRoundTipps method public static function cmpDayWin($user1, $user2) { return ($user1[1] < $user2[1]); // Feld0: user_id, Feld1: dayScoreWithRankScore } }