[Toss-devel-svn] SF.net SVN: toss:[1254] trunk/Toss/WebClient
Status: Beta
Brought to you by:
lukaszkaiser
From: <luk...@us...> - 2010-12-18 17:50:00
|
Revision: 1254 http://toss.svn.sourceforge.net/toss/?rev=1254&view=rev Author: lukaszkaiser Date: 2010-12-18 17:49:52 +0000 (Sat, 18 Dec 2010) Log Message: ----------- Continue to improve WebClient, order in file names, registration and user table. Modified Paths: -------------- trunk/Toss/WebClient/README trunk/Toss/WebClient/index.html trunk/Toss/WebClient/make_db.py trunk/Toss/WebClient/register.html Added Paths: ----------- trunk/Toss/WebClient/Connect.js trunk/Toss/WebClient/DefaultStyle.js trunk/Toss/WebClient/Handler.py trunk/Toss/WebClient/Login.js trunk/Toss/WebClient/Main.js trunk/Toss/WebClient/Style.css Removed Paths: ------------- trunk/Toss/WebClient/TossConnect.js trunk/Toss/WebClient/TossDefaultStyle.js trunk/Toss/WebClient/TossHandler.py trunk/Toss/WebClient/TossMain.js trunk/Toss/WebClient/TossStyle.css Copied: trunk/Toss/WebClient/Connect.js (from rev 1253, trunk/Toss/WebClient/TossConnect.js) =================================================================== --- trunk/Toss/WebClient/Connect.js (rev 0) +++ trunk/Toss/WebClient/Connect.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,212 @@ +// JavaScript Toss Module -- Connect (basic Toss Server connection routines) + +var UNAME = ""; + +var MODEL_MAXX = 0.0; +var MODEL_MINX = 0.0; +var MODEL_MAXY = 0.0; +var MODEL_MINY = 0.0; +var MODEL_WIDTH = 0.0; +var MODEL_HEIGHT = 0.0; +var SVG_WIDTH = 500; +var SVG_HEIGHT = 500; +var SVG_MARGINX = 50; +var SVG_MARGINY = 50; +var VIEW_WIDTH = "19em"; +var VIEW_HEIGHT = "19em"; +var VIEW_MIRROR = 0; + +var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" +var ELEMS = []; // used to store the list of elements +var ELEM_POS = {}; // positions of elements +var RELS = []; // relations +var SUGGESTED_ELEM_SIZEX = 25; // suggested size of elements +var SUGGESTED_ELEM_SIZEY = 25; // suggested size of elements + +var CACHED_MOVES = "" + +var DIM_STR = "" +var ELEM_STR = "" +var RELS_STR = "" +var MOVES_STR = "" + + +// Helper function: sign of a number. +function sign (x) { + if (x > 0.01) { return (1); } + else if (x < -0.01) { return (-1); } + else { return (0); } +} + +// Clears cached moves. +function clear_move_cache () { + CACHED_MOVES = ""; +} + +function set_info (info) { + var res_arr = []; + res_arr = info.split("$"); + if (res_arr.length != 4) { return (false); } + DIM_STR = res_arr[0]; + ELEM_STR = res_arr[1]; + RELS_STR = res_arr[2]; + MOVES_STR = res_arr[3]; + var dim = strip('(', ')', DIM_STR).split(','); + MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); + MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); + MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); + MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); + MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); + MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); + + return (true); +} + +// Send [msg] to server and return response text. +function sync_server_msg (msg) { + var xml_request = new XMLHttpRequest (); + xml_request.open ('POST', 'TossHandler.py', false); + xml_request.setRequestHeader ('Content-Type', + 'application/x-www-form-urlencoded; charset=UTF-8'); + xml_request.send (msg); + resp = xml_request.responseText; + if (resp.indexOf ("MOD_PYTHON ERROR") > -1) { + alert (resp.substring(resp.indexOf("Traceback"))); + return (""); + } + return (resp) +} + +// Send [msg] to server attaching prefix '[cmd]#' and return response text. +function srv (cmd, msg) { + return (sync_server_msg (cmd + '#' + msg)); +} + +// Strip [c1] and [c2] from beginning and end of [str]. +function strip (c1, c2, str) { + if (str.length == 0) return (str); + var i = 0; var j = 0; + for (i = 0; i < str.length; i++) { + if (str.charAt(i) != c1 && str.charAt(i) != c2) break; + } + for (j = str.length - 1; j > -1; j--) { + if (str.charAt(j) != c1 && str.charAt(j) != c2) break; + } + if (i > j) { return ("") }; + return (str.substring(i, j+1)); +} + +// Convert a string [str] representing python list to array and return it. +// WARNING: we use [sep] as separator, it must not occur in list elements! +function convert_python_list (sep, str) { + var res_arr = []; + res_arr = strip('[', ']', str).split(sep); + if (res_arr.length == 1 && res_arr[0] == "") { return ([]); } + for (i = 0; i < res_arr.length; i++) { + res_arr[i] = strip (' ', '\'', res_arr[i]) + } + return (res_arr); +} + + +// Get moves applicable to [elem] in a game. +function get_moves (elem) { + if (CACHED_MOVES == "") { + CACHED_MOVES = MOVES_STR + } + var all_moves = convert_python_list (';', CACHED_MOVES); + var elem_moves = [] + for (i = 0; i < all_moves.length; i++) { + if (all_moves[i].indexOf(elem) >= 0) { + elem_moves.push(all_moves[i]) + } + } + return (elem_moves) +} + +// Get relation tuples. +function get_rels () { + var r = convert_python_list(';', RELS_STR); + var rels = []; + for (var i = 0; i < r.length; i++) { + var rel_name = strip(' ', '\'', r[i].substring(1,r[i].indexOf(','))); + var args_s = r[i].substring(r[i].indexOf('[')+1, r[i].indexOf(']')); + if (rel_name[0] != "_" && args_s != "''") { + rels.push ([rel_name, convert_python_list (',', args_s)]); + } + } + return (rels) +} + +// Translate position from Toss Model coordinates to SVG coordinates. +function translate_pos (pos) { + var x = ((pos[0] - MODEL_MINX) * SVG_WIDTH) / MODEL_WIDTH; + if (VIEW_MIRROR == 0) { + var y = ((pos[1] - MODEL_MINY) * SVG_HEIGHT) / MODEL_HEIGHT; + } else { + var y = ((MODEL_HEIGHT - (pos[1] - MODEL_MINY)) * SVG_WIDTH) / MODEL_HEIGHT; + } + return ([x + SVG_MARGINX, y + SVG_MARGINY]) +} + +// Get elements and positions. +function get_elems_with_pos () { + var l = convert_python_list(',', ELEM_STR); + ELEMS = []; + ELEM_POS = {}; + for (var i = 0; i < l.length; i++) { + var e = convert_python_list (';', l[i]); + ELEMS.push (e[0]); + ELEM_POS[e[0]] = translate_pos ([parseFloat(e[1]), parseFloat(e[2])]); + } +} + + +// Open [file_name] on Toss Server and get info. +function toss_open_db (file_name_params) { + var info = srv ("OPEN_DB", file_name_params); + set_info (info); +} + + +// ---- Two functions below are very basic and thus in this file. --- + +// Create basic svg box. +function create_svg_box (bwidth, bheight, margx, margy, parent_id) { + VIEW_WIDTH = bwidth; + VIEW_HEIGHT = bheight; + SVG_MARGINX = margx; + SVG_MARGINY = margx; + var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + svg.setAttribute('id', 'svg'); + svg.setAttribute('width', bwidth); + svg.setAttribute('height', bheight); + var wx = SVG_WIDTH + 2*SVG_MARGINX; + var wy = SVG_HEIGHT + 2*SVG_MARGINY; + svg.setAttribute('viewBox', '0 0 ' + wx + " " + wy); + document.getElementById(parent_id).appendChild(svg); +} + +// Create new svg element [elem], child of svg, with [attributes]. +function svg_from_string (x, y, sizex, sizey, s) { + var parser = new DOMParser (); + var svgs = '<svg version="1.1" xmlns="http://www.w3.org/2000/svg">'; + var scfx = (SUGGESTED_ELEM_SIZEX - 10) / sizex; + var scfy = (SUGGESTED_ELEM_SIZEY - 10) / sizey; + var sc = "scale(" + scfx + "," + scfy + ")"; + var gs = '<g transform="translate(' + x + "," + y + ") " + sc + '">'; + var doc = parser.parseFromString(svgs+ gs+ s + ' </g> </svg>', "text/xml"); + var elem = document.adoptNode(doc.childNodes[0]); + return(elem.childNodes[0]); +} + + +// Create new svg element [elem], child of svg, with [attributes]. +function add_svg (elem, attributes) { + var elem = document.createElementNS("http://www.w3.org/2000/svg", elem); + elem.setAttribute ("class", "svgelem"); + for (var i = 0; i < attributes.length; i++) { + elem.setAttribute (attributes[i][0], attributes[i][1].toString()); + } + document.getElementById("svg").appendChild(elem); +} Copied: trunk/Toss/WebClient/DefaultStyle.js (from rev 1253, trunk/Toss/WebClient/TossDefaultStyle.js) =================================================================== --- trunk/Toss/WebClient/DefaultStyle.js (rev 0) +++ trunk/Toss/WebClient/DefaultStyle.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,272 @@ +// JavaScript Toss Module -- DefaultStyle (requires TossConnect.js) + +// This module implements default drawing style for games. +// Functions expected from this module: +// - draw_outline () +// - draw_elem (elem) +// - highlight_elem (elem) +// - unhighlight_elem (elem) +// - draw_rel (rel_name, args) + + +var DEFpawn = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 22,9 C 19.792,9 18,10.792 18,13 C 18,13.885 18.294,14.712 18.781,15.375 C 16.829,16.497 15.5,18.588 15.5,21 C 15.5,23.034 16.442,24.839 17.906,26.031 C 14.907,27.089 10.5,31.578 10.5,39.5 L 33.5,39.5 C 33.5,31.578 29.093,27.089 26.094,26.031 C 27.558,24.839 28.5,23.034 28.5,21 C 28.5,18.588 27.171,16.497 25.219,15.375 C 25.706,14.712 26,13.885 26,13 C 26,10.792 24.208,9 22,9 z " \ + class="chess-path-A" /> \ + </g>'; + +var DEFknight = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 22,10 C 32.5,11 38.5,18 38,39 L 15,39 C 15,30 25,32.5 23,18" \ + class="chess-path-B" /> \ + <path \ + d="M 24,18 C 24.384,20.911 18.447,25.369 16,27 C 13,29 13.181,31.343 11,31 C 9.9583,30.056 12.413,27.962 11,28 C 10,28 11.187,29.232 10,30 C 9,30 5.9968,31 6,26 C 6,24 12,14 12,14 C 12,14 13.886,12.098 14,10.5 C 13.274,9.5056 13.5,8.5 13.5,7.5 C 14.5,6.5 16.5,10 16.5,10 L 18.5,10 C 18.5,10 19.282,8.0081 21,7 C 22,7 22,10 22,10" \ + class="chess-path-B" /> \ + <path \ + d="M 9 23.5 A 0.5 0.5 0 1 1 8,23.5 A 0.5 0.5 0 1 1 9 23.5 z" \ + transform="translate(0.5,2)" \ + class="chess-path-C" /> \ + <path \ + d="M 15 15.5 A 0.5 1.5 0 1 1 14,15.5 A 0.5 1.5 0 1 1 15 15.5 z" \ + transform="matrix(0.866,0.5,-0.5,0.866,9.6926,-5.1734)" \ + class="chess-path-C" /> \ + <path \ + d="M 37,39 C 38,19 31.5,11.5 25,10.5" \ + class="chess-path-D" /> \ + </g>'; + +var DEFbishop = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9,36 C 12.385,35.028 19.115,36.431 22.5,34 C 25.885,36.431 32.615,35.028 36,36 C 36,36 37.646,36.542 39,38 C 38.323,38.972 37.354,38.986 36,38.5 C 32.615,37.528 25.885,38.958 22.5,37.5 C 19.115,38.958 12.385,37.528 9,38.5 C 7.6459,38.986 6.6771,38.972 6,38 C 7.3541,36.055 9,36 9,36 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 15,32 C 17.5,34.5 27.5,34.5 30,32 C 30.5,30.5 30,30 30,30 C 30,27.5 27.5,26 27.5,26 C 33,24.5 33.5,14.5 22.5,10.5 C 11.5,14.5 12,24.5 17.5,26 C 17.5,26 15,27.5 15,30 C 15,30 14.5,30.5 15,32 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 25 10 A 2.5 2.5 0 1 1 20,10 A 2.5 2.5 0 1 1 25 10 z" \ + transform="translate(0,-2)" \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 17.5,26 L 27.5,26" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 15,30 L 30,30" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 22.5,15.5 L 22.5,20.5" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + <path \ + d="M 20,18 L 25,18" \ + style="stroke-linecap:butt;" class="chess-path-D" /> \ + </g>'; + +var DEFrook = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9,39 L 36,39 L 36,36 L 9,36 L 9,39 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 12,36 L 12,32 L 33,32 L 33,36 L 12,36 z " \ + style="stroke-linecap:butt;" class="chess-path-Bx" /> \ + <path \ + d="M 11,14 L 11,9 L 15,9 L 15,11 L 20,11 L 20,9 L 25,9 L 25,11 L 30,11 L 30,9 L 34,9 L 34,14" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 34,14 L 31,17 L 14,17 L 11,14" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 31,17 L 31,29.5 L 14,29.5 L 14,17" \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 31,29.5 L 32.5,32 L 12.5,32 L 14,29.5" \ + class="chess-path-Bx" /> \ + <path \ + d="M 11,14 L 34,14" \ + class="chess-path-D" /> \ + </g>'; + +var DEFqueen = '<g transform="translate(-22.5,-22.5)"> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(-1,-1)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(15.5,-5.5)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(32,-1)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(7,-4.5)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9 13 A 2 2 0 1 1 5,13 A 2 2 0 1 1 9 13 z" \ + transform="translate(24,-4)" \ + style="fill-rule: none;" class="chess-path-B" /> \ + <path \ + d="M 9,26 C 17.5,24.5 30,24.5 36,26 L 38,14 L 31,25 L 31,11 L 25.5,24.5 L 22.5,9.5 L 19.5,24.5 L 14,10.5 L 14,25 L 7,14 L 9,26 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 9,26 C 9,28 10.5,28 11.5,30 C 12.5,31.5 12.5,31 12,33.5 C 10.5,34.5 10.5,36 10.5,36 C 9,37.5 11,38.5 11,38.5 C 17.5,39.5 27.5,39.5 34,38.5 C 34,38.5 35.5,37.5 34,36 C 34,36 34.5,34.5 33,33.5 C 32.5,31 32.5,31.5 33.5,30 C 34.5,28 36,28 36,26 C 27.5,24.5 17.5,24.5 9,26 z " \ + style="stroke-linecap:butt;" class="chess-path-B" /> \ + <path \ + d="M 11.5,30 C 15,29 30,29 33.5,30" \ + class="chess-path-D" /> \ + <path \ + d="M 12,33.5 C 18,32.5 27,32.5 33,33.5" \ + class="chess-path-D" /> \ + <path \ + d="M 10.5,36 C 15.5,35 29,35 34,36" \ + class="chess-path-D" /> \ + </g>'; + +var DEFking = '<g transform="translate(-22.5,-22.5)"> \ + <path d="M 22.5,11.625 L 22.5,6" class="chess-path-D" /> \ + <path d="M 22.5,25 C 22.5,25 27,17.5 25.5,14.5 C 25.5,14.5 24.5,12 22.5,12 C 20.5,12 19.5,14.5 19.5,14.5 C 18,17.5 22.5,25 22.5,25" \ + style="fill:stroke-linecap:butt;" class="chess-path-B" /> \ + <path d="M 11.5,37 C 17,40.5 27,40.5 32.5,37 L 32.5,30 C 32.5,30 41.5,25.5 38.5,19.5 C 34.5,13 25,16 22.5,23.5 L 22.5,27 L 22.5,23.5 C 19,16 9.5,13 6.5,19.5 C 3.5,25.5 11.5,29.5 11.5,29.5 L 11.5,37 z " \ + class="chess-path-D" /> \ + <path d="M 20,8 L 25,8" class="chess-path-D" /> \ + <path d="M 11.5,29.5 C 17,27 27,27 32.5,30" class="chess-path-D" /> \ + <path d="M 11.5,37 C 17,34.5 27,34.5 32.5,37" \ + class="chess-path-D" /> \ + <path d="M 11.5,33.5 C 17,31.5 27,31.5 32.5,33.5" \ + class="chess-path-D" /> \ + </g>'; + +// Draw a box around the board. +function draw_outline () { + var w = SVG_WIDTH + 2*SVG_MARGINX; + var h = SVG_HEIGHT + 2*SVG_MARGINY; + add_svg ("rect", [["class", "board-outline"], ["width", w], ["height", h]]); +} + +// Draw the element [elem]. +function draw_elem (elem) { + var pos = ELEM_POS[elem]; + add_svg ("rect", + [["x", pos[0] - SUGGESTED_ELEM_SIZEX], + ["y", pos[1] - SUGGESTED_ELEM_SIZEY], + ["width", 2 * SUGGESTED_ELEM_SIZEX], + ["height", 2 * SUGGESTED_ELEM_SIZEX], + ["id", "elem_" + elem], + ["class", "model-elem"], + ["onclick", ("handle_elem_click('" + elem + "')")]] + ); +} + +// Highlight the element [elem]. +function highlight_elem (elem) { + var e = document.getElementById ("elem_" + elem); + e.setAttribute ("class", "model-elem-highlight"); +} + +// Unhighlight the element [elem]. +function unhighlight_elem (elem) { + var e = document.getElementById ("elem_" + elem); + e.setAttribute ("class", "model-elem"); +} + +// Draw relation [rel_name] between elements [args]. +function draw_rel (rel_name, args) { + if (args.length == 1) { + var is = 'id="' + "pred_" + args[0] + "_" + rel_name + '" '; + var hs = 'onclick="' + "handle_elem_click('" + args[0] + "')" + '" '; + var pos = ELEM_POS[args[0]]; + if (rel_name == "P") { // Tic-tac-toe cross + var cs = 'class="' + "model-pred-" + rel_name + '" '; + var ls1 = '<line x1="-10" y1="-10" x2="10" y2="10" />'; + var ls2 = '<line x1="10" y1="-10" x2="-10" y2="10" />'; + var cr = svg_from_string (pos[0], pos[1], 12, 12, + '<g ' + cs + is + hs + '>' + ls1 + ls2 + '</g>'); + document.getElementById("svg").appendChild(cr); + } else if (rel_name == "R") { // Robber in Entanglement + add_svg ("circle", + [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 5], + ["id", "pred_" + args[0] + "_" + rel_name], + ["class", "model-pred-" + rel_name], + ["onclick", ("handle_elem_click('" + args[0] + "')")]]); + } else if (rel_name == "wP") { // Chess Figure: white pawn + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFpawn + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bP") { // Chess Figure: black pawn + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFpawn + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wN") { // Chess Figure: white knight + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFknight + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bN") { // Chess Figure: black knight + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFknight + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wB") { // Chess Figure: white bishop + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFbishop + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bB") { // Chess Figure: black bishop + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFbishop + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wR") { // Chess Figure: white rook + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFrook + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bR") { // Chess Figure: black rook + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFrook + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wQ") { // Chess Figure: white queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFqueen + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bQ") { // Chess Figure: black queen + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFqueen + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "wK") { // Chess Figure: white king + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessW" ' + is + hs + '>' + DEFking + '</g>'); + document.getElementById("svg").appendChild(f); + } else if (rel_name == "bK") { // Chess Figure: black king + var f = svg_from_string (pos[0], pos[1], 20, 20, + '<g class="chessB" ' + is + hs + '>' + DEFking + '</g>'); + document.getElementById("svg").appendChild(f); + } else { + add_svg ("circle", + [["cx", pos[0]], ["cy", pos[1]], ["r", SUGGESTED_ELEM_SIZEX - 12], + ["id", "pred_" + args[0] + "_" + rel_name], + ["class", "model-pred-" + rel_name], + ["stroke-width", (SUGGESTED_ELEM_SIZEX / 10) + 2], + ["onclick", ("handle_elem_click('" + args[0] + "')")]]); + } + } + if (args.length == 2) { + if (rel_name == "E") { + var pos1 = ELEM_POS[args[0]]; + var pos2 = ELEM_POS[args[1]]; + if (sign (pos1[0] - pos2[0]) == 0) { + var d = SUGGESTED_ELEM_SIZEY * sign (pos1[1] - pos2[1]); + add_svg ("line", [["x1", pos1[0]], ["y1", pos1[1] - d], + ["x2", pos2[0]], ["y2", pos2[1] + d], + ["class", "model-edge-E"]]); + } else if (sign (pos1[1] - pos2[1]) == 0) { + var d = SUGGESTED_ELEM_SIZEX * sign (pos1[0] - pos2[0]); + add_svg ("line", [["x1", pos1[0] - d], ["y1", pos1[1]], + ["x2", pos2[0] + d], ["y2", pos2[1]], + ["class", "model-edge-E"]]); + } + else { + var dx = SUGGESTED_ELEM_SIZEX * sign (pos1[0] - pos2[0]); + var dy = SUGGESTED_ELEM_SIZEY * sign (pos1[1] - pos2[1]); + add_svg ("line", [["x1", pos1[0] + dx], ["y1", pos1[1] + dy], + ["x2", pos2[0] - dx], ["y2", pos2[1] - dy], + ["class", "model-edge-E"]]); + } + } + } +} Copied: trunk/Toss/WebClient/Handler.py (from rev 1253, trunk/Toss/WebClient/TossHandler.py) =================================================================== --- trunk/Toss/WebClient/Handler.py (rev 0) +++ trunk/Toss/WebClient/Handler.py 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,227 @@ +import subprocess +import socket +import time +from Wrapper import * +from mod_python import apache, Cookie +from pysqlite2 import dbapi2 as sqlite3 + +DB_FILE = "/var/www/WebClient/tossdb.sqlite" + +TUID = "toss_id_05174_" + +def tmp_log (str): + file = open ("/tmp/th.log", 'a') + file.write (str) + file.close() + +def get_all_from_db (db, tbl, select_s): + res = [] + for r in db.execute("select * from " + tbl + " where " + select_s): + res.append(r) + return (res) + +def open_toss_server (port): + args = ["/var/www/WebClient/TossServer", + "-s", "localhost", "-p", str(port)] + server_proc = subprocess.Popen(args) + time.sleep (0.1) + return (port) + +def get_global_lock (db): + cur = db.cursor () + cur.execute ("update lock set locked='true' " + + " where locked='false' and tid='" + str(TUID) + "'") + db.commit () + if cur.rowcount == 1: + return + time.sleep (0.1) + get_global_lock (db) + +def release_global_lock (db): + db.execute ("update lock set locked='false' " + + " where locked='true' and tid='" + str(TUID) + "'") + db.commit () + +def get_toss_port (db): + get_global_lock (db) + free_ports = get_all_from_db (db, "ports", "locked='false'") + if len(free_ports) == 0: + fid = 0 + for f in db.execute ("select count(*) from ports"): + fid = int(f[0]) + port = 8110+fid+1 + db.execute ("insert into ports(port, locked) values (?, ?)", + (port, 'true')) + release_global_lock (db) + open_toss_server (port) + return (port) + (port, _) = free_ports[0] + db.execute ("update ports set locked='true' where port=" + str(port)) + release_global_lock (db) + return (port) + +def release_toss_port (db, port): + db.execute ("update ports set locked='false' where port=" + str(port)) + db.commit () + +def cp (f1, f2): + subprocess.call(["cp", f1, f2]) + +def list_plays (db, game, player_id): + or_s = "(player1='" + player_id + "' or player2='" + player_id + "')" + plays = get_all_from_db (db, "cur_states", "game='"+ game + "' and " + or_s) + def play_name (p): + (pid, g, p1, p2, move, _, _, _) = p + return ("/plays/" + str(g) + "_" + str(p1) + "_" + str(p2) + "_" + + str(pid) + "_" + str(move)) + return (str([play_name (p) for p in plays])) + +def db_cur_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into cur_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) + db.commit () + +def db_old_insert (db, game, p1, p2, pid, move, toss, info, svg_str): + db.execute ("insert into old_states(playid, game, player1, player2, move, toss, info, svg) values (?, ?, ?, ?, ?, ?, ?, ?)", + (pid, game, p1, p2, move, toss, info, svg_str)) + db.commit () + +def get_game_info (client): + dim_s = str(client.model.get_dim()) + model_s = str(client.model.get_elems_with_pos()) + rels_s = str(client.model.get_rels_simple()) + moves_s = str(client.cur_moves()) + return (dim_s + "$" + model_s + "$" + rels_s + "$" + moves_s) + +def new_play (db, client, game, p1, p2, pid, move): + res = get_all_from_db (db, "games", "game='" + game + "'") + (_, toss) = res[0] + client.open_from_str (toss) + info = get_game_info (client) + model = client.get_model () + db_cur_insert (db, game, p1, p2, pid, move, model, info, "") + return (info) + +def game_select_s (g, p1, p2, pid, m): + return("game='" + g + "' and player1='" + p1 + "' and player2='" + p2 + + "' and playid=" + pid + " and move=" + m) + +def open_db (db, game, p1, p2, pid, move): + select_s = game_select_s (game, p1, p2, pid, move) + res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, _, info, _) = res[0] + return (info) + + +def move_play (db, client, move_tup, g, p1, p2, pid, m): + select_s = game_select_s (g, p1, p2, pid, m) + old_res = get_all_from_db (db, "cur_states", select_s) + (_, _, _, _, _, old_toss, old_info, old_svg) = old_res[0] + res = get_all_from_db (db, "games", "game='" + g + "'") + (_, game_toss) = res[0] + client.open_from_str (game_toss + "\n MODEL " + old_toss) + (move1, move2, move3) = move_tup + client.make_move (move1, move2, move3) + new_toss = client.get_model () + new_info = get_game_info (client) + db.execute ("delete from cur_states where " + select_s) + db_old_insert (db, g, p1, p2, pid, m, old_toss, old_info, old_svg) + db_cur_insert (db, g, p1, p2, pid, int(m) + 1, new_toss, new_info, "") + return (new_info) + +def upd_svg (db, g, p1, p2, pid, m, svg_s): + select_s = game_select_s (g, p1, p2, pid, m) + db.execute ("update cur_states set svg='" + svg_s + "' where " + select_s) + db.commit () + +def passwd_from_db (db, uid): + res = get_all_from_db (db, "users", "id='" + uid + "'") + if len(res) > 1: raise Exception ("db", "multiple entries for " + uid) + if len(res) == 0: return (None) + (uid, _, _, _, passwd) = res[0] + return (str(passwd)) + +def confirm_username (db, req): + cookies = Cookie.get_cookies(req) + if not (cookies.has_key(TUID + 'username')): return "" + if not (cookies.has_key(TUID + 'passphrase')): return "" + uid = cookies[TUID + 'username'].value + pwd1 = cookies[TUID + 'passphrase'].value + pwd2 = passwd_from_db (db, uid) + if (pwd1 != pwd2): return "" + return (uid) + +def login_user (db, req, uid, pwd): + db_pwd = passwd_from_db (db, uid) + if not db_pwd: return ("no such user registered") + if (pwd != db_pwd): return ("wrong password") + t = time.time() + 3600; + cookie1 = Cookie.Cookie(TUID + 'username', uid, expires=t) + cookie2 = Cookie.Cookie(TUID + 'passphrase', pwd, expires=t) + Cookie.add_cookie(req, cookie1) + Cookie.add_cookie(req, cookie2) + return ("OK") + +def register_user (db, ui): + if len(ui) != 5: return (False) + (uid, name, surname, email, pwd) = (ui[0], ui[1], ui[2], ui[3], ui[4]) + if passwd_from_db (db, uid): return (False) + db.execute ("insert into users(id, name, surname, email, passwd) " + + "values (?, ?, ?, ?, ?)", (uid, name, surname, email, pwd)) + db.commit () + return (True) + +def get_free_id (db): + fid = 0 + for f in db.execute ("select count(*) from cur_states"): + fid = int(f[0]) + return (fid + 1) + +def handler(req): + req.content_type = "text/plain" + db = sqlite3.connect(DB_FILE) + usr = confirm_username (db, req) + msg = req.read () + #tmp_log(msg) + cmd, sep, data = msg.partition('#') + if cmd == "USERNAME": + req.write(usr) + return apache.OK + if cmd == "REGISTER": + ui = data.split('$') + if register_user (db, ui): + req.write("Registration successful for " + ui[0] + ".") + return apache.OK + req.write("Registration failed:\n username "+ui[0]+" already in use."+ + "\nPlease choose another username and try again.") + return apache.OK + if cmd == "LOGIN": + uname, sep, pwd = data.partition(' ') + res = login_user (db, req, uname, pwd) + if res == "OK": + req.write("OK") + return apache.OK + req.write("Login failed for " + uname + ": " + res) + return apache.OK + if cmd == "LOGOUT": + cookie = Cookie.Cookie(TUID + 'passphrase', "a") + cookie = Cookie.Cookie(TUID + 'username', "a") + Cookie.add_cookie(req, cookie) + req.write ("user logged out: " + usr + ".") + return apache.OK + if cmd == "FREEID": + req.write(str(get_free_id (db))) + return apache.OK + if (cmd == "LIST_PLAYS") or (cmd == "OPEN_DB") or (cmd == "UPD_SVG"): + res = eval (cmd.lower() + "(db, " + data + ")") + req.write(str(res)) + return apache.OK + if (cmd == "NEW_PLAY") or (cmd == "MOVE_PLAY"): + port = get_toss_port (db) + c = SystemClient ("localhost", port) + res = eval (cmd.lower() + "(db, " + data + ")") + release_toss_port (db, port) + req.write(str(res)) + return apache.OK + req.write("MOD_PYTHON ERROR ; Traceback: Unknown Toss Command! \n " + cmd) + return apache.OK Added: trunk/Toss/WebClient/Login.js =================================================================== --- trunk/Toss/WebClient/Login.js (rev 0) +++ trunk/Toss/WebClient/Login.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,113 @@ +// JavaScript Toss Module -- Login (requires Main.js, all other) + +TSALT = "toss##in$$some167S4lT_-"; +CORRMSG = "\nPlease correct this and try again." + + +// Simple encryption +function crypt (s) { + var c = Crypto.SHA256(s, true); + var d = c.replace("#", "@"); + return (d.replace("$", "@")); +} + +// Setup a user +function setup_user (un) { + UNAME = un + document.getElementById("topuser").innerHTML = "Welcome " + un; + document.getElementById("loginform").style.display = "none"; + document.getElementById("topright-register").style.display = "none"; + document.getElementById("topright").style.display = "inline"; + document.getElementById("welcome").style.display = "none"; + document.getElementById("plays").style.display = "block"; + list_plays ("Breakthrough"); + list_plays ("Chess"); + list_plays ("Entanglement"); + list_plays ("Gomoku"); + list_plays ("Tic-Tac-Toe"); +} + +// Clear view +function clear_view () { + document.getElementById("loginform").style.display = "inline"; + document.getElementById("topright-register").style.display = "inline"; + document.getElementById("topright").style.display = "none"; + document.getElementById("topuser").innerHTML = ""; + document.getElementById("plays").style.display = "none"; + document.getElementById("game-title").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("welcome").style.display = "block"; +} + +// Onload handler +function startup () { + if (navigator.userAgent.indexOf('MSIE') !=-1) { + document.getElementById("nosvg").style.display = "block"; + } else { + var un = srv("USERNAME", "user"); + if (un != "") { setup_user (un) }; + } +} + +// Login +function login () { + un = document.getElementById('username').value; + pwd = document.getElementById('password').value; + resp = sync_server_msg ("LOGIN#" + un + " " + crypt(TSALT + pwd)); + if (resp == "OK") { + setup_user (un) + } else { + alert (resp) + } +} + +// Logout +function logout () { + clear_view (); +} + +// Register new user +function register () { + un = document.getElementById('username').value; + pwd = document.getElementById('password').value; + rptpwd = document.getElementById('rptpassword').value; + name = document.getElementById('name').value; + surname = document.getElementById('surname').value; + email = document.getElementById('email').value; + if (un.length < 2) { + alert ("Your username must contain at least 2 letters." + CORRMSG); + return; + } + if (un.indexOf(" ") > 0) { + alert ("Your username must not contain spaces." + CORRMSG); + return; + } + if (pwd.length < 3) { + alert ("Your password is too short." + CORRMSG); + return; + } + if (pwd != rptpwd) { + alert ("Password and Repeated Password do not match." + CORRMSG); + return; + } + if (name == "") { + alert ("Your name was not given and it is necessary." + CORRMSG); + return; + } + if (surname == "") { + alert ("Your surname was not given and it is necessary." + CORRMSG); + return; + } + if (email.indexOf("@") < 1 || email.indexOf(".") < 1) { + alert ("Please provide a valid email address."); + return; + } + if (un.indexOf ("$") > 0 || name.indexOf ("$") > 0 || + surname.indexOf ("$") > 0 || email.indexOf ("$") > 0) { + alert ("Your data must not contain $, i.e. the dolar sign." + CORRMSG); + return; + } + data = un + "$" + name + "$" + surname + "$" + email; + resp = sync_server_msg ("REGISTER#" + data + "$" + crypt(TSALT + pwd)); + alert (resp); +} Copied: trunk/Toss/WebClient/Main.js (from rev 1253, trunk/Toss/WebClient/TossMain.js) =================================================================== --- trunk/Toss/WebClient/Main.js (rev 0) +++ trunk/Toss/WebClient/Main.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,321 @@ +// JavaScript Toss Module -- Main (requires Connect.js, DefaultStyle.js) + +var ELEM_COUNTERS = {}; +var CUR_MOVE = ""; +var CUR_ELEMS = []; + +var PLAYS = []; +var CUR_PLAY_I = -1; + +var FRIENDS = [] + +var MAX_OPNT_LEN = 20; +var FULL_OPNT_LEN = 0; +var CUR_OPNT_START = 0; + +// Get model information from server. +function get_model_info () { + get_elems_with_pos (); + for (var i = 0; i < ELEMS.length; i++) { + ELEM_COUNTERS[ELEMS[i]] = 0; + } + RELS = get_rels (); + var sqrt = Math.round (Math.sqrt (ELEMS.length)); + if (sqrt * sqrt == ELEMS.length) { // perhaps a grid + SUGGESTED_ELEM_SIZEX = SVG_WIDTH / (2.0 * (sqrt-1)); + SUGGESTED_ELEM_SIZEY = SVG_HEIGHT / (2.0 * (sqrt-1)); + } else { + SUGGESTED_ELEM_SIZEX = SVG_WIDTH / 20; + SUGGESTED_ELEM_SIZEY = SVG_HEIGHT / 20; + } +} + +// Draw the model using function from Toss[X]Style.js. +// WARNING: must call get_model_info first! +function draw_model () { + draw_outline (); + for (var i = 0; i < ELEMS.length; i++) { + draw_elem (ELEMS[i]); + } + for (var i = 0; i < RELS.length; i++) { + draw_rel (RELS[i][0], RELS[i][1]); + } +} + +// Clear whole svg box. +function clear_svg () { + clear_move_cache (); + ELEM_COUNTERS = {}; + CUR_MOVE = ""; + CUR_ELEMS = []; + document.getElementById('cur-move').innerHTML = "none"; + var svg_e = document.getElementById("svg"); + svg_e.parentNode.removeChild (svg_e); +} + +// Full redraw. +function full_redraw () { + clear_svg (); + document.getElementById("working").style.display = "block"; + get_model_info (); + create_svg_box (VIEW_WIDTH, VIEW_HEIGHT, SVG_MARGINX, SVG_MARGINY, "board"); + draw_model (); + document.getElementById("working").style.display = "none"; +} + +// Helper function: get value elements from a move string [s]. +function get_move_elems (s) { + var vals = []; + var arr = strip('(', ')', s).split(','); + for (var i = 0; i < arr.length; i++) { + if (arr[i].indexOf(':') > -1) { + var v = arr[i].substring (arr[i].indexOf(':')+1, arr[i].length); + vals.push (strip ('\'', ' ', strip ('{', '}', v))); + } + } + return (vals) +} + +// Helper function: highlight move, unhighlight old, save current. +function show_move (m) { + var m_act = get_move_elems (m); + var m_rule = m.substring (m.indexOf("},")+4, m.lastIndexOf(',')-1); + for (var i = 0; i < CUR_ELEMS.length; i++) { + unhighlight_elem (CUR_ELEMS[i]); + } + for (var i = 0; i < m_act.length; i++) { + highlight_elem (m_act[i]); + } + var m_str = strip (' ', ' ', m_act.toString ()); + if (m_str == "") { + document.getElementById('cur-move').innerHTML = "none"; + } else { + document.getElementById('cur-move').innerHTML = + m_rule + ': <br/>' + m_str; + } + CUR_ELEMS = m_act; + CUR_MOVE = m.toString(); +} + +// Handler for clicks on elements. +function handle_elem_click (elem) { + var moves = get_moves (elem); + if (moves.length > ELEM_COUNTERS[elem]) { + show_move (moves[ELEM_COUNTERS[elem]]); + ELEM_COUNTERS[elem] += 1; + } else if (moves.length > 0) { + show_move (moves[0]); + ELEM_COUNTERS[elem] = 1; + } +} + +function play_py_id (i) { + return ("'" + GAME_NAME + "', '" + PLAYS[i][0] + "', '" + + PLAYS[i][1] + "', '" + PLAYS[i][2] + "', '" + PLAYS[i][3] + "'") +} + +function new_play_item (game, i) { + var li = document.createElement('li'); + li.setAttribute ("class", "plays-list-elem"); + li.setAttribute ("id", "plays-list-" + game + "-elem-" + i); + var p = PLAYS[i][2]; + li.innerHTML = "" + PLAYS[i][2] + ': ' + PLAYS[i][0] + " vs " + + PLAYS[i][1] + " " + //" move " + PLAYS[i][3] + " "+ + '<a title="Open" href="#" onclick="'+ "play_click('"+ game + "', " + p + + ", " + i + ')">Open</a>'; + // +'<a href="#" onclick="'+ "del_play('"+ fn + "')" + '">Delete</a>'; + return (li); +} + +function list_plays (game) { + var lst = srv ("LIST_PLAYS", "'" + game + "', '" + UNAME + "'"); + PLAYS = convert_python_list (',', lst); + var plist = document.getElementById("plays-list-" + game); + while (plist.childNodes.length > 0) { plist.removeChild(plist.firstChild); } + var d = game.length + 2; + for (var i = 0; i < PLAYS.length; i++) { + var p = PLAYS[i].substring(PLAYS[i].lastIndexOf('/') + d); + PLAYS[i] = convert_python_list ('_', p); + plist.appendChild(new_play_item (game, i)); + } + if (PLAYS.length == 0) { + document.getElementById("plays-list-" + game).style.display = "none"; + } else { + document.getElementById("plays-list-" + game).style.display = "block"; + } +} + +function game_click (game) { + document.getElementById("welcome").style.display = "none"; + document.getElementById("game-disp").style.display = "none"; + document.getElementById("plays").style.display = "none"; + GAME_NAME = game; + if (game == "Tic-Tac-Toe") { // bigger margins needed + create_svg_box ("19em", "19em", 130, 130, "board"); + } else { + create_svg_box ("19em", "19em", 40, 40, "board"); + } + document.getElementById("opening").style.display = "block"; + document.getElementById("opening").style.display = "none"; + document.getElementById("game-disp").style.display = "block"; +} + +function play_click (game, play_id, pi) { + list_plays (game); + game_click (game); + document.getElementById ("game-title").innerHTML = game; + document.getElementById("game-disp").style.display = "block"; + document.getElementById("play-number").innerHTML = "" + play_id; + CUR_PLAY_I = pi; + VIEW_MIRROR = (PLAYS[CUR_PLAY_I][0] == UNAME) ? 0 : 1; + document.getElementById("cur-player").innerHTML = + PLAYS[CUR_PLAY_I][PLAYS[CUR_PLAY_I][3] % 2]; + toss_open_db (play_py_id(pi)); + full_redraw (); +} + + +// Apply current move. +function make_move () { + if (CUR_MOVE == "") return; + var m = PLAYS[CUR_PLAY_I][3] % 2; + if (PLAYS[CUR_PLAY_I][m] != UNAME) { + alert ("It is your Opponent's turn"); + return; + } + var info = srv("MOVE_PLAY", 'c, '+ CUR_MOVE +', '+ play_py_id (CUR_PLAY_I)); + set_info (info); + clear_move_cache (); + CUR_MOVE = ""; + CUR_ELEMS = []; + ELEM_COUNTERS = {}; + document.getElementById("cur-player").innerHTML = + PLAYS[CUR_PLAY_I][(m + 1) % 2]; + document.getElementById('cur-move').innerHTML = "none"; + full_redraw (); + PLAYS[CUR_PLAY_I][3] = parseInt(PLAYS[CUR_PLAY_I][3]) + 1; + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + var old_li = document.getElementById ("plays-list-" + GAME_NAME + "-elem-" + CUR_PLAY_I); + var li = new_play_item (GAME_NAME, CUR_PLAY_I); + old_li.parentNode.replaceChild (li, old_li); +} + + +function del_play (play) { + alert ("Deleting " + play); +} + +function store_friend_names () { + for (var i = 0; i < FRIENDS.length; i++) { + ID_TO_USER_MAP[FRIENDS[i].id] = FRIENDS[i].name; + ID_TO_USER_FNAME_MAP[FRIENDS[i].id] = FRIENDS[i].first_name; + } +} + +function opponent_item (data, index) { + var li = document.createElement('li'); + li.setAttribute ("class", "opponents-list-elem"); + li.setAttribute ("id", "opponent-" + data.id + "-" + index); + li.innerHTML = '<a href="#" onclick="new_play_do(' + data.id + ')">' + + data.name + '</a>'; + return (li); +} + +function data_cmp (d1, d2) { + if (d1.name < d2.name) { return -1; } + if (d1.name > d2.name) { return 1; } + return (0); +} + +function make_opnt_list () { + var o = document.getElementById("opponents-list"); + FULL_OPNT_LEN = FRIENDS.length + 1; + CUR_OPNT_START = 0; + document.getElementById("opponents-prev").style.display = "none"; + if (MAX_OPNT_LEN > FULL_OPNT_LEN) { + document.getElementById("opponents-next").style.display = "none" + } + var zeroli = document.createElement('li'); + zeroli.setAttribute ("class", "opponents-list-elem"); + zeroli.setAttribute ("id", "opponent-" + "-0"); + zeroli.innerHTML = '<a href="#" onclick="new_play_do(-1)">Play against Yourself</a>'; + o.appendChild (zeroli); + for (var i = 0; i < FRIENDS.length; i++) { + var oi = opponent_item (FRIENDS[i], i+1); + if (i > MAX_OPNT_LEN - 2) { oi.style.display = "none"; } + o.appendChild (oi); + } + document.getElementById("opponents").style.display = "block"; +} + +function new_play (game) { + if (UNAME == "") { alert ("Please log in to create plays"); return; } + GAME_NAME = game; + make_opnt_list (); +} + +function opponents_next () { + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + document.getElementById("opponent-" + "-" + i).style.display = "none"; + } + CUR_OPNT_START += MAX_OPNT_LEN; + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + if (i < FULL_OPNT_LEN) { + document.getElementById("opponent-" + "-" + i).style.display = "list-item"; + } + } + document.getElementById("opponents-prev").style.display = "block" + if (CUR_OPNT_START + MAX_OPNT_LEN > FULL_OPNT_LEN) { + document.getElementById("opponents-next").style.display = "none" + } +} + +function opponents_prev () { + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + if (i < FULL_OPNT_LEN) { + document.getElementById("opponent-" + "-" + i).style.display = "none"; + } + } + CUR_OPNT_START -= MAX_OPNT_LEN; + for (var i = CUR_OPNT_START; i < CUR_OPNT_START + MAX_OPNT_LEN; i++) { + document.getElementById("opponent-" + "-" + i).style.display = "list-item"; + } + document.getElementById("opponents-next").style.display = "block" + if (CUR_OPNT_START == 0) { + document.getElementById("opponents-prev").style.display = "none" + } +} + +function svg_string () { + var svg_el = document.getElementById ("svg"); + var svg_s = (new XMLSerializer()).serializeToString(svg_el); + svg_s = svg_s.replace(/onclick="[^\"]*"/g, ""); + return ("'''" + svg_s + "'''"); +} + +function new_play_do (opp_uid) { + list_plays (GAME_NAME) + game_click (GAME_NAME) + document.getElementById("opponents").style.display = "none"; + var olist = document.getElementById("opponents-list"); + while (olist.childNodes.length > 0) { olist.removeChild(olist.firstChild); } + if (opp_uid == -1) { opp_uid = UNAME; } + if (opp_uid == 0 || UNAME == "") { return; } + document.getElementById("plays-list-" + GAME_NAME).style.display = "block"; + FREE_PLAY_NO = parseInt(srv("FREEID", "play")) + document.getElementById("play-number").innerHTML = "" + FREE_PLAY_NO; + CUR_PLAY_I = PLAYS.length; + VIEW_MIRROR = 0; + document.getElementById("cur-player").innerHTML = UNAME; + document.getElementById("game-disp").style.display = "block"; + document.getElementById("plays").style.left = "30em"; + var p = [UNAME, opp_uid, FREE_PLAY_NO, 0]; + PLAYS.push(p); + var fn = play_py_id (CUR_PLAY_I); + info = srv ("NEW_PLAY", "c, " + fn); + set_info(info); + full_redraw (); + srv ("UPD_SVG", play_py_id(CUR_PLAY_I) + ", " + svg_string()); + li = new_play_item (GAME_NAME, CUR_PLAY_I); + document.getElementById("plays-list-" + GAME_NAME).appendChild(li); +} Modified: trunk/Toss/WebClient/README =================================================================== --- trunk/Toss/WebClient/README 2010-12-18 00:52:28 UTC (rev 1253) +++ trunk/Toss/WebClient/README 2010-12-18 17:49:52 UTC (rev 1254) @@ -7,19 +7,19 @@ in the file /etc/apache2/sites-enabled/[your-site] add e.g. <Directory /var/www/WebClient> AddHandler mod_python .py - PythonHandler TossHandler + PythonHandler Handler # During development you might turn debugging on PythonDebug On </Directory> -The main handler script is called TossHander.py (server side) and corresponding -JavaScript functions are in Toss*.js. To start client open index.html, but +The main handler script is called Hander.py (server side) and corresponding +JavaScript functions are in *.js. To start client open index.html, but first make sure that WebClient is linked in /var/www (ln -s should suffice). -Then run "./make_db" from WebClient and make sure TossHandler top is ok. +Then run "./make_db" from WebClient and make sure Handler entry (above) is ok. Also copy Server from main Toss dir as TossServer to the WebClient directory. TODO: - - better register html and user table + - use name in interface, try buttons, add oponents table and adding page - move interface: first click all, second click toggle, if one - confirm msg - after the above: remove left-of-board div, confirm in the middle - after the above: show game result in the middle / instead of move Copied: trunk/Toss/WebClient/Style.css (from rev 1253, trunk/Toss/WebClient/TossStyle.css) =================================================================== --- trunk/Toss/WebClient/Style.css (rev 0) +++ trunk/Toss/WebClient/Style.css 2010-12-18 17:49:52 UTC (rev 1254) @@ -0,0 +1,515 @@ +/* General */ + +html { + height: 100%; + width: 100%; +} + +body { + background-color: #b5bf8f; + font-family: Verdana, 'TeXGyreHerosRegular', sans; + height: 100%; +} + +.reglabel { + float: left; + clear: left; + width: 10em; +} + +#logo { + font-size: 2em; + float: left; + font-family: arial, 'OFLSortsMillGoudyRegular', serif; + width: 4.5em; + padding-left: 0.25em; +} + +#logo a, #logo a:link, #logo a:active, #logo a:visited { + color: #ffe4aa; + background-color: transparent; + text-decoration: none; +} + +#logo a:hover { + color: #b5bf8f; +} + +.logo-in { + /*font-family: 'OFL Sorts Mill Goudy TT', arial, serif; + font-size: 1.2em;*/ +} + +#top { + font-weight: bold; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 2.5em; + color: #ffe4aa; + background-color: #400827; + border-color: #260314; + border-style: solid; + border-width: 0px 0px 5px 0px; +} + +#topbar { + margin-left: 9.5em; + padding-left: 1em; + padding-right: 1em; + padding-top: 0.7em; +} + +#topright { + float: right; + margin-right: 0em; + display: none; +} + +#topright-register { + float: right; + margin-right: 0em; +} + +#bottom { + position: relative; + bottom: 0px; + left: -0.5em; + width: 100%; + padding-right: 1em; + height: 1.3em; + text-align: right; + color: #ffe4aa; + background-color: #400827; + border-color: #260314; + border-style: solid; + border-width: 5px 0px 0px 0px; +} + +#menu-top-par { + margin-top: 0.5em; + margin-bottom: 0em; +} + +#menu-list { + list-style: none; + padding: 0em; + margin: 0.25em; + margin-bottom: 0.5em; +} + +#topbar a { + font-weight: bold; + text-decoration: none; + color: #ffe4aa; + width: 100%; +} + +#topbar a:hover { + color: #b5bf8f; +} + + +/* Content */ + +.game_list { + font-weight: bold; +} + +.game_list a { + font-weight: normal; +} + +#main { + margin-top: 2.5em; + color: #260314; + background-color: #ffe4aa; + margin-left: 1em; + margin-right: 1em; + padding: 1em; + min-height: 100%; + padding-bottom: 2em; + border: 1px solid #260314; + border-bottom: 0px; +} + +#main a, #main a:link, #main a:active, #main a:visited { + color: #260314; + text-decoration: underline; +} + +#main a:hover { + color: #400827; + text-decoration: none; +} + + +#opponents { + display: none; + position: absolute; + left: 19em; + top: 3.5em; + min-width: 20em; + color: #ffe4aa; + background-color: #400827; + font-weight: bold; + padding: 1em; + border: 1px solid #260314; + z-index: 10; +} + +#opponents a, #opponents a:link, #opponents a:active, #opponents a:visited { + color: #ffe4aa; + text-decoration: none; + font-weight: bold; +} + +#opponents a:hover { + color: #b5bf8f; +} + +#opponents-list { + list-style: square; + margin-top: 0.5em; +} + +.opponents-list-elem { + /* margin-left: -1em; */ +} + +#opponents-next { + position: absolute; + right: 1em; + bottom: 0.25em; +} + +#opponents-prev { + position: absolute; + left: 1em; + bottom: 0.25em; + display: none; +} + +#welcome { + text-align: justify; + margin-top: 1em; +} + +#welcome-top { + font-size: 1.2em; + font-weight: bold; + padding-left: 1.25em; +} + +.short { + max-width: 40em; +} + +#features-list { + list-style: square; +} + +#game-title { + font-size: 1.2em; + font-weight: bold; + margin-top: 1em; + margin-bottom: 2em; +} + +#game-disp { + position: relative; + display: none; +} + +#game-desc { + text-align: justify; + display: none; + width: 29em; + height: 19em; + margin-right: 1em; + padding-right: 1em; + border-right: 1px solid #260314; +} + +#board { + position: absolute; + left: 9em; + padding-right: 1em; + top: 0px; + width: 20em; + height: 19em; + border-right: 1px solid #260314; +} + +#working { + position: absolute; + left: 4.5em; + top: 7em; + width: 10em; + text-align: center; + font-weight: bold; + color: #ffe4aa; + background-color: #400827; + display: none; + padding: 1em; +} + +#opening { + position: absolute; + left: 10em; + top: 7em; + width: 16em; + text-align: center; + font-weight: bold; + color: #ffe4aa; + background-color: #400827; + display: none; + padding: 1em; +} + +#move { + position: absolute; + left: 0px; + top: 0px; +} + +#play-no-div { + padding-bottom: 0.5em; + padding-left: 1em; +} + +#cur-move, #cur-player { + padding-left: 1em; + margin-top: 0.5em; + margin-bottom: 0.5em; +} + +#mk-move { + padding-left: 0em; +} + +#plays { + display: none; + padding-left: 1em; +} + +#plays-list { + list-style: none; + margin-top: 0.25em; +} + +.plays-list-elem { + margin-left: -1.5em; +} + +.plays-list-elem a { + margin-right: 0.5em; +} + +.plays-list-elem .thumb { + position: relative; + top: 5px; + left: 0px; + border: 1px solid #260314; +} + + + +/* SVG styling */ +.board-outline { + fill: #b5bf8f; + stroke: #260314; + stroke-width: 10px; +} + +.model-elem { + fill: #b5bf8f; + stroke: #260314; + stroke-width: 3px; +} + +.model-elem-highlight { + fill: #ffe4aa; + stroke: #400827; + stroke-width: 3px; +} + +.model-pred-P { + fill: #400827; + stroke: #260314; + stroke-width: 5px; +} + +.model-pred-Q { + fill: #b5bf8f; + stroke: #260314; +} + +.model-pred-C { + fill: #ffe4aa; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-R { + fill: #400827; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-W { + fill: #ffe4aa; + stroke: #260314; + stroke-width: 3px; +} + +.model-pred-B { + fill: #400827; + stroke: #260314; + stroke-width: 3px; +} + +.model-edge-E { + fill: #260314; + stroke: #260314; + stroke-width: 3px; +} + +.chessW .chess-path-A { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:nonzero; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:miter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-dashoffset:10; + stroke-opacity:1; +} + +.chessB .chess-path-A { + opacity:1; + fill:#400827; + fill-opacity:1; + fill-rule:nonzero; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:miter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-dashoffset:10; + stroke-opacity:1; +} + +.chessW .chess-path-B { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-B { + opacity:1; + fill: #400827; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-Bx { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-Bx { + opacity:1; + fill: #ffe4aa; + fill-opacity:1; + fill-rule:evenodd; + stroke: #400827; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-C { + opacity:1; + fill:#400827; + fill-opacity:1; + stroke:#260314; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-C { + opacity:1; + fill:#ffe4aa; + fill-opacity:1; + stroke:#ffe4aa; + stroke-width:1.5; + stroke-linecap:round; + stroke-linejoin:round; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessW .chess-path-D { + fill: #ffe4aa; + fill-opacity: 0.75; + fill-rule:evenodd; + stroke: #260314; + stroke-width:1; + stroke-linecap:round; + stroke-linejoin:mitter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} + +.chessB .chess-path-D { + fill: #400827; + fill-opacity: 0.75; + fill-rule:evenodd; + stroke: #ffe4aa; + stroke-width:1; + stroke-linecap:round; + stroke-linejoin:mitter; + stroke-miterlimit:4; + stroke-dasharray:none; + stroke-opacity:1; +} Deleted: trunk/Toss/WebClient/TossConnect.js =================================================================== --- trunk/Toss/WebClient/TossConnect.js 2010-12-18 00:52:28 UTC (rev 1253) +++ trunk/Toss/WebClient/TossConnect.js 2010-12-18 17:49:52 UTC (rev 1254) @@ -1,219 +0,0 @@ -// JavaScript Toss Module -- Connect (basic Toss Server connection routines) - -var UNAME = ""; - -var MODEL_MAXX = 0.0; -var MODEL_MINX = 0.0; -var MODEL_MAXY = 0.0; -var MODEL_MINY = 0.0; -var MODEL_WIDTH = 0.0; -var MODEL_HEIGHT = 0.0; -var SVG_WIDTH = 500; -var SVG_HEIGHT = 500; -var SVG_MARGINX = 50; -var SVG_MARGINY = 50; -var VIEW_WIDTH = "19em"; -var VIEW_HEIGHT = "19em"; -var VIEW_MIRROR = 0; - -var GAME_NAME = ""; // name of current game, e.g. "Breakthrough" -var ELEMS = []; // used to store the list of elements -var ELEM_POS = {}; // positions of elements -var RELS = []; // relations -var SUGGESTED_ELEM_SIZEX = 25; // suggested size of elements -var SUGGESTED_ELEM_SIZEY = 25; // suggested size of elements - -var CACHED_MOVES = "" - -var DIM_STR = "" -var ELEM_STR = "" -var RELS_STR = "" -var MOVES_STR = "" - - -// Helper function: sign of a number. -function sign (x) { - if (x > 0.01) { return (1); } - else if (x < -0.01) { return (-1); } - else { return (0); } -} - -// Clears cached moves. -function clear_move_cache () { - CACHED_MOVES = ""; -} - -function set_info (info) { - var res_arr = []; - res_arr = info.split("$"); - if (res_arr.length != 4) { return (false); } - DIM_STR = res_arr[0]; - ELEM_STR = res_arr[1]; - RELS_STR = res_arr[2]; - MOVES_STR = res_arr[3]; - var dim = strip('(', ')', DIM_STR).split(','); - MODEL_MAXX = parseFloat(strip(' ', ' ', dim[0])); - MODEL_MINX = parseFloat(strip(' ', ' ', dim[1])); - MODEL_MAXY = parseFloat(strip(' ', ' ', dim[2])); - MODEL_MINY = parseFloat(strip(' ', ' ', dim[3])); - MODEL_WIDTH = Math.max (SVG_WIDTH / 100, (MODEL_MAXX - MODEL_MINX)); - MODEL_HEIGHT = Math.max (SVG_HEIGHT / 100, (MODEL_MAXY - MODEL_MINY)); - - return (true); -} - -// Send [msg] to server and return response text. -function sync_server_msg (msg) { - var xml_request = new XMLHttpRequest (); - xml_request.open ('POST', 'TossHandler.py', false); - xml_request.setRequestHeader ('Content-Type', - 'application/x-www-form-urlencoded; charset=UTF-8'); - xml_request.send (msg); - resp = xml_request.responseText; - if (resp.indexOf ("MOD_PYTHON ERROR") > -1) { - alert (resp.substring(resp.indexOf("Traceback"))); - return (""); - } - return (resp) -} - -// Simple encryption -function crypt (s) { - var c = Crypto.SHA256(s, true); - var d = c.replace("#", "$"); - return (d.replace(" ", "$")); -} - -// Send [msg] to server attaching prefix '[cmd]#' and return response text. -function srv (cmd, msg) { - return (sync_server_msg (cmd + '#' + msg)); -} - -// Strip [c1] and [c2] from beginning and end of [str]. -function strip (c1, c2, str) { - if (str.length == 0) return (str); - var i = 0; var j = 0; - for (i = 0; i < str.length; i++) { - if (str.charAt(i) != c1 && str.charAt(i) != c2) break; - } - for (j = str.length - 1; j > -1; j--) { - if (str.charAt(j) != c1 && str.charAt(j) != c2) break; - } - if (i > j) { return ("") }; - return (str.substring(i, j+1)); -} - -// Convert a string [str] representing python list to array and return it. -// WARNING: we use [sep] as separator, it must not occur in list elements! -funct... [truncated message content] |