From 9f58535ce529a9ec77a0f5efc653d160a16c384e Mon Sep 17 00:00:00 2001 From: Kenneth Krohn Date: Tue, 17 Sep 2024 01:17:27 +0300 Subject: [PATCH] Original code upload --- FhtagnGenerator.php | 551 ++++++++++++++++++++++++++++++++++++++++++++ README.md | 13 ++ images/cthicon.ico | Bin 0 -> 1406 bytes images/cthulhu.png | Bin 0 -> 16356 bytes 4 files changed, 564 insertions(+) create mode 100644 FhtagnGenerator.php create mode 100644 images/cthicon.ico create mode 100644 images/cthulhu.png diff --git a/FhtagnGenerator.php b/FhtagnGenerator.php new file mode 100644 index 0000000..e0d606e --- /dev/null +++ b/FhtagnGenerator.php @@ -0,0 +1,551 @@ + + + Cthuvian Ipsum Generator + + + + + + +
+

Cthuvian Ipsum Generator + +

+
+ + +
+ + + + + + + + + + + +
+ +
+ + + + + + 333333) $iCount = '333333'; + if($iCount < 1) $iCount = '1'; + +?> + + + + + + + + + + + + + + + + + + +
Word count:
Format: + +
Fixed first sentence: + +Yes'; + echo 'No'; + +?> +
+
+ +
+ +
+ + + + + +A lorem ipsun generator based on H.P.Lovecraft's Cthulhu Mythos
+Code based on Mathew Tinsley's PHP Lorem Ipsum
+Wordlist from Cthuvian / English dictionary at www.yog-sothoth.com forums
+Source code at Github
. +Why lorem ipsum when you can Cthulhu fhtagn? + +
+
+ +'; +} + +function checkBool(&$iFhtagn) +{ + if($iFhtagn == 'yes') + { + $iFhtagn = true; + return true; + } + else if($iFhtagn == 'no') + { + $iFhtagn = false; + return true; + } + else + { + return false; + } +} +?> + +
+ by ephemer +
+ + + + + + + BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + private $words, $wordsPerParagraph, $wordsPerSentence, $prefix, $suffix, $start; + + function __construct($wordsPer = 100) + { + $this->wordsPerParagraph = $wordsPer; + $this->wordsPerSentence = 24.460; + $this->start = array( + 'Ph\'nglui', + 'mglw\'nafh', + 'Cthulhu', + 'R\'lyeh', + 'wgah\'nagl', + 'fhtagn.'); + + $this->words = array( + 'Cthulhu', + 'R\'lyeh', + 'Dagon', + 'Hastur', + 'Yoggoth', + 'Nyarlathotep', + 'Shub-Niggurath', + 'Tsathoggua', + 'Azathoth', + 'Chaugnar Faugn', + 'ah', + '\'ai', + 'athg', + '\'bthnk', + 'bug', + 'ch\'', + 'chtenff', + 'ebunma', + 'ee', + 'ehye', + 'ep', + '\'fhalma', + 'fhtagn', + 'fm\'latgh', + 'ftaghu', + 'geb', + 'gnaiih', + 'gof\'nn', + 'goka', + 'gotha', + 'grah\'n', + 'hafh\'drn', + 'hai', + 'hlirgh', + 'hrii', + 'hupadgh', + 'ilyaa', + 'k\'yarnak', + 'kadishtu', + 'kn\'a', + 'li\'hee', + 'llll', + 'lloig', + 'lw\'nafh', + 'mg', + 'mnahn\'', + 'n\'gha', + 'n\'ghft', + 'nglui', + 'nilgh\'ri', + 'nog', + 'nw', + 'ooboshu', + 'orr\'e', + 'phlegeth', + 'r\'luh', + 'ron', + 's\'uhn', + 'sgn\'wahl', + 'shagg', + 'shogg', + 'shtunggli', + 'shugg', + 'sll\'ha', + 'stell\'bsna', + 'syha\'h', + 'tharanak', + 'throd', + 'uaaah', + 'uh\'e', + 'uln', + 'vulgtlagln', + 'vulgtm', + 'wgah\'n', + 'y\'hah', + 'ya', + 'zhro'); + + $this->prefix = array( + 'c', + 'f\'', + 'h\'', + 'na', + 'nafl', + 'ng', + 'nnn', + 'ph\'', + 'y-'); + + $this->suffix = array( + 'agl', + 'nyth', + 'og', + 'or', + 'oth', + 'yar'); + } + + function getContent($count, $format = 'html', $fhtagn = true) + { + $format = strtolower($format); + + if($count <= 0) + return ''; + + switch($format) + { + case 'text': + return $this->getText($count, $fhtagn); + case 'plain': + return $this->getPlain($count, $fhtagn); + default: + return $this->getHTML($count, $fhtagn); + } + } + + private function getWords(&$arr, $count, $fhtagn) + { + $i = 0; + + if($fhtagn) + { + $j = 0; + for($j; $j < count($this->start); $j++) + { + $arr[$j] = $this->start[$j]; + } + $i = count($this->start); + } + + for($i; $i < $count; $i++) + { + $index = array_rand($this->words); + $word = $this->words[$index]; + + //echo $index . '=>' . $word . '
'; + + if($i > 0 && $arr[$i - 1] == $word) + $i--; + else + { + if(mt_rand(0,99) > 79) + $word = $this->prefix[array_rand($this->prefix)] . $word; + else if(mt_rand(0,99) > 89) + $word .= $this->suffix[array_rand($this->suffix)]; + + if($fhtagn && $i == count($this->start)) $word = ucfirst($word); + + $arr[$i] = $word; + } + } + } + + private function getPlain($count, $fhtagn, $returnStr = true) + { + $words = array(); + $this->getWords($words, $count, $fhtagn); + //print_r($words); + + $delta = $count; + $curr = 0; + $sentences = array(); + while($delta > 0) + { + $senSize = $this->gaussianSentence(); + //echo $curr . '
'; + if(($delta - $senSize) < 4) + $senSize = $delta; + + $delta -= $senSize; + + $sentence = array(); + for($i = $curr; $i < ($curr + $senSize); $i++) + $sentence[] = $words[$i]; + + $this->punctuate($sentence); + $curr = $curr + $senSize; + $sentences[] = $sentence; + } + + if($returnStr) + { + $output = ''; + foreach($sentences as $s) + foreach($s as $w) + $output .= $w . ' '; + + return $output; + } + else + return $sentences; + } + + private function getText($count, $fhtagn) + { + $sentences = $this->getPlain($count, $fhtagn, false); + $paragraphs = $this->getParagraphArr($sentences); + + $paragraphStr = array(); + foreach($paragraphs as $p) + { + $paragraphStr[] = $this->paragraphToString($p); + } + + $paragraphStr[0] = "\t" . $paragraphStr[0]; + return implode("\n\n\t", $paragraphStr); + } + + private function getParagraphArr($sentences) + { + $wordsPer = $this->wordsPerParagraph; + $sentenceAvg = $this->wordsPerSentence; + $total = count($sentences); + + $paragraphs = array(); + $pCount = 0; + $currCount = 0; + $curr = array(); + + for($i = 0; $i < $total; $i++) + { + $s = $sentences[$i]; + $currCount += count($s); + $curr[] = $s; + if($currCount >= ($wordsPer - round($sentenceAvg / 2.00)) || $i == $total - 1) + { + $currCount = 0; + $paragraphs[] = $curr; + $curr = array(); + //print_r($paragraphs); + } + //print_r($paragraphs); + } + + return $paragraphs; + } + + private function getHTML($count, $fhtagn) + { + $sentences = $this->getPlain($count, $fhtagn, false); + $paragraphs = $this->getParagraphArr($sentences); + //print_r($paragraphs); + + $paragraphStr = array(); + foreach($paragraphs as $p) + { + $paragraphStr[] = "

\n" . $this->paragraphToString($p, true) . '

'; + } + + //add new lines for the sake of clean code + return implode("\n", $paragraphStr); + } + + private function paragraphToString($paragraph, $htmlCleanCode = false) + { + $paragraphStr = ''; + foreach($paragraph as $sentence) + { + foreach($sentence as $word) + $paragraphStr .= $word . ' '; + + if($htmlCleanCode) + $paragraphStr .= "\n"; + } + return $paragraphStr; + } + + /* + * Inserts commas and periods in the given + * word array. + */ + private function punctuate(& $sentence) + { + $count = count($sentence); + $sentence[$count - 1] = $sentence[$count - 1] . '.'; + $sentence[0] = ucfirst($sentence[0]); + + if($count < 4) + return $sentence; + + $commas = $this->numberOfCommas($count); + + for($i = 1; $i <= $commas; $i++) + { + $index = (int) round($i * $count / ($commas + 1)); + + if($index < ($count - 1) && $index > 0) + { + $sentence[$index] = $sentence[$index] . ','; + } + } + } + + /* + * Determines the number of commas for a + * sentence of the given length. Average and + * standard deviation are determined superficially + */ + private function numberOfCommas($len) + { + $avg = (float) log($len, 6); + $stdDev = (float) $avg / 6.000; + + return (int) round($this->gauss_ms($avg, $stdDev)); + } + + /* + * Returns a number on a gaussian distribution + * based on the average word length of an english + * sentence. + * Statistics Source: + * http://hearle.nahoo.net/Academic/Maths/Sentence.html + * Average: 24.46 + * Standard Deviation: 5.08 + */ + private function gaussianSentence() + { + $avg = (float) 24.460; + $stdDev = (float) 5.080; + + return (int) round($this->gauss_ms($avg, $stdDev)); + } + + /* + * The following three functions are used to + * compute numbers with a guassian distrobution + * Source: + * http://us.php.net/manual/en/function.rand.php#53784 + */ + private function gauss() + { // N(0,1) + // returns random number with normal distribution: + // mean=0 + // std dev=1 + + // auxilary vars + $x=$this->random_0_1(); + $y=$this->random_0_1(); + + // two independent variables with normal distribution N(0,1) + $u=sqrt(-2*log($x))*cos(2*pi()*$y); + $v=sqrt(-2*log($x))*sin(2*pi()*$y); + + // i will return only one, couse only one needed + return $u; + } + + private function gauss_ms($m=0.0,$s=1.0) + { + return $this->gauss()*$s+$m; + } + + private function random_0_1() + { + return (float)rand()/(float)getrandmax(); + } +} // class +?> + + + + + diff --git a/README.md b/README.md index eaf8ed1..39079fc 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,15 @@ # Cthuvian-Ipsum-Generator Cthuvian Ipsum Generator +A lorem ipsun generator based on [H.P. Lovecraft's](https://www.hplovecraft.com/) [Cthulhu Mythos](https://en.wikipedia.org/wiki/Cthulhu_Mythos) + +## History +Way back in 2010, I wanted to try out this PHP thing, and ended up doing a [page](https://ephemer.kapsi.fi/FhtagnGenerator.php) for generating lorem ipsum placeholder text in Cthuvian (also called R'lyehian), the fictional language from H.P. Lovecraft's writings. + +I used some resources which seem to no longer exist on the internet: ++ PHP Lorem Ipsum generator by Mathew Tinsley, originally found at [http://tinsology.net/scripts/php-lorem-ipsum-generator/](http://tinsology.net/scripts/php-lorem-ipsum-generator/) ++ Improved wordlist (with prefixes and suffixes) from Cthuvian / English dictionary, originally found at [http://www.yog-sothoth.com/threads/8683-The-Complete-CTHUVIAN-ENGLISH-DICTIONARY](http://www.yog-sothoth.com/threads/8683-The-Complete-CTHUVIAN-ENGLISH-DICTIONARY) + +The code is put here "as was" for historical accuracy and is outdated and horrible in many ways, but hey, it still works, as seen on the [original page](https://ephemer.kapsi.fi/FhtagnGenerator.php). Maybe I'll make a modern version of it. Probably I won't. + +## License +[MIT](https://choosealicense.com/licenses/mit/) \ No newline at end of file diff --git a/images/cthicon.ico b/images/cthicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f36a0debb7c18e0c16366ffe71124ed43590b0cc GIT binary patch literal 1406 zcmd^;TQJ;r6vw|mm)M9VHi8Xeu~-&ymlf6}6(sI9K}v)s6%j%ZjnxQhlT|j-NC*)P zv8^i6xV0OS){Ai&V+>=AX@^#6)@21tT>8*|(}(uGk3DBTzwh^)hx3~=zxe@#N=;3? zi$qmGhjJDaf3=J#2x!##&it+a@`Hne`1!Xf)HXbYPLKtNw=T|SCxIJr3|m`UAh}i` z0ebj-{x!zN#y~`eA(Jm)o}#eiHj-~z8c)R%)!^6WMJ`Bvw&7rZe5hPe2Jv}`T3WcbssRS+1kea^;Qfv#;Q_h%} zm;kxwfaT?7kaNapYion3tQcHxHw+96z<|dFxnzoZi3Ch<4(b~uAYMAuU7OgX=7k&g5X49Wi*Mv0ckQu6>Ez@jGIFzUH9rfqC>B;$R&YE%7`oo(AXQFSTUS6qL9S4> zn>J=}^ z=B#6#VrupmNTpJ!)^Kq!fCJ*8gUzi?kQ@$dJRL!VHc$>R012lkq4qn&#KQ6tv^-5f z${o?(-VRhcqWDe;vU08?AS(2qfAK$aM8BG;&ah(aO{+9dW7PU`i{8KG>a3aZ@wsPq zhfU+uj+}nF+xEcjU99I_g%>|N@AdHIHN(fLE>7(qsHCKuy)-Dzec)jIo$>Six;`g_ zm-f8iryV+Z^F&oux&uAkQ!C9}EKoD~qOIloI*##m8;0OTli%GRlM-7h{44an{yeUx z>C6v3+VKZ3NM41}qyhDgZWb<|iW1qPZVeIrqliz!pM)qM*V8c0KYFD^<58^px4a;e z;1BQ60Ne+mg-|4BY01ISv4xV!8@-bvt0UBfk4c?f9xzQ ipY1D7HoB)2#N{^gbp)-E-`sA>D!uQ=ztQ|(pZiZH8*+jG literal 0 HcmV?d00001 diff --git a/images/cthulhu.png b/images/cthulhu.png new file mode 100644 index 0000000000000000000000000000000000000000..b070e3ba4173411e528d48a637cfd6242cebbc9c GIT binary patch literal 16356 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 mkw)vQnB7DfA#y<|^#1~*T@JNL0aKs=0000