]> git.localhorst.tv Git - alttp.git/blob - app/Models/ChatLib.php
d6d4f56e71bc57ffef6d545cc8f2913402070fa2
[alttp.git] / app / Models / ChatLib.php
1 <?php
2
3 namespace App\Models;
4
5 class ChatLib {
6
7         public function addMessage($msg) {
8                 $tokens = array_values(array_filter(preg_split('/\b/', $msg->text_content)));
9                 if (empty($tokens)) return;
10                 $tokens [] = '';
11                 foreach ($tokens as $num => $token) {
12                         if ($num === 0) {
13                                 $this->addStart($token);
14                         } else if ($num === 1) {
15                                 $this->addOne($tokens[0], $token);
16                         } else if ($num === 2) {
17                                 $this->addOne($tokens[1], $token);
18                                 $this->addTwo($tokens[0], $tokens[1], $token);
19                         } else {
20                                 $this->addOne($tokens[$num - 1], $token);
21                                 $this->addTwo($tokens[$num - 2], $tokens[$num - 1], $token);
22                                 $this->addThree($tokens[$num - 3], $tokens[$num - 2], $tokens[$num - 1], $token);
23                         }
24                 }
25         }
26
27         public function compile() {
28                 $this->start = $this->index($this->start);
29                 foreach ($this->one as $key => $value) {
30                         $this->one[$key] = $this->index($this->one[$key]);
31                 }
32                 foreach ($this->two as $key => $value) {
33                         $this->two[$key] = $this->index($this->two[$key]);
34                 }
35                 foreach ($this->three as $key => $value) {
36                         $this->three[$key] = $this->index($this->three[$key]);
37                 }
38         }
39
40         public function generate($limit = 50) {
41                 $tokens = [];
42                 $start = $this->randomStart();
43                 $tokens[] = $start;
44                 $generated = $start;
45                 while (strlen($generated) < $limit) {
46                         $next = $this->randomNext($tokens);
47                         if (empty($next)) break;
48                         $tokens[] = $next;
49                         $generated .= $next;
50                 }
51                 return $generated;
52         }
53
54         private function index($arr) {
55                 $result = [];
56                 $sum = 0;
57                 asort($arr);
58                 foreach ($arr as $key => $weight) {
59                         $lower = $sum;
60                         $sum += $weight;
61                         $result[] = [$key, $lower, $sum];
62                 }
63                 return $result;
64         }
65
66         private function randomStart() {
67                 return $this->pick($this->start);
68         }
69
70         private function randomNext($tokens) {
71                 $cnt = count($tokens);
72                 if ($cnt >= 3) {
73                         $cmb = $tokens[$cnt - 3].$tokens[$cnt - 2].$tokens[$cnt - 1];
74                         if (isset($this->three[$cmb])) {
75                                 return $this->pick($this->three[$cmb]);
76                         }
77                 }
78                 if ($cnt >= 2) {
79                         $cmb = $tokens[$cnt - 2].$tokens[$cnt - 1];
80                         if (isset($this->two[$cmb])) {
81                                 return $this->pick($this->two[$cmb]);
82                         }
83                 }
84                 if ($cnt >= 1) {
85                         $cmb = $tokens[$cnt - 1];
86                         if (isset($this->one[$cmb])) {
87                                 return $this->pick($this->one[$cmb]);
88                         }
89                 }
90                 return '';
91         }
92
93         private function pick($options) {
94                 $max = end($options)[2];
95                 $num = random_int(0, $max);
96                 $min_index = 0;
97                 $max_index = count($options) - 1;
98                 while ($min_index < $max_index) {
99                         $cur_index = intval(($min_index + $max_index) / 2);
100                         $cur_low = $options[$cur_index][1];
101                         $cur_high = $options[$cur_index][2];
102                         if ($cur_low > $num) {
103                                 $max_index = $cur_index;
104                         } else if ($cur_high < $num) {
105                                 $min_index = $cur_index + 1;
106                         } else {
107                                 $min_index = $cur_index;
108                                 break;
109                         }
110                 }
111                 return $options[$min_index][0];
112         }
113
114         private function addStart($token) {
115                 if (empty($token)) return;
116                 if (!isset($this->start[$token])) {
117                         $this->start[$token] = 1;
118                 } else {
119                         ++$this->start[$token];
120                 }
121         }
122
123         private function addOne($one, $token) {
124                 if (!isset($this->one[$one])) {
125                         $this->one[$one] = [];
126                 }
127                 if (!isset($this->one[$one][$token])) {
128                         $this->one[$one][$token] = 1;
129                 } else {
130                         ++$this->one[$one][$token];
131                 }
132         }
133
134         private function addTwo($one, $two, $token) {
135                 $cmb = $one.$two;
136                 if (!isset($this->two[$cmb])) {
137                         $this->two[$cmb] = [];
138                 }
139                 if (!isset($this->two[$cmb][$token])) {
140                         $this->two[$cmb][$token] = 1;
141                 } else {
142                         ++$this->two[$cmb][$token];
143                 }
144         }
145
146         private function addThree($one, $two, $three, $token) {
147                 $cmb = $one.$two.$three;
148                 if (!isset($this->three[$cmb])) {
149                         $this->three[$cmb] = [];
150                 }
151                 if (!isset($this->three[$cmb][$token])) {
152                         $this->three[$cmb][$token] = 1;
153                 } else {
154                         ++$this->three[$cmb][$token];
155                 }
156         }
157
158         private $start = [];
159         private $one = [];
160         private $two = [];
161         private $three = [];
162
163 }