Created
December 1, 2016 15:59
-
-
Save robawtic/5fa124ffdf48d06a33dcccaf0798884f to your computer and use it in GitHub Desktop.
I am trying to avoid query the database x times to get the match participant data displayed. I would like to be able to do something like $match->home->player->blah. From within Bracket.php the fucntion getMatches returns the Matches but has no relations which is where I think all this would be solved.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\lib; | |
use frontend\models\Tournament; | |
use frontend\models\TournamentParticipant; | |
use frontend\models\TournamentMatch; | |
class Bracket { | |
const ROUND_FINALS = 0; | |
const ROUND_SEMI_FINALS = 1; | |
const QUARTER_FINALS = 2; | |
protected $_tournament; | |
public $_matches; | |
protected $_participants; | |
protected $_rounds; | |
public function __construct( Tournament $tournament ) { | |
$this->_tournament = Tournament::findOne($tournament); | |
$this->_matches = $this->_tournament->allTournamentMatches; | |
} | |
public function calculateRoundMatches( $round ) { | |
$max = $this->_tournament->starting_matches; | |
$round--; | |
while( $round > 0 ) { | |
$max = ceil ( $max / 2 ); | |
$round--; | |
} | |
return $max; | |
} | |
public function getMatch($id) { | |
foreach($this->_matches as $match) { | |
if($match->id == $id ) | |
return $match; | |
} | |
return NULL; | |
} | |
public function getParticipant($id) { | |
foreach($this->_participants as $participant) { | |
if($participant->id == $id ) | |
return $participant; | |
} | |
return NULL; | |
} | |
public function getMatches($round, $pool = null, $participant_id = null) { | |
if ($pool) { | |
$ids = $this->_pools->round; | |
} else if (empty($this->_rounds[$round])) { | |
return array(); | |
} else { | |
$ids = $this->_rounds[$round]; | |
} | |
// Filter down again to participant | |
if ($participant_id) { | |
$ids = $ids[$participant_id]; | |
} | |
$matches = array(); | |
foreach ($ids as $match_id) { | |
$match = $this->getMatch($match_id); | |
$matches[$match->order] = $match; | |
} | |
return $matches; | |
} | |
public function getMaxRounds() { | |
return (int) $this->_tournament->max_rounds; | |
} | |
public function setMatches($matches = []) { | |
foreach( $matches as $match ) { | |
$this->_matches[$match->id] = $match; | |
} | |
return $this; | |
} | |
public function setParticipants( $participants = [] ) { | |
foreach( $participants as $participant ) { | |
$id = $participant['id']; | |
//$id = $participant->id ?: $participant->team_id; | |
$this->_participants[$id] = $participant; | |
} | |
return $this; | |
} | |
public function setRounds( $rounds = [] ) { | |
$this->_rounds = $rounds; | |
if( empty( $this->_matches ) ) { | |
return false; | |
} | |
return $this; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\models; | |
use Yii; | |
/** | |
* This is the model class for table "player". | |
* | |
* @property integer $id | |
* @property integer $user_id | |
* @property string $screenname | |
* @property string $battletag | |
* @property string $bnet_profile_link | |
* @property integer $main_race | |
* @property integer $league | |
* @property integer $tier | |
* @property integer $clan_id | |
* @property integer $created_at | |
* @property integer $updated_at | |
* | |
* @property Clan[] $clans | |
* @property ClanWarMatch[] $clanWarMatches | |
* @property ClanWarMatch[] $clanWarMatches0 | |
* @property User $user | |
* @property TournamentParticipant[] $tournamentParticipants | |
*/ | |
class Player extends \yii\db\ActiveRecord | |
{ | |
const ZERG = 1; | |
const TERRAN = 2; | |
const PROTOSS = 3; | |
const RANDOM = 4; | |
const BRONZE = 1; | |
const SILVER = 2; | |
const GOLD = 3; | |
const PLAT = 4; | |
const DIAMOND = 5; | |
const MASTER = 6; | |
const GRANDMASTER = 7; | |
/** | |
* @inheritdoc | |
*/ | |
public static function tableName() | |
{ | |
return 'player'; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['user_id', 'screenname'], 'required'], | |
[['user_id', 'main_race', 'league', 'tier', 'clan_id', 'created_at', 'updated_at'], 'integer'], | |
[['screenname', 'battletag', 'bnet_profile_link'], 'string', 'max' => 255], | |
[['screenname'], 'unique'], | |
[['battletag'], 'unique'], | |
[['user_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['user_id' => 'id']], | |
]; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'id' => 'ID', | |
'user_id' => 'User ID', | |
'screenname' => 'Screenname', | |
'battletag' => 'Battletag', | |
'bnet_profile_link' => 'Bnet Profile Link', | |
'main_race' => 'Main Race', | |
'league' => 'League', | |
'tier' => 'Tier', | |
'clan_id' => 'Clan ID', | |
'created_at' => 'Created At', | |
'updated_at' => 'Updated At', | |
]; | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getClans() | |
{ | |
return $this->hasMany(Clan::className(), ['owner_id' => 'id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getClanWarMatches() | |
{ | |
return $this->hasMany(ClanWarMatch::className(), ['away_id' => 'id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getClanWarMatches0() | |
{ | |
return $this->hasMany(ClanWarMatch::className(), ['home_id' => 'id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getUser() | |
{ | |
return $this->hasOne(User::className(), ['id' => 'user_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournamentParticipants() | |
{ | |
return $this->hasMany(TournamentParticipant::className(), ['player_id' => 'id']); | |
} | |
public function getRaceList() | |
{ | |
return [ | |
self::ZERG=>'Zerg', | |
self::TERRAN=>'Terran', | |
self::PROTOSS=>'Protoss', | |
self::RANDOM=>'Random', | |
]; | |
} | |
public static function getLeagueText($race) | |
{ | |
switch($race) | |
{ | |
case 1: | |
return "Bronze"; | |
case 2: | |
return "Silver"; | |
case 3: | |
return "Gold"; | |
case 4: | |
return "Plat"; | |
case 5: | |
return "Diamond"; | |
case 6: | |
return "Master"; | |
case 7: | |
return "Grandmaster"; | |
default: | |
return "Not Set"; | |
} | |
} | |
public function getLeagueList() | |
{ | |
return [ | |
self::BRONZE=>'Bronze', | |
self::SILVER=>'Silver', | |
self::GOLD=>'Gold', | |
self::PLAT=>'Plat', | |
self::DIAMOND=>'Diamond', | |
self::MASTER=>'Master', | |
self::GRANDMASTER=>'Grandmaster', | |
]; | |
} | |
public static function getRaceText($race) | |
{ | |
switch($race) | |
{ | |
case 1: | |
return "Zerg"; | |
case 2: | |
return "Terran"; | |
case 3: | |
return "Protoss"; | |
case 4: | |
return "Random"; | |
default: | |
return "Not Set"; | |
} | |
} | |
public static function getPlayerNameById($id) | |
{ | |
return static::find()->where(['id'=>$id])->select('screenname')->one(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\models; | |
use Yii; | |
use yii\db\Query; | |
use frontend\models\TournamentParticipant; | |
/** | |
* This is the model class for table "tournament". | |
* | |
* @property integer $id | |
* @property integer $creator_id | |
* @property string $name | |
* @property string $description | |
* @property integer $type | |
* @property integer $seed | |
* @property integer $round | |
* @property integer $min_participants | |
* @property integer $max_participants | |
* @property integer $max_rounds | |
* @property integer $best_of | |
* @property integer $starting_matches | |
* @property integer $starting_byes | |
* @property integer $pool_size | |
* @property integer $status | |
* @property integer $checkin_start | |
* @property integer $checkin_end | |
* @property integer $registration_start | |
* @property integer $registration_end | |
* @property integer $start_time | |
* @property integer $created_at | |
* @property integer $updated_at | |
* | |
* @property User $creator | |
* @property TournamentMatch[] $tournamentMatches | |
* @property TournamentParticipant[] $tournamentParticipants | |
*/ | |
class Tournament extends \yii\db\ActiveRecord | |
{ | |
const FORMAT_TEAM = 1; | |
const FORMAT_PLAYER = 2; | |
const TYPE_SINGLE_ELIMINATION = 1; | |
const TYPE_DOUBLE_ELIMINATION = 2; | |
const TYPE_ROUND_ROBIN = 3; | |
const TYPE_SWISS = 4; | |
const TYPE_PROLEAGUE = 5; | |
const STATUS_CREATED = 1; | |
const STATUS_IS_RUNNING = 2; | |
const STATUS_IS_FINISHED = 3; | |
const REGISTRATION_IS_OPEN = 1; | |
const REGISTRATION_IS_CLOSED = 2; | |
const REGISTRATION_IS_INVITE_ONLY = 3; | |
const REGISTRATION_IS_CLAN_IN_HOUSE = 4; | |
const CHECK_IN_IS_OPEN = 1; | |
const CHECK_IN_IS_CLOSED = 2; | |
const SEED_RANDOM = 1; | |
const SEED_POINTS = 2; | |
/** | |
* @inheritdoc | |
*/ | |
public static function tableName() | |
{ | |
return 'tournament'; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['creator_id'], 'required'], | |
[['creator_id', 'type', 'format', 'status', 'max_participants', 'pool_size', 'seed', 'round', 'min_participants', 'max_rounds', 'starting_matches', 'starting_byes', 'checkin_start', 'checkin_end', 'registration_status', 'registration_start', 'registration_end', 'start_time', 'best_of', 'created_at', 'updated_at'], 'integer'], | |
[['description'], 'string'], | |
[['name'], 'string', 'max' => 255], | |
[['creator_id'], 'exist', 'skipOnError' => true, 'targetClass' => User::className(), 'targetAttribute' => ['creator_id' => 'id']], | |
]; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'id' => 'ID', | |
'creator_id' => 'Creator ID', | |
'name' => 'Name', | |
'description' => 'Description', | |
'type' => 'Type', | |
'seed' => 'Seed', | |
'round' => 'Round', | |
'format' => 'Format', | |
'status' => 'Status', | |
'min_participants' => 'Min Participants', | |
'max_participants' => 'Max Participants', | |
'pool_size' => 'Pool Size', | |
'best_of' => 'Best Of', | |
'max_rounds' => 'Max Rounds', | |
'starting_matches' => 'Starting Matches', | |
'starting_byes' => 'Starting Byes', | |
'registration_status' => 'Registration Status', | |
'checkin_start' => 'Checkin Start', | |
'checkin_end' => 'Checkin End', | |
'starting_matches' => 'Starting matches', | |
'registration_start' => 'Registration Start', | |
'registration_end' => 'Registration End', | |
'start_time' => 'Start Time', | |
'created_at' => 'Created At', | |
'updated_at' => 'Updated At', | |
]; | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getCreator() | |
{ | |
return $this->hasOne(User::className(), ['id' => 'creator_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournamentMatches($tournament_id, $status) | |
{ | |
//SELECT `home`.`screenname` as `home_player`, `away`.`screenname` as `away_player`, | |
//`tm`.`home_score` as `home_score`, `tm`.`away_score` as `away_score`, | |
//`tm`.`reported_at` as `reported_at` From `tournament_match` as `tm` | |
//LEFT JOIN `player` as `home` ON `tm`.`home_id` = `home`.`id` | |
//LEFT JOIN `player` as `away` ON `tm`.`away_id` = `away`.`id` | |
//where `tm`.`tournament_id` = 1 AND `tm`.`status` = 2 | |
$query = new Query; | |
return $query->select( | |
'`home`.`screenname` as `home_player`, `away`.`screenname` as `away_player`,' | |
. '`tm`.`home_id` as `home_id`, `tm`.`away_id` as `away_id`,' | |
. '`tm`.`home_score` as `home_score`, `tm`.`away_score` as `away_score`,' | |
. '`tm`.`reported_at` as `reported_at`, `tm`.`round`, `tm`.`reported_by` as `reporter`') | |
->from('`tournament_match` as `tm`') | |
->leftJoin('`player` as `home`', '`tm`.`home_id` = `home`.`id`') | |
->leftJoin('`player` as `away`', '`tm`.`away_id` = `away`.`id`') | |
->where(['`tm`.`tournament_id`' => $tournament_id]) | |
->andWhere(['`tm`.`status`' => $status]) | |
->all(); | |
} | |
public function getDiscussions($tournament_id) | |
{ | |
$query = new Query; | |
return $query->select( | |
'`d`.`subject` as `subject`, `p`.`screenname` as `poster`, `d`.`posted_at` as `post_time`') | |
->from('`tournament_discussion` as `d`') | |
->leftJoin('`player` as `p`', '`d`.`poster_id` = `p`.`id`') | |
->where(['`d`.`tournament_id`' => $tournament_id]) | |
->all(); | |
} | |
public function getAllTournamentMatches() | |
{ | |
return $this->hasMany(TournamentMatch::className(), ['tournament_id' => 'id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournamentParticipants() | |
{ | |
return $this->hasMany(TournamentParticipant::className(), ['tournament_id' => 'id']); | |
} | |
public function getParticipantCount($id) | |
{ | |
return Yii::$app->db->createCommand('SELECT COUNT(*) FROM tournament_participant WHERE tournament_id = :id') | |
->bindValue(':id', $id) | |
->queryScalar(); | |
} | |
public function getAllParticipants($id) | |
{ | |
$query = new Query; | |
return $query->select('*') | |
->from('`tournament_participant`') | |
->where(['tournament_id' => $id]) | |
->all(); | |
} | |
public function getParticipants() | |
{ | |
return $this->hasMany(TournamentMatch::className(), ['tournament_id' => 'id']) | |
->viaTable('tournament_participant', ['tournament_id' => 'id']) | |
->with(['home', 'away']) | |
->with(['home.player' => function ($q) { | |
$q->from ('player h'); | |
}, 'away.player' => function ($q) { | |
$q->from ('player a'); | |
},]) | |
->select('h.screenname as home_team, a.screenname as away_team'); | |
} | |
public static function getTypeText($type) | |
{ | |
switch($type) | |
{ | |
case 1: | |
return "Single Elmination"; | |
case 2: | |
return "Double Elimination"; | |
case 3: | |
return "Round Robin"; | |
case 4: | |
return "Swiss"; | |
default: | |
return "Not Set"; | |
} | |
} | |
public static function getTypeLink($type) | |
{ | |
switch($type) | |
{ | |
case 1: | |
return "_singleElimination"; | |
case 2: | |
return "_doubleElimination"; | |
case 3: | |
return "_roundRobin"; | |
case 4: | |
return "_swiss"; | |
} | |
} | |
public function randomlySeedParticipants($participants = []) | |
{ | |
$max = count($participants); | |
$seeds = range(1, $max); | |
shuffle($seeds); | |
$seed = 0; | |
foreach($participants as $participant) | |
{ | |
$id = $participant['id']; | |
$model = TournamentParticipant::findOne($id); | |
$model['seed'] = $seeds[$seed]; | |
if(!$model->save()){ | |
return false; | |
} | |
$seed++; | |
} | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\controllers; | |
use Yii; | |
use yii\data\ActiveDataProvider; | |
use yii\web\Controller; | |
use yii\web\NotFoundHttpException; | |
use yii\filters\VerbFilter; | |
use frontend\models\Tournament; | |
use frontend\models\TournamentMatch; | |
use frontend\models\Player; | |
use frontend\models\TournamentParticipant; | |
use frontend\models\TournamentDiscussion; | |
use frontend\lib\TournamentFactory; | |
use frontend\lib\Bracket; | |
class TournamentController extends Controller | |
{ | |
/** | |
* @inheritdoc | |
*/ | |
public function behaviors() | |
{ | |
return [ | |
'verbs' => [ | |
'class' => VerbFilter::className(), | |
'actions' => [ | |
'delete' => ['POST'], | |
], | |
], | |
]; | |
} | |
/** | |
* Lists all Tournament models. | |
* @return mixed | |
*/ | |
public function actionIndex() | |
{ | |
$dataProvider = new ActiveDataProvider([ | |
'query' => Tournament::find()->with('creator'), | |
]); | |
return $this->render('index', [ | |
'dataProvider' => $dataProvider, | |
]); | |
} | |
/** | |
* Displays Tournament Bracket. | |
* @param type $id | |
* @return mixed | |
*/ | |
public function actionBracket($id) | |
{ | |
$model = $this->findModel($id); | |
$bracket = TournamentMatch::getBrackets($model); | |
return $this->render('bracket', [ | |
'model' => $model, | |
'bracket' => $bracket | |
]); | |
} | |
/** | |
* Seeds the Participants | |
* @param type $id | |
* @return mixed | |
*/ | |
public function actionSeedParticipants($id) | |
{ | |
$model = $this->findModel($id); | |
$participants = $model->getAllParticipants($model->id); | |
$model->randomlySeedParticipants($participants); | |
return $this->redirect(['bracket', 'id' => $model->id]); | |
} | |
/** | |
* Displays current Tournament Standings | |
* @param type $id | |
* @return mixed | |
*/ | |
public function actionStandings($id) | |
{ | |
$model = $this->findModel($id); | |
TournamentFactory::factory($model)->generateMatches(); | |
return $this->render('standings', [ | |
'model' => $model, | |
]); | |
} | |
/** | |
* Displays Tournament Discussion Thread | |
* @param type $id | |
* @return Mixed | |
*/ | |
public function actionDiscussion($id) | |
{ | |
$model = $this->findModel($id); | |
$discussion = new TournamentDiscussion(); | |
$posts = $model->getDiscussions($id); | |
if ($discussion->load(Yii::$app->request->post())) | |
{ | |
$discussion->tournament_id = $id; | |
$discussion->poster_id = Yii::$app->user->getId(); | |
$discussion->posted_at = time(); | |
$discussion->created_at = time(); | |
$discussion->modified_at = time(); | |
if ($discussion->save()) { | |
return $this->redirect(['discussion', 'id' => $model->id]); | |
} | |
} else { | |
return $this->render('discussion', [ | |
'model' => $model, | |
'discussion' => $discussion, | |
'posts' => $posts, | |
]); | |
} | |
} | |
/** | |
* Lists Tournament events :creation, player sign-up, start of tournamnet, | |
* match reports etc.. | |
* @param type $id | |
* @return Mixed | |
*/ | |
public function actionLog($id) | |
{ | |
$model = $this->findModel($id); | |
$matches = $model->getTournamentMatches($model->id, 2); | |
return $this->render('log', [ | |
'model' => $this->findModel($id), | |
'matches' => $matches | |
]); | |
} | |
/** | |
* Player Registration for Tournament | |
* @param type $id | |
* @return Mixed | |
* @throws NotFoundHttpException | |
*/ | |
public function actionRegister($id) | |
{ | |
$model = $this->findModel($id); | |
if($model->registration_status == 2) { | |
throw new NotFoundHttpException('Registration is closed.'); | |
} | |
if ((Yii::$app->request->post()) && $model->registration_status == 1) | |
{ | |
$participant = new TournamentParticipant(); | |
//Need to add check to see if player exsists, if not send user to create | |
// a player profile. | |
$player = Player::findOne(['user_id' => \Yii::$app->user->getId()]); | |
$participant->player_id = $player->id; | |
$participant->clan_id = $player->clan_id; | |
$participant->tournament_id = $id; | |
$participant->created_at = time(); | |
$participant->updated_at = time(); | |
//Need to Add check on if current tournament requires check-in or if | |
// check-in has already begun. | |
$participant->status = 1; | |
if($participant->save()) { | |
return $this->render('register', [ | |
'model' => $model, | |
]); | |
} | |
} else { | |
return $this->render('register', [ | |
'model' => $model, | |
]); | |
} | |
} | |
public function actionCreate() | |
{ | |
$model = new Tournament(); | |
if ($model->load(Yii::$app->request->post()) && $model->save()) { | |
return $this->redirect(['view', 'id' => $model->id]); | |
} else { | |
return $this->render('create', [ | |
'model' => $model, | |
]); | |
} | |
} | |
public function actionStart($id) | |
{ | |
$model = Tournament::findModel($id); | |
return $this->render('brackets', [ | |
'model' => $model, | |
]); | |
} | |
public function actionView($id) | |
{ | |
return $this->render('view', [ | |
'model' => $this->findModel($id), | |
]); | |
} | |
public function actionDelete($id) | |
{ | |
$this->findModel($id)->delete(); | |
return $this->redirect(['index']); | |
} | |
/** | |
* Finds the Clan model based on its primary key value. | |
* If the model is not found, a 404 HTTP exception will be thrown. | |
* @param integer $id | |
* @return Clan the loaded model | |
* @throws NotFoundHttpException if the model cannot be found | |
*/ | |
protected function findModel($id) | |
{ | |
if (($model = Tournament::findOne($id)) !== null) { | |
return $model; | |
} else { | |
throw new NotFoundHttpException('The requested page does not exist.'); | |
} | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\lib; | |
use frontend\models\Tournament; | |
use frontend\models\TournamentParticipant; | |
use frontend\models\TournamentMatch; | |
use yii\db\Query; | |
/** | |
* @property Tournament $Event | |
* @property TournamentParticipant $TournamentParticipant | |
* @property TournamentMatch $TournamentMatch | |
*/ | |
abstract class TournamentFactory | |
{ | |
// Status flags | |
const PENDING = 0; | |
const ACTIVE = 1; | |
const DISABLED = 2; | |
// Participant flags | |
const TEAM = 0; | |
const PLAYER = 1; | |
// Winner flags | |
// PENDING = 0; | |
const HOME_TEAM = 1; | |
const AWAY_TEAM = 2; | |
const NONE = 3; | |
// Outcome flags | |
// PENDING = 0; | |
const WIN = 1; | |
const LOSS = 2; | |
const TIE = 3; | |
const BYE = 4; | |
protected $_id; | |
protected $_tournament; | |
protected $_forModel; | |
protected $_forField; | |
protected $_bracketSize; | |
final public function __construct( Tournament $tournament ) { | |
if(!$tournament){ | |
$this->Tournament = new Tournament; | |
}else{ | |
$this->Tournament = $tournament; | |
} | |
$this->_tournament = $tournament; | |
$this->_id = $tournament->id; | |
$this->_forModel = ($this->_tournament->format == Tournament::FORMAT_TEAM) ? 'Team' : 'Player'; | |
$this->_forField = ($this->_tournament->format == Tournament::FORMAT_TEAM) ? 'team_id' : 'player_id'; | |
} | |
public static function factory($tourney) | |
{ | |
if(is_numeric($tourney)) | |
{ | |
$tournament = Tournament::findOne($tourney); | |
} else { | |
$tournament = $tourney; | |
} | |
switch ( $tournament->type ) | |
{ | |
case Tournament::TYPE_SINGLE_ELIMINATION: | |
return new SingleElimination($tournament); | |
case Tournament::TYPE_DOUBLE_ELIMINATION: | |
return new DoubleElimination($tournament); | |
case Tournament::TYPE_ROUND_ROBIN: | |
return new RoundRobin($tournament); | |
case Tournament::TYPE_SWISS: | |
return new Swiss($tournament); | |
case Tournament::TYPE_PROLEAGUE: | |
return new ProLeague($tournament); | |
} | |
} | |
abstract public function generateMatches(); | |
public function getParticipants($order = array(), $return = false) | |
{ | |
$for = $this->_forModel; // Team or Player | |
//Returns Teams or Players that are ready for the tournament. | |
if (!$order) { | |
if ($this->_tournament['seed'] == Tournament::SEED_POINTS) { | |
$order = [$for . '.points' => 'ASC']; | |
} else { | |
$order = ' RAND()'; | |
} | |
} | |
$query = new Query; | |
$participants = $query->select( | |
'*') | |
->from('`tournament_participant`') | |
->where( | |
[ | |
'tournament_id' => $this->_id, | |
'status' => TournamentParticipant::STATUS_CHECKED_IN | |
] | |
) | |
->orderBy($order) | |
->all(); | |
if (!$participants) { | |
//no players exception | |
} | |
if ($return) { | |
return $participants; | |
} | |
$participant_ids = array(); | |
foreach ($participants as $participant) | |
{ | |
$participant_ids[] = $participant['player_id']; | |
} | |
return $participant_ids; | |
} | |
public function organizeBrackets($matches) | |
{ | |
$participants = $this->getParticipants(array(), true); | |
$rounds = []; | |
foreach($matches as $match) { | |
$round = (int) $match->round; | |
if(empty($rounds[$round])) { | |
$rounds[$round] = array(); | |
} | |
$rounds[$round][] = $match->id; | |
} | |
foreach($rounds as &$r) { | |
sort($r, SORT_NUMERIC); | |
} | |
ksort($rounds); | |
$bracket = new Bracket($this->_tournament); | |
$bracket->setMatches($matches); | |
$bracket->setParticipants($participants); | |
$bracket->setRounds($rounds); | |
return $bracket; | |
} | |
public function organizeSeeds($participants) | |
{ | |
$seeds = $participants; | |
$seed = 1; | |
foreach($participants as $participant) | |
{ | |
if($participant) | |
{ | |
$this->flagParticipant($participant, $seed); | |
$seed++; | |
} | |
} | |
$count = count($seeds); | |
$half = ceil($count / 2); | |
$slice = 1; | |
while ($slice < $half) | |
{ | |
$temp = $seeds; | |
$seeds = array(); | |
while(count($temp) > 0) | |
{ | |
$seeds = array_merge($seeds, array_splice($temp, 0, $slice)); | |
$seeds = array_merge($seeds, array_splice($temp, -$slice, $slice)); | |
} | |
$slice *= 2; | |
} | |
return $seeds; | |
} | |
/** | |
* Create new matches for byes in the next round. | |
* | |
* @param int $round | |
*/ | |
public function advanceByes($round) { | |
$query = new Query; | |
$matches = $query->select( | |
'*') | |
->from('`tournament_match`') | |
->where( | |
[ | |
'tournament_id' => $this->_id, | |
'round' => $round, | |
'home_score' => TournamentMatch::PLAYER_STATUS_BYE | |
] | |
) | |
->orderBy(['order' => SORT_ASC]) | |
->all(); | |
if ($matches) { | |
$nextRound = $round + 1; | |
foreach ($matches as $match) { | |
$order = $this->findWinIndex($match['order'], $nextRound); | |
$home_id = $match['home_id']; | |
$away_id = null; | |
if ($order < 1) { | |
$order = 1; | |
} | |
// Find a match in the next round in case 2 byes meet | |
$query = new Query; | |
$target = $query->select( | |
'*') | |
->from('`tournament_match`') | |
->where( | |
[ | |
'tournament_id' => $this->_id, | |
'round' => $nextRound, | |
'order' => $order | |
] | |
) | |
->orderBy(['order' => SORT_ASC]) | |
->all(); | |
if ($target) { | |
$tournament_match = TournamentMatch::findOne($target[0]['id']); | |
$tournament_match->away_id = $home_id; | |
$tournament_match->save(); | |
} else { | |
$this->createMatch($home_id, $away_id, $order, $nextRound, null, false); | |
} | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\models; | |
use Yii; | |
use frontend\lib\TournamentFactory; | |
use frontend\lib\Bracket; | |
/** | |
* This is the model class for table "tournament_match". | |
* | |
* @property integer $id | |
* @property integer $tournament_id | |
* @property integer $home_id | |
* @property integer $away_id | |
* @property integer $home_score | |
* @property integer $away_score | |
* @property integer $home_points | |
* @property integer $away_points | |
* @property integer $bracket | |
* @property integer $winner | |
* @property integer $type | |
* @property integer $best_of | |
* @property integer $status | |
* @property integer $round | |
* @property integer $pool | |
* @property integer $order | |
* @property integer $map_id | |
* @property integer $reported_by | |
* @property integer $created_at | |
* @property integer $updated_at | |
* | |
* @property TournamentParticipant $away | |
* @property TournamentParticipant $home | |
* @property MapPool $map | |
* @property Tournament $tournament | |
*/ | |
class TournamentMatch extends \yii\db\ActiveRecord | |
{ | |
const PLAYER_STATUS_PENDING = 0; | |
const PLAYER_STATUS_WIN = 1; | |
const PLAYER_STATUS_LOSS = 2; | |
const PLAYER_STATUS_TIE = 3; | |
const PLAYER_STATUS_BYE = 4; | |
const MATCH_STATUS_PENDING = 0; | |
const MATCH_STATUS_PLAYING = 1; | |
const MATCH_STATUS_FINISHED = 2; | |
const MATCH_STATUS_FORFEITED = 3; | |
/** | |
* @inheritdoc | |
*/ | |
public static function tableName() | |
{ | |
return 'tournament_match'; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['tournament_id', 'home_id', 'away_id', 'home_score', 'away_score', 'bracket', 'type', 'pool', 'round', 'order', 'best_of', 'home_points', 'away_points', 'winner', 'status', 'round', 'map_id', 'reported_by', 'reported_at', 'created_at', 'updated_at'], 'integer'], | |
[['away_id'], 'exist', 'skipOnError' => true, 'targetClass' => TournamentParticipant::className(), 'targetAttribute' => ['away_id' => 'player_id']], | |
[['home_id'], 'exist', 'skipOnError' => true, 'targetClass' => TournamentParticipant::className(), 'targetAttribute' => ['home_id' => 'player_id']], | |
[['map_id'], 'exist', 'skipOnError' => true, 'targetClass' => MapPool::className(), 'targetAttribute' => ['map_id' => 'id']], | |
[['tournament_id'], 'exist', 'skipOnError' => true, 'targetClass' => Tournament::className(), 'targetAttribute' => ['tournament_id' => 'id']], | |
]; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'id' => 'ID', | |
'tournament_id' => 'Tournament ID', | |
'home_id' => 'Home ID', | |
'away_id' => 'Away ID', | |
'home_score' => 'Home Score', | |
'away_score' => 'Away Score', | |
'home_points' => 'Home Points', | |
'away_pointss' => 'Away Points', | |
'bracket' => 'Bracket', | |
'type' => 'Type', | |
'winner' => 'Winner', | |
'order' => 'Order', | |
'best_of' => 'Best of', | |
'status' => 'Status', | |
'pool' => 'Pool', | |
'round' => 'Round', | |
'map_id' => 'Map ID', | |
'reported_by' => 'Reported By', | |
'reported_at' => 'Reported At', | |
'created_at' => 'Created At', | |
'updated_at' => 'Updated At', | |
]; | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getAway() | |
{ | |
return $this->hasOne(TournamentParticipant::className(), ['player_id' => 'away_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getHome() | |
{ | |
return $this->hasOne(TournamentParticipant::className(), ['player_id' => 'home_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getMap() | |
{ | |
return $this->hasOne(MapPool::className(), ['id' => 'map_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournament() | |
{ | |
return $this->hasOne(Tournament::className(), ['id' => 'tournament_id']); | |
} | |
public static function getBrackets($tournament) { | |
$matches = TournamentMatch::find() | |
->with('tournament') | |
->where(['tournament_id' => $tournament->id]) | |
->orderBy('order ASC') | |
->all(); | |
return TournamentFactory::factory($tournament)->organizeBrackets($matches); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace frontend\models; | |
use Yii; | |
/** | |
* This is the model class for table "tournament_participant". | |
* | |
* @property integer $id | |
* @property integer $tournament_id | |
* @property integer $player_id | |
* @property integer $clan_id | |
* @property integer $status | |
* @property integer $seed | |
* @property integer $pool | |
* @property integer $created_at | |
* @property integer $updated_at | |
* | |
* @property TournamentMatch[] $tournamentMatches | |
* @property TournamentMatch[] $tournamentMatches0 | |
* @property Player $player | |
* @property Tournament $tournament | |
*/ | |
class TournamentParticipant extends \yii\db\ActiveRecord | |
{ | |
const STATUS_REGISTERED = 1; | |
const STATUS_CHECKED_IN = 2; | |
const STATUS_ELMINATED = 3; | |
const STATUS_FAILED_TO_CHECK_IN = 4; | |
/** | |
* @inheritdoc | |
*/ | |
public static function tableName() | |
{ | |
return 'tournament_participant'; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function rules() | |
{ | |
return [ | |
[['tournament_id', 'player_id', 'clan_id', 'status', 'seed', 'pool', 'created_at', 'updated_at'], 'integer'], | |
[['player_id'], 'exist', 'skipOnError' => true, 'targetClass' => Player::className(), 'targetAttribute' => ['player_id' => 'id']], | |
[['tournament_id'], 'exist', 'skipOnError' => true, 'targetClass' => Tournament::className(), 'targetAttribute' => ['tournament_id' => 'id']], | |
]; | |
} | |
/** | |
* @inheritdoc | |
*/ | |
public function attributeLabels() | |
{ | |
return [ | |
'id' => 'ID', | |
'tournament_id' => 'Tournament ID', | |
'player_id' => 'Player ID', | |
'clan_id' => 'Clan ID', | |
'status' => 'Status', | |
'seed' => 'Seed', | |
'pool' => 'Pool', | |
'created_at' => 'Created At', | |
'updated_at' => 'Updated At', | |
]; | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournamentMatches() | |
{ | |
return $this->hasMany(TournamentMatch::className(), ['away_id' => 'player_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournamentMatches0() | |
{ | |
return $this->hasMany(TournamentMatch::className(), ['home_id' => 'player_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getPlayer() | |
{ | |
return $this->hasOne(Player::className(), ['id' => 'player_id']); | |
} | |
/** | |
* @return \yii\db\ActiveQuery | |
*/ | |
public function getTournament() | |
{ | |
return $this->hasOne(Tournament::className(), ['id' => 'tournament_id']); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment