X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=app%2FModels%2FChatLib.php;h=c7a19b6998d7acafc09e4fefb2b708ba8087f02f;hb=1a863c3ecfa04eacf7df3c5bce71c12244e4625b;hp=c89ef941be5f4c2802eb89c92cc2be6dd7bcfd9d;hpb=64f5be008ef28c812cb7ed87149f4eb86f6021eb;p=alttp.git diff --git a/app/Models/ChatLib.php b/app/Models/ChatLib.php index c89ef94..c7a19b6 100644 --- a/app/Models/ChatLib.php +++ b/app/Models/ChatLib.php @@ -6,6 +6,20 @@ use Illuminate\Support\Facades\Storage; class ChatLib { + public function __construct($size = 6) { + $this->size = $size; + + $converted = []; + foreach ($this->categories as $category => $patterns) { + $converted_patterns = []; + foreach ($patterns as $pattern) { + $converted_patterns[] = '/\b'.$pattern.'\b/u'; + } + $converted['%'.strtoupper($category).'%'] = $converted_patterns; + } + $this->categories = $converted; + } + public function addMessage(ChatLog $msg) { $this->addText($msg->text_content); } @@ -22,19 +36,30 @@ class ChatLib { $end = $num; for ($i = $start; $i < $end; ++$i) { $this->addTransition(array_slice($tokens, $i, $end - $i), $token); - if ($end - $i < 4) break; + if ($end - $i < 5) break; } } + $this->addExample(array_slice($tokens, 0, $num), $token); } } public function compile() { - foreach ($this->transitions as $key => $value) { - $this->transitions[$key] = $this->index($this->transitions[$key]); + foreach ($this->transitions as $key => $values) { + $this->transitions[$key] = $this->index($values, 2); if (empty($this->transitions[$key])) { unset($this->transitions[$key]); } } + foreach ($this->examples as $key => $values) { + if (in_array($key, ['', ' '])) { + unset($this->examples[$key]); + continue; + } + $this->examples[$key] = $this->index($values, 1); + if (empty($this->examples[$key]) || (count($this->examples[$key]) === 1 && $this->examples[$key][0][0] === $key)) { + unset($this->examples[$key]); + } + } } public function generate($limit = 100) { @@ -53,6 +78,7 @@ class ChatLib { $data = [ 'size' => $this->size, 'transitions' => $this->transitions, + 'examples' => $this->examples, ]; Storage::disk('chatlib')->put($name.'.json', json_encode($data)); } @@ -61,29 +87,17 @@ class ChatLib { $data = json_decode(Storage::disk('chatlib')->get($name.'.json'), true); $this->size = $data['size']; $this->transitions = $data['transitions']; + $this->examples = $data['examples']; } - private function index($arr) { + private function index($arr, $min_weight = 2) { $result = []; $sum = 0; - foreach ($arr as $key => $entry) { - $weight = $entry['count']; - if ($weight == 1) continue; + foreach ($arr as $key => $weight) { + if ($weight < $min_weight) continue; $lower = $sum; $sum += $weight; - $examples = []; - if (is_array(end($entry['examples']))) { - // already processed - $examples = $entry['examples']; - } else { - $subsum = 0; - foreach ($entry['examples'] as $example => $subweight) { - $sublower = $subsum; - $subsum += $subweight; - $examples[] = [$example, $sublower, $subsum]; - } - } - $result[] = [$key, $lower, $sum, $examples]; + $result[] = [$key, $lower, $sum]; } return $result; } @@ -95,7 +109,7 @@ class ChatLib { if (isset($this->transitions[$cmb])) { $pick = $this->pick($this->transitions[$cmb]); if (!is_null($pick)) { - return $this->exampleOf($pick); + return $this->exampleOf($pick, $tokens); } } } @@ -104,14 +118,18 @@ class ChatLib { private function pick($options) { if (empty($options)) return null; - $max = end($options)[2]; + $max = end($options)[2] - 1; $num = random_int(0, $max); + return static::search($options, $num); + } + + public static function search($options, $num) { $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]; + $cur_high = $options[$cur_index][2] - 1; if ($cur_low > $num) { $max_index = $cur_index; } else if ($cur_high < $num) { @@ -125,34 +143,33 @@ class ChatLib { } private function addTransition($state, $next) { - $cmb = $this->generalize($state); - if (!isset($this->transitions[$cmb])) { - $this->transitions[$cmb] = []; + $ctx = $this->generalize($state); + $cmb = $this->generalize([$next]); + if (!isset($this->transitions[$ctx])) { + $this->transitions[$ctx] = []; + } + if (!isset($this->transitions[$ctx][$cmb])) { + $this->transitions[$ctx][$cmb] = 1; + } else { + ++$this->transitions[$ctx][$cmb]; } - $this->increment($this->transitions[$cmb], $next); } - private function increment(&$which, $token) { - $generalized = $this->generalize([$token]); - if (!isset($which[$generalized])) { - $which[$generalized] = [ - 'count' => 1, - 'examples' => [], - ]; - $which[$generalized]['examples'][$token] = 1; + private function addExample($context, $token) { + $cmb = $this->generalize([$token]); + if (!isset($this->examples[$cmb])) { + $this->examples[$cmb] = []; + } + if (!isset($this->examples[$cmb][$token])) { + $this->examples[$cmb][$token] = 1; } else { - ++$which[$generalized]['count']; - if (!isset($which[$generalized]['examples'][$token])) { - $which[$generalized]['examples'][$token] = 1; - } else { - ++$which[$generalized]['examples'][$token]; - } + ++$this->examples[$cmb][$token]; } } private function tokenize($str) { return array_values(array_filter(preg_split('/\b/u', $str), function($token) { - if (empty($token)) return false; + if ($token === '') return false; if (preg_match('/cheer\d+/u', strtolower($token))) return false; return true; })); @@ -161,19 +178,311 @@ class ChatLib { private function generalize($tokens) { $str = ''; foreach ($tokens as $token) { - $replaced = preg_replace('/\d+/', '0', $token); + $replaced = preg_replace('/\d+/u', '0', $token); + $replaced = preg_replace('/\s+/u', ' ', $replaced); + $replaced = preg_replace('/(.)\1{2,}/u', '$1$1', $replaced); $replaced = strtolower($replaced); + foreach ($this->aliases as $canonical => $variants) { + if (in_array($replaced, $variants)) { + $replaced = $canonical; + break; + } + if ($replaced === $canonical) { + break; + } + } $str .= $replaced; } + foreach ($this->categories as $category => $patterns) { + $str = preg_replace($patterns, $category, $str); + } return $str; } - private function exampleOf($pick) { - $example = $this->pick($pick[3]); - return $example[0]; + private function exampleOf($pick, $context) { + if (!isset($this->examples[$pick[0]])) { + return $pick[0]; + } + if (isset($this->examples[$pick[0]])) { + $example = $this->pick($this->examples[$pick[0]]); + return $example[0]; + } + return $pick[0]; } - private $size = 5; + private $size; private $transitions = []; + private $examples = []; + + private $aliases = [ + 'chest' => ['kiste'], + 'einen' => ['n', 'nen'], + 'musik' => ['mukke'], + 'schade' => ['schad', 'schaade'], + ]; + + private $categories = [ + 'fail' => [ + 'failfish', + 'holysm0notlikethis', + 'notlikethis', + 'tetobridge0', + 'vinter0clown', + ], + + 'hype' => [ + 'dergoaparty', + 'dinodance', + 'elemen0party', + 'muftaahype', + 'luckwuhype', + 'olliwahype', + 'osora0umbrihype', + 'partyhat', + 'peepocheer', + 'rei0hype', + 'sakayahype', + 'tetotroete', + 'ticknaboargeil0', + 'ticknahype0', + ], + + 'kappa' => [ + 'kappa(claus|hd)?', + ], + + 'jam' => [ + '(cat|dog|rat)jam', + 'kanash0jam', + 'rei0jamers', + 'samusdance', + ], + + 'lol' => [ + ':d', + 'boothi0lul', + 'kekw', + 'lol', + 'lul', + 'rei0lul', + 'samusgrin', + 'ticknaauslachen', + 'xd', + ], + + 'love' => [ + '<3', + 'duden0love', + 'exec0love', + 'krawal0heart', + 'lodanzhug', + 'luckwulove', + 'luvsign', + 'muftaal', + 'osora0love', + 'peepoexcitedhug', + 'spirit0love', + 'svenkalove', + 'ticknaherz', + ], + + 'name' => [ + 'baba', + 'baka', + 'bobe?r', + 'brog(i|or)', + 'cfate', + 'danny', + 'danzi+', + 'daruck', + 'dennsen', + 'dimez', + 'divi', + 'dud(en|i+)', + 'ele', + 'eri(ror)?', + '(name)?faker', + 'fetti+', + 'gamma(chuu)?', + 'goat(buster|ie?|y)?', + 'hitsu(yan)?', + 'holy', + 'jem', + 'kala(marino)?', + 'kromb', + 'koval', + 'kum(i|o|p)', + 'lanux', + 'len(esha|chen)', + 'leya+', + 'magno', + 'malmo', + 'markam', + 'micha', + 'mimsy', + 'muf(fy|taay)', + 'murd(elizer|i+)', + 'nami', + 'nula', + 'onio', + 'paulinche', + 'phaaze', + 'ralen', + 'ramond', + 'ray(vis)?', + 'schulzer', + 'skunk(ner)?', + 'skipsy', + 'soli+', + 'sven(ka+)?', + 'tantalus', + 'teto', + 'thalanee?', + 'tick(i+|naldo|y+)', + 'tofu', + 'tr[i0]x+', + 'vin(nie?|ny|ter)', + 'xall', + 'yasi', + ], + + 'pog' => [ + 'bumble0Pog', + 'komodohype', + 'pog', + 'pogchamp', + 'poggers', + 'satono0pog', + ], + + 'run' => [ + 'dennsenboots', + 'lodanzrun', + 'ticknaldosprint', + 'vinter0run', + ], + + 'wave' => [ + 'dennsenhi', + 'dergoawave', + 'falcnwavehi', + 'heyguys', + 'holysm0heyguys', + 'muftaahey', + 'rei0wave', + 'sayuri0wave', + 'shindi0wave', + 'svenkawave', + 'wuschlwave', + ], + + 'zb' => [ + 'aga(hnim)?', + 'armos( knights)?', + 'arrghus', + 'blind', + 'ganon(dorf)?', + 'helma', + 'kholdstare', + 'lanmo(las)?', + 'moldorm', + 'mothula', + 'mott[ei]', + 'trinexx', + 'vit(reous|ty)', + ], + + 'zd' => [ + 'eastern', + 'desert( palace)?', + 'gt', + 'hera', + 'ice ?(palace)?', + '(misery )?mire', + 'pod', + 'skull ?woods', + 'swamp', + 'thieve\'?s\'? ?town', + 'tr', + 'tt', + ], + + 'zi' => [ + '(big|small|retro|generic) ?keys?', + 'b[oö]gen', + 'bombos', + 'boots', + 'bottle', + 'bows?', + 'bugnet', + 'byrna', + 'cape', + 'ether', + 'flasche', + 'flippers', + 'fl[uö]te', + 'frod', + '(gloves?|mitts|handschuhe?)', + '(half|quarter) ?magic', + 'hammer', + 'hookshot', + '(ice|fire) ?rod', + 'lampe?', + 'laser ?bridge', + 'mearl', + 'mirror', + 'moon ?pearl', + 'mushroom', + 'ocarina', + 'pilz', + 'powder', + 'puder', + 'quake', + '(red|blue) ?cane', + '(red|green|blue) ?(goo|potion)', + '(red|green|blue|baby) ?mail', + '(red|blue|bu|boo|good|bad|both)merang', + 'schaufel', + '(gro(ss|ß)er? |kleiner? )?schlüssel', + 'schwert', + 'shovel', + 'silvers', + 'somaria', + 'spiegel', + 'sword', + ], + + 'zl' => [ + 'big chest', + 'bumper( cave)?( ledge)?', + '(hyrule)? ?castle ?(tower)?', + 'catfish', + 'cave 0?', + 'chest ?game', + 'cutscene ?chest', + 'damm', + 'desert( ledge)?', + 'dig(ging)? ?game', + '((back|front) of )?escape', + 'gyl', + 'hobo', + 'hook ?(shot) cave', + 'lava ?chest', + '(light|dark) ?world', + 'lss', + 'magic bat', + '(dark )?(death )?mountain', + 'ped(estal)?', + 'pyramid( fairy)?( ledge)?', + 'red bomb', + 'sahasrahla', + 'sasha', + 'sick kid', + 'stumpy', + 'tile ?room', + 'torch', + 'zora( ledge)?', + ], + ]; }