isundil 8 лет назад
Родитель
Сommit
fb709e5919
11 измененных файлов с 247 добавлено и 4 удалено
  1. 26 0
      js/Makefile
  2. BIN
      js/closure-compiler-v20170218.jar
  3. 80 0
      js/grid.js
  4. 13 0
      js/resources.js
  5. 53 0
      js/ui.js
  6. 46 0
      js/workflow.js
  7. 3 0
      public/crosswords.min.js
  8. 11 0
      public/game.html
  9. 0 1
      public/index.html
  10. 14 2
      src/Grid.js
  11. 1 1
      src/httpServer.js

+ 26 - 0
js/Makefile

@@ -0,0 +1,26 @@
+
+SRC=		\
+			resources.js		\
+			ui.js				\
+			grid.js				\
+			workflow.js
+
+OUTPUT=		../public/crosswords.min.js
+
+CLOSURE=	closure-compiler-v20170218.jar
+
+all:
+	java -jar ${CLOSURE} --compilation_level ADVANCED --language_in=ECMASCRIPT5_STRICT --warning_level=VERBOSE --js_output_file ${OUTPUT} ${SRC}
+
+debug:
+	java -jar ${CLOSURE} --compilation_level WHITESPACE_ONLY --language_in=ECMASCRIPT5_STRICT --js_output_file ${OUTPUT} ${SRC}
+
+$OUTPUT: all
+
+clean:
+	$(RM) $(OUTPUT)
+
+re:	clean all
+
+.PHONY: all debug clean re
+

BIN
js/closure-compiler-v20170218.jar


+ 80 - 0
js/grid.js

@@ -0,0 +1,80 @@
+
+/**
+ * @constructor
+**/
+function Definition(data) {
+    /** @type {Array.<string>} */
+    this.text = data["text"];
+    /** @type {number} */
+    this.direction = data["pos"];
+}
+
+/** @const */
+Definition.RIGHT_HORIZONTAL = 1;
+/** @const */
+Definition.RIGHT_VERTICAL = 2;
+/** @const */
+Definition.BOTTOM_HORIZONTAL = 3;
+/** @const */
+Definition.BOTTOM_VERTICAL = 4;
+
+/**
+ * @constructor
+**/
+function Cell() {
+    /** @type {boolean} */
+    this.isBlack = false;
+    /** @type {Array.<Definition>} */
+    this.definitions = null;
+}
+
+Cell.prototype.update = function(data) {
+    if (data["type"] === null) {
+        this.isBlack = true;
+    } else if (data["definitions"] !== undefined) {
+        this.definitions = [];
+        data["definitions"].forEach(function(definition) {
+            this.definitions.push(new Definition(definition));
+        }.bind(this));
+    } else {
+        // Grid letter
+        // TODO return version
+    }
+    return 0;
+};
+
+/**
+ * @constructor
+**/
+function Grid(data) {
+    /** @type {string} */
+    this.title = data["title"] || "";
+    /** @type {number} */
+    this.difficulty = data["difficulty"];
+    /** @type {number} */
+    this.width = data["w"];
+    /** @type {number} */
+    this.height = data["h"];
+
+    this.grid = [];
+    for (var i =0; i < this.width; i++) {
+        this.grid[i] = [];
+        for (var j =0; j < this.height; j++) {
+            this.grid[i][j] = new Cell();
+        }
+    }
+}
+
+/**
+ * @return {number|null}
+**/
+Grid.prototype.update = function(data) {
+    var maxVersion = null
+        ,grid = this.grid;
+
+    data.forEach(function(cellData) {
+        maxVersion = Math.max(maxVersion || 0, grid[cellData["x"]][cellData["y"]].update(cellData));
+    });
+    return maxVersion;
+};
+

+ 13 - 0
js/resources.js

@@ -0,0 +1,13 @@
+
+var R = {
+    klass: {
+        line: "crossword-line"
+        ,cell: {
+            item: "cell"
+            ,black: "cell-disabled"
+            ,definition: "cell-definition"
+            ,letter: "cell-letter"
+        }
+    }
+};
+

+ 53 - 0
js/ui.js

@@ -0,0 +1,53 @@
+
+var UI_CELLS = [];
+
+function dCreate(domName) {
+    return document.createElement(domName);
+}
+
+function uiCreateCell(cellData) {
+    var cell = dCreate("div");
+
+    cell.className = R.klass.cell.item;
+    if (cellData.isBlack) {
+        cell.classList.add(R.klass.cell.black);
+    } else if (cellData.definitions !== null) {
+        cell.classList.add(R.klass.cell.definition);
+    } else {
+        cell.classList.add(R.klass.cell.letter);
+        console.log(cellData);
+    }
+    return cell;
+}
+
+function uiCreateGrid() {
+    var frag = document.createDocumentFragment();
+
+    for (var i =0; i < GRID.height; i++) {
+        var line = dCreate("div");
+
+        line.className = R.klass.line;
+        frag.appendChild(line);
+        for (var j =0; j < GRID.width; j++) {
+            var cell = uiCreateCell(GRID.grid[j][i]);
+            line.appendChild(cell);
+            UI_CELLS.push({
+                x: j
+                ,y: i
+                ,dom: cell
+                ,data: GRID.grid[j][i]
+            });
+        }
+    }
+    document.body.textContent = "";
+    document.body.appendChild(frag);
+}
+
+function onGridUpdated() {
+    UI_CELLS.forEach(function(i) {
+        if (!i.data.definitions && !i.data.isBlack) {
+            //TODO
+        }
+    });
+}
+

+ 46 - 0
js/workflow.js

@@ -0,0 +1,46 @@
+
+var GRID_PUBLIC_ID
+    ,KNOWN_VERSION = 0
+    ,GRID;
+
+function doGet(url, callback) {
+    var xhr = new XMLHttpRequest();
+    xhr.onreadystatechange = function(e) {
+        if (xhr.readyState === 4) {
+            var resp = null;
+
+            if (xhr.status === 200) {
+                resp = xhr.response;
+                try {
+                    resp = JSON.parse(/** @type {string} */ (resp));
+                } catch (e) {
+                    resp = null;
+                }
+            }
+            callback(resp);
+        }
+    };
+    xhr.open('GET', url, true);
+    xhr.send(null);
+}
+
+function initPolling() {
+    doGet("/api/poll?grid=" +GRID_PUBLIC_ID +"&v=" +KNOWN_VERSION, function(resp) {
+        GRID = new Grid(resp);
+        if (resp["grid"]) {
+            KNOWN_VERSION = Math.max(GRID.update(resp["grid"]) || 0, KNOWN_VERSION);
+            uiCreateGrid();
+        }
+    });
+}
+
+document.addEventListener('DOMContentLoaded', function() {
+    GRID_PUBLIC_ID = (document.location.hash.substr(1));
+
+    if (GRID_PUBLIC_ID == "") {
+        document.location.href = "/";
+        return;
+    }
+    initPolling();
+});
+

+ 3 - 0
public/crosswords.min.js

@@ -0,0 +1,3 @@
+var e=[];function h(){}function k(){this.g=!1;this.b=null}k.prototype.update=function(a){null===a.type?this.g=!0:void 0!==a.definitions&&(this.b=[],a.definitions.forEach(function(){this.b.push(new h)}.bind(this)));return 0};function l(a){this.f=a.w;this.c=a.h;this.a=[];for(a=0;a<this.f;a++){this.a[a]=[];for(var b=0;b<this.c;b++)this.a[a][b]=new k}}l.prototype.update=function(a){var b=null,c=this.a;a.forEach(function(a){b=Math.max(b||0,c[a.x][a.y].update(a))});return b};var m,n=0,p;function q(a){var b="/api/poll?grid="+m+"&v="+n,c=new XMLHttpRequest;c.onreadystatechange=function(){if(4===c.readyState){var b=null;if(200===c.status){b=c.response;try{b=JSON.parse(b)}catch(d){b=null}}a(b)}};c.open("GET",b,!0);c.send(null)}
+function r(){q(function(a){p=new l(a);if(a.grid){n=Math.max(p.update(a.grid)||0,n);a=document.createDocumentFragment();for(var b=0;b<p.c;b++){var c=document.createElement("div");c.className="crossword-line";a.appendChild(c);for(var f=0;f<p.f;f++){var d;d=p.a[f][b];var g=document.createElement("div");g.className="cell";d.g?g.classList.add("cell-disabled"):null!==d.b?g.classList.add("cell-definition"):(g.classList.add("cell-letter"),console.log(d));d=g;c.appendChild(d);e.push({x:f,y:b,i:d,data:p.a[f][b]})}}document.body.textContent=
+"";document.body.appendChild(a)}})}document.addEventListener("DOMContentLoaded",function(){m=document.location.hash.substr(1);""==m?document.location.href="/":r()});

+ 11 - 0
public/game.html

@@ -0,0 +1,11 @@
+<!DOCTYPE html5>
+<html>
+	<head>
+		<title>Crosswords</title>
+		<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet"/>
+		<link href="crosswords.min.css" rel="stylesheet"/>
+	</head>
+	<body>
+		<script src="crosswords.min.js"></script>
+	</body>
+</html>

+ 0 - 1
public/index.html

@@ -6,6 +6,5 @@
 		<link href="crosswords.min.css" rel="stylesheet"/>
 	</head>
 	<body>
-		<script src="crosswords.min.js"></script>
 	</body>
 </html>

+ 14 - 2
src/Grid.js

@@ -9,6 +9,18 @@ GridCell.prototype.toStatic = function() {
     return { x: this.px, y: this.py };
 };
 
+function EmptyCell(x, y) {
+    GridCell.call(this, x, y);
+}
+EmptyCell.prototype = Object.create(GridCell);
+EmptyCell.prototype.constructor = EmptyCell;
+
+EmptyCell.prototype.toStatic = function() {
+    var ret = GridCell.prototype.toStatic.call(this);
+    ret["type"] = null;
+    return ret;
+};
+
 function LetterCell(x, y, letter) {
     GridCell.call(this, x, y);
     this.letter = letter;
@@ -136,7 +148,7 @@ function parseGrid(grid, definitions, w, h) {
             if (c == c.toUpperCase()) {
                 resultGrid.push(new LetterCell(j, i, c));
             } else if (c == 'z') {
-                resultGrid.push(null);
+                resultGrid.push(new EmptyCell(j, i));
             } else {
                 let cell = new DefinitionCell(j, i, c.charCodeAt(0) -firstCharCode, definitions, currentDefinition);
                 currentDefinition += cell.definitions.length;
@@ -166,7 +178,7 @@ Grid.prototype.toStatic = function(v) {
     }
     var grid = [];
     this.grid.forEach((cell) => {
-        if (cell instanceof DefinitionCell && !v) {
+        if ((cell instanceof DefinitionCell || cell instanceof EmptyCell) && !v) {
             grid.push(cell.toStatic());
         } else if (cell instanceof LetterCell && cell.found && cell.v >= v) {
             grid.push(cell.toStatic());

+ 1 - 1
src/httpServer.js

@@ -125,7 +125,7 @@ HttpServer.prototype.serveApi = function(req, url, res) {
         }
         GridManager.createGrid(GridManager.hash('' +req.socket.remoteAddress +req.reqT.getTime() +gridId), gridId, (grid)=>{
             if (grid) {
-                res.setHeader("Location", "/#" +grid.publicId);
+                res.setHeader("Location", "/game.html#" +grid.publicId);
                 res.writeHeader("302");
             } else {
                 res.writeHeader("400", "Bad request");