302 lines
11 KiB
PHP
302 lines
11 KiB
PHP
<?php
|
|
|
|
namespace App\Leagues;
|
|
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use App\Leagues\League;
|
|
use App\Leagues\LeagueMember;
|
|
|
|
use App\User;
|
|
use App\Round;
|
|
use App\Season;
|
|
use App\Tipp;
|
|
|
|
use Log;
|
|
use DB;
|
|
|
|
class Match extends Model
|
|
{
|
|
protected $table ='leagues_matches';
|
|
protected $fillable = [
|
|
'id','league_id','round_id','user1_id','user2_id'
|
|
];
|
|
|
|
// https://en.wikipedia.org/wiki/Round-robin_tournament
|
|
public static function createMatchups()
|
|
|
|
{ // should be restricted to league ranks 1,2,3 and 4. All other leagues will have to use some
|
|
// incremental matchmaking system.
|
|
|
|
Log::info("Match::Creating matchups()");
|
|
$currentSeason = Season::getCurrent();
|
|
$leagues = League::where('season_id', '=', $currentSeason->id)->get();
|
|
foreach ($leagues as $league) {
|
|
error_log("Match::createMatchups league_id=".$league->id);
|
|
Log::info("Creating matchups for league_id=".$league->id);
|
|
// Wenn es keine previous League gibt, dann ist $league->rank immer RANK_QUALIFICATION,
|
|
// ansonsten ist es einer von RANK_LEAGUE1, RANK_LEAGUE2, RANK_LEAGUE3
|
|
|
|
Log::info("rank_id of league_id ".$league->id." = ".$league->rank);
|
|
|
|
if ($league->rank <= League::RANK_QUALIFICATION) {
|
|
|
|
$rounds = Round::where('id','>=',$league->start_round_id)->get();
|
|
|
|
error_log("Match::createMatchups. start_round_id = ".$league->start_round_id);
|
|
|
|
$roundNr=1;
|
|
$neededRoundCount = Match::getNumberOfNeededRounds($league->id);
|
|
|
|
Log::info("Match::createMatchups( league_id=".$league->id.", numberOfrounds=".sizeof($rounds));
|
|
$allPairings=Match::getAllPairings($league->id);
|
|
|
|
foreach ($rounds as $round) {
|
|
$pairings = $allPairings[$roundNr];
|
|
// Save pairings
|
|
foreach($pairings as $pair) {
|
|
Log::info("Saving match. " . $pair[0] . " vs " . $pair[1] . " roundid=" . $round->id);
|
|
$newMatch = Match::create([
|
|
'league_id' => $league->id,
|
|
'round_id' => $round->id,
|
|
'user1_id' => $pair[0],
|
|
'user2_id' => $pair[1]
|
|
]);
|
|
$newMatch->save();
|
|
//Log::info("Saving match: league_id=".$league->id.", round_id=".$round->id.", ".$pair[0]." vs ".$pair[2]);
|
|
}
|
|
$roundNr += 1;
|
|
if ($roundNr > $neededRoundCount) break;
|
|
}
|
|
|
|
} else {Log::info("Skipped match creation because of unfitting rank=".$league->rank);}
|
|
}
|
|
}
|
|
|
|
public static function hasMatched($user1_id, $user2_id, $league_id)
|
|
{
|
|
$matches = DB::table('leagues_matches')
|
|
->where('league_id', '=', $league_id)
|
|
->where('user1_id', '=', $user1_id)
|
|
->where('user2_id', '=', $user2_id)
|
|
->get();
|
|
if (sizeof($matches)) {
|
|
return true;
|
|
}
|
|
|
|
$matches = DB::table('leagues_matches')
|
|
->where('league_id', '=', $league_id)
|
|
->where('user1_id', '=', $user2_id)
|
|
->where('user2_id', '=', $user1_id)
|
|
->get();
|
|
if (sizeof($matches)) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
// Selektiert nur die "Heimspiele"
|
|
public static function getMatches($user_id, $league_id) {
|
|
$matches = DB::table('leagues_matches')->where('league_id', '=', $league_id)->where('user1_id','=',$user_id)->get();
|
|
return $matches;
|
|
}
|
|
|
|
|
|
public static function getLeagueMatches($leagueId) {
|
|
//error_log("App\Match::getLeagueMatches(leagueId=".$leagueId.")");
|
|
$matches = DB::table('leagues_matches')->where('league_id','=',$leagueId)->orderBy('round_id')->get();
|
|
$league=League::where('id','=',$leagueId)->first();
|
|
$season = Season::where('id','=',$league->season_id)->first();
|
|
$roundnames = Round::getNames($season->id);
|
|
$usernames = User::getNames();
|
|
|
|
foreach($matches as $match) {
|
|
//error_log("Needed round_id: ".$match->round_id);
|
|
$match->round_name = $roundnames[$match->round_id];
|
|
$match->user1_name = $usernames[$match->user1_id];
|
|
$match->user2_name = $usernames[$match->user2_id];
|
|
// Punktauswertung in Match::getMatchResults($leagueId, $maxRoundId);
|
|
}
|
|
return $matches;
|
|
}
|
|
|
|
|
|
// Hier findet RoundRobin statt.
|
|
public static function getAllPairings($leagueId) {
|
|
$members = LeagueMember::getMembers($leagueId);
|
|
|
|
$roundCount=sizeof($members)-1;
|
|
|
|
if (sizeof($members) % 2 == 1) { // ungerade memberzahl => freilos einfügen
|
|
error_log("Adding -1 free entry");
|
|
array_push($members,-1);
|
|
}
|
|
|
|
shuffle($members);
|
|
error_log("Number of members:".sizeof($members));
|
|
$pairingCount = Match::getNumberOfPairingsPerRound($leagueId);
|
|
|
|
error_log("pairingCount=".$pairingCount);
|
|
|
|
$all = array();
|
|
|
|
for ($currentRoundNr=1; $currentRoundNr<= $roundCount; $currentRoundNr++) {
|
|
|
|
$roundRobin = array();
|
|
foreach ($members as $userId) {
|
|
array_push($roundRobin, $userId);
|
|
}
|
|
|
|
error_log("RoundNr ".$currentRoundNr." Array start:");
|
|
error_log(implode(",",$roundRobin));
|
|
|
|
$_roundNr = $currentRoundNr;
|
|
while ($_roundNr >= 1) {
|
|
// Round-Robin shift: First element stays, rest rotates
|
|
$first = array_shift($roundRobin); // Erstes Element sichern & entfernen
|
|
$last = array_pop($roundRobin); // Letztes Element sichern & entfernen
|
|
array_unshift($roundRobin, $last); // Vorne einfügen
|
|
array_unshift($roundRobin, $first); // Vorne einfügen
|
|
$_roundNr--;
|
|
}
|
|
|
|
//error_log("RoundNr ".$currentRoundNr." Array end:");
|
|
//error_log(implode(",",$roundRobin));
|
|
|
|
$idx = 0;
|
|
$slot = 0;
|
|
$pairings = array();
|
|
foreach ($roundRobin as $index => $userId) {
|
|
$idx = $index;
|
|
if ($index >= $pairingCount) {
|
|
$idx = 2 * $pairingCount - $index - 1;
|
|
$slot = 1;
|
|
}
|
|
$pairings[$idx][$slot] = $userId;
|
|
//error_log($idx.",".$slot." => ".$userId);
|
|
}
|
|
|
|
// Matches die nur einen Teilnehmer haben entfernen. Passiert bei ungerader Teilnehmerzahl.
|
|
// Der nicht im Pairing befindliche Spieler hat einen spielfreien Tag.
|
|
|
|
//error_log(" Cleaning up Round pairings");
|
|
$pairings_clean=array();
|
|
//error_log(":".$pairings[0]);
|
|
foreach($pairings as $idx => $pairing) {
|
|
|
|
if ($pairing[0] == -1 || $pairing[1] == -1) {
|
|
//error_log("DONT ADD");
|
|
} else {
|
|
//error_log("adding...");
|
|
$pairings_clean[$idx] = $pairing;
|
|
}
|
|
}
|
|
$all[$currentRoundNr]=$pairings_clean;
|
|
//$all[$currentRoundNr]=$pairings;
|
|
|
|
}
|
|
|
|
//foreach ($all as $roundNr => $pairings) {
|
|
// foreach ($pairings as $slotIdx => $pairing) {
|
|
// error_log($pairing[0]." vs ".$pairing[1]);
|
|
// }
|
|
// error_log("");
|
|
//}
|
|
|
|
return $all; // $all[$roundnr]= Array of Tuples ( UserId1, UserId2 )
|
|
//return null;
|
|
|
|
}
|
|
|
|
public static function getNumberOfPairingsPerRound($leagueId) {
|
|
$members = LeagueMember::getMembers($leagueId);
|
|
$pairingsPerRound = intdiv(sizeof($members),2);
|
|
if (sizeof($members)-$pairingsPerRound*2) {
|
|
$pairingsPerRound+=1;
|
|
}
|
|
return $pairingsPerRound;
|
|
}
|
|
|
|
public static function getNumberOfNeededRounds($leagueId) {
|
|
$members = LeagueMember::getMembers($leagueId);
|
|
$memberCount = sizeof($members);
|
|
|
|
if ($memberCount % 2 == 1) { return $memberCount; } // 1 Runde mehr wg. Freilos für 1 Spieler
|
|
return $memberCount-1;
|
|
}
|
|
|
|
public static function getMatchResults($leagueId, $maxRoundId=-1) {
|
|
|
|
$league=League::where('id','=',$leagueId)->first();
|
|
$season=Season::where('id','=',$league->season_id)->first();
|
|
|
|
$roundtipps = Tipp::getRoundTipps($maxRoundId, $season->id);
|
|
$roundtipps = $roundtipps["roundtipps"];
|
|
$matches = Match::getLeagueMatches($leagueId, $maxRoundId);
|
|
|
|
if ($maxRoundId==-1) { $maxRoundId = Round::getLastRoundId($season->id); }
|
|
|
|
foreach($matches as $key => $match) {
|
|
|
|
$user1_key = $match->round_id."_".$match->user1_id;
|
|
$user2_key = $match->round_id."_".$match->user2_id;
|
|
|
|
if (Round::isCompleted($match->round_id)) {
|
|
|
|
$user1_score = $roundtipps[$user1_key]["rankscore"];
|
|
$user2_score = $roundtipps[$user2_key]["rankscore"];
|
|
|
|
$matches[$key]->user1_rankscore = $user1_score;
|
|
$matches[$key]->user2_rankscore = $user2_score;
|
|
|
|
//$matches[$key]->user1_hits = $roundtipps[$user1_key][]
|
|
|
|
if ($user1_score > $user2_score) {
|
|
$matches[$key]->user1_league_score = 3;
|
|
$matches[$key]->user2_league_score = 0;
|
|
|
|
}
|
|
else if ($user1_score < $user2_score){
|
|
$matches[$key]->user1_league_score = 0;
|
|
$matches[$key]->user2_league_score = 3;
|
|
} else {
|
|
$matches[$key]->user1_league_score = 1;
|
|
$matches[$key]->user2_league_score = 1;
|
|
}
|
|
|
|
} else { // Untipped/future round
|
|
$matches[$key]->user1_league_score = 0;
|
|
$matches[$key]->user2_league_score = 0;
|
|
$matches[$key]->user1_rankscore = -1;
|
|
$matches[$key]->user2_rankscore = -1;
|
|
}
|
|
|
|
}
|
|
return $matches;
|
|
}
|
|
|
|
public static function getMatchResultsForUser($userId, $maxRoundId=-1) {
|
|
$season = Season::getCurrent();
|
|
$leagues = League::where('season_id','=',$season->id)->get();
|
|
|
|
$matchList=array();
|
|
|
|
foreach($leagues as $league) {
|
|
$member=LeagueMember::where('league_id','=',$league->id)->where('user_id','=',$userId)->first();
|
|
if ($member) {
|
|
// $userId ist member dieser League
|
|
$matchResults = Match::getMatchResults($league->id,$maxRoundId);
|
|
foreach($matchResults as $result) {
|
|
if ($result->user1_id == $userId || $result->user2_id==$userId) {
|
|
array_push($matchList, $result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $matchList;
|
|
|
|
}
|
|
|
|
}
|