episodes() ->where('start', '<', now()->subMinutes(10)) ->orderBy('start', 'DESC') ->first(); } public function getGuessingLeaderboard() { return $this->winners()->selectRaw('(select t2.uname from guessing_winners t2 where t2.uid = guessing_winners.uid order by created_at desc limit 1) as name, sum(score) as score')->groupBy('uid')->orderBy('score', 'desc')->limit(10)->get(); } public function hasActiveGuessing() { return !is_null($this->guessing_start); } public function isAcceptingGuesses() { return !is_null($this->guessing_start) && is_null($this->guessing_end); } public function startGuessing($type) { $this->guessing_type = $type; $this->guessing_start = now(); $this->save(); } public function stopGuessing() { $this->guessing_end = now(); $this->save(); } public function getGuessingSetting($name, $default = null) { if (empty($this->guessing_settings) || empty($this->guessing_type) || !array_key_exists($this->guessing_type, $this->guessing_settings) || !array_key_exists($name, $this->guessing_settings[$this->guessing_type]) ) { return $default; } return $this->guessing_settings[$this->guessing_type][$name]; } public function solveGuessing($solution) { $start = $this->guessing_start; $end = is_null($this->guessing_end) ? now() : $this->guessing_end; $guesses = $this->guesses()->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'ASC')->get(); $unique_guesses = []; foreach ($guesses as $guess) { $unique_guesses[$guess->uid] = $guess; } $candidates = []; foreach ($unique_guesses as $guess) { if ($guess->guess == $solution) { $candidates[] = $guess; } } if (empty($candidates) && is_numeric($solution)) { $min_distance = null; foreach ($unique_guesses as $guess) { $distance = abs(intval($guess->guess) - intval($solution)); if (is_null($min_distance) || $distance == $min_distance) { $candidates[] = $guess; } else if ($distance < $min_distance) { $candidates = [$guess]; $min_distance = $distance; } } } $winners = []; $first = true; foreach ($candidates as $candidate) { $score = $this->scoreGuessing($solution, $candidate->guess, $first); $winner = new GuessingWinner(); $winner->channel()->associate($this); $winner->pod = $start; $winner->uid = $candidate->uid; $winner->uname = $candidate->uname; $winner->guess = $candidate->guess; $winner->solution = $solution; $winner->score = $score; $winner->save(); $winners[] = $winner; $first = false; } return $winners; } public function clearGuessing() { $this->guessing_start = null; $this->guessing_end = null; $this->save(); } public function registerGuess($uid, $uname, $guess) { $model = new GuessingGuess(); $model->channel()->associate($this); $model->uid = $uid; $model->uname = $uname; $model->guess = $guess; $model->save(); } public function scoreGuessing($solution, $guess, $first) { if ($guess == $solution) { if ($first) { return $this->getGuessingSetting('points_exact_first', 1); } return $this->getGuessingSetting('points_exact_other', 1); } $distance = abs(intval($guess) - intval($solution)); if ($distance <= $this->getGuessingSetting('points_close_max', 3)) { if ($first) { return $this->getGuessingSetting('points_close_first', 1); } return $this->getGuessingSetting('points_close_other', 1); } return 0; } public function isValidGuess($solution) { if ($this->guessing_type == 'gtbk') { $int_solution = intval($solution); return $int_solution > 0 && $int_solution < 23; } return false; } public function crews() { return $this->hasMany(ChannelCrew::class); } public function episodes() { return $this->belongsToMany(Episode::class) ->using(Restream::class) ->withPivot('accept_comms', 'accept_tracker'); } public function guesses() { return $this->hasMany(GuessingGuess::class); } public function organization() { return $this->belongsTo(Organization::class); } public function winners() { return $this->hasMany(GuessingWinner::class); } protected $casts = [ 'chat' => 'boolean', 'chat_commands' => 'array', 'chat_settings' => 'array', 'guessing_settings' => 'array', 'guessing_start' => 'datetime', 'guessing_end' => 'datetime', 'languages' => 'array', 'join' => 'boolean', ]; protected $hidden = [ 'created_at', 'ext_id', 'updated_at', ]; }