]> git.localhorst.tv Git - alttp.git/blob - app/Models/Channel.php
8debe4f9434ab554d70eb5e16086bf875ed1875e
[alttp.git] / app / Models / Channel.php
1 <?php
2
3 namespace App\Models;
4
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;
11
12 class Channel extends Model {
13
14         use BroadcastsEvents;
15         use HasFactory;
16
17         public function broadcastOn($event) {
18                 $channels = [
19                         new PrivateChannel('Channel.'.$this->id),
20                 ];
21                 if (!empty($this->access_key)) {
22                         $channels[] = new PublicChannel('ChannelKey.'.$this->access_key);
23                 }
24                 return $channels;
25         }
26
27         public function getCurrentEpisode() {
28                 return $this->episodes()
29                         ->where('start', '<', now()->subMinutes(10))
30                         ->orderBy('start', 'DESC')
31                         ->first();
32         }
33
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();
36         }
37
38         public function hasActiveGuessing() {
39                 return !is_null($this->guessing_start);
40         }
41
42         public function isAcceptingGuesses() {
43                 return !is_null($this->guessing_start) && is_null($this->guessing_end);
44         }
45
46         public function startGuessing($type) {
47                 $this->guessing_type = $type;
48                 $this->guessing_start = now();
49                 $this->save();
50         }
51
52         public function stopGuessing() {
53                 $this->guessing_end = now();
54                 $this->save();
55         }
56
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])
62                 ) {
63                         return $default;
64                 }
65                 return $this->guessing_settings[$this->guessing_type][$name];
66         }
67
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();
72                 $unique_guesses = [];
73                 foreach ($guesses as $guess) {
74                         $unique_guesses[$guess->uid] = $guess;
75                 }
76                 $candidates = [];
77                 foreach ($unique_guesses as $guess) {
78                         if ($guess->guess == $solution) {
79                                 $candidates[] = $guess;
80                         }
81                 }
82                 if (empty($candidates) && is_numeric($solution)) {
83                         $min_distance = null;
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;
90                                         }
91                                 } else if ($distance < $min_distance) {
92                                         $candidates = [$guess];
93                                         $min_distance = $distance;
94                                 }
95                         }
96                 }
97                 $winners = [];
98                 $first = true;
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;
109                         $winner->save();
110                         $winners[] = $winner;
111                         $first = false;
112                 }
113                 return $winners;
114         }
115
116         public function clearGuessing() {
117                 $this->guessing_start = null;
118                 $this->guessing_end = null;
119                 $this->save();
120         }
121
122         public function registerGuess($uid, $uname, $guess) {
123                 $model = new GuessingGuess();
124                 $model->channel()->associate($this);
125                 $model->uid = $uid;
126                 $model->uname = $uname;
127                 $model->guess = $guess;
128                 $model->save();
129         }
130
131         public function scoreGuessing($solution, $guess, $first) {
132                 if ($guess == $solution) {
133                         if ($first) {
134                                 return $this->getGuessingSetting('points_exact_first', 1);
135                         }
136                         return $this->getGuessingSetting('points_exact_other', 1);
137                 }
138                 $distance = abs(intval($guess) - intval($solution));
139                 if ($distance <= $this->getGuessingSetting('points_close_max', 3)) {
140                         if ($first) {
141                                 return $this->getGuessingSetting('points_close_first', 1);
142                         }
143                         return $this->getGuessingSetting('points_close_other', 1);
144                 }
145                 return 0;
146         }
147
148         public function isValidGuess($solution) {
149                 if ($this->guessing_type == 'gtbk') {
150                         $int_solution = intval($solution);
151                         return $int_solution > 0 && $int_solution < 23;
152                 }
153                 return false;
154         }
155
156         public function listAnd($entries) {
157                 $lang = empty($this->languages) ? 'en' : $this->languages[0];
158                 if ($lang == 'de') {
159                         return Arr::join($entries, ', ', ' und ');
160                 }
161                 return Arr::join($entries, ', ', ' and ');
162         }
163
164         public function crews() {
165                 return $this->hasMany(ChannelCrew::class);
166         }
167
168         public function episodes() {
169                 return $this->belongsToMany(Episode::class)
170                         ->using(Restream::class)
171                         ->withPivot('accept_comms', 'accept_tracker');
172         }
173
174         public function guesses() {
175                 return $this->hasMany(GuessingGuess::class);
176         }
177
178         public function organization() {
179                 return $this->belongsTo(Organization::class);
180         }
181
182         public function winners() {
183                 return $this->hasMany(GuessingWinner::class);
184         }
185
186         protected $casts = [
187                 'chat' => 'boolean',
188                 'chat_commands' => 'array',
189                 'chat_settings' => 'array',
190                 'guessing_end' => 'datetime',
191                 'guessing_settings' => 'array',
192                 'guessing_start' => 'datetime',
193                 'languages' => 'array',
194                 'join' => 'boolean',
195         ];
196
197         protected $hidden = [
198                 'access_key',
199                 'chat',
200                 'chat_commands',
201                 'chat_settings',
202                 'created_at',
203                 'ext_id',
204                 'guessing_settings',
205                 'join',
206                 'twitch_chat',
207                 'updated_at',
208         ];
209
210 }