X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=app%2FModels%2FChannel.php;h=8af6a7d43e201e191651a4ab9b28fc7c11642ec5;hb=147c5f43c5d41fa18e82edb6651fe5a37c789353;hp=025bb34151cdd9ab56fa32b59c6f89412fd05616;hpb=e10222af705e3475fcea6e0b17d1c9984a62db26;p=alttp.git diff --git a/app/Models/Channel.php b/app/Models/Channel.php index 025bb34..8af6a7d 100644 --- a/app/Models/Channel.php +++ b/app/Models/Channel.php @@ -2,13 +2,28 @@ namespace App\Models; +use Illuminate\Broadcasting\Channel as PublicChannel; +use Illuminate\Broadcasting\PrivateChannel; +use Illuminate\Database\Eloquent\BroadcastsEvents; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Arr; -class Channel extends Model -{ +class Channel extends Model { + + use BroadcastsEvents; use HasFactory; + public function broadcastOn($event) { + $channels = [ + new PrivateChannel('Channel.'.$this->id), + ]; + if (!empty($this->access_key)) { + $channels[] = new PublicChannel('ChannelKey.'.$this->access_key); + } + return $channels; + } + public function getCurrentEpisode() { return $this->episodes() ->where('start', '<', now()->subMinutes(10)) @@ -16,6 +31,219 @@ class Channel extends Model ->first(); } + public function randomOfClass($class) { + return $this->queryChatlog() + ->where('classification', '=', $class) + ->first(); + } + + public function queryChatlog() { + return ChatLog::where('type', '=', 'chat') + ->where('banned', '=', false) + ->where('created_at', '<', now()->sub(1, 'day')) + ->where(function ($query) { + $query->whereNull('detected_language'); + $query->orWhereIn('detected_language', $this->getPreferredLanguages()); + }) + ->inRandomOrder(); + } + + public function getPreferredLanguages() { + $setting = $this->getChatSetting('language'); + if ($setting) { + return [$setting]; + } + if (!empty($this->languages)) { + return $this->languages; + } + return ['de']; + } + + public function getChatSetting($name, $default = null) { + if (array_key_exists($name, $this->chat_settings)) { + return $this->chat_settings[$name]; + } + return $default; + } + + public function getGuessingLeaderboard() { + $query = $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') + ->where('score', '!=', 0) + ->groupBy('uid') + ->orderBy('score', 'desc') + ->limit(10); + $type = $this->getGuessingSetting('leaderboard_type', 'all'); + if ($type == 'month') { + $query->where('created_at', '>=', now()->startOfMonth()); + } else if ($type == 'year') { + $query->where('created_at', '>=', now()->startOfYear()); + } else if (is_numeric($type)) { + $query->where('created_at', '>=', now()->sub($type, 'days')); + } + return $query->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; + if (is_null($min_distance)) { + $min_distance = $distance; + } + } 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 transformGuess($original) { + $transformed = trim($original); + if ($this->guessing_type == 'gtbk') { + $transformed = str_replace(['roodyo1Gtbigkey'], ['2'], $transformed); + $transformed = str_ireplace(['vier 4Head'], ['4'], $transformed); + } + return $transformed; + } + + public function registerGuess($uid, $uname, $guess) { + $model = new GuessingGuess(); + $model->channel()->associate($this); + $model->uid = $uid; + $model->uname = $uname; + $model->guess = $this->transformGuess($guess); + $model->save(); + } + + public function scoreGuessing($solution, $guess, $first) { + $transformed = $this->transformGuess($guess); + if ($transformed == $solution) { + if ($first) { + return $this->getGuessingSetting('points_exact_first', 1); + } + return $this->getGuessingSetting('points_exact_other', 1); + } + $distance = abs(intval($transformed) - 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) { + $transformed = $this->transformGuess($solution); + if ($this->guessing_type == 'gtbk') { + $int_solution = intval($transformed); + return is_numeric($transformed) && $int_solution > 0 && $int_solution < 23; + } + return false; + } + + public function listGuessingWinners($winners) { + $names = []; + $distance = 0; + foreach ($winners as $winner) { + if ($winner->score > 0) { + $names[] = $winner->uname; + $distance = abs(intval($winner->guess) - intval($winner->solution)); + } + } + $msg = ''; + if (empty($names)) { + $msg = $this->getGuessingSetting('no_winners_message'); + } else { + $msg = $this->getGuessingSetting($distance ? 'close_winners_message' : 'winners_message', $this->getGuessingSetting('winners_message')); + $msg = str_replace(['{distance}', '{names}'], [$distance, $this->listAnd($names)], $msg); + } + return $msg; + } + + public function listAnd($entries) { + $lang = empty($this->languages) ? 'en' : $this->languages[0]; + if ($lang == 'de') { + return Arr::join($entries, ', ', ' und '); + } + return Arr::join($entries, ', ', ' and '); + } + + public function chat_bot_logs() { + return $this->hasMany(ChatBotLog::class); + } + public function crews() { return $this->hasMany(ChannelCrew::class); } @@ -26,19 +254,39 @@ class Channel extends Model ->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_end' => 'datetime', + 'guessing_settings' => 'array', + 'guessing_start' => 'datetime', 'languages' => 'array', 'join' => 'boolean', ]; protected $hidden = [ + 'access_key', + 'chat', + 'chat_commands', + 'chat_settings', 'created_at', 'ext_id', + 'guessing_settings', + 'join', + 'twitch_chat', 'updated_at', ];