1. <html>
  2. <head>
  3. <title>Surkits</title>
  4. <script type="text/javascript">
  5. // Surkits - Main Code
  6. var Surkit = function( cv ) {
  7. this.mx = 0;
  8. this.my = 0;
  9. this.ctx = document.getElementById( cv ).getContext( '2d' );
  10. this.comps = [ ];
  11. }
  12. Surkit.prototype.ComponentSize = 20;
  13. Surkit.prototype.SetMousePosition = function( x , y ) {
  14. this.mx = x - 0;
  15. this.my = y - 0;
  16. }
  17. Surkit.prototype.AddComponent = function( com ) {
  18. this.comps[ this.comps.length ] = com;
  19. }
  20. Surkit.prototype.MouseDown = function( ) {
  21. for ( com in this.comps ) {
  22. if ( Math.abs( this.mx - this.comps[ com ].x ) < ( this.ComponentSize / 2 ) & Math.abs( this.my - this.comps[ com ].y ) < ( this.ComponentSize / 2 ) & typeof this.comps[ com ].MouseDown != "undefined" ) {
  23. this.comps[ com ].MouseDown( this );
  24. }
  25. }
  26. }
  27. Surkit.prototype.DrawWire = function( active , sx , sy , ex , ey ) {
  28. var c = this.ctx;
  29. var len = Math.sqrt( Math.pow( ex - sx , 2 ) + Math.pow( ey - sy , 2 ) );
  30. var tx = ( ey - sy ) / len;
  31. var ty = -( ex - sx ) / len;
  32. var gradient = c.createLinearGradient( sx , sy , ex , ey );
  33. gradient.addColorStop( 0 , ( ( active ) ? "#900" : "#000" ) );
  34. gradient.addColorStop( 1 , ( ( active ) ? "#f00" : "#200" ) );
  35. c.fillStyle = gradient;
  36. c.beginPath( );
  37. c.moveTo( sx + tx * 1 , sy + ty * 1 );
  38. c.lineTo( sx - tx * 1 , sy - ty * 1 );
  39. c.lineTo( ex - tx * 1 , ey - ty * 1 );
  40. c.lineTo( ex + tx * 1 , ey + ty * 1 );
  41. c.fill( );
  42. }
  43. Surkit.prototype.DrawComponent = function( com , color , icon ) {
  44. var c = this.ctx;
  45. var tlx = com.x - this.ComponentSize / 2, tly = com.y - this.ComponentSize / 2;
  46. c.fillStyle = color;
  47. c.fillRect( tlx , tly , this.ComponentSize , this.ComponentSize );
  48. c.fillStyle = "rgb(0,0,0)";
  49. c.textAlign = "center";
  50. c.font = "normal 16px Tahoma";
  51. c.fillText( icon , com.x , tly - 5 + this.ComponentSize );
  52. if ( Math.abs( this.mx - com.x ) < ( this.ComponentSize / 2 ) & Math.abs( this.my - com.y ) < ( this.ComponentSize / 2 ) ) {
  53. this.MouseLabel = com.Name;
  54. }
  55. }
  56. Surkit.prototype.Draw = function( ) {
  57. this.ctx.clearRect( 0 , 0 , screen.width , screen.height );
  58. this.MouseLabel = "";
  59. for ( com in this.comps ) {
  60. for ( input in this.comps[ com ].input ) {
  61. var inp = this.comps[ com ].input[ input ][ 0 ];
  62. var active = inp.output[ this.comps[ com ].input[ input ][ 1 ] ];
  63. this.DrawWire( active , inp.x + this.ComponentSize / 2 , inp.y , this.comps[ com ].x - this.ComponentSize / 2 , this.comps[ com ].y );
  64. }
  65. }
  66. for ( com in this.comps ) {
  67. var col = ( this.comps[ com ].Color ) ? ( ( typeof this.comps[ com ].Color == "string" ) ? this.comps[ com ].Color : this.comps[ com ].Color( this ) ) : "rgb(0,200,0)";
  68. var icon = ( this.comps[ com ].Icon ) ? this.comps[ com ].Icon : "?";
  69. this.DrawComponent( this.comps[ com ] , col , icon );
  70. }
  71. if ( this.MouseLabel != "" ) {
  72. this.ctx.font = "italic 12px Tahoma";
  73. this.ctx.textAlign = "start";
  74. this.ctx.fillStyle = "rgb(100,100,100)";
  75. this.ctx.fillText( this.MouseLabel , this.mx + 5 , this.my - 5 );
  76. }
  77. this.ctx.textAlign = "start";
  78. this.ctx.font = "normal 10px Tahoma";
  79. this.ctx.fillStyle = "rgb(150,150,150)";
  80. this.ctx.fillText( this.mx + ", " + this.my , 15 , 15 );
  81. }
  82. Surkit.prototype.LoadSurkit = function( text ) {
  83. this.comps = [ ];
  84. lines = text.split( "\n" );
  85. for ( line in lines ) {
  86. if ( lines[ line ].length == 0 ) continue;
  87. var dat = lines[ line ].split( " " );
  88. if ( dat[ 0 ] == "wire" ) {
  89. this.comps[ parseInt( dat[ 1 ] , 10 ) ].SetInput( parseInt( dat[ 2 ] , 10 ) , this.comps[ parseInt( dat[ 3 ] , 10 ) ] , parseInt( dat[ 4 ] , 10 ) );
  90. } else if ( dat[ 0 ].substr( 0 , 2 ) != "--" ) {
  91. this.comps[ parseInt( dat[ 0 ] , 10 ) ] = eval( "new " + dat[ 1 ] + "(" + dat[ 2 ] + "," + dat[ 3 ] + ")" );
  92. }
  93. }
  94. for ( com in this.comps ) {
  95. if ( typeof this.comps[ com ].Trigger != "undefined" ) {
  96. this.comps[ com ].Trigger( );
  97. }
  98. }
  99. }
  100. // Logic Gate - AND
  101. var Gate_And = function( x , y ) {
  102. this.x = x;
  103. this.y = y;
  104. this.input = [ ];
  105. this.output = [ ];
  106. this.gates = [ ];
  107. }
  108. Gate_And.prototype.Name = "AND Gate";
  109. Gate_And.prototype.Icon = "&";
  110. Gate_And.prototype.Hook = function( conn ) {
  111. this.gates[ this.gates.length ] = conn;
  112. }
  113. Gate_And.prototype.SetInput = function( id , in_gate , out_id ) {
  114. this.input[ id ] = [ in_gate , out_id ];
  115. in_gate.Hook( this );
  116. }
  117. Gate_And.prototype.Trigger = function( ) {
  118. var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] & this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] );
  119. if ( out != this.output[ 0 ] ) {
  120. this.output[ 0 ] = out;
  121. for ( conn in this.gates ) {
  122. this.gates[ conn ].Trigger( );
  123. }
  124. }
  125. }
  126. // Logic Gate - NAND
  127. var Gate_Nand = function( x , y ) {
  128. this.x = x;
  129. this.y = y;
  130. this.input = [ ];
  131. this.output = [ ];
  132. this.gates = [ ];
  133. }
  134. Gate_Nand.prototype.Name = "NAND Gate";
  135. Gate_Nand.prototype.Icon = "!&";
  136. Gate_Nand.prototype.Hook = function( conn ) {
  137. this.gates[ this.gates.length ] = conn;
  138. }
  139. Gate_Nand.prototype.SetInput = function( id , in_gate , out_id ) {
  140. this.input[ id ] = [ in_gate , out_id ];
  141. in_gate.Hook( this );
  142. }
  143. Gate_Nand.prototype.Trigger = function( ) {
  144. var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] & this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] );
  145. if ( out != this.output[ 0 ] ) {
  146. this.output[ 0 ] = out;
  147. for ( conn in this.gates ) {
  148. this.gates[ conn ].Trigger( );
  149. }
  150. }
  151. }
  152. // Logic Gate - OR
  153. var Gate_Or = function( x , y ) {
  154. this.x = x;
  155. this.y = y;
  156. this.input = [ ];
  157. this.output = [ ];
  158. this.gates = [ ];
  159. }
  160. Gate_Or.prototype.Name = "OR Gate";
  161. Gate_Or.prototype.Icon = "|";
  162. Gate_Or.prototype.Hook = function( conn ) {
  163. this.gates[ this.gates.length ] = conn;
  164. }
  165. Gate_Or.prototype.SetInput = function( id , in_gate , out_id ) {
  166. this.input[ id ] = [ in_gate , out_id ];
  167. in_gate.Hook( this );
  168. }
  169. Gate_Or.prototype.Trigger = function( ) {
  170. var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] | this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
  171. if ( out != this.output[ 0 ] ) {
  172. this.output[ 0 ] = out;
  173. for ( conn in this.gates ) {
  174. this.gates[ conn ].Trigger( );
  175. }
  176. }
  177. }
  178. // Logic Gate - NOR
  179. var Gate_Nor = function( x , y ) {
  180. this.x = x;
  181. this.y = y;
  182. this.input = [ ];
  183. this.output = [ ];
  184. this.gates = [ ];
  185. }
  186. Gate_Nor.prototype.Name = "NOR Gate";
  187. Gate_Nor.prototype.Icon = "!|";
  188. Gate_Nor.prototype.Hook = function( conn ) {
  189. this.gates[ this.gates.length ] = conn;
  190. }
  191. Gate_Nor.prototype.SetInput = function( id , in_gate , out_id ) {
  192. this.input[ id ] = [ in_gate , out_id ];
  193. in_gate.Hook( this );
  194. }
  195. Gate_Nor.prototype.Trigger = function( ) {
  196. var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] | this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
  197. if ( out != this.output[ 0 ] ) {
  198. this.output[ 0 ] = out;
  199. for ( conn in this.gates ) {
  200. this.gates[ conn ].Trigger( );
  201. }
  202. }
  203. }
  204. // Logic Gate - XOR
  205. var Gate_Xor = function( x , y ) {
  206. this.x = x;
  207. this.y = y;
  208. this.input = [ ];
  209. this.output = [ ];
  210. this.gates = [ ];
  211. }
  212. Gate_Xor.prototype.Name = "XOR Gate";
  213. Gate_Xor.prototype.Icon = "x|";
  214. Gate_Xor.prototype.Hook = function( conn ) {
  215. this.gates[ this.gates.length ] = conn;
  216. }
  217. Gate_Xor.prototype.SetInput = function( id , in_gate , out_id ) {
  218. this.input[ id ] = [ in_gate , out_id ];
  219. in_gate.Hook( this );
  220. }
  221. Gate_Xor.prototype.Trigger = function( ) {
  222. var out = ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ^ this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
  223. if ( out != this.output[ 0 ] ) {
  224. this.output[ 0 ] = out;
  225. for ( conn in this.gates ) {
  226. this.gates[ conn ].Trigger( );
  227. }
  228. }
  229. }
  230. // Logic Gate - XNOR
  231. var Gate_Xnor = function( x , y ) {
  232. this.x = x;
  233. this.y = y;
  234. this.input = [ ];
  235. this.output = [ ];
  236. this.gates = [ ];
  237. }
  238. Gate_Xnor.prototype.Name = "XNOR Gate";
  239. Gate_Xnor.prototype.Icon = "x!|";
  240. Gate_Xnor.prototype.Hook = function( conn ) {
  241. this.gates[ this.gates.length ] = conn;
  242. }
  243. Gate_Xnor.prototype.SetInput = function( id , in_gate , out_id ) {
  244. this.input[ id ] = [ in_gate , out_id ];
  245. in_gate.Hook( this );
  246. }
  247. Gate_Xnor.prototype.Trigger = function( ) {
  248. var out = !( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ^ this.input[ 1 ][ 0 ].output[ this.input[ 1 ][ 1 ] ] )
  249. if ( out != this.output[ 0 ] ) {
  250. this.output[ 0 ] = out;
  251. for ( conn in this.gates ) {
  252. this.gates[ conn ].Trigger( );
  253. }
  254. }
  255. }
  256. // Logic Gate - Inverter
  257. var Gate_Inv = function( x , y ) {
  258. this.x = x;
  259. this.y = y;
  260. this.input = [ ];
  261. this.output = [ ];
  262. this.gates = [ ];
  263. }
  264. Gate_Inv.prototype.Name = "Inverter Gate";
  265. Gate_Inv.prototype.Icon = "!";
  266. Gate_Inv.prototype.Hook = function( conn ) {
  267. this.gates[ this.gates.length ] = conn;
  268. }
  269. Gate_Inv.prototype.SetInput = function( id , in_gate , out_id ) {
  270. this.input[ id ] = [ in_gate , out_id ];
  271. in_gate.Hook( this );
  272. }
  273. Gate_Inv.prototype.Trigger = function( ) {
  274. var out = !this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ];
  275. if ( out != this.output[ 0 ] ) {
  276. this.output[ 0 ] = out;
  277. for ( conn in this.gates ) {
  278. this.gates[ conn ].Trigger( );
  279. }
  280. }
  281. }
  282. // Input - Logic Input
  283. var Input = function( x , y ) {
  284. this.x = x;
  285. this.y = y;
  286. this.input = [ ];
  287. this.output = [ ];
  288. this.gates = [ ];
  289. this.Icon = "0";
  290. }
  291. Input.prototype.Name = "Logic Input";
  292. Input.prototype.Hook = function( conn ) {
  293. this.gates[ this.gates.length ] = conn;
  294. }
  295. Input.prototype.SetInput = function( ) { }
  296. Input.prototype.MouseDown = function( parent ) {
  297. this.output[ 0 ] = ( this.output[ 0 ] ) ? false : true;
  298. this.Icon = ( this.output[ 0 ] ) ? "1" : "0";
  299. for ( conn in this.gates ) {
  300. this.gates[ conn ].Trigger( );
  301. }
  302. }
  303. Input.prototype.Color = function( parent ) {
  304. return ( this.output[ 0 ] ) ? "rgb(150,150,150)" : "rgb(75,75,75)";
  305. }
  306. // Input - Logic Output
  307. var Output = function( x , y ) {
  308. this.x = x;
  309. this.y = y;
  310. this.input = [ ];
  311. this.output = [ ];
  312. this.gates = [ ];
  313. this.Icon = "0";
  314. }
  315. Output.prototype.Name = "Logic Output";
  316. Output.prototype.Hook = function( conn ) {
  317. this.gates[ this.gates.length ] = conn;
  318. }
  319. Output.prototype.SetInput = function( id , in_gate , out_id ) {
  320. this.input[ id ] = [ in_gate , out_id ];
  321. in_gate.Hook( this );
  322. }
  323. Output.prototype.Color = function( parent ) {
  324. return ( this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ] ) ? "rgb(0,200,0)" : "rgb(150,0,0)";
  325. }
  326. Output.prototype.Trigger = function( parent ) {
  327. var out = this.input[ 0 ][ 0 ].output[ this.input[ 0 ][ 1 ] ];
  328. if ( out != this.output[ 0 ] ) {
  329. this.output[ 0 ] = out;
  330. this.Icon = ( this.output[ 0 ] ) ? "1" : "0";
  331. for ( conn in this.gates ) {
  332. this.gates[ conn ].Trigger( );
  333. }
  334. }
  335. }
  336. // Initialization Code Here
  337. var circuit;
  338. var myComponent;
  339. window.onload = function( ) {
  340. circuit = new Surkit( "cvs" );
  341. setInterval( "circuit.Draw( )" , 50 );
  342. document.getElementById( "cvs" ).onmousemove = function( e ) {
  343. var cv = document.getElementById( "cvs" );
  344. var x = 0;
  345. var y = 0;
  346. e = ( window.event ) ? window.event : e;
  347. if ( e.pageX || e.pageY ) {
  348. x = e.pageX;
  349. y = e.pageY;
  350. }
  351. else if ( e.clientX || e.clientY ) {
  352. x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  353. y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  354. }
  355. circuit.SetMousePosition( x - parseInt( cv.style.left , 10 ) , y - parseInt( cv.style.top , 10 ) );
  356. }
  357. document.getElementById( "cvs" ).onmousedown = function( e ) {
  358. circuit.MouseDown( );
  359. return false;
  360. }
  361. }
  362. </script>
  363. </head>
  364. <body>
  365. <canvas id="cvs" style="position:absolute;top:10px;left:10px;border:1px solid" width="800" height="500"></canvas><br />
  366. <textarea id="input" style="position:absolute;top:520px;left:10px;width:700px;height:100px"></textarea>
  367. <input type="button" style="position:absolute;top:520px;left:712px;width:100px;height:100px" onclick="circuit.LoadSurkit( document.getElementById('input').value )" value="Load" />
  368. </body>
  369. </html>