Преглед изворни кода

[bugfix] version stuff
[add] color success/wrong letters

isundil пре 9 година
родитељ
комит
234e646e52
9 измењених фајлова са 92 додато и 32 уклоњено
  1. 24 1
      css/main.less
  2. 8 3
      js/grid.js
  3. 3 0
      js/resources.js
  4. 23 11
      js/ui.js
  5. 14 3
      js/workflow.js
  6. 0 1
      public/crosswords.min.css
  7. 10 7
      public/crosswords.min.js
  8. 9 6
      src/Grid.js
  9. 1 0
      src/httpServer.js

+ 24 - 1
css/main.less

@@ -4,6 +4,12 @@
 @arrow-color: darkblue;
 @disabled-color: #263340;
 
+html,body {
+    font-family: Lato, sans-serif;
+    margin: 0;
+    padding: 0;
+}
+
 .crossword-line {
     display: block;
     height: @cell-size;
@@ -15,6 +21,7 @@
         border-left: 1px solid @border-color;
         border-top: 1px solid @border-color;
         overflow: hidden;
+        text-align: center;
 
         &:last-child {
             border-right: 1px solid @border-color;
@@ -34,7 +41,6 @@
             .definition {
                 display: block;
                 font-size: .75em;
-                text-align: center;
 
                 & > * {
                     display: inline-block;
@@ -61,6 +67,7 @@
         &.definition-right-vt:after {
             top: 0;
             bottom: 0;
+            left: 0;
             margin: auto;
             width: @cell-size /8;
             border-top: 1px solid @arrow-color;
@@ -69,6 +76,7 @@
         &.definition-right-hz:after {
             top: 0;
             bottom: 0;
+            left: 0;
             width: @cell-size /8;
             margin: auto;
             border-top: 1px solid @arrow-color;
@@ -76,6 +84,7 @@
         &.definition-bottom-vt:after {
             left: 0;
             right: 0;
+            top: 0;
             margin: auto;
             height: @cell-size /8;
             border-left: 1px solid @arrow-color;
@@ -83,12 +92,26 @@
         &.definition-bottom-hz:after {
             left: 0;
             right: 0;
+            top: 0;
             margin: auto;
             height: @cell-size /8;
             border-left: 1px solid @arrow-color;
             border-bottom: 1px solid @arrow-color;
         }
 
+        &.cell-letter {
+            font-size: @cell-size /3;
+            line-height: @cell-size;
+            font-weight: 900;
+
+            &.cell-letter-correct {
+                color: green;
+            }
+            &.cell-letter-wrong {
+                background-color: #ffb6b6;
+            }
+        }
+
         &.cell-selected {
             background: #e1e8ff;
         }

+ 8 - 3
js/grid.js

@@ -28,6 +28,10 @@ function Cell() {
     this.isBlack = false;
     /** @type {Array.<Definition>} */
     this.definitions = null;
+    /** @type {boolean} */
+    this.found = false;
+    /** @type {string|null} */
+    this.letter = null;
 }
 
 Cell.prototype.update = function(data) {
@@ -38,9 +42,10 @@ Cell.prototype.update = function(data) {
         data["definitions"].forEach(function(definition) {
             this.definitions.push(new Definition(definition));
         }.bind(this));
-    } else {
-        // Grid letter
-        // TODO return version
+    } else if (data["letter"]) {
+        this.letter = data["letter"];
+        this.found = true;
+        return data["v"];
     }
     return 0;
 };

+ 3 - 0
js/resources.js

@@ -16,6 +16,9 @@ var R = {
                 ,bottomHorizontal: "definition-bottom-hz"
             }
 
+            ,found: "cell-letter-correct"
+            ,pending: "cell-letter-pending"
+            ,wrong: "cell-letter-wrong"
             ,selected: "cell-selected"
             ,currentInput: "cell-input"
         }

+ 23 - 11
js/ui.js

@@ -6,7 +6,7 @@ function dCreate(domName) {
     return document.createElement(domName);
 }
 
-function uiCreateCell(cellData) {
+function uiCreateCell(cellData, x, y) {
     var cell = dCreate("div");
 
     cell.className = R.klass.cell.item;
@@ -15,12 +15,16 @@ function uiCreateCell(cellData) {
     } else if (cellData.definitions !== null) {
         cell.classList.add(R.klass.cell.definition);
         var cellContent =dCreate("span");
-        cellData.definitions.forEach(function(definition) {
-            var domDefinition = dCreate("span");
+        for (var i =0, nbDefinitions = cellData.definitions.length; i < nbDefinitions; i++) {
+            var definition = cellData.definitions[i]
+                ,domDefinition = dCreate("span");
+            domDefinition.dataset.x = x;
+            domDefinition.dataset.y = y;
+            domDefinition.dataset.definition = i;
             domDefinition.className = R.klass.cell.definitions.item;
             domDefinition.innerHTML = definition.text.join("<br/>");
             cellContent.appendChild(domDefinition);
-        });
+        }
         cell.appendChild(cellContent);
     } else {
         cell.classList.add(R.klass.cell.letter);
@@ -37,7 +41,7 @@ function uiCreateGrid() {
         line.className = R.klass.line;
         frag.appendChild(line);
         for (var j =0; j < GRID.width; j++) {
-            var cell = uiCreateCell(GRID.grid[j][i]);
+            var cell = uiCreateCell(GRID.grid[j][i], j, i);
             cell.dataset.x = j;
             cell.dataset.y = i;
             line.appendChild(cell);
@@ -75,6 +79,7 @@ function uiCreateGrid() {
             }
         }
     }
+    onGridUpdated();
     document.body.textContent = "";
     document.body.appendChild(frag);
 }
@@ -82,14 +87,21 @@ function uiCreateGrid() {
 function onGridUpdated() {
     UI_CELLS.forEach(function(i) {
         if (!i.data.definitions && !i.data.isBlack) {
-            //TODO
+            if (i.data.letter) {
+                i.dom.textContent = i.data.letter;
+                if (i.data.found) {
+                    i.dom.classList.add(R.klass.cell.found);
+                }
+            } else {
+                i.dom.textContent = "";
+            }
         }
     });
 }
 
 function gridClickDelegate(e) {
     var target = e.target;
-    while (target && !target.classList.contains(R.klass.cell.item))
+    while (target && (target.dataset && !target.dataset.x))
         target = target.parentElement;
     if (target && target.dataset && target.dataset.x && target.dataset.y) {
         var clickedCell = UI_CELLS[parseInt(target.dataset.x, 10) +parseInt(target.dataset.y, 10) *GRID.width];
@@ -98,14 +110,14 @@ function gridClickDelegate(e) {
         } else if (clickedCell.data.definitions) {
             var first = true;
             unselect();
-            if (clickedCell.data.definitions.length) {
-                clickedCell.data.definitions[0].word.forEach(function(coordinates) {
+            if (clickedCell.data.definitions[target.dataset.definition]) {
+                clickedCell.data.definitions[target.dataset.definition].word.forEach(function(coordinates) {
                     select(coordinates[0], coordinates[1]);
-                    if (first) {
+                    if (first && !UI_CELLS[coordinates[0] +coordinates[1] *GRID.width].data.found) {
                         CURRENTINPUT = UI_CELLS[coordinates[0] +coordinates[1] *GRID.width];
                         CURRENTINPUT.dom.classList.add(R.klass.cell.currentInput);
-                        first = false;
                     }
+                    first = false;
                 });
             }
         } else {

+ 14 - 3
js/workflow.js

@@ -35,6 +35,7 @@ function initPolling() {
                 KNOWN_VERSION = Math.max(GRID.update(resp["grid"]) || 0, KNOWN_VERSION);
                 uiCreateGrid();
             }
+            KNOWN_VERSION = Math.max(KNOWN_VERSION, resp["v"] || 0);
         } // TODO else cannot init party
     });
 }
@@ -54,11 +55,19 @@ function pollNow() {
 }
 
 function keyPressHandler(cell, key) {
+    cell.dom.classList.add(R.klass.cell.pending);
     doGet("/api/put?grid=" +GRID_PUBLIC_ID +"&key=" +key +"&x=" +cell.x +"&y=" +cell.y, function(status, resp) {
-        if (status === 403) {
+        cell.dom.classList.remove(R.klass.cell.pending);
+        if (status === 403 && !cell.data.found) {
+            cell.dom.classList.add(R.klass.cell.wrong);
             // TODO wrong
         } else if (status === 204) {
-            // TODO good
+            cell.dom.classList.remove(R.klass.cell.wrong);
+            cell.data.letter = key;
+            cell.data.found = true;
+            onGridUpdated();
+        } else {
+            // out of sync ?
             pollNow();
         }
     });
@@ -91,10 +100,12 @@ document.addEventListener('DOMContentLoaded', function() {
 
     document.addEventListener('click', gridClickDelegate);
     document.addEventListener('keypress', function(e) {
-        if (CURRENTINPUT) {
+        if (CURRENTINPUT && !CURRENTINPUT.data.found) {
             var key = e.key.charAt(0).toUpperCase();
             if (key.match(/[A-Z]/)) {
+                CURRENTINPUT.data.letter = key;
                 keyPressHandler(CURRENTINPUT, key);
+                onGridUpdated();
             }
         }
     });

Разлика између датотеке није приказан због своје велике величине
+ 0 - 1
public/crosswords.min.css


+ 10 - 7
public/crosswords.min.js

@@ -1,7 +1,10 @@
-var f=[];function h(a){var b=document.createElement("div");b.className="cell";if(a.i)b.classList.add("cell-disabled");else if(null!==a.b){b.classList.add("cell-definition");var c=document.createElement("span");a.b.forEach(function(a){var b=document.createElement("span");b.className="definition";b.innerHTML=a.text.join("<br/>");c.appendChild(b)});b.appendChild(c)}else b.classList.add("cell-letter");return b}
-function k(){for(var a=document.createDocumentFragment(),b=0;b<m.g;b++){var c=document.createElement("div");c.className="crossword-line";a.appendChild(c);for(var d=0;d<m.a;d++){var e=h(m.c[d][b]);e.dataset.x=d;e.dataset.y=b;c.appendChild(e);f.push({x:d,y:b,f:e,data:m.c[d][b]})}}for(b=0;b<m.g;b++)for(d=0;d<m.a;d++)e=f[b*m.a+d],e.data.b&&e.data.b.forEach(function(a){switch(a.direction){case 2:f[b*m.a+d+1].f.classList.add("definition-right-vt");break;case 1:f[b*m.a+d+1].f.classList.add("definition-right-hz");
-break;case 4:f[(b+1)*m.a+d].f.classList.add("definition-bottom-vt");break;case 3:f[(b+1)*m.a+d].f.classList.add("definition-bottom-hz")}});document.body.textContent="";document.body.appendChild(a)}
-function n(a){for(a=a.target;a&&!a.classList.contains("cell");)a=a.parentElement;if(a&&a.dataset&&a.dataset.x&&a.dataset.y){var b=f[parseInt(a.dataset.x,10)+parseInt(a.dataset.y,10)*m.a];if(b.data.i)p();else if(b.data.b){var c=!0;p();b.data.b.length&&b.data.b[0].l.forEach(function(a){q(a[0],a[1]);c&&(r=f[a[0]+a[1]*m.a],r.f.classList.add("cell-input"),c=!1)})}else{var d=t(b.x,b.y);p();d.forEach(function(a){a.forEach(function(a){q(a[0],a[1])})});a.classList.add("cell-input");r=b}}};function u(a){this.text=a.text;this.direction=a.pos;this.l=null}function v(){this.i=!1;this.b=null}v.prototype.update=function(a){null===a.type?this.i=!0:void 0!==a.definitions&&(this.b=[],a.definitions.forEach(function(a){this.b.push(new u(a))}.bind(this)));return 0};function w(a){this.a=a.w;this.g=a.h;this.j=[];this.c=[];for(a=0;a<this.a;a++){this.c[a]=[];for(var b=0;b<this.g;b++)this.c[a][b]=new v}}
-function x(a,b,c,d,e){if(!a.c[b+d]||!a.c[b+d][c+e]||a.c[b+d][c+e].b||a.c[b+d][c+e].i)return[[b,c]];a=x(a,b+d,c+e,d,e);a.unshift([b,c]);return a}function t(a,b){var c=[];m.j.forEach(function(d){for(var e=0,g=d.length;e<g;e++)if(d[e][0]==a&&d[e][1]==b){c.push(d);break}});return c}
-w.prototype.update=function(a){var b=null,c=this.c,d=!1;a.forEach(function(a){a=c[a.x][a.y].update(a);b=Math.max(b||0,a);0===a&&(d=!0)});if(d){for(var e=[],g=0;g<this.a;g++)for(var l=0;l<this.g;l++)c[g][l].b&&c[g][l].b.forEach(function(a){var b;switch(a.direction){case 2:b=x(this,g+1,l,0,1);break;case 1:b=x(this,g+1,l,1,0);break;case 4:b=x(this,g,l+1,0,1);break;case 3:b=x(this,g,l+1,1,0)}e.push(b);a.l=b}.bind(this));this.j=e}return b};var y,z=0,m,A=[],r=null;function B(a,b){var c=new XMLHttpRequest;c.onreadystatechange=function(){if(4===c.readyState){var a=null;if(200===c.status){a=c.response;try{a=JSON.parse(a)}catch(e){a=null}}b(a)}};c.open("GET",a,!0);c.send(null)}function C(){B("/api/poll?grid="+y+"&v="+z,function(a){a&&(m=new w(a),a.grid&&(z=Math.max(m.update(a.grid)||0,z),k()))})}function D(a){var b=r;B("/api/put?grid="+y+"&key="+a+"&x="+b.x+"&y="+b.y,function(a){console.log(a)})}
-function p(){A.forEach(function(a){a.f.classList.remove("cell-selected")});r&&(r.f.classList.remove("cell-input"),r=null);A=[]}function q(a,b){var c=f[a+b*m.a];A.push(c);c.f.classList.add("cell-selected")}document.addEventListener("DOMContentLoaded",function(){y=document.location.hash.substr(1);""==y?document.location.href="/":(document.addEventListener("click",n),document.addEventListener("keypress",function(a){r&&(a=a.key.charAt(0).toUpperCase(),a.match(/[A-Z]/)&&D(a))}),C())});
+var f=[];function h(a,b,c){var d=document.createElement("div");d.className="cell";if(a.i)d.classList.add("cell-disabled");else if(null!==a.b){d.classList.add("cell-definition");for(var e=document.createElement("span"),g=0,k=a.b.length;g<k;g++){var A=a.b[g],n=document.createElement("span");n.dataset.x=b;n.dataset.y=c;n.dataset.definition=g;n.className="definition";n.innerHTML=A.text.join("<br/>");e.appendChild(n)}d.appendChild(e)}else d.classList.add("cell-letter");return d}
+function l(){for(var a=document.createDocumentFragment(),b=0;b<m.l;b++){var c=document.createElement("div");c.className="crossword-line";a.appendChild(c);for(var d=0;d<m.c;d++){var e=h(m.f[d][b],d,b);e.dataset.x=d;e.dataset.y=b;c.appendChild(e);f.push({x:d,y:b,a:e,data:m.f[d][b]})}}for(b=0;b<m.l;b++)for(d=0;d<m.c;d++)e=f[b*m.c+d],e.data.b&&e.data.b.forEach(function(a){switch(a.direction){case 2:f[b*m.c+d+1].a.classList.add("definition-right-vt");break;case 1:f[b*m.c+d+1].a.classList.add("definition-right-hz");
+break;case 4:f[(b+1)*m.c+d].a.classList.add("definition-bottom-vt");break;case 3:f[(b+1)*m.c+d].a.classList.add("definition-bottom-hz")}});p();document.body.textContent="";document.body.appendChild(a)}function p(){f.forEach(function(a){a.data.b||a.data.i||(a.data.j?(a.a.textContent=a.data.j,a.data.g&&a.a.classList.add("cell-letter-correct")):a.a.textContent="")})}
+function q(a){for(a=a.target;a&&a.dataset&&!a.dataset.x;)a=a.parentElement;if(a&&a.dataset&&a.dataset.x&&a.dataset.y){var b=f[parseInt(a.dataset.x,10)+parseInt(a.dataset.y,10)*m.c];if(b.data.i)r();else if(b.data.b){var c=!0;r();b.data.b[a.dataset.definition]&&b.data.b[a.dataset.definition].o.forEach(function(a){t(a[0],a[1]);c&&!f[a[0]+a[1]*m.c].data.g&&(u=f[a[0]+a[1]*m.c],u.a.classList.add("cell-input"));c=!1})}else{var d=v(b.x,b.y);r();d.forEach(function(a){a.forEach(function(a){t(a[0],a[1])})});
+a.classList.add("cell-input");u=b}}};function w(a){this.text=a.text;this.direction=a.pos;this.o=null}function x(){this.i=!1;this.b=null;this.g=!1;this.j=null}x.prototype.update=function(a){if(null===a.type)this.i=!0;else if(void 0!==a.definitions)this.b=[],a.definitions.forEach(function(a){this.b.push(new w(a))}.bind(this));else if(a.letter)return this.j=a.letter,this.g=!0,a.v;return 0};function y(a){this.c=a.w;this.l=a.h;this.m=[];this.f=[];for(a=0;a<this.c;a++){this.f[a]=[];for(var b=0;b<this.l;b++)this.f[a][b]=new x}}
+function z(a,b,c,d,e){if(!a.f[b+d]||!a.f[b+d][c+e]||a.f[b+d][c+e].b||a.f[b+d][c+e].i)return[[b,c]];a=z(a,b+d,c+e,d,e);a.unshift([b,c]);return a}function v(a,b){var c=[];m.m.forEach(function(d){for(var e=0,g=d.length;e<g;e++)if(d[e][0]==a&&d[e][1]==b){c.push(d);break}});return c}
+y.prototype.update=function(a){var b=null,c=this.f,d=!1;a.forEach(function(a){a=c[a.x][a.y].update(a);b=Math.max(b||0,a);0===a&&(d=!0)});if(d){for(var e=[],g=0;g<this.c;g++)for(var k=0;k<this.l;k++)c[g][k].b&&c[g][k].b.forEach(function(a){var b;switch(a.direction){case 2:b=z(this,g+1,k,0,1);break;case 1:b=z(this,g+1,k,1,0);break;case 4:b=z(this,g,k+1,0,1);break;case 3:b=z(this,g,k+1,1,0)}e.push(b);a.o=b}.bind(this));this.m=e}return b};var B,C=0,m,D=[],u=null;function E(a,b){var c=new XMLHttpRequest;c.onreadystatechange=function(){if(4===c.readyState){var a=null;if(200===c.status){a=c.response;try{a=JSON.parse(a)}catch(e){a=null}}b(c.status,a)}};c.open("GET",a,!0);c.send(null)}function F(){E("/api/poll?grid="+B+"&v="+C,function(a,b){b&&(m=new y(b),b.grid&&(C=Math.max(m.update(b.grid)||0,C),l()),C=Math.max(C,b.v||0))})}
+function G(){E("/api/poll?grid="+B+"&v="+C,function(a,b){if(b&&b.grid){var c=Math.max(m.update(b.grid)||0,C);c!==C&&(p(),C=c)}})}function H(a){var b=u;b.a.classList.add("cell-letter-pending");E("/api/put?grid="+B+"&key="+a+"&x="+b.x+"&y="+b.y,function(c){b.a.classList.remove("cell-letter-pending");403!==c||b.data.g?204===c?(b.a.classList.remove("cell-letter-wrong"),b.data.j=a,b.data.g=!0,p()):G():b.a.classList.add("cell-letter-wrong")})}
+function r(){D.forEach(function(a){a.a.classList.remove("cell-selected")});u&&(u.a.classList.remove("cell-input"),u=null);D=[]}function t(a,b){var c=f[a+b*m.c];D.push(c);c.a.classList.add("cell-selected")}
+document.addEventListener("DOMContentLoaded",function(){B=document.location.hash.substr(1);""==B?document.location.href="/":(document.addEventListener("click",q),document.addEventListener("keypress",function(a){u&&!u.data.g&&(a=a.key.charAt(0).toUpperCase(),a.match(/[A-Z]/)&&(u.data.j=a,H(a),p()))}),F())});

+ 9 - 6
src/Grid.js

@@ -31,9 +31,8 @@ LetterCell.prototype.constructor = LetterCell;
 
 LetterCell.prototype.toStatic = function() {
     var ret = GridCell.prototype.toStatic.call(this);
-    if (this.found) {
-        ret.letter = this.letter;
-    }
+    ret.letter = this.letter;
+    ret.v = this.version;
     return ret;
 };
 
@@ -166,6 +165,7 @@ function Grid(publicId, data) {
     this.height = data["nbcaseshauteur"];
     this.grid = parseGrid(data["grille"], data["definitions"], this.width, this.height);
     this.publicId = publicId;
+    this.minVersion = 0;
 };
 
 Grid.prototype.getCell = function(x, y) {
@@ -184,12 +184,15 @@ Grid.prototype.toStatic = function(v) {
         ret.difficulty = this.difficulty;
         ret.w = this.width;
         ret.h = this.height;
+        ret.v = this.minVersion;
     }
     var grid = [];
     this.grid.forEach((cell) => {
-        if ((cell instanceof DefinitionCell || cell instanceof EmptyCell) && !v) {
-            grid.push(cell.toStatic());
-        } else if (cell instanceof LetterCell && cell.found && cell.v >= v) {
+        if (cell instanceof DefinitionCell || cell instanceof EmptyCell) {
+            if (!v) {
+                grid.push(cell.toStatic());
+            }
+        } else if (cell.found && cell.version > v) {
             grid.push(cell.toStatic());
         }
     });

+ 1 - 0
src/httpServer.js

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

Неке датотеке нису приказане због велике количине промена