--- /dev/null
+<html>
+<head>
+<title>Dennco Sample5 - SimplePerceptron</title>
+<script type="text/javascript">
+
+try {
+ if (!engine)
+ {
+ alert("This page is expected to be executed on 'dennco engine'. This won't work properly on a browser.");
+ }
+}
+catch(e)
+{
+ alert("This page is expected to be executed on 'dennco engine'. This won't work properly on a browser.");
+}
+
+//dennco interfaces
+var CELLV1INPUT = "/1/1_a.xhtml#cell1v1input";
+var CELLV2INPUT = "/1/1_a.xhtml#cell1v2input";
+var CELLOUTPUT = "/3/3_a.xhtml#cell1output";
+var CELLRATE = "/1/1_a.xhtml#cell1rate";
+var CELLLEARN = "/1/1_a.xhtml#cell1learn";
+var CELLDESIRED = "/1/1_a.xhtml#cell1desired";
+
+//status
+var isInsideGraph = false;
+var point_v1;
+var point_v2;
+
+//layour
+var WIDTH=400;
+var HEIGHT=400;
+var GRAPH_X0 = 30;
+var GRAPH_Y0 = 370;
+var GRAPH_WIDTH = 360;
+var GRAPH_HEIGHT = 360;
+var GRAPH_S = 8;
+var GRAPH_V1MIN = - 2;
+var GRAPH_V1MAX = 2;
+var GRAPH_V2MIN = - 2;
+var GRAPH_V2MAX = 2;
+
+//window.addEventListener("load", uiInit, false);
+
+var testTimerId = null;
+//
+var learnTimerId = null;
+var isLearning = false;
+var isPrepareForNextSample = false;
+var learnCount = 0;
+var learnDesired = 0;
+var learnGood = 0;
+
+function updateTestIO()
+{
+ engine.setValue(CELLV1INPUT, point_v1);
+ engine.setValue(CELLV2INPUT, point_v2);
+ document.getElementById("testOutput").value = engine.getValue(CELLOUTPUT);
+}
+
+function learnSample()
+{
+ engine.setValue(CELLRATE,Number((document.getElementById("learningRateTextInput")).value));
+
+ if (isPrepareForNextSample)
+ {
+ isPrepareForNextSample = false;
+
+ var output = engine.getValue(CELLOUTPUT);
+ if (output == learnDesired)
+ {
+ learnGood ++;
+ }
+ engine.setValue(CELLLEARN, 0);
+ learnCount ++;
+ }
+ else
+ {
+ var list = document.getElementById("lerningItems");
+ var nextIndex = list.selectedIndex + 1;
+ if (nextIndex >= list.options.length)
+ nextIndex = 0;
+ list.selectedIndex = nextIndex;
+ var v = list.options[nextIndex].value.split(",");
+ drawLearnPoints();
+ learnDesired = v[2];
+ engine.setValue(CELLV1INPUT, v[0]);
+ engine.setValue(CELLV2INPUT, v[1]);
+ engine.setValue(CELLDESIRED, v[2]);
+ engine.setValue(CELLLEARN, 1);
+
+ isPrepareForNextSample = true;
+ }
+
+ var message = "Learning.. " + learnCount + "/ 50 \rGood:" + learnGood + " Corrected:" + (learnCount - learnGood);
+
+ if (message.length > 0)
+ document.getElementById("learnStatusMessage").innerText = message;
+
+ if (learnCount >= 50)
+ stopLearn();
+}
+
+function learnButtonClicked()
+{
+ if (!isLearning)
+ {
+ startLearn();
+ }
+ else
+ {
+ stopLearn();
+ }
+}
+
+function startLearn()
+{
+ if (document.getElementById("lerningItems").options.length == 0)
+ {
+ alert("No sample to learn");
+ return;
+ }
+
+ isLearning = true;
+ setLearnModeUIEnable(false);
+ document.getElementById("learnButton").value = "Stop";
+
+ if (learnTimerId != null)
+ {
+ clearInterval(learnTimerId);
+ }
+ learnCount = 0;
+ learnDesired = 0;
+ learnGood = 0;
+ learnTimerId = setInterval("learnSample()", 50);
+}
+
+function stopLearn()
+{
+ engine.setValue(CELLLEARN, 0);
+ isLearning = false;
+ setLearnModeUIEnable(true);
+ document.getElementById("learnButton").value = "Start to learn";
+
+ if (learnTimerId != null)
+ {
+ clearInterval(learnTimerId);
+ learnTimerId = null;
+ }
+}
+
+function startTestMode()
+{
+ stopTimer();
+ testTimerId = setInterval("updateTestIO()",20);
+}
+
+function stopTestMode()
+{
+ stopTimer();
+}
+
+function setLearnModeUIEnable(enable)
+{
+ document.getElementById("mode").disabled = !enable;
+// document.getElementById("v1Input").disabled = !enable;
+// document.getElementById("v2Input").disabled = !enable;
+// document.getElementById("cursorValue").disabled = !enable;
+// document.getElementById("lerningItems").disabled = !enable;
+// document.getElementById("learningRateRangeInput").disabled = !enable;
+// document.getElementById("learningRateTextInput").disabled = !enable;
+}
+
+function uiInit()
+{
+ var canvasHolder = document.getElementById("canvasHolder");
+ canvasHolder.addEventListener("mousemove", mouseMoveHandler, true);
+ canvasHolder.addEventListener("mousedown", mouseDownHandler, false);
+ canvasHolder.addEventListener("mouseup", mouseUpHandler, false);
+ drawGraphBase();
+ pointColor = "red";
+
+ addLearnPoint(0,0,1);
+ addLearnPoint(0,1,1);
+ addLearnPoint(1,0,1);
+ addLearnPoint(1,1,0);
+}
+
+function stopTimer()
+{
+ if (testTimerId != null)
+ {
+ clearInterval(testTimerId);
+ testTimerId = null;
+ }
+ if (learnTimerId != null)
+ {
+ clearInterval(learnTimerId);
+ learnTimerId = null;
+ }
+}
+
+function addLearnPointFromUI()
+{
+ var v1 = Number(document.getElementById("v1Input").value);
+ var v2 = Number(document.getElementById("v2Input").value);
+ var d = Number(document.getElementById("cursorValue").value);
+
+ addLearnPoint(v1,v2,d);
+}
+
+function addTestPointFromUI()
+{
+ var v1 = Number(document.getElementById("testV1Input").value);
+ var v2 = Number(document.getElementById("testV2Input").value);
+ var o = Number(document.getElementById("testOutput").value);
+
+ addTestPoint(v1,v2,o);
+}
+
+function addLearnPoint(v1,v2,d)
+{
+
+ var text = "v1:" + v1 + " v2:" + v2 + " d:" + d;
+ var value = v1 +"," + v2 + "," + d;
+
+ var list = document.getElementById("lerningItems");
+
+ var opt = document.createElement("option");
+ opt.value = value;
+ opt.text = text;
+ list.options.add(opt, list.options.length);
+ list.selectedIndex = list.options.length -1;
+ drawLearnPoints();
+}
+
+function addTestPoint(v1,v2,o)
+{
+ var text = "v1:" + v1 + " v2:" + v2 + " output:" + o;
+ var value = v1 +"," + v2 + "," + o;
+
+ var list = document.getElementById("testItems");
+ var opt = document.createElement("option");
+ opt.value = value;
+ opt.text = text;
+ list.options.add(opt, list.options.length);
+ list.selectedIndex = list.options.length -1;
+ drawTestPoint(v1,v2,o);
+}
+
+function removeSelectedPoint()
+{
+ var list = document.getElementById("lerningItems");
+ var index = list.selectedIndex;
+ if (index >= 0)
+ {
+ var list = document.getElementById("lerningItems");
+ list.remove(index);
+
+ drawLearnPoints();
+ }
+}
+
+function pointToCanvas(v1,v2)
+{
+ var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+ var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+
+ var x = (v1 - GRAPH_V1MIN) / xrange * GRAPH_WIDTH + GRAPH_X0;
+ var y = GRAPH_Y0 - (v2 - GRAPH_V2MIN) / yrange * GRAPH_HEIGHT;
+
+ return {x:x, y:y};
+}
+
+function drawGraphBase()
+{
+ var can = document.getElementById("canvasLayer1");
+ var context = can.getContext("2d");
+ context.fillStyle = "black";
+ context.strokeStyle = "rgb(0, 10, 0)";
+ context.beginPath();
+ context.lineWidth = 1;
+ context.moveTo(GRAPH_X0,GRAPH_Y0 - GRAPH_HEIGHT);
+ context.lineTo(GRAPH_X0,GRAPH_Y0);
+ context.lineTo(GRAPH_X0 + GRAPH_WIDTH,GRAPH_Y0);
+ context.stroke();
+
+ var xstep = GRAPH_WIDTH / GRAPH_S;
+ var ystep = GRAPH_HEIGHT / GRAPH_S;
+
+ var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+ var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+
+ context.font = "10px sans-serif";
+
+ for (var i = 1; i <= GRAPH_S; i++)
+ {
+ hp = GRAPH_X0 + i * xstep;
+ vp = GRAPH_Y0 - i * ystep;
+
+ context.beginPath();
+ context.lineWidth = 1;
+ context.moveTo(hp ,GRAPH_Y0 - 5);
+ context.lineTo(hp ,GRAPH_Y0);
+ context.stroke();
+
+ context.beginPath();
+ context.lineWidth = 1;
+ context.moveTo(GRAPH_X0, vp);
+ context.lineTo(GRAPH_X0 + 5, vp);
+ context.stroke();
+
+ var ux = GRAPH_V1MIN + xrange / GRAPH_S * i;
+ var uy = GRAPH_V2MIN + yrange / GRAPH_S * i;
+
+ context.textAlign = "center";
+ context.textBaseline = "top";
+ context.fillText(ux, hp, GRAPH_Y0 + 2);
+
+ context.textAlign = "right";
+ context.textBaseline = "middle";
+ context.fillText(uy, GRAPH_X0 - 3, vp);
+ }
+
+ context.textAlign = "right";
+ context.textBaseline = "bottom";
+ context.fillText(GRAPH_V2MIN, GRAPH_X0 - 3, GRAPH_Y0);
+
+ context.textAlign = "left";
+ context.textBaseline = "top";
+ context.fillText(GRAPH_V1MIN, GRAPH_X0, GRAPH_Y0 + 2);
+}
+
+
+function drawCursor()
+{
+ var can = document.getElementById("canvasLayer4");
+ var context = can.getContext("2d");
+
+ context.clearRect(0, 0, WIDTH, HEIGHT);
+
+ var cp = pointToCanvas(point_v1, point_v2);
+
+ if ((document.getElementById("mode")).value == "learn" )
+ {
+ document.getElementById("v1Input").value = point_v1;
+ document.getElementById("v2Input").value = point_v2;
+ context.strokeStyle = (document.getElementById("cursorValue").value == "0") ? "blue" : "red";
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x-5 ,cp.y);
+ context.lineTo(cp.x+5 ,cp.y);
+ context.stroke();
+
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x ,cp.y-5);
+ context.lineTo(cp.x ,cp.y+5);
+ context.stroke();
+ }
+ else
+ {
+ document.getElementById("testV1Input").value = point_v1;
+ document.getElementById("testV2Input").value = point_v2;
+ var c = Number(document.getElementById("testOutput").value) == 0 ? "blue" : "red";
+ context.strokeStyle = c;
+ context.fillStyle = c;
+ context.fillRect(cp.x-4,cp.y-4,8,8);
+ }
+}
+
+function drawLearnPoints()
+{
+ var can = document.getElementById("canvasLayer2");
+ var context = can.getContext("2d");
+ context.clearRect(0, 0, WIDTH, HEIGHT);
+
+ var learnMode = (document.getElementById("mode")).value == "learn";
+ var list = document.getElementById("lerningItems");
+ for (var i = 0; i < list.length; i++)
+ {
+ var v = list.options[i].value.split(",");
+ var cp = pointToCanvas(v[0], v[1]);
+ context.strokeStyle = (v[2] == 0) ? "blue" : "red";
+
+ if (learnMode)
+ {
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x-4 ,cp.y-4);
+ context.lineTo(cp.x+4 ,cp.y+4);
+ context.stroke();
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x-4 ,cp.y+4);
+ context.lineTo(cp.x+4 ,cp.y-4);
+ context.stroke();
+
+ if (list.selectedIndex == i)
+ {
+ context.strokeRect(cp.x-5 ,cp.y-5,10,10);
+ }
+ }
+ else
+ {
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x-2 ,cp.y-2);
+ context.lineTo(cp.x+2 ,cp.y+2);
+ context.stroke();
+ context.beginPath();
+ context.lineWidth = 0;
+ context.moveTo(cp.x-2 ,cp.y+2);
+ context.lineTo(cp.x+2 ,cp.y-2);
+ context.stroke();
+ }
+ }
+}
+
+function clearTestPoints()
+{
+ var can = document.getElementById("canvasLayer3");
+ var context = can.getContext("2d");
+ context.clearRect(0, 0, WIDTH, HEIGHT);
+
+ var list = document.getElementById("testItems");
+
+ while(list.options.length > 0)
+ {
+ list.options.remove(list.options.length - 1);
+ }
+ drawCursor();
+}
+
+function drawTestPoint(v1,v2,output)
+{
+ var can = document.getElementById("canvasLayer3");
+ var context = can.getContext("2d");
+
+ var cp = pointToCanvas(v1, v2);
+
+ var c = (output == 0) ? "blue" : "red";
+ context.strokeStyle = c;
+ context.fillStyle = c;
+
+ context.fillRect(cp.x-3 ,cp.y-3,6,6);
+}
+
+
+function mouseMoveHandler(e)
+{
+ var rect = e.target.getBoundingClientRect();
+ var x = e.clientX - rect.left;
+ var y = e.clientY - rect.top;
+
+ if (x < GRAPH_X0 || x > GRAPH_X0 + GRAPH_WIDTH || y < GRAPH_Y0 - GRAPH_HEIGHT || y > GRAPH_Y0)
+ {
+ isInsideGraph = false;
+ return;
+ }
+ isInsideGraph = true;
+
+ var xrange = GRAPH_V1MAX - GRAPH_V1MIN;
+ var yrange = GRAPH_V2MAX - GRAPH_V2MIN;
+
+ point_v1 = Number((x - GRAPH_X0) / GRAPH_WIDTH * xrange + GRAPH_V1MIN).toFixed(2);
+ point_v2 = Number((GRAPH_Y0 - y) / GRAPH_HEIGHT * yrange + GRAPH_V2MIN).toFixed(2);
+
+ drawCursor();
+}
+
+function mouseDownHandler()
+{
+ if (isInsideGraph)
+ {
+ if ((document.getElementById("mode")).value == "learn")
+ addLearnPointFromUI();
+ else
+ addTestPointFromUI();
+ }
+}
+
+function mouseUpHandler()
+{
+}
+
+function modeChanged()
+{
+ if ((document.getElementById("mode")).value == "learn")
+ {
+ //learning mode
+ (document.getElementById("testModePanel")).style.zIndex = 1;
+ (document.getElementById("lerningModePanel")).style.zIndex = 2;
+ stopTestMode();
+ }
+ else
+ {
+ //test mode
+ (document.getElementById("testModePanel")).style.zIndex = 2;
+ (document.getElementById("lerningModePanel")).style.zIndex = 1;
+ startTestMode();
+ }
+ clearTestPoints();
+ drawLearnPoints();
+}
+
+function rateRangeInputChanged()
+{
+ var newValue = (Number((document.getElementById("learningRateRangeInput")).value)/100.0).toFixed(2);
+ if ((Number(document.getElementById("learningRateTextInput")).value) != newValue)
+ (document.getElementById("learningRateTextInput")).value = newValue;
+}
+
+function rateTextInputChanged()
+{
+ var newValue = (Number((document.getElementById("learningRateTextInput")).value)*100).toFixed(0);
+ if ((Number(document.getElementById("learningRateRangeInput")).value) != newValue)
+ (document.getElementById("learningRateRangeInput")).value = newValue;
+}
+
+</script>
+</head>
+<body onLoad="uiInit();" onUnload="stopTimer();" >
+
+<table border="0" cellspacing="0" cellpadding="0">
+<tr valign="top">
+<td rowspan="2">
+<div id="canvasHolder" style="position:relative; width:400px; height:400px; border:1px solid #c3c3c3;">
+<canvas id="canvasLayer1" style="z-index: 1;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer2" style="z-index: 2;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer3" style="z-index: 3;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+<canvas id="canvasLayer4" style="z-index: 4;position:absolute;left:0px;top:0px;" height="400px" width="400">
+</canvas>
+</div>
+</td>
+
+<td rowspan="2" width="20"></td>
+
+<td height="15">
+<select id="mode" size="1" style="font-size: large; width:320; height:100%" onChange="modeChanged()">
+<option value="learn">Learning mode
+<option value="test">Testing mode
+</select>
+</td>
+
+<tr>
+<td valign="top">
+<!--- control panels -->
+<div style="position:relative;" >
+<div id="lerningModePanel" style="z-index: 2;position:absolute;left:0px;top:0px;background-color:#f0f0f0;width:320;height:375">
+<table border="0" >
+<tr >
+<td>V1</td><td><input type="text" size="6", style="text-align:right; width:100%" id="v1Input"/></td><td><button style="width:100" id="addButton" onClick="addLearnPointFromUI()">Add</button></td>
+</tr>
+<tr>
+<td>V2</td><td><input type="text" size="6", style="text-align:right; width:100%" id="v2Input"/></td><td></td>
+</tr>
+<tr>
+<td>Desired</td><td><SELECT id="cursorValue" style="width:100%" SIZE="1" ><option value="0">0 (BLUE)<option value="1">1 (RED)</SELECT></td><td></td>
+</tr>
+
+<tr>
+<td colspan="2"><SELECT id="lerningItems" SIZE="6" style="width:200;font-family:monospace;" onChange="drawLearnPoints()"></SELECT></td>
+<td valign="top"><button style="width:100" id="removeButton" onClick="removeSelectedPoint()">Remove</button></td>
+</tr>
+
+<tr>
+<td>
+Learning rate
+</td>
+<td colspan="2" valign="middle">
+<input type="range" MIN="0" MAX="100" value="10" id="learningRateRangeInput" onChange="rateRangeInputChanged()"/><input type="text" size="5", style="text-align:right;" id="learningRateTextInput" onChange="rateTextInputChanged()" value="0.1"/>
+</td>
+</tr>
+
+<tr>
+<td colspan="3"><input type="button" style="width:300;height:50" id="learnButton" value="Start to learn" onClick="learnButtonClicked()"/></td>
+</tr>
+<tr>
+<td colspan="3"><p id="learnStatusMessage"> </p></td>
+</table>
+
+</div>
+
+<div id="testModePanel" style="z-index: 1;position:absolute;left:0px;top:0px;background-color:#f0f0f0;;width:320;height:375">
+
+<table border="0" >
+<tr >
+<td>V1</td><td><input type="text" size="6", style="text-align:right; width:100%" id="testV1Input" disabled="true"/></td>
+</tr>
+<tr>
+<td>V2</td><td><input type="text" size="6", style="text-align:right; width:100%" id="testV2Input" disabled="true"/></td><td></td>
+</tr>
+<tr>
+<td>Out</td><td><input type="text" size="6", style="text-align:right; width:100%" id="testOutput" disabled="true"/></td><td></td>
+</tr>
+<tr>
+<td colspan="2"><SELECT id="testItems" SIZE="10" style="width:300; font-family:monospace;" ></SELECT></td>
+</tr>
+</table>
+
+</div>
+</div>
+
+</td>
+</td>
+</tr>
+</table>
+<p>Sample implementation of Perceptron with dennco engine. See: <a href="javascript:void(0)" onclick="window.open('http://en.wikipedia.org/wiki/Perceptron');">http://en.wikipedia.org/wiki/Perceptron</a> for the detail information about Perceptron.</P>
+</body>
+</html>