7 public function addMessage($msg) {
8 $tokens = array_values(array_filter(preg_split('/\b/', $msg->text_content)));
9 if (empty($tokens)) return;
11 foreach ($tokens as $num => $token) {
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);
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);
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]);
32 foreach ($this->two as $key => $value) {
33 $this->two[$key] = $this->index($this->two[$key]);
35 foreach ($this->three as $key => $value) {
36 $this->three[$key] = $this->index($this->three[$key]);
40 public function generate($limit = 50) {
42 $start = $this->randomStart();
45 while (strlen($generated) < $limit) {
46 $next = $this->randomNext($tokens);
47 if (empty($next)) break;
54 private function index($arr) {
58 foreach ($arr as $key => $weight) {
61 $result[] = [$key, $lower, $sum];
66 private function randomStart() {
67 return $this->pick($this->start);
70 private function randomNext($tokens) {
71 $cnt = count($tokens);
73 $cmb = $tokens[$cnt - 3].$tokens[$cnt - 2].$tokens[$cnt - 1];
74 if (isset($this->three[$cmb])) {
75 return $this->pick($this->three[$cmb]);
79 $cmb = $tokens[$cnt - 2].$tokens[$cnt - 1];
80 if (isset($this->two[$cmb])) {
81 return $this->pick($this->two[$cmb]);
85 $cmb = $tokens[$cnt - 1];
86 if (isset($this->one[$cmb])) {
87 return $this->pick($this->one[$cmb]);
93 private function pick($options) {
94 $max = end($options)[2];
95 $num = random_int(0, $max);
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;
107 $min_index = $cur_index;
111 return $options[$min_index][0];
114 private function addStart($token) {
115 if (empty($token)) return;
116 if (!isset($this->start[$token])) {
117 $this->start[$token] = 1;
119 ++$this->start[$token];
123 private function addOne($one, $token) {
124 if (!isset($this->one[$one])) {
125 $this->one[$one] = [];
127 if (!isset($this->one[$one][$token])) {
128 $this->one[$one][$token] = 1;
130 ++$this->one[$one][$token];
134 private function addTwo($one, $two, $token) {
136 if (!isset($this->two[$cmb])) {
137 $this->two[$cmb] = [];
139 if (!isset($this->two[$cmb][$token])) {
140 $this->two[$cmb][$token] = 1;
142 ++$this->two[$cmb][$token];
146 private function addThree($one, $two, $three, $token) {
147 $cmb = $one.$two.$three;
148 if (!isset($this->three[$cmb])) {
149 $this->three[$cmb] = [];
151 if (!isset($this->three[$cmb][$token])) {
152 $this->three[$cmb][$token] = 1;
154 ++$this->three[$cmb][$token];