]> git.localhorst.tv Git - alttp.git/blob - app/Models/Channel.php
guessing game settings
[alttp.git] / app / Models / Channel.php
1 <?php
2
3 namespace App\Models;
4
5 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 use Illuminate\Database\Eloquent\Model;
7
8 class Channel extends Model
9 {
10         use HasFactory;
11
12         public function getCurrentEpisode() {
13                 return $this->episodes()
14                         ->where('start', '<', now()->subMinutes(10))
15                         ->orderBy('start', 'DESC')
16                         ->first();
17         }
18
19         public function hasActiveGuessing() {
20                 return !is_null($this->guessing_start);
21         }
22
23         public function isAcceptingGuesses() {
24                 return !is_null($this->guessing_start) && is_null($this->guessing_end);
25         }
26
27         public function startGuessing($type) {
28                 $this->guessing_type = $type;
29                 $this->guessing_start = now();
30                 $this->save();
31         }
32
33         public function stopGuessing() {
34                 $this->guessing_end = now();
35                 $this->save();
36         }
37
38         public function getGuessingSetting($name, $default = null) {
39                 if (empty($this->guessing_settings) ||
40                         empty($this->guessing_type) ||
41                         !array_key_exists($this->guessing_type, $this->guessing_settings) ||
42                         !array_key_exists($name, $this->guessing_settings[$this->guessing_type])
43                 ) {
44                         return $default;
45                 }
46                 return $this->guessing_settings[$this->guessing_type][$name];
47         }
48
49         public function solveGuessing($solution) {
50                 $start = $this->guessing_start;
51                 $end = is_null($this->guessing_end) ? now() : $this->guessing_end;
52                 $guesses = $this->guesses()->whereBetween('created_at', [$start, $end])->orderBy('created_at', 'ASC')->get();
53                 $unique_guesses = [];
54                 foreach ($guesses as $guess) {
55                         $unique_guesses[$guess->uid] = $guess;
56                 }
57                 $candidates = [];
58                 foreach ($unique_guesses as $guess) {
59                         if ($guess->guess == $solution) {
60                                 $candidates[] = $guess;
61                         }
62                 }
63                 if (empty($candidates) && is_numeric($solution)) {
64                         $min_distance = null;
65                         foreach ($unique_guesses as $guess) {
66                                 $distance = abs(intval($guess->guess) - intval($solution));
67                                 if (is_null($min_distance) || $distance == $min_distance) {
68                                         $candidates[] = $guess;
69                                 } else if ($distance < $min_distance) {
70                                         $candidates = [$guess];
71                                         $min_distance = $distance;
72                                 }
73                         }
74                 }
75                 $winners = [];
76                 $first = true;
77                 foreach ($candidates as $candidate) {
78                         $score = $this->scoreGuessing($solution, $candidate->guess, $first);
79                         $winner = new GuessingWinner();
80                         $winner->channel()->associate($this);
81                         $winner->pod = $start;
82                         $winner->uid = $candidate->uid;
83                         $winner->uname = $candidate->uname;
84                         $winner->guess = $candidate->guess;
85                         $winner->solution = $solution;
86                         $winner->score = $score;
87                         $winner->save();
88                         $winners[] = $winner;
89                         $first = false;
90                 }
91                 return $winners;
92         }
93
94         public function clearGuessing() {
95                 $this->guessing_start = null;
96                 $this->guessing_end = null;
97                 $this->save();
98         }
99
100         public function registerGuess($uid, $uname, $guess) {
101                 $model = new GuessingGuess();
102                 $model->channel()->associate($this);
103                 $model->uid = $uid;
104                 $model->uname = $uname;
105                 $model->guess = $guess;
106                 $model->save();
107         }
108
109         public function scoreGuessing($solution, $guess, $first) {
110                 if ($guess == $solution) {
111                         if ($first) {
112                                 return $this->getGuessingSetting('points_exact_first', 1);
113                         }
114                         return $this->getGuessingSetting('points_exact_other', 1);
115                 }
116                 $distance = abs(intval($guess) - intval($solution));
117                 if ($distance <= $this->getGuessingSetting('points_close_max', 3)) {
118                         if ($first) {
119                                 return $this->getGuessingSetting('points_close_first', 1);
120                         }
121                         return $this->getGuessingSetting('points_close_other', 1);
122                 }
123                 return 0;
124         }
125
126         public function isValidGuess($solution) {
127                 if ($this->guessing_type == 'gtbk') {
128                         $int_solution = intval($solution);
129                         return $int_solution > 0 && $int_solution < 23;
130                 }
131                 return false;
132         }
133
134         public function crews() {
135                 return $this->hasMany(ChannelCrew::class);
136         }
137
138         public function episodes() {
139                 return $this->belongsToMany(Episode::class)
140                         ->using(Restream::class)
141                         ->withPivot('accept_comms', 'accept_tracker');
142         }
143
144         public function guesses() {
145                 return $this->hasMany(GuessingGuess::class);
146         }
147
148         public function organization() {
149                 return $this->belongsTo(Organization::class);
150         }
151
152         protected $casts = [
153                 'chat' => 'boolean',
154                 'chat_commands' => 'array',
155                 'chat_settings' => 'array',
156                 'guessing_settings' => 'array',
157                 'guessing_start' => 'datetime',
158                 'guessing_end' => 'datetime',
159                 'languages' => 'array',
160                 'join' => 'boolean',
161         ];
162
163         protected $hidden = [
164                 'created_at',
165                 'ext_id',
166                 'updated_at',
167         ];
168
169 }