We can think of JavaScript running within a clients browser as a robotic agent. It has an environment in which it can sense things. The ability to look at the environment and make decisions based on plans.

clientagent.JPG

So whys that useful, well why is a robot useful? You can produce many different complex plans and give them to the robot and forget about it while it does the work potentially over and over again. If we are really lucky the robot can demonstrate some intelligence and deal with uncertainty.

Well I tried out a small part of this idea to build a server side service which delivered plans in JavaScript to the client. The JavaScript planning agent followed the plans. Its not a intelligent robot but this is just a prototype. The plans where focused on validation conditions that a user needed to get through to post a form.

Example:

planCollection = Array();
planCollection[0][0]= Array();
planCollection[0][0]= document.forms['iwfmsForm'].elements['age'].value>18;
planCollection[0][1]= ocument.forms['iwfmsForm'].elements['ward'].value=='adult’;

Timings where implied by ordering of plans in an array. i.e. for plan 0 - value > 18 must happen before ward == adult.

Array dimensions imply different plans or forks in the plan.

Its a rather crude plan referencing form names and lots of low level javascript but it helps simplify the boring bits!

The Environment

The environment represents the different states the form elements and the user can be in.

The See process

This function maps the form elements to their associated values.

The Message Store

The message store is used to represent events generated by the user. Events could be the result of clicking on a form element or clicking away from a form element. Such events generate messages which the plan executor responds to. These events are the points where the planner is activated.

The Plans

The plans represent a sequence of constraints within the JavaScript syntax on form elements. This type of action is not executed but used to help decided upon which plan path to follow.

The Action process

This process deals with selecting actions based on the see process which provides information about the form element’s values. There may only be a single plan and thus no decision to make. If there are multiple plans the decision to follow an action is only made for the first action of a plan. Which initial action to decide upon is decided by testing each of the first actions of the plans until one holds from the information provided by the see process. This plan is then used to further test the next constraint of the plan and so on. If multiple first actions hold each of the plans is tested to see if any of them reach the goal.

The Goals

The goals of the plans can be regarded as ensuring that all the conditions in the plan hold based on the data in the HTML form.

The Execution of Actions

Within the planner the actions are not executed. Since we are constraining the user all we need to do is find a valid plan path. The planner affects the environment by alerting the user if it cannot find any valid plan path.

The plan executor needs to be able to handle two different situations:

  • Form submission
    When the user inputs information into a form and then submits the form the planner will have to ensure that a valid plan path is reflected by the values that are held in the form. The form submission should be prevented if such a plan cannot be found.
  • Real time user input
    • a. Guidance through a plan
      As the user inputs information the planner needs to be aware of the current position in multiple plans and what effect this has on the current form element being filled in. Alerting the user if they have failed to achieve any plan as a result of the data they entered into the form.
    • b. Temporal ordering restrictions
      The planner needs to be able to handle temporal restrictions on the form elements. Indicating in which order form elements have to be completed. Therefore we have to look at the impact that a real time input action will have on the rest of the form. For example one form element being completed may have the effect that another disabled form element can be activated for input.

