diff options
Diffstat (limited to '')
-rw-r--r-- | comm/suite/chatzilla/js/tests/DP.js | 612 |
1 files changed, 612 insertions, 0 deletions
diff --git a/comm/suite/chatzilla/js/tests/DP.js b/comm/suite/chatzilla/js/tests/DP.js new file mode 100644 index 0000000000..5320b38c35 --- /dev/null +++ b/comm/suite/chatzilla/js/tests/DP.js @@ -0,0 +1,612 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Dissociated Press javascript for the jsbot + * see: http://wombat.doc.ic.ac.uk/foldoc/foldoc.cgi?query=dissociated%20press + */ + +DP_DEBUG = false; + +if (DP_DEBUG) + dpprint = dd; +else + dpprint = (function () {}); + +function CDPressMachine() +{ + + this.wordPivots = new Object(); + this.cleanCounter = 0; + this.cleanCount = 0; + +} + +CDPressMachine.CLEAN_CYCLE = 1000; // list will be trimmed after this many + // or never if < 1 addPhrase()s +CDPressMachine.CLEAN_THRESHOLD = 2; // anything <= this will be trimmed +CDPressMachine.RANDOMIZE_DEPTH = 10; // not used yet +CDPressMachine.MIN_PHRASE_LENGTH = 3; // requested minimum phrase length +CDPressMachine.MAX_PHRASE_LENGTH = 8; // requested maximum phrase length +CDPressMachine.LENGTH_RETRIES = 3 // number of retries per word + // (to reach maxlen) +CDPressMachine.WORD_PATTERN = /[\x21-\x7e]+/; // pattern for words + +/** + * Adds a phrase to the engine + */ +CDPressMachine.prototype.addPhrase = +function DPM_addPhrase (strPhrase, weight) +{ + if (strPhrase == "") + return; + + this.cleanCounter++; + if ((CDPressMachine.CLEAN_CYCLE >= 1) && + (this.cleanCounter >= CDPressMachine.CLEAN_CYCLE)) + { + dpprint ("** cleaning list"); + + this.cleanCounter = 0; + this.trimList (CDPressMachine.CLEAN_THRESHOLD); + this.cleancount++; + } + + strPhrase = strPhrase.toLowerCase(); + + /* split the phrase */ + var aryWordMatches = strPhrase.split (" "); + var previousWord = aryWordMatches[aryWordMatches.length - 1]; + previousWord = previousWord.match(CDPressMachine.WORD_PATTERN); + var nextWord = ""; + + /* loop through each word */ + for (var i=-1; i < aryWordMatches.length; i++) + { + var currentWord = nextWord; + var currentWordPivot = this.wordPivots[currentWord]; + + if (typeof currentWordPivot == "undefined") + currentWordPivot = + (this.wordPivots[currentWord] = new CWordPivot (currentWord)); + + currentWordPivot.previousList.addLink (previousWord, weight); + + if (i < aryWordMatches.length - 1) + { + nextWord = aryWordMatches[i + 1]; + if (nextWord == (String.fromCharCode(1) + "action")) + nextWord = escape(nextWord.toUpperCase()); + else + nextWord = nextWord.match(CDPressMachine.WORD_PATTERN); + + if (nextWord == null) + nextWord = ""; //this is weak + + currentWordPivot.nextList.addLink (nextWord, weight); + } + else + currentWordPivot.nextList.addLink (""); + + previousWord = currentWord; + + } + +} + +CDPressMachine.prototype.addPhrases = +function DPM_addPhrases(phrases) +{ + + for (var i in phrases) + this.addPhrase (phrases[i]); + +} + +/** + * Gets a phrase from the engine, starting from seedWord. + * if dir is greater than 0, then seedWord will be the first in + * the phrase, otherwise it will be the last + */ +CDPressMachine.prototype.getPhraseDirected = +function DPM_getPhraseDirected(seedWord, dir) +{ + var word = (typeof seedWord != "undefined") ? seedWord : ""; + var tempword = word; + var rval = ""; + var c = 0, retry = 0; + + dpprint ("DPM_getPhraseDirected: '" + word + "' " + dir); + + if (typeof this.wordPivots[word] == "undefined") + return; + + do + { + if (typeof this.wordPivots[word] == "undefined") + { + dd ("** DP Error: Word '" + word + "' is not a pivot **"); + return; + } + + if (dir > 0) // pick a word + word= this.wordPivots[word].nextList.getRandomLink().link; + else + word= this.wordPivots[word].previousList.getRandomLink().link; + + if (word != "") // if it isn't blank + { + dpprint ("DPM_getPhraseDirected: got word '" + word + "'"); + + if (c < CDPressMachine.MIN_PHRASE_LENGTH) + retry = 0; + + if (c > CDPressMachine.MAX_PHRASE_LENGTH) + if (((dir > 0) && (this.wordPivots[word].nextList.list[""])) || + ((dir <= 0) && + (this.wordPivots[word].previousList.list[""]))) + { + dpprint ("DPM_getPhraseDirected: forcing last word"); + word=""; + rval = rval.substring (0, rval.length - 1); + break; + } + + if (dir > 0) + rval += word + " "; // put it in the rslt + else + rval = word + " " + rval; + + c++; // count the word + } + else // otherwise + { + dpprint ("DPM_getPhraseDirected: last word"); + // if it's too short + // and were not out of retrys + if ((c < CDPressMachine.MIN_PHRASE_LENGTH) && + (retry++ < CDPressMachine.LENGTH_RETRIES)) + word = tempword; // try again + else + // otherwise, we're done + rval = rval.substring (0, rval.length - 1); + } + + tempword = word; + + } while (word != ""); + + rval = unescape (rval); + + return rval; + +} + +CDPressMachine.prototype.getPhraseForward = +function DPM_getPhraseForward(firstWord) +{ + return this.getPhraseDirected (firstWord, 1) +} + +CDPressMachine.prototype.getPhraseReverse = +function DPM_getPhraseReverse(lastWord) +{ + return this.getPhraseDirected (lastWord, -1) +} + +/** + * locates a random pivot by following CDPressMachine.RANDOMIZE_DEPTH + * links from |word|. + */ +CDPressMachine.prototype.getRandomPivot = +function DPM_getRandomPivot (word) +{ + + /** + * XXXrgg: erm, this is currently pointless, but could be neat later + * if max phrase length's were implemented. + */ + if (false) + { + var depth = parseInt (Math.round + (CDPressMachine.RANDOMIZE_DEPTH * Math.random())); + word = ""; + for (var i = 0; + i < depth, word = + this.wordPivots[word].nextList.getRandomLink().link; + i++); /* empty loop */ + + } + +} + +CDPressMachine.prototype.getPhrase = +function DPM_getPhrase(word) +{ + var rval = this.getPhraseContaining (word); + + return rval; + +} + +/** + * Returns a phrase with |word| somewhere in it. + */ +CDPressMachine.prototype.getPhraseContaining = +function DPM_getPhraseContaining(word) +{ + if (typeof word == "undefined") + word = ""; + else + word = word.toString(); + + dpprint ("* DPM_getPhraseContaining: '" + word + "'"); + + var rval, spc; + var post, pre = this.getPhraseReverse (word); + if (word != "") + var post = this.getPhraseForward (word); + + dpprint ("* DPM_getPhraseContaining: pre = '" + pre + "' post = '" + + post + "'"); + dpprint ("* DPM_getPhraseContaining: " + (post == "" && pre == "")); + + if (word) + { + word = unescape (word); + spc = " "; + } + else + spc = ""; + + if (pre) + { + if (post) + rval = pre + spc + word + spc + post; + else + rval = pre + spc + word; + } + else + { + if (post) + rval = word + spc + post; + else + if (post == "" && pre == "") + rval = word; + } + + if (rval && (rval.charCodeAt(0) == 1)) + rval += String.fromCharCode(1); + + dpprint ("* DPM_getPhraseContaining: returning '" + rval + "'"); + + return rval; + +} + +CDPressMachine.prototype.getPhraseWeight = +function DPM_getPhraseWeight (phrase) +{ + var ary = this.getPhraseWeights (phrase); + var w = 0; + + while (ary.length > 0) + w += ary.pop(); + + return w; +} + +CDPressMachine.prototype.getPhraseWeights = +function DPM_getPhraseWeights (phrase) +{ + var words, ary = new Array(); + var lastword = ""; + var link, pivot; + + if (!phrase) + return ary; + + words = phrase.split (" "); + + for (var i = 0; i < words.length; i++) + { + + if (i == 0) + { + lastWord = ""; + nextWord = words[i + 1]; + } + else if (i == words.length - 1) + { + lastWord = words[i - 1]; + nextWord = ""; + } + else + { + lastWord = words[i - 1]; + nextWord = words[i + 1]; + } + + pivot = this.wordPivots[words[i]]; + + if (pivot) + { + link = pivot.previousList.list[lastWord]; + + if (link) + ary.push(link.weight); + else + ary.push(0); + + link = pivot.nextList.list[nextWord]; + + if (link) + ary.push(link.weight); + else + ary.push(0); + } + else + { + ary.push(0); + ary.push(0); + } + + } + + return ary; + +} + +CDPressMachine.prototype.getPivot = +function DPM_getPivot(word) +{ + + return this.wordPivots[word]; + +} + +CDPressMachine.prototype.trimList = +function DPM_trimList(threshold) +{ + var el; + var c; + + for (el in this.wordPivots) + { + c = this.wordPivots[el].nextList.trimList (threshold); + if (c == 0) + delete this.wordPivots[el]; + else + { + c = this.wordPivots[el].previousList.trimList (threshold); + if (c == 0) + delete this.wordPivots[el]; + } + + } + +} + +CDPressMachine.prototype.getMachineStatus = +function DPM_getMachineStatus() +{ + var o = new Object(); + + o.pivotcount = 0; + o.linkcount = 0; + o.linksperpivot = 0; + o.maxweight = 0; + o.minweight = Number.MAX_VALUE; + o.averageweight = 0; + o.cleancounter = this.cleanCounter; + o.cleancount = this.cleanCount; + + for (var pivot in this.wordPivots) + { + o.pivotcount++; + + for (var link in this.wordPivots[pivot].previousList.list) + { + var l = this.wordPivots[pivot].previousList.list[link]; + + o.linkcount++; + + o.maxweight = Math.max (o.maxweight, l.weight); + o.minweight = Math.min (o.minweight, l.weight); + + (o.averageweight == 0) ? + o.averageweight = l.weight : + o.averageweight = (l.weight + o.averageweight) / 2; + + } + } + + o.linksperpivot = o.linkcount / o.pivotcount; + + return o; + +} + +//////////////////////// +function CWordPivot (word) +{ + + dpprint ("* new pivot : '" + word + "'"); + this.word = word; + this.nextList = new CPhraseLinkList(word, "next"); + this.previousList = new CPhraseLinkList(word, "previous"); + +} + +/////////////////////// + +function CPhraseLinkList (parentWord, listID) +{ + + if (DP_DEBUG) + { + this.parentWord = parentWord; + this.listID = listID; + } + + this.list = new Object(); + +} + +CPhraseLinkList.prototype.addLink = +function PLL_addLink (link, weight) +{ + var existingLink = this.list[link]; + + dpprint ("* adding link to '" + link + "' from '" + this.parentWord + + "' in list '" + this.listID + "'"); + + if (typeof weight == "undefined") + weight = 1; + + if (typeof existingLink == "undefined") + this.list[link] = new CPhraseLink (link, weight); + else + if (!(typeof existingLink.adjust == "function")) + dd("existingLink.adjust is a '" + existingLink.adjust + "' " + + "not a function! link is '" + link +"'"); + else + existingLink.adjust (weight); + +} + +CPhraseLinkList.prototype.getRandomLink = +function PLL_getRandomLink () +{ + var tot = 0; + var lastMatch = ""; + var aryChoices = new Array(); + var fDone = false; + + dpprint ("* PLL_getRandomLink: from '" + this.parentWord + "'"); + + for (el in this.list) + { + tot += this.list[el].weight; + + for (var i = 0; i< aryChoices.length; i++) + if (this.list[el].weight <= aryChoices[i].weight) + break; + + arrayInsertAt (aryChoices, i, this.list[el]); + } + + if (DP_DEBUG) + for (var i = 0; i < aryChoices.length; i++) + dpprint ("** potential word '" + aryChoices[i].link + "', weight " + + aryChoices[i].weight); + + var choice = parseInt (Math.round(((tot - 1) * Math.random()) + 1)); + + dpprint ("* PLL_getRandomLink: tot = " + tot + ", choice = " + choice); + + tot = 0; + for (i = 0; i < aryChoices.length; i++) + { + if ((tot += aryChoices[i].weight) >= choice) + { + lastMatch = aryChoices[i]; + break; + } + } + + if (lastMatch == "") + lastMatch = aryChoices[aryChoices.length - 1]; + + if (!lastMatch) + lastMatch = {link: ""} + + dpprint ("* PLL_getRandomLink: returning: " + lastMatch); + + return lastMatch; + +} + +CPhraseLinkList.prototype.getListWeights = +function PLL_getListWeights () +{ + var ary = new Array(); + + for (var el in this.list) + ary.push (this.list[el].weight); + + return ary; + +} + +CPhraseLinkList.prototype.getListLinks = +function PLL_getListLinks () +{ + var ary = new Array(); + + for (var el in this.list) + ary.push (this.list[el].link); + + return ary; + +} + +CPhraseLinkList.prototype.trimList = +function PLL_trimList (threshold) +{ + var el; + var c; + + dpprint ("trimming '" + this.parentWord + "'s list to " + threshold); + + for (el in this.list) + { + c++; + + if (this.list[el].weight <= threshold) + { + dpprint ("removing '" + el + "' from '" + this.parentWord + "'s '" + + this.listID + "' list, because it's weight is " + + this.list[el].weight); + + delete this.list[el]; + c--; + } + } + + return c; + +} + +//////////////////////// + +function CPhraseLink (link, weight) +{ + if (typeof weight == "undefined") + this.weight = 1; + else + this.weight = weight; + + this.link = link; + +} + +CPhraseLink.prototype.adjust = +function PL_adjust(weight) +{ + + if ((this.weight += weight) < 1) + this.weight = 1; + +} + +CPhraseLink.prototype.weight = +function PL_weight () +{ + + return this.weight; + +} |