/ Learner.js
Learner.js
  1  (function(global) {//main wrapper
  2  	/*Here we define all of the functions that may be used throught the porgect that we don't want to be internal*/
  3  	
  4  	var hideFunc="function() { /*Look at the scource code if you really want to see how this works! :p*/ }";
  5  	function ret(val) {
  6  		var f=function() {
  7  			return val;
  8  		};
  9  		Object.defineProperty(f, 'toString', { get: function() { return ret(hideFunc); } });//prevents stackoverflow error by running ret() only when requested
 10  		Object.defineProperty(f, 'toLocaleString', { get: function() { return ret(hideFunc); } });
 11  		return f;
 12  	}
 13  	function hide(f) {
 14  		f.toString=ret(hideFunc);
 15  		f.toLocaleString=ret(hideFunc);
 16  	}
 17  	function applyDefaults(input,defaults) {
 18  		if ((typeof(defaults)).toString()==='undefined'||(typeof(defaults)).toString()==='string') {
 19  			return input;
 20  		}else if ((typeof(input)).toString()==='undefined') {
 21  			return defaults;
 22  		}/*else if ((typeof(input)).toString()!==(typeof(defaults)).toString()) {//typeof would not work in many situations
 23  			return defaults;
 24  		}*/
 25  		var output=JSON.parse(JSON.stringify(input)),i;
 26  		for(i in defaults) {
 27  			output[i]=applyDefaults(input[i],defaults[i]);
 28  		}
 29  		output=JSON.parse(JSON.stringify(output));
 30  		for(i in output) {
 31  			output[i]=applyDefaults(input[i],defaults[i]);
 32  		}
 33  		return output;
 34  	}
 35  	function def(str,v) {
 36  		Object.defineProperty(this,str,{get:function(){return v;}});// no changes to the varuble unless done internally via this core
 37  	}
 38  
 39  	(function(Learner) {//globaliser
 40  		/*Here we export the Learner.js's modules through various exporting formats*/
 41  		if (typeof module!=="undefined") {
 42  			module=Learner;//for Node.js
 43  		}else if(typeof define!=="undefined"){
 44  			define("Learner",function() {
 45  				return Learner;//for Require.js and similar tools (like Dojo)
 46  			});
 47  		}
 48  		global.Learner=Learner;//For all web browsers (or the like)
 49  	})((function() {//definer
 50  		/*Here we define the first module: Learner at the end of this function we return Learner when it is ready, then it is handled by the above function.*/
 51  		var Learner=function(e) {
 52  			/*This function builds base constructor.
 53  			  e is the settings for this instance of Learner 
 54  			*/
 55  			e=applyDefaults(e,this.defaults);// uses Learner.prototype.defaults for the defaults
 56  			this.cores[e.core].apply(this,e.coreSettings);
 57  			//passes e.coreSettings (Learner.prototype.defaults.coreSettings) into the core function that is specified in e.core (Learner.prototype.defaults.core)
 58  			this.core=e.core;//for debugging
 59  		};
 60  		hide(Learner);
 61  		
 62  		Learner.prototype={
 63  			//Nothing core specific is defined here, excluding things in the .cores obj
 64  			constructor:Learner,
 65  			toString:ret(null),
 66  			toLocaleString:ret(null),
 67  			database:null,
 68  			defaults:{
 69  				core:"default",   //determines what core is being used
 70  				coreSettings:[],  //passed into core function that is specified in the line above and are specific to the core, not the library in general
 71  			},
 72  			cores:{
 73  				/*All of the learning happens within these cores.
 74  				  Each of these functions are only executed once per instalisation of the Learner object, and are expected to edit the "this" object, as they are executed using the apply function on the this object in the Learner constructor function.
 75  				  The values passed into these functions are dependant on the documentation of each core, and can be entirely different, however, they must be able to handle the default core function values (found @ Learner.prototype.defaults.coreSettings)
 76  				  Note that extensions of this library can add learning cores to this object.
 77  				*/
 78  				"default":function(e) {
 79  					e=applyDefaults(e,{
 80  						thinkInterval:100,//the amount of time between each thought in milliseconds, as it is passed directly to the second argument of setTimeout(). If thinkInterval===false, the bot can't think before it does anything.
 81  						thinkFilter:function(input) { return "thought:"+input;},//an oppertunity to change the thought to a proper input format, if needed.
 82  						reinforcementDecay:0.875,//see "this.reinforcement" as defined in this core
 83  						reinforcementDecayLimit:0.5,//see "this.reinforcement" as defined in this core
 84  						actionMap:{//an array of all of the actions that the bot can take. Currently the bot can do naught but wonder
 85  							think:function(str) {
 86  								if (!this.thinkInterval) return;
 87  								setTimeout(function() {//this is so we don't get a stackoverflow error
 88  									this.action(this.thinkFilter(str));
 89  								},this.thinkInterval);
 90  							},
 91  						},
 92  					});
 93  					
 94  					var selfEsteem=0,//The greater the number, the more self-esteem the bot is estimated to have. Negitive is a bad thing. Clearly shows depression.
 95  					myHistory=[],//a list of outputs that the bot has sent to a method in the action map
 96  					envHistory=[],//a list of enviromential updates
 97  					allHistory=[],//a list of all enviromential updates and outputs that the bot has sent to a method in the action map
 98  					words={};//all of the sub-strings that have a value asociated with them
 99  					
100  					//make all of these varubles acccesssable to the enviroment, but not changeable
101  					def.call(this,'selfEsteem',selfEsteem);//as this number would be more usefull in the enviroment the underscores marking that it is internal is unneccicary
102  					def.call(this,'__myHistory__',myHistory);
103  					def.call(this,'__envHistory__',envHistory);
104  					def.call(this,'__allHistory__',allHistory);
105  					def.call(this,'__words__',words);
106  					
107  					var action=function(e0) {
108  						/*called on user action, or other enviromential changes*/
109  						e1=applyDefaults(e1,{
110  							val:"",//The string that will now be manipulated.
111  						});
112  						//I am still working on this, and actually have forgotten some of what happens here. I do recall that it has two steps.
113  						//Step 1:?  <- I told you I forgot things.
114  					};
115  					hide(action);
116  					def.call(this,'action',action);
117  					
118  					var reinforcement=function f(e1) {
119  						/*user rewards or punishes (positive or negitive reinforcemnt)*/
120  						
121  						e1=applyDefaults(e1,{
122  							val:0,//the value to apply to each string and substring - <0 is a punishment >0 is a reward zero does nothing
123  							reinforcementDecay:e.reinforcementDecay,//before working on an older string, "val" is multiplied by this number
124  							reinforcementDecayLimit:e.reinforcementDecayLimit,//the limit for how close "val" can be to zero before aborting "recursive" history reinforcement
125  						});
126  						
127  						var i,len,index,part;//prevents a varuble from being redefined at every iteration of a loop, these varubles will be defined via their first usage
128  						
129  						this.selfEsteem+=e1.val;//this is where the self-esteem-related magic happens. To be honest, this is really jsut a way to proove that the bot has or hasn't been abused, by anyone. Including itself.
130  						
131  						for (i=myHistory.length; (i>=0&&e1.val<e1.reinforcementDecayLimit); i--) {//every item in the output history, as long as the reinforcementDecayLimit allows, then leave the loop if the criteria doesn't fit anymore
132  							
133  							for (len=(myHistory[i].length); len>1; len--){//the length of the sub-string
134  								for (index=0; index<(myHistory[i].length-len); index++) {//the position of the sub-string
135  								
136  									part=myHistory[i].substr(index,len);//this is the actual sub-string
137  									
138  									/*if the sub-string has not been incountered before, make a spot for it to go*/
139  									if(typeof words[len]==="undefined"){//place for this length of sub-string
140  										words[len]={};
141  									}
142  									if(typeof words[len][part]==="undefined"){//the value itself
143  										words[len][part]=el.val;
144  										continue;//in this case it would be a waste of prossessing to set it to zero now then change it later, so set it now, then go on to the next sub-string
145  									}
146  									
147  									words[len][part]+=el.val;//this is where the value is actually changed
148  								}
149  							}
150  							
151  							el.val*=e1.reinforcementDecay;//and thus it decays.
152  						}
153  					};
154  					hide(reinforcement);
155  					def.call(this,'reinforcement',reinforcement);
156  				},
157  				
158  				"__brickWall__":function(e) {//this can be used as a template for the more simple cores, but if this is an unsatisfactory example, look at the default core.
159  					e=applyDefaults(e,{
160  						act:function(str) {//bot acts
161  							console.log(str);
162  						},
163  					});
164  					this.action=function(str) {//user acts
165  						e.act(str);
166  					};
167  				},
168  				
169  				//"deep":function() {},
170  				//"Q":function() {},
171  			},
172  		};
173  		return Learner;
174  	})());
175  
176  })(this);