]> git.localhorst.tv Git - alttp.git/blobdiff - app/Models/ChatLib.php
chat adlib prototype
[alttp.git] / app / Models / ChatLib.php
diff --git a/app/Models/ChatLib.php b/app/Models/ChatLib.php
new file mode 100644 (file)
index 0000000..d6d4f56
--- /dev/null
@@ -0,0 +1,163 @@
+<?php
+
+namespace App\Models;
+
+class ChatLib {
+
+       public function addMessage($msg) {
+               $tokens = array_values(array_filter(preg_split('/\b/', $msg->text_content)));
+               if (empty($tokens)) return;
+               $tokens [] = '';
+               foreach ($tokens as $num => $token) {
+                       if ($num === 0) {
+                               $this->addStart($token);
+                       } else if ($num === 1) {
+                               $this->addOne($tokens[0], $token);
+                       } else if ($num === 2) {
+                               $this->addOne($tokens[1], $token);
+                               $this->addTwo($tokens[0], $tokens[1], $token);
+                       } else {
+                               $this->addOne($tokens[$num - 1], $token);
+                               $this->addTwo($tokens[$num - 2], $tokens[$num - 1], $token);
+                               $this->addThree($tokens[$num - 3], $tokens[$num - 2], $tokens[$num - 1], $token);
+                       }
+               }
+       }
+
+       public function compile() {
+               $this->start = $this->index($this->start);
+               foreach ($this->one as $key => $value) {
+                       $this->one[$key] = $this->index($this->one[$key]);
+               }
+               foreach ($this->two as $key => $value) {
+                       $this->two[$key] = $this->index($this->two[$key]);
+               }
+               foreach ($this->three as $key => $value) {
+                       $this->three[$key] = $this->index($this->three[$key]);
+               }
+       }
+
+       public function generate($limit = 50) {
+               $tokens = [];
+               $start = $this->randomStart();
+               $tokens[] = $start;
+               $generated = $start;
+               while (strlen($generated) < $limit) {
+                       $next = $this->randomNext($tokens);
+                       if (empty($next)) break;
+                       $tokens[] = $next;
+                       $generated .= $next;
+               }
+               return $generated;
+       }
+
+       private function index($arr) {
+               $result = [];
+               $sum = 0;
+               asort($arr);
+               foreach ($arr as $key => $weight) {
+                       $lower = $sum;
+                       $sum += $weight;
+                       $result[] = [$key, $lower, $sum];
+               }
+               return $result;
+       }
+
+       private function randomStart() {
+               return $this->pick($this->start);
+       }
+
+       private function randomNext($tokens) {
+               $cnt = count($tokens);
+               if ($cnt >= 3) {
+                       $cmb = $tokens[$cnt - 3].$tokens[$cnt - 2].$tokens[$cnt - 1];
+                       if (isset($this->three[$cmb])) {
+                               return $this->pick($this->three[$cmb]);
+                       }
+               }
+               if ($cnt >= 2) {
+                       $cmb = $tokens[$cnt - 2].$tokens[$cnt - 1];
+                       if (isset($this->two[$cmb])) {
+                               return $this->pick($this->two[$cmb]);
+                       }
+               }
+               if ($cnt >= 1) {
+                       $cmb = $tokens[$cnt - 1];
+                       if (isset($this->one[$cmb])) {
+                               return $this->pick($this->one[$cmb]);
+                       }
+               }
+               return '';
+       }
+
+       private function pick($options) {
+               $max = end($options)[2];
+               $num = random_int(0, $max);
+               $min_index = 0;
+               $max_index = count($options) - 1;
+               while ($min_index < $max_index) {
+                       $cur_index = intval(($min_index + $max_index) / 2);
+                       $cur_low = $options[$cur_index][1];
+                       $cur_high = $options[$cur_index][2];
+                       if ($cur_low > $num) {
+                               $max_index = $cur_index;
+                       } else if ($cur_high < $num) {
+                               $min_index = $cur_index + 1;
+                       } else {
+                               $min_index = $cur_index;
+                               break;
+                       }
+               }
+               return $options[$min_index][0];
+       }
+
+       private function addStart($token) {
+               if (empty($token)) return;
+               if (!isset($this->start[$token])) {
+                       $this->start[$token] = 1;
+               } else {
+                       ++$this->start[$token];
+               }
+       }
+
+       private function addOne($one, $token) {
+               if (!isset($this->one[$one])) {
+                       $this->one[$one] = [];
+               }
+               if (!isset($this->one[$one][$token])) {
+                       $this->one[$one][$token] = 1;
+               } else {
+                       ++$this->one[$one][$token];
+               }
+       }
+
+       private function addTwo($one, $two, $token) {
+               $cmb = $one.$two;
+               if (!isset($this->two[$cmb])) {
+                       $this->two[$cmb] = [];
+               }
+               if (!isset($this->two[$cmb][$token])) {
+                       $this->two[$cmb][$token] = 1;
+               } else {
+                       ++$this->two[$cmb][$token];
+               }
+       }
+
+       private function addThree($one, $two, $three, $token) {
+               $cmb = $one.$two.$three;
+               if (!isset($this->three[$cmb])) {
+                       $this->three[$cmb] = [];
+               }
+               if (!isset($this->three[$cmb][$token])) {
+                       $this->three[$cmb][$token] = 1;
+               } else {
+                       ++$this->three[$cmb][$token];
+               }
+       }
+
+       private $start = [];
+       private $one = [];
+       private $two = [];
+       private $three = [];
+
+}