JavaScript Planning agent Code

  1. /*
  2. * Replace all instances of a boolean expression within a source string with english equivalents
  3. */
  4. function expressionsToString(expression, source){
  5.  
  6. switch(expression){
  7.  
  8. case ‘>=’ :
  9. re = new RegExp(expression);
  10. var newstr = source.replace(re, " must be greater than or equal to ");
  11. break;
  12.  
  13. case ‘<’ :
  14. re = new RegExp(expression);
  15. var newstr = source.replace(re, " must be less than ");
  16. break;
  17.  
  18.  
  19. case "==" :
  20. re = new RegExp(expression);
  21. var newstr = source.replace(re, " must be equal to ");
  22. break;
  23.  
  24. }
  25.  
  26. if(newstr!=){ //replace succeded
  27. return newstr;
  28. }
  29. else{//No expressions matched
  30. return source;
  31. }
  32. }
  33.  
  34.  
  35. /**
  36. * Convert all boolean expressions in a string to english
  37. */
  38. function english(str){
  39.  
  40. var ar = str.match(/([^.]+).([^.]+).([^.]+).([^\s.>=<]+)(.*)/);
  41. var strtr = (RegExp.$5);
  42.  
  43. var englishString;
  44.  
  45. englishString = expressionsToString("==", strtr);
  46. englishString = expressionsToString(">=", englishString);
  47. englishString = expressionsToString("<", englishString);
  48.  
  49. return englishString
  50. }
  51.  
  52.  
  53. /**
  54. * Find out if any of the plans currently hold
  55. */
  56. function testPlans(verbrose){
  57.  
  58. var planMatched;
  59. var matchingPath;
  60.  
  61. planNotMatched=true;
  62. matchingPath= 0;
  63.  
  64. //Keep trying other plans if this plan was not matched
  65. for(index=0; index < planCollection.length && planNotMatched ;index++){
  66.  
  67. planMatched = true;
  68.  
  69. //Check whether this plan holds
  70. for(planIndex=0; planIndex < planCollection[index].length; planIndex = planIndex+2){
  71.  
  72. if(verbrose){
  73. alert(planCollection[index][planIndex]);
  74. }
  75.  
  76. planMatched = planMatched && eval(planCollection[index][planIndex]);
  77.  
  78. if(planIndex==0 && eval(planCollection[index][planIndex])){
  79.  
  80. matchingPath = index;
  81.  
  82. }
  83.  
  84. planNotMatched = !(planMatched);
  85.  
  86. if(verbrose){
  87. alert(planMatched);
  88. }
  89.  
  90. }
  91. }
  92.  
  93. if(planMatched == false){//No plans where matched
  94.  
  95. if(verbrose){
  96. alert(‘If ‘ + planCollection[matchingPath][1] + english(planCollection[matchingPath][0]) + ‘ then ‘ + planCollection[matchingPath][3] + english(planCollection[matchingPath][2]) );
  97. //alert(’None of the javaScript plans where found to match youre input’);
  98. }
  99.  
  100. }
  101.  
  102. return planMatched;
  103.  
  104. }
  105.  
  106.  
  107. /**
  108. * Check passed value is a member of a plan
  109. */
  110. function memberPlanArray(value){
  111.  
  112. var match;
  113.  
  114. match = false;
  115.  
  116. for(index=0; index < planCollection.length; index++){
  117.  
  118. for(planIndex=0; (planIndex < planCollection[index].length) && (!match); planIndex = planIndex+2){
  119.  
  120. if( planCollection[index][planIndex+1] == value){
  121.  
  122. match=true;
  123.  
  124. }
  125.  
  126. }
  127. }
  128.  
  129. return match;
  130. }
  131.  
  132.  
  133. /**
  134. *
  135. */
  136. function checkTime(current){
  137.  
  138. var search = false;
  139.  
  140. for(index=0; (search==false)&& (index < timeline.length) ;index++){
  141.  
  142. if( timeline[index] == current ){
  143.  
  144. search=true;
  145.  
  146. }
  147.  
  148. }
  149.  
  150. if(index < timeline.length){//We dont want to process the last item
  151.  
  152. //alert(timeline[index]);
  153. document.forms[‘iwfmsForm’].elements[timeline[index]].disabled = false;
  154.  
  155. }
  156. }
  157.  
  158.  
  159. /**
  160. *
  161. */
  162. function validate(){
  163.  
  164. for(index=0; index < timeline.length ;index++){
  165.  
  166. if (document.forms[‘iwfmsForm’].elements[timeline[index]].value == ""   || document.forms[‘iwfmsForm’].elements[timeline[index]].disabled){
  167.  
  168. alert(‘You have not completed the required form elements! Please fill in ‘ + timeline[index]);
  169.  
  170. return false;
  171.  
  172. }
  173.  
  174. }
  175.  
  176. return true;
  177. }
  178.  
  179.  
  180. /**
  181. *
  182. */
  183. function checkPlanTime(current){
  184.  
  185. var planMatched;
  186. var currentPlanTimeIsNow;
  187. var matchingPath;
  188. var limit;
  189.  
  190. limit=false;
  191.  
  192. planMatched=false;
  193. currentPlanTimeIsNow = false;
  194.  
  195. if( memberPlanArray(current) ){
  196.  
  197. //Keep trying other plans if this plan was not matched
  198. for(index=0; index < planCollection.length && !planMatched ;index++){
  199.  
  200. planMatched = true;
  201. currentPlanTimeIsNow = false;
  202.  
  203. //Check whether this plan holds
  204. for(planIndex=0; (planIndex < planCollection[index].length) && (!currentPlanTimeIsNow); planIndex = planIndex+2){
  205.  
  206. //Skip testing an element of the plan if it has no value at all !
  207. if( document.forms[‘iwfmsForm’].elements[(planCollection[index][planIndex+1])].value != ){
  208. planMatched = planMatched && eval(planCollection[index][planIndex]);
  209. //                                      alert(planMatched);
  210.  
  211. }
  212.  
  213. if(planIndex==0 && eval(planCollection[index][planIndex])){
  214.  
  215. matchingPath = index;
  216. limit = true;
  217.  
  218. }
  219.  
  220. }
  221. }
  222.  
  223. if(planMatched == false && limit){
  224.  
  225. alert(‘If ‘ + planCollection[matchingPath][1] + english(planCollection[matchingPath][0]) + ‘ then ‘ + planCollection[matchingPath][3] + english(planCollection[matchingPath][2]) );
  226. //alert(’None of the javaScript plans where found to match youre input’);
  227.  
  228. }
  229.  
  230. return planMatched;
  231. }
  232.  
  233. }

Leave a Reply