5 use Illuminate\Broadcasting\Channel as PublicChannel;
6 use Illuminate\Broadcasting\PrivateChannel;
7 use Illuminate\Database\Eloquent\BroadcastsEvents;
8 use Illuminate\Database\Eloquent\Factories\HasFactory;
9 use Illuminate\Database\Eloquent\Model;
10 use Illuminate\Support\Arr;
12 class Channel extends Model {
17 public function broadcastOn($event) {
19 new PrivateChannel('Channel.'.$this->id),
21 if (!empty($this->access_key)) {
22 $channels[] = new PublicChannel('ChannelKey.'.$this->access_key);
27 public function getCurrentEpisode() {
28 return $this->episodes()
29 ->where('start', '<', now()->subMinutes(10))
30 ->orderBy('start', 'DESC')
34 public function getGuessingLeaderboard() {
35 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();
38 public function hasActiveGuessing() {
39 return !is_null($this->guessing_start);
42 public function isAcceptingGuesses() {
43 return !is_null($this->guessing_start) && is_null($this->guessing_end);
46 public function startGuessing($type) {
47 $this->guessing_type = $type;
48 $this->guessing_start = now();
52 public function stopGuessing() {
53 $this->guessing_end = now();
57 public function getGuessingSetting($name, $default = null) {
58 if (empty($this->guessing_settings) ||
59 empty($this->guessing_type) ||
60 !array_key_exists($this->guessing_type, $this->guessing_settings) ||
61 !array_key_exists($name, $this->guessing_settings[$this->guessing_type])
65 return $this->guessing_settings[$this->guessing_type][$name];
68 public function solveGuessing($solution) {
69 $start = $this->guessing_start;
70 $end = is_null($this->guessing_end) ? now() : $this->guessing_end;
71 $guesses = $this->guesses()->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'ASC')->get();
73 foreach ($guesses as $guess) {
74 $unique_guesses[$guess->uid] = $guess;
77 foreach ($unique_guesses as $guess) {
78 if ($guess->guess == $solution) {
79 $candidates[] = $guess;
82 if (empty($candidates) && is_numeric($solution)) {
84 foreach ($unique_guesses as $guess) {
85 $distance = abs(intval($guess->guess) - intval($solution));
86 if (is_null($min_distance) || $distance == $min_distance) {
87 $candidates[] = $guess;
88 if (is_null($min_distance)) {
89 $min_distance = $distance;
91 } else if ($distance < $min_distance) {
92 $candidates = [$guess];
93 $min_distance = $distance;
99 foreach ($candidates as $candidate) {
100 $score = $this->scoreGuessing($solution, $candidate->guess, $first);
101 $winner = new GuessingWinner();
102 $winner->channel()->associate($this);
103 $winner->pod = $start;
104 $winner->uid = $candidate->uid;
105 $winner->uname = $candidate->uname;
106 $winner->guess = $candidate->guess;
107 $winner->solution = $solution;
108 $winner->score = $score;
110 $winners[] = $winner;
116 public function clearGuessing() {
117 $this->guessing_start = null;
118 $this->guessing_end = null;
122 public function registerGuess($uid, $uname, $guess) {
123 $model = new GuessingGuess();
124 $model->channel()->associate($this);
126 $model->uname = $uname;
127 $model->guess = $guess;
131 public function scoreGuessing($solution, $guess, $first) {
132 if ($guess == $solution) {
134 return $this->getGuessingSetting('points_exact_first', 1);
136 return $this->getGuessingSetting('points_exact_other', 1);
138 $distance = abs(intval($guess) - intval($solution));
139 if ($distance <= $this->getGuessingSetting('points_close_max', 3)) {
141 return $this->getGuessingSetting('points_close_first', 1);
143 return $this->getGuessingSetting('points_close_other', 1);
148 public function isValidGuess($solution) {
149 if ($this->guessing_type == 'gtbk') {
150 $int_solution = intval($solution);
151 return $int_solution > 0 && $int_solution < 23;
156 public function listAnd($entries) {
157 $lang = empty($this->languages) ? 'en' : $this->languages[0];
159 return Arr::join($entries, ', ', ' und ');
161 return Arr::join($entries, ', ', ' and ');
164 public function crews() {
165 return $this->hasMany(ChannelCrew::class);
168 public function episodes() {
169 return $this->belongsToMany(Episode::class)
170 ->using(Restream::class)
171 ->withPivot('accept_comms', 'accept_tracker');
174 public function guesses() {
175 return $this->hasMany(GuessingGuess::class);
178 public function organization() {
179 return $this->belongsTo(Organization::class);
182 public function winners() {
183 return $this->hasMany(GuessingWinner::class);
188 'chat_commands' => 'array',
189 'chat_settings' => 'array',
190 'guessing_end' => 'datetime',
191 'guessing_settings' => 'array',
192 'guessing_start' => 'datetime',
193 'languages' => 'array',
197 protected $hidden = [