/ AI.js
AI.js
  1  (function(g,Ai) {
  2  	if (typeof module!="undefined") {
  3  		module.exports=Ai;
  4  	}else{
  5  		g.Ai=Ai;
  6  	}
  7  })(this,(function() {
  8  	function randomString(len, an){//comes from http://stackoverflow.com/a/27872144
  9  		an = an&&an.toLowerCase();
 10  		var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62;
 11  		for(;i++<Math.ceil(len);){//the "Math.ceil(len)" part used to be just "len"
 12  			var r = Math.random()*(max-min)+min <<0,
 13  			n = String.fromCharCode(r+=r>9?r<36?55:61:48);
 14  			if (Math.random()*100<=18) {
 15  				n=" ";
 16  			}
 17  			str+=n;
 18  		}
 19  		return str;
 20  	}
 21  	function lint(str){
 22  		var bestBefore="",bestBeforeVal=0,len=0,index=0,index2=0,part="",newPart="",newPartVal=0,qWord;
 23  		for(len=str.length;len>=3;len--){//each possable length of part>=3
 24  			//find bad parts
 25  			bestBefore=newPart=randomString(len,"an");//alfa-numeric string with length of len
 26  			for(index=0; index<(str.length-len); index++) {
 27  				part=str.substr(index,len);
 28  				if(typeof this.words[len]==="undefined"){
 29  					this.words[len]={};
 30  				}
 31  				if(typeof this.context[len]==="undefined"){
 32  					this.context[len]={};
 33  				}
 34  				if(typeof this.words[len][part]==="undefined"){
 35  					this.words[len][part]=0;
 36  				}
 37  				if(typeof this.context[len][part]==="undefined"){
 38  					this.context[len][part]={
 39  						before:[str.substr(0,index)],
 40  						after:[str.slice(index+len)],
 41  					};
 42  				}
 43  				if(this.words[len][part]<0){//if part is bad
 44  					//replace bad parts with alternative if any. Otherwise replace them with a random string
 45  					for(index2 in this.context[len][part].before){//all before parts
 46  						qWord=this.context[len][part].before[index2];
 47  						if(qWord.length<1){
 48  							qWord=randomString(3,"an");
 49  						}
 50  						if(typeof this.words[qWord.length]==="undefined"){
 51  							this.words[qWord.length]={};
 52  						}
 53  						if(typeof this.words[qWord.length][part]==="undefined"){
 54  							this.words[qWord.length][qWord]=0;
 55  						}
 56  						if(this.words[qWord.length][qWord]>=bestBeforeVal){//if this "question word" is the best
 57  							bestBeforeVal=this.words[qWord.length][qWord];
 58  							bestBefore=qWord;
 59  						}
 60  					}
 61  					//by now the best "before part" has been determined
 62  					for(index2 in this.context[bestBefore.length][bestBefore].after){//all before parts
 63  						qWord=this.context[bestBefore.length][bestBefore].after[index2];
 64  						if(qWord.length<1){
 65  							qWord=randomString(3,"an");
 66  						}
 67  						if(typeof this.words[qWord.length]==="undefined"){
 68  							this.words[qWord.length]={};
 69  						}
 70  						if(typeof this.words[qWord.length][part]==="undefined"){
 71  							this.words[qWord.length][qWord]=0;
 72  						}
 73  						if(this.words[qWord.length][qWord]>=newPartVal){//if this "question word" is the best
 74  							newPartVal=this.words[qWord.length][qWord];
 75  							newPart=qWord;
 76  						}
 77  					}
 78  					//by now the new part has been found
 79  					str=[str.substr(0,index),newPart,str.slice(index+len)].join("");
 80  				}
 81  			}
 82  		}
 83  		//return the clean string
 84  		return str;
 85  	}
 86  	var Ai=function(name,obj) {
 87  		/*
 88  		There are 2 ways two run this function
 89  
 90  			var myAi= new Ai("My AI's name");//1st
 91  			var mySecondAi= new Ai("My 2nd AI's name",{
 92  				//values here
 93  			});//2nd
 94  		*/
 95  		if  (arguments.length===0||arguments.length>2) throw "The Ai constructor requires 1-2 values passed";
 96  		obj=obj||{};//prevent bugs
 97  		this.name=name;
 98  		this.defaultResponces={
 99  			"How are you?":"If you got this message, I am at least 25% operational.",
100  		};
101  		this.lastResponce="";
102  		this.words=[];
103  		this.context=[];
104  		this.inputTypes={
105  			string:function(str) {return str;},
106  		};
107  		if(typeof obj!="undefined") {
108  			for (var i in this) {
109  				if (typeof this[i]!="undefined") {
110  					for (var ii in obj[i]) {
111  						this[i][ii]=obj[i][ii];
112  					}
113  				}else this[i]=obj[i];//overwrite with obj
114  			}
115  		}
116  		/*if (typeof this.name!=="string") {
117  			throw "The name for your Ai bot must be a string";
118  		}*/
119  		this.reactTo=function(input,type) {
120  			/*
121  			How to use this function:
122  
123  				var myAi= new Ai("My AI's name");
124  				var aisOutput=myAi.reactTo("input","usersname","type of input(optional but will use the typeof operator to determine this value if not specified)");
125  			*/
126  			var output=randomString(Math.random()*this.lastResponce.length),len,index,word;//set varubles
127  			type=type||typeof input;
128  
129  			//check varubles
130  			if (typeof this.inputTypes[type]==="undefined") {
131  				throw "Invalid type";
132  			}else{
133  				input=this.inputTypes[type](input);
134  			}
135  
136  			//apply default responce
137  			if (this.defaultResponces.hasOwnProperty(input)) output=this.defaultResponces[input];
138  			//lint
139  			output=lint.call(this,output);
140  			//add to memory
141  			this.defaultResponces[input]=output;
142  			this.lastResponce=output;//For the punish and reward functions
143  			for (len=1; len<output.length; len++) {
144  				if (!this.words[len]) {
145  					this.words[len]={};
146  					this.context[len]={};
147  				}
148  				for (index=0; index<(output.length-len); index++) {
149  					word=output.substr(index,len);
150  					if(!this.words[len][word]) {
151  						this.words[len][word]=0;//value indicates how "good" a word is
152  						this.context[len][word]={
153  							before:[output.substr(index-len,len)],
154  							after:[output.substr(index+len,len)],
155  						};
156  					}else{
157  						this.context[len][word].before.push(output.substr(index-len,len));
158  						this.context[len][word].after.push(output.substr(index+len,len));
159  					}
160  				}
161  			}
162  			//act & remember
163  			this.lastResponce=output;
164  			return output;
165  		};
166  		this.punish=function(str){
167  			if (typeof str==="undefined") {
168  				str=this.lastResponce;
169  			}
170  			for (var len=1; len<str.length; len++) {
171  				if (typeof this.words[len]==="undefined") this.words[len]={};
172  				for (var index=0; index<(str.length-len); index++) {
173  					var word=str.substr(index,len);
174  					if(!this.words[len][word]) {
175  						this.words[len][word]=0;//value indicates how "good" a word is
176  					}else{
177  						this.words[len][word]--;
178  					}
179  				}
180  			}
181  		};
182  		this.reward=function(str){
183  			if (typeof str==="undefined") {
184  				str=this.lastResponce;
185  			}
186  			for (var len=1; len<str.length; len++) {
187  				if (typeof this.words[len]==="undefined") this.words[len]={};
188  				for (var index=0; index<(str.length-len); index++) {
189  					var word=str.substr(index,len);
190  					if(!this.words[len][word]) {
191  						this.words[len][word]=0;//value indicates how "good" a word is
192  					}else{
193  						this.words[len][word]++;
194  					}
195  				}
196  			}
197  		};
198  	};
199  	return Ai;
200  })());