adding german option
This commit is contained in:
		
							
								
								
									
										57
									
								
								js_client/english.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								js_client/english.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| <!doctype html> | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
|     <!-- Polyfills only needed for Firefox and Edge. --> | ||||
|     <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script> | ||||
|     <!-- Works only on browsers that support Javascript modules like | ||||
|        Chrome, Safari, Firefox 60, Edge 17 --> | ||||
|  | ||||
|     <style> | ||||
|         body { | ||||
|             background-color: black; | ||||
|             font-size: 1.5vh; | ||||
|         } | ||||
|  | ||||
|         @media (max-aspect-ratio: 3/2) { | ||||
|             body { | ||||
|                 font-size: 1.5vh; | ||||
|             } | ||||
|         } | ||||
|     </style> | ||||
|     // Original viewport definition, note the "id" that I use to modify the viewport later on: | ||||
|     <meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/> | ||||
|      | ||||
|     <script> | ||||
|     // Global boolean variable that holds the current orientation | ||||
|     var pageInPortraintMode; | ||||
|      | ||||
|     // Listen for window resizes to detect orientation changes | ||||
|     window.addEventListener("resize", windowSizeChanged); | ||||
|      | ||||
|     // Set the global orientation variable as soon as the page loads | ||||
|     addEventListener("load", function() { | ||||
|       pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|       document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|     }) | ||||
|      | ||||
|     // Adjust viewport values only if orientation has changed (not on every window resize) | ||||
|     function windowSizeChanged() { | ||||
|       if (((pageInPortraintMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraintMode === false) && (window.innerHeight > window.innerWidth))) { | ||||
|         pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|         document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|       } | ||||
|     } | ||||
|     </script> | ||||
|      | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|     <info-box id="infobox"></info-box> | ||||
|     <server-connection id="server-connection" lang="en" grid_id="grid" url="wss://the-cake-is-a-lie.net:8765"></server-connection> | ||||
|     <crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid> | ||||
|     <script type="module" src="./main.js"></script> | ||||
|  | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
							
								
								
									
										57
									
								
								js_client/german.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								js_client/german.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | ||||
| <!doctype html> | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
|     <!-- Polyfills only needed for Firefox and Edge. --> | ||||
|     <script src="https://unpkg.com/@webcomponents/webcomponentsjs@latest/webcomponents-loader.js"></script> | ||||
|     <!-- Works only on browsers that support Javascript modules like | ||||
|        Chrome, Safari, Firefox 60, Edge 17 --> | ||||
|  | ||||
|     <style> | ||||
|         body { | ||||
|             background-color: black; | ||||
|             font-size: 1.5vh; | ||||
|         } | ||||
|  | ||||
|         @media (max-aspect-ratio: 3/2) { | ||||
|             body { | ||||
|                 font-size: 1.5vh; | ||||
|             } | ||||
|         } | ||||
|     </style> | ||||
|     // Original viewport definition, note the "id" that I use to modify the viewport later on: | ||||
|     <meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/> | ||||
|      | ||||
|     <script> | ||||
|     // Global boolean variable that holds the current orientation | ||||
|     var pageInPortraintMode; | ||||
|      | ||||
|     // Listen for window resizes to detect orientation changes | ||||
|     window.addEventListener("resize", windowSizeChanged); | ||||
|      | ||||
|     // Set the global orientation variable as soon as the page loads | ||||
|     addEventListener("load", function() { | ||||
|       pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|       document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|     }) | ||||
|      | ||||
|     // Adjust viewport values only if orientation has changed (not on every window resize) | ||||
|     function windowSizeChanged() { | ||||
|       if (((pageInPortraintMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraintMode === false) && (window.innerHeight > window.innerWidth))) { | ||||
|         pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|         document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|       } | ||||
|     } | ||||
|     </script> | ||||
|      | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|     <info-box id="infobox"></info-box> | ||||
|     <server-connection id="server-connection" lang="de" grid_id="grid" url="ws://localhost:8765"></server-connection> | ||||
|     <crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid> | ||||
|     <script type="module" src="./main.js"></script> | ||||
|  | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
| @ -116,7 +116,13 @@ customElements.define('grid-box', GridBox); | ||||
| export class GridLetter extends GridBox { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             .letter { | ||||
|                 display: grid; | ||||
|             } | ||||
|  | ||||
|             input[type='text'] { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 width: 1.5em; | ||||
|                 height: 1.5em; | ||||
|                 text-align: center; | ||||
| @ -131,18 +137,47 @@ export class GridLetter extends GridBox { | ||||
|             } | ||||
|  | ||||
|             input[type='text']:focus { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 background-color: LightYellow; | ||||
|                 border-color: Yellow; | ||||
|  | ||||
|             } | ||||
|  | ||||
|             input[type='text']:read-only { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 background-color: LightGreen; | ||||
|             } | ||||
|  | ||||
|             input[type='text']:selection { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 background: transparent; | ||||
|             } | ||||
|  | ||||
|             .circle { | ||||
|                 margin: auto; | ||||
|                 text-align: left; | ||||
|                 vertical-align: bottom; | ||||
|                 bottom: 0; | ||||
|                 position: relative; | ||||
|                 z-index: 0; | ||||
|                 pointer-events: none; | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 border: 0.1em solid lightGray; | ||||
|                 color: black; | ||||
|                 height: 80%; | ||||
|                 width: 80%; | ||||
|                 border-radius:50%; | ||||
|                 -moz-border-radius:50%; | ||||
|                 -webkit-border-radius:50%; | ||||
|                 background: transparent; | ||||
|                  | ||||
|             } | ||||
|  | ||||
|  | ||||
|         `; | ||||
|     } | ||||
|  | ||||
| @ -159,7 +194,10 @@ export class GridLetter extends GridBox { | ||||
|         super(); | ||||
|         this._value = ''; | ||||
|         this.is_focused = false; | ||||
|         this.key_delay = false; | ||||
|         this.firstKeydownOver = true; | ||||
|         this.solutionIndex = -1; | ||||
|         this.lastFocusedX = -1; | ||||
|         this.lastFocusedY = -1; | ||||
|         this.updateGridElement(); | ||||
|     } | ||||
|  | ||||
| @ -179,7 +217,9 @@ export class GridLetter extends GridBox { | ||||
|  | ||||
|     onInput(e) { | ||||
|  | ||||
|  | ||||
|         if (!this.is_focused) { | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
| @ -213,7 +253,7 @@ export class GridLetter extends GridBox { | ||||
|         } | ||||
|  | ||||
|         if (!e.handled && this.value.length === 0) { | ||||
|             this.crosswordGrid.focusPrevCell(this.x, this.y); | ||||
|             this.crosswordGrid.focusPrevCell(this.x, this.y, this.lastFocusedX, this.lastFocusedY); | ||||
|             e.handled = true; | ||||
|         } | ||||
|         else if (!e.handled && this.value.length === 1) { | ||||
| @ -233,7 +273,7 @@ export class GridLetter extends GridBox { | ||||
|             }) | ||||
|         } | ||||
|  | ||||
|         if (!e.handled){ | ||||
|         if (!e.handled) { | ||||
|  | ||||
|             e.target.select(); | ||||
|  | ||||
| @ -242,28 +282,43 @@ export class GridLetter extends GridBox { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     onKeydown(e) { | ||||
|  | ||||
|         if (!this.is_focused) { | ||||
|     onKeyup(e) { | ||||
|         if (!this.firstKeydownOver) { | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         var key = e.key; | ||||
|         if (this.value.length == 0 || this.revealed) { | ||||
|             if (key === 'Backspace' || key === 'Delete') { | ||||
|                 this.crosswordGrid.focusPrevCell(this.x, this.y, this.lastFocusedX, this.lastFocus); | ||||
|                 e.handled = true; | ||||
|                 return | ||||
|  | ||||
|             } | ||||
|             else if (this.revealed) { | ||||
|                 this.crosswordGrid.focusNextCell(this.x, this.y); | ||||
|                 e.handled = true; | ||||
|                 return | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     onKeydown(e) { | ||||
|  | ||||
|         this.firstKeydownOver = true; | ||||
|  | ||||
|         if (!this.is_focused) { | ||||
|             e.handled = true; | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         this.key_delay = false; | ||||
|  | ||||
|         var key = e.key; | ||||
|  | ||||
|         console.log(key); | ||||
|  | ||||
|  | ||||
|         if (this.value.length == 0) { | ||||
|             if (key === 'Backspace' || key === 'Delete') { | ||||
|                 this.crosswordGrid.focusPrevCell(this.x, this.y); | ||||
|                 e.handled = true; | ||||
|                 return | ||||
|  | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // check arrow keys | ||||
|         if (key === "ArrowLeft") { | ||||
|             // left | ||||
| @ -301,14 +356,20 @@ export class GridLetter extends GridBox { | ||||
|     onFocus(e) { | ||||
|         e.target.select(); | ||||
|         this.is_focused = true; | ||||
|         this.key_delay = true; | ||||
|  | ||||
|         this.crosswordGrid.updateHints(this.x, this.y); | ||||
|     } | ||||
|  | ||||
|     focus() { | ||||
|     focus(lastX = -1, lastY = -1) { | ||||
|         if (lastX > 0 && lastY > 0) { | ||||
|             this.lastFocusedX = lastX; | ||||
|             this.lastFocusedY = lastY; | ||||
|         } | ||||
|         var element = this.shadowRoot.getElementById(`${this.x}-${this.y}`); | ||||
|         this.firstKeydownOver = false; | ||||
|         element.focus(); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     blur() { | ||||
| @ -323,13 +384,13 @@ export class GridLetter extends GridBox { | ||||
|         if (this.grid_id != null) { | ||||
|  | ||||
|             this.gridElement.setGridLetter(this); | ||||
|             this.solutionIndex = this.crosswordGrid.getSolutionIndex(this.x, this.y) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateLetter(letter, revealed) { | ||||
|         this.value = letter; | ||||
|         if (revealed) | ||||
|         { | ||||
|         if (revealed) { | ||||
|             console.log("rec") | ||||
|             this.shadowRoot.getElementById(`${this.x}-${this.y}`).readOnly = true; | ||||
|             this.blur(); | ||||
| @ -339,7 +400,25 @@ export class GridLetter extends GridBox { | ||||
|  | ||||
|     render() { | ||||
|         this.updateGridElement(); | ||||
|         return html`<input type="text" id="${this.x}-${this.y}" value="${this.value}" @input=${this.onInput} @focus=${this.onFocus} @keydown=${this.onKeydown} autocomplete="off"></input>`; | ||||
|  | ||||
|         var solutionOverlay = html``; | ||||
|  | ||||
|         if (this.solutionIndex >= 0) { | ||||
|             solutionOverlay = html` | ||||
|                 <div class="circle">${this.solutionIndex}</div> | ||||
|             `; | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         return html` | ||||
|             <div class="letter"> | ||||
|                 <input type="text" id="${this.x}-${this.y}" value="${this.value}" @input=${this.onInput} @focus=${this.onFocus} @keydown=${this.onKeydown} @keyup=${this.onKeyup} autocomplete="off"></input> | ||||
|                 ${solutionOverlay} | ||||
|             </div> | ||||
|  | ||||
|         `; | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -508,7 +587,7 @@ export class CrosswordGrid extends LitElement { | ||||
|             id: { type: String }, | ||||
|             width: { type: Number }, | ||||
|             height: { type: Number }, | ||||
|             infobox_id: {type: String} | ||||
|             infobox_id: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -527,6 +606,18 @@ export class CrosswordGrid extends LitElement { | ||||
|         this.infobox = null; | ||||
|  | ||||
|         this.serverConnection = null; | ||||
|  | ||||
|         this.solution_locations = null; | ||||
|     } | ||||
|  | ||||
|     getSolutionIndex(x, y) { | ||||
|         var i = 0; | ||||
|         for (i = 0; i < this.solution_locations.length; i++) { | ||||
|             if (this.solution_locations[i][0] == y && this.solution_locations[i][1] == x) { | ||||
|                 return i; | ||||
|             } | ||||
|         } | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     createGridByJson(json_grid) { | ||||
| @ -536,6 +627,8 @@ export class CrosswordGrid extends LitElement { | ||||
|         const width = json_grid.w; | ||||
|         const height = json_grid.h; | ||||
|  | ||||
|         this.solution_locations = json_grid.solution | ||||
|  | ||||
|         var y; | ||||
|         var x; | ||||
|  | ||||
| @ -573,7 +666,7 @@ export class CrosswordGrid extends LitElement { | ||||
|             if (this.grid[y][x].getGridType() === gridType.LETTER) { | ||||
|                 this.grid[y][x].getGridLetter().blur(); | ||||
|             } | ||||
|             this.grid[y][x + 1].getGridLetter().focus(); | ||||
|             this.grid[y][x + 1].getGridLetter().focus(x, y); | ||||
|  | ||||
|  | ||||
|             return true; | ||||
| @ -601,7 +694,7 @@ export class CrosswordGrid extends LitElement { | ||||
|             if (this.grid[y][x].getGridType() === gridType.LETTER) { | ||||
|                 this.grid[y][x].getGridLetter().blur(); | ||||
|             } | ||||
|             this.grid[y + 1][x].getGridLetter().focus(); | ||||
|             this.grid[y + 1][x].getGridLetter().focus(x, y); | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
| @ -642,7 +735,11 @@ export class CrosswordGrid extends LitElement { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     focusPrevCell(x, y) { | ||||
|     focusPrevCell(x, y, lastX = -1, lastY = -1) { | ||||
|         if (lastX > 0 && lastY > 0) { | ||||
|             this.grid[lastY][lastX].getGridLetter().focus(); | ||||
|             return; | ||||
|         } | ||||
|         if (this.lastMoveVertical) { | ||||
|             if (this.focusPrevCellVertical(x, y)) { | ||||
|                 return; | ||||
| @ -675,9 +772,9 @@ export class CrosswordGrid extends LitElement { | ||||
|         super.update() | ||||
|     } | ||||
|  | ||||
|     updateHints(x,y) { | ||||
|     updateHints(x, y) { | ||||
|         var cell = this.grid[y][x]; | ||||
|         if (cell.getGridType() != gridType.LETTER){ | ||||
|         if (cell.getGridType() != gridType.LETTER) { | ||||
|             console.error("cannot get hints for non letter cell"); | ||||
|         } | ||||
|  | ||||
| @ -697,15 +794,14 @@ export class CrosswordGrid extends LitElement { | ||||
|  | ||||
|         if (left_end.getGridType() === gridType.HINT) { | ||||
|             var box = left_end.getHintBox(); | ||||
|             if (box.hasHorizontalHint()){ | ||||
|             if (box.hasHorizontalHint()) { | ||||
|                 hHint = `${box.hint_id}: ${box.horizontal_hint}`; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (upper_end.getGridType() === gridType.HINT) { | ||||
|             var box = upper_end.getHintBox() | ||||
|             if (box.hasVerticalHint()) | ||||
|             { | ||||
|             if (box.hasVerticalHint()) { | ||||
|                 vHint = `${box.hint_id}: ${box.vertical_hint}`; | ||||
|             } | ||||
|         } | ||||
| @ -728,10 +824,10 @@ export class CrosswordGrid extends LitElement { | ||||
|                 var vertical_hint = this.json_grid.grid[el.y][el.x].vertical_hint; | ||||
|                 var horizontal_hint = this.json_grid.grid[el.y][el.x].horizontal_hint; | ||||
|  | ||||
|                 if (!vertical_hint){ | ||||
|                 if (!vertical_hint) { | ||||
|                     vertical_hint = ""; | ||||
|                 } | ||||
|                 if (!horizontal_hint){ | ||||
|                 if (!horizontal_hint) { | ||||
|                     horizontal_hint = ""; | ||||
|                 } | ||||
|  | ||||
| @ -745,19 +841,19 @@ export class CrosswordGrid extends LitElement { | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     updateLetter(x,y,letter,revealed) { | ||||
|     updateLetter(x, y, letter, revealed) { | ||||
|         var cell = this.grid[y][x]; | ||||
|         if (cell.getGridType() != gridType.LETTER){ | ||||
|         if (cell.getGridType() != gridType.LETTER) { | ||||
|             console.error("received bad message"); | ||||
|         } | ||||
|         cell.getGridLetter().updateLetter(letter, revealed) | ||||
|     } | ||||
|  | ||||
|     registerServerConnection(connection){ | ||||
|     registerServerConnection(connection) { | ||||
|         this.serverConnection = connection | ||||
|     } | ||||
|  | ||||
|     sendMessage(msg){ | ||||
|     sendMessage(msg) { | ||||
|         if (!this.serverConnection) { | ||||
|             console.error("no server connection registered") | ||||
|         } | ||||
|  | ||||
| @ -10,47 +10,71 @@ | ||||
|     <style> | ||||
|         body { | ||||
|             background-color: black; | ||||
|             font-size: 1vw; | ||||
|             font-size: 1.5vh; | ||||
|             text-align: center; | ||||
|             margin: auto; | ||||
|         } | ||||
|  | ||||
|         @media (max-aspect-ratio: 3/2) { | ||||
|             body { | ||||
|                 font-size: 1vh; | ||||
|                 font-size: 1.5vh; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         html { | ||||
|             width: 100%; | ||||
|             height: 100%; | ||||
|         } | ||||
|  | ||||
|         body { | ||||
|             min-width: 100%; | ||||
|             min-height: 100%; | ||||
|         } | ||||
|  | ||||
|         .centerbox { | ||||
|             background-color: black; | ||||
|             border-style: none; | ||||
|             box-shadow: none; | ||||
|             outline: none; | ||||
|             position: absolute; | ||||
|             width: 15em; | ||||
|             height: 10em; | ||||
|             top: 0; | ||||
|             right: 0; | ||||
|             bottom: 0; | ||||
|             left: 0; | ||||
|             margin: auto; | ||||
|             padding: 1em; | ||||
|             color: white; | ||||
|             font-size: 1em; | ||||
|         } | ||||
|  | ||||
|         .box { | ||||
|             background-color: black; | ||||
|             border-color: white; | ||||
|             border-width: 0.2em; | ||||
|             border-style: solid; | ||||
|             max-width: 15em; | ||||
|             max-height: 3em; | ||||
|             box-shadow: none; | ||||
|             outline: none; | ||||
|             position: relative; | ||||
|             margin: 1em; | ||||
|             padding: 1em; | ||||
|             color: white; | ||||
|             font-size: 1em; | ||||
|         } | ||||
|     </style> | ||||
|     // Original viewport definition, note the "id" that I use to modify the viewport later on: | ||||
|     <meta name="viewport" id="viewport" content="width=device-width, height=device-height, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/> | ||||
|      | ||||
|     <script> | ||||
|     // Global boolean variable that holds the current orientation | ||||
|     var pageInPortraintMode; | ||||
|      | ||||
|     // Listen for window resizes to detect orientation changes | ||||
|     window.addEventListener("resize", windowSizeChanged); | ||||
|      | ||||
|     // Set the global orientation variable as soon as the page loads | ||||
|     addEventListener("load", function() { | ||||
|       pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|       document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|     }) | ||||
|      | ||||
|     // Adjust viewport values only if orientation has changed (not on every window resize) | ||||
|     function windowSizeChanged() { | ||||
|       if (((pageInPortraintMode === true) && (window.innerHeight < window.innerWidth)) || ((pageInPortraintMode === false) && (window.innerHeight > window.innerWidth))) { | ||||
|         pageInPortraintMode = window.innerHeight > window.innerWidth; | ||||
|         document.getElementById("viewport").setAttribute("content", "width=" + window.innerWidth + ", height=" + window.innerHeight + ", initial-scale=1.0, maximum-scale=1.0, user-scalable=0"); | ||||
|       } | ||||
|     } | ||||
|     </script> | ||||
|      | ||||
|  | ||||
| </head> | ||||
|  | ||||
| <body> | ||||
|     <info-box id="infobox"></info-box> | ||||
|     <server-connection id="server-connection" grid_id="grid" url="wss://the-cake-is-a-lie.net:8765"></server-connection> | ||||
|     <crossword-grid id="grid" infobox_id="infobox" width="10" height="10"></crossword-grid> | ||||
|     <script type="module" src="./main.js"></script> | ||||
|  | ||||
|     <div class="centerbox"> | ||||
|         <h3>Select the language:</h3> | ||||
|         <a href="./german.html"> <div class="box"> German </div> </a> | ||||
|         <a href="./english.html"> <div class="box"> English </div> </a> | ||||
|     </div> | ||||
|  | ||||
| </body> | ||||
|  | ||||
|  | ||||
| @ -79,13 +79,13 @@ export class InfoBox extends LitElement { | ||||
|         this.horizontal_hint = ""; | ||||
|     } | ||||
|  | ||||
|     onNew(){ | ||||
|         setCookie("session",""); | ||||
|     onNew() { | ||||
|         setCookie("session", ""); | ||||
|         window.location.href = location.protocol + '//' + location.host + location.pathname; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     onShare(){ | ||||
|     onShare() { | ||||
|         copyToClipboard(window.location.href); | ||||
|     } | ||||
|  | ||||
|  | ||||
| @ -10,7 +10,8 @@ export class ServerConnection extends WebsocketConnection { | ||||
|     static get properties() { | ||||
|         return { | ||||
|             url: { type: String }, | ||||
|             grid_id: { type: String } | ||||
|             grid_id: { type: String }, | ||||
|             lang: { type: String } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -19,6 +20,7 @@ export class ServerConnection extends WebsocketConnection { | ||||
|         this.sessionId = null; | ||||
|         this.isRegistered = false; | ||||
|         this.crossword_grid = null; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
| @ -51,7 +53,8 @@ export class ServerConnection extends WebsocketConnection { | ||||
|         console.log("register", this.sessionId); | ||||
|         this.sendMessage({ | ||||
|             'type': 'register', | ||||
|             'sessionId': this.sessionId | ||||
|             'sessionId': this.sessionId, | ||||
|             'lang': this.lang | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|  | ||||
							
								
								
									
										90
									
								
								js_client/solutionBox.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								js_client/solutionBox.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,90 @@ | ||||
| import { html, css, LitElement, unsafeCSS } from 'https://unpkg.com/lit-element/lit-element.js?module'; | ||||
|  | ||||
| export class SolutionBox extends LitElement { | ||||
|     static get styles() { | ||||
|         return css` | ||||
|             .letter { | ||||
|                 display: grid; | ||||
|             } | ||||
|  | ||||
|             input[type='text'] { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 width: 1.5em; | ||||
|                 height: 1.5em; | ||||
|                 text-align: center; | ||||
|                 border-style: solid; | ||||
|                 border-width: 0.2 em; | ||||
|                 border-color: black; | ||||
|                 outline: none; | ||||
|                 color: black; | ||||
|                 font-size: 2em; | ||||
|                 user-select: none; | ||||
|                 text-transform: capitalize; | ||||
|             } | ||||
|  | ||||
|             input[type='text']:read-only { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 background-color: LightGreen; | ||||
|             } | ||||
|  | ||||
|             input[type='text']:selection { | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 background: transparent; | ||||
|             } | ||||
|  | ||||
|             .circle { | ||||
|                 margin: auto; | ||||
|                 text-align: left; | ||||
|                 vertical-align: bottom; | ||||
|                 bottom: 0; | ||||
|                 position: relative; | ||||
|                 z-index: 0; | ||||
|                 pointer-events: none; | ||||
|                 grid-column: 1; | ||||
|                 grid-row: 1; | ||||
|                 border: 0.1em solid lightGray; | ||||
|                 color: black; | ||||
|                 height: 80%; | ||||
|                 width: 80%; | ||||
|                 border-radius:50%; | ||||
|                 -moz-border-radius:50%; | ||||
|                 -webkit-border-radius:50%; | ||||
|                 background: transparent; | ||||
|                  | ||||
|             } | ||||
|  | ||||
|         `; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     static get properties() { | ||||
|         return { | ||||
|             length: { type: Number } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     constructor() { | ||||
|         super(); | ||||
|         this.length = 0; | ||||
|         this.values = []; | ||||
|     } | ||||
|  | ||||
|     update(props) { | ||||
|         if (props.has("length")) { | ||||
|             var i; | ||||
|             for (i = 0; i < this.length; i++) { | ||||
|                 this.values.push(""); | ||||
|             } | ||||
|         } | ||||
|         super.update() | ||||
|     } | ||||
|  | ||||
|     render() { | ||||
|         return html` | ||||
|  | ||||
|         `; | ||||
|     } | ||||
| } | ||||
| @ -105,12 +105,13 @@ class LetterField(Field): | ||||
|  | ||||
|  | ||||
| class Grid(object): | ||||
|     def __init__(self, width: int, height: int, lang_code: str, density=0.5): | ||||
|     def __init__(self, width: int, height: int, lang_code: str, density=0.55): | ||||
|         self._width = width | ||||
|         self._height = height | ||||
|         self._lang_code = lang_code | ||||
|         self._density = density | ||||
|         self._grid = [] | ||||
|         self._solution_locations = None | ||||
|         try: | ||||
|             self._build_grid() | ||||
|         except Exception as e: | ||||
| @ -245,12 +246,21 @@ class Grid(object): | ||||
|                 'y': y, | ||||
|                 'user_input': cell.get_user_content() | ||||
|             }] | ||||
|          | ||||
|  | ||||
|         return revealed_changes | ||||
|  | ||||
|     def get_solution_locations(self): | ||||
|         return self._solution_locations | ||||
|  | ||||
|     def _build_grid(self): | ||||
|         raw_grid, word_infos = crossword_generator.create_word_grid( | ||||
|             self._width - 1, self._height - 1, lang_code="en", target_density=self._density) | ||||
|         raw_grid, word_infos, solution_locations = crossword_generator.create_word_grid( | ||||
|             self._width - 1, self._height - 1, lang_code=self._lang_code, target_density=self._density) | ||||
|  | ||||
|         self._solution_locations = solution_locations | ||||
|         # fix solution locations offsets | ||||
|         for i in range(len(self._solution_locations)): | ||||
|             self._solution_locations[i][0] += 1 | ||||
|             self._solution_locations[i][1] += 1 | ||||
|  | ||||
|         # note: we will append an additional row and column, to have enough space to place hint fields | ||||
|  | ||||
| @ -304,17 +314,18 @@ class Crossword(object): | ||||
|         return { | ||||
|             'w': self._width, | ||||
|             'h': self._height, | ||||
|             'grid': self._grid.serialize() | ||||
|             'grid': self._grid.serialize(), | ||||
|             'solution': self._grid.get_solution_locations() | ||||
|         } | ||||
|  | ||||
|     def user_input(self, x: int, y: int, letter: str) -> list: | ||||
|         return self._grid.user_input(x=x, y=y, letter=letter) | ||||
|      | ||||
|  | ||||
|     def get_status(self) -> list: | ||||
|         return self._grid.get_status() | ||||
|  | ||||
|  | ||||
| if __name__ == "__main__": | ||||
|     logging.basicConfig(level=logging.INFO) | ||||
|     cw = Crossword(15, 15, "en") | ||||
|     cw = Crossword(30, 30, "de") | ||||
|     print(cw.serialize()) | ||||
|  | ||||
| @ -14,7 +14,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|  | ||||
|         self._session = None | ||||
|  | ||||
|     async def send_crossword(self, sessionId: str): | ||||
|     async def send_crossword(self, sessionId: str, lang:str = "en"): | ||||
|         if sessionId not in CrosswordConnection.sessions: | ||||
|             await self.send_error(msg="unknown session") | ||||
|             return | ||||
| @ -28,7 +28,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|             await self.send_error(msg="you are not registered to given session") | ||||
|             return | ||||
|  | ||||
|         crossword = sess.get_crossword() | ||||
|         crossword = sess.get_crossword(lang=lang) | ||||
|         await self.send({ | ||||
|             'type': 'crossword', | ||||
|             'crossword': crossword.serialize() | ||||
| @ -53,7 +53,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|                 'updates': update_message | ||||
|             }) | ||||
|  | ||||
|     async def register(self, sessionId: str = None): | ||||
|     async def register(self, sessionId: str = None, lang: str = "en"): | ||||
|  | ||||
|         if sessionId is None: | ||||
|  | ||||
| @ -68,7 +68,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|             await self.send_error("unknown session id") | ||||
|  | ||||
|             # register with new id: | ||||
|             await self.register() | ||||
|             await self.register(lang=lang) | ||||
|             return | ||||
|  | ||||
|         sess = CrosswordConnection.sessions[sessionId] | ||||
| @ -81,7 +81,7 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|             'sessionId': sessionId | ||||
|         }) | ||||
|  | ||||
|         await self.send_crossword(sessionId) | ||||
|         await self.send_crossword(sessionId, lang=lang) | ||||
|  | ||||
|     async def send_error(self, msg: str): | ||||
|         await self.send({ | ||||
| @ -98,9 +98,12 @@ class CrosswordConnection(json_websockets.JsonWebsocketConnection): | ||||
|  | ||||
|         if message['type'] == 'register': | ||||
|             sessionId = None | ||||
|             lang = "en" | ||||
|             if 'sessionId' in message: | ||||
|                 sessionId = message['sessionId'] | ||||
|             await self.register(sessionId=sessionId) | ||||
|             if "lang" in message: | ||||
|                 lang = message['lang'] | ||||
|             await self.register(sessionId=sessionId, lang = lang) | ||||
|             return | ||||
|  | ||||
|         if self._session is None: | ||||
|  | ||||
| @ -16,157 +16,190 @@ def get_database(lang: str = "en") -> dict: | ||||
|         with open(db_file, "r") as f: | ||||
|             db = json.load(f) | ||||
|             get_database._dbs[lang] = db | ||||
|          | ||||
|  | ||||
|         logging.info("database loaded") | ||||
|      | ||||
|  | ||||
|     return get_database._dbs[lang] | ||||
|  | ||||
|  | ||||
| get_database._dbs = {} | ||||
|  | ||||
|  | ||||
| class NoDataException(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class WordInfo(object): | ||||
|     def __init__(self, word:str, y:int, x:int, is_vertical: bool, database: dict): | ||||
|     def __init__(self, word: str, y: int, x: int, is_vertical: bool, database: dict, opposite_prefix: str = "opposite of", synonym_prefix: str = "other word for"): | ||||
|         self._dictionary_database = database | ||||
|         self._y = y | ||||
|         self._x = x | ||||
|         self._word = word | ||||
|         self._hint = None | ||||
|         self._is_vertical = is_vertical | ||||
|          | ||||
|  | ||||
|         self.opposite_prefix = opposite_prefix | ||||
|         self.synonym_prefix = synonym_prefix | ||||
|  | ||||
|         self.choose_info() | ||||
|  | ||||
|     def get_attribute(self, attr: str): | ||||
|         attr = self._dictionary_database[self._word][attr] | ||||
|         if attr is None: | ||||
|         if attr is None or len(attr) == 0: | ||||
|             raise NoDataException | ||||
|         return attr | ||||
|      | ||||
|  | ||||
|     def get_best_antonym(self) -> str: | ||||
|         antonyms = self.get_attribute("antonyms") | ||||
|         return random.choice(antonyms) | ||||
|      | ||||
|  | ||||
|     def get_best_synonym(self) -> str: | ||||
|         synonyms = self.get_attribute("synonyms") | ||||
|         return random.choice(synonyms) | ||||
|      | ||||
|  | ||||
|     def get_best_sense(self) -> str: | ||||
|         senses = self.get_attribute("senses") | ||||
|         return random.choice(senses) | ||||
|          | ||||
|     def choose_info(self): | ||||
|  | ||||
|     def choose_info(self, n: int = 1): | ||||
|         assert n <= 4 | ||||
|         # first choose antonyms, then synonyms, then senses | ||||
|          | ||||
|  | ||||
|         hints = [] | ||||
|  | ||||
|         try: | ||||
|             self._hint = f"opposite of {self.get_best_antonym()}" | ||||
|             return | ||||
|             antonyms = self.get_attribute("antonyms") | ||||
|             antonyms = [f"{self.opposite_prefix} {w}" for w in antonyms] | ||||
|             hints = hints + antonyms | ||||
|         except NoDataException: | ||||
|             pass | ||||
|          | ||||
|  | ||||
|         try: | ||||
|             self._hint = f"other word for {self.get_best_synonym()}" | ||||
|             return | ||||
|             synonyms = self.get_attribute("synonyms") | ||||
|             synonyms = [f"{self.synonym_prefix} {w}" for w in synonyms] | ||||
|  | ||||
|             hints = hints + synonyms | ||||
|         except NoDataException: | ||||
|             pass | ||||
|          | ||||
|         self._hint = self.get_best_sense() | ||||
|      | ||||
|  | ||||
|         try: | ||||
|             senses = self.get_attribute("senses") | ||||
|             hints = hints + senses | ||||
|         except NoDataException: | ||||
|             pass | ||||
|  | ||||
|         final_hints = [] | ||||
|         for i in range(n): | ||||
|             choice = random.choice(hints) | ||||
|             hints.remove(choice) | ||||
|             final_hints.append(choice) | ||||
|  | ||||
|         if n == 1: | ||||
|             self._hint = final_hints[0] | ||||
|             return | ||||
|  | ||||
|         hint_symbols = ['a)', 'b)', 'c)', 'd)'] | ||||
|  | ||||
|         self._hint = "" | ||||
|         for i in range(n): | ||||
|             self._hint += hint_symbols[i] + " " + final_hints[i] + ". " | ||||
|  | ||||
|     def get_hint(self) -> str: | ||||
|         return self._hint | ||||
|      | ||||
|  | ||||
|     def get_hint_location(self): | ||||
|         x = self._x if self._is_vertical else self._x - 1 | ||||
|         y = self._y - 1 if self._is_vertical else self._y | ||||
|         return (y, x) | ||||
|      | ||||
|  | ||||
|     def is_vertical(self): | ||||
|         return self._is_vertical | ||||
|  | ||||
| def create_word_grid(w: int, h: int, lang_code: str = "en", target_density = 0.5): | ||||
|  | ||||
| def create_word_grid(w: int, h: int, lang_code: str = "en", target_density=0.5): | ||||
|     logging.info("generate new crossword") | ||||
|  | ||||
|     database = get_database(lang = lang_code) | ||||
|     database = get_database(lang=lang_code) | ||||
|     list_words = list(database.keys()) | ||||
|  | ||||
|     grid = np.full(shape=(h,w), dtype=np.unicode, fill_value = ' ') | ||||
|      | ||||
|     grid = np.full(shape=(h, w), dtype=np.unicode, fill_value=' ') | ||||
|  | ||||
|     locations = {} | ||||
|      | ||||
|  | ||||
|     word_hints = {} | ||||
|      | ||||
|  | ||||
|     def store_location(char: str, y: int, x: int): | ||||
|         assert len(char) == 1 | ||||
|          | ||||
|  | ||||
|         if char not in locations: | ||||
|             locations[char] = [] | ||||
|          | ||||
|         locations[char].append([y,x]) | ||||
|          | ||||
|  | ||||
|         locations[char].append([y, x]) | ||||
|  | ||||
|     remove_digits = str.maketrans('', '', digits) | ||||
|     n_words = len(list_words) | ||||
|      | ||||
|     def get_word(max_length: int, min_length = 0): | ||||
|  | ||||
|     def get_word(max_length: int, min_length=0): | ||||
|         assert max_length > 1 | ||||
|          | ||||
|         index = random.randint(0,n_words-1) | ||||
|  | ||||
|         index = random.randint(0, n_words-1) | ||||
|         word = list_words[index][:] | ||||
|          | ||||
|  | ||||
|         while len(word) >= max_length or not word.isalnum() or len(word) <= min_length: | ||||
|             index = random.randint(0,n_words-1) | ||||
|             index = random.randint(0, n_words-1) | ||||
|             word = list_words[index][:] | ||||
|          | ||||
|  | ||||
|         return word | ||||
|              | ||||
|     def normalize_word(word:str): | ||||
|  | ||||
|     def normalize_word(word: str): | ||||
|         word = word.translate(remove_digits) | ||||
|         return word.lower() | ||||
|      | ||||
|     def place_word(word:str, y: int, x:int, vertical:bool = False): | ||||
|  | ||||
|     opposite_prefix = "opposite of" if lang_code == "en" else "Gegenteil von" | ||||
|     synonym_prefix = "other word for" if lang_code == "en" else "anderes Wort für" | ||||
|  | ||||
|     def place_word(word: str, y: int, x: int, vertical: bool = False): | ||||
|         normalized_word = normalize_word(word) | ||||
|         n = len(normalized_word) | ||||
|         if vertical: | ||||
|             assert grid.shape[0] - n >= y | ||||
|             for i, char in enumerate(normalized_word): | ||||
|                 grid[y + i,x] = char | ||||
|                 grid[y + i, x] = char | ||||
|                 store_location(char, y+i, x) | ||||
|         else: | ||||
|             assert grid.shape[1] - n >= x | ||||
|             for i, char in enumerate(normalized_word): | ||||
|                 grid[y,x + i] = char | ||||
|                 grid[y, x + i] = char | ||||
|                 store_location(char, y, x+i) | ||||
|          | ||||
|         word_hints[normalized_word] = WordInfo(word, y, x, vertical, database) | ||||
|          | ||||
|          | ||||
|      | ||||
|  | ||||
|         word_hints[normalized_word] = WordInfo( | ||||
|             word, y, x, vertical, database, opposite_prefix, synonym_prefix) | ||||
|  | ||||
|     def density(): | ||||
|         return 1 - (grid == " ").sum() / (w * h) | ||||
|      | ||||
|      | ||||
|      | ||||
|     def check_if_fits(word:str, y:int, x:int, vertical:bool): | ||||
|  | ||||
|     def check_if_fits(word: str, y: int, x: int, vertical: bool): | ||||
|         n = len(word) | ||||
|         if vertical: | ||||
|              | ||||
|  | ||||
|             # check if there is space before and after | ||||
|             if y - 1 >= 0 and grid[y - 1, x] != " ": | ||||
|                 return False | ||||
|             if y + n < grid.shape[0] - 1 and grid[y+n,x] != " ": | ||||
|             if y + n < grid.shape[0] - 1 and grid[y+n, x] != " ": | ||||
|                 return False | ||||
|              | ||||
|  | ||||
|             if grid.shape[0] - n < y or y < 0: | ||||
|                 # print("over board") | ||||
|                 return False | ||||
|              | ||||
|  | ||||
|             for i, char in enumerate(word): | ||||
|                 char_x = x | ||||
|                 char_y = y + i | ||||
|                  | ||||
|  | ||||
|                 if not (grid[char_y, char_x] == " " or grid[char_y, char_x] == char): | ||||
|                     # print("not matching") | ||||
|                     return False | ||||
|                  | ||||
|  | ||||
|                 if grid[char_y, char_x] == " ": | ||||
|                     # check for horizonatal neighbors: | ||||
|                     if char_x - 1 >= 0 and grid[char_y, char_x - 1] != " ": | ||||
| @ -175,27 +208,27 @@ def create_word_grid(w: int, h: int, lang_code: str = "en", target_density = 0.5 | ||||
|                     if char_x + 1 < grid.shape[1] and grid[char_y, char_x + 1] != " ": | ||||
|                         # print("4") | ||||
|                         return False | ||||
|          | ||||
|  | ||||
|         else: | ||||
|              | ||||
|  | ||||
|             # check if there is space before and after | ||||
|             if x - 1 >= 0 and grid[y, x - 1] != " ": | ||||
|                 return False | ||||
|             if x + n < grid.shape[1] - 1 and grid[y,x + n] != " ": | ||||
|             if x + n < grid.shape[1] - 1 and grid[y, x + n] != " ": | ||||
|                 return False | ||||
|              | ||||
|  | ||||
|             if grid.shape[1] - n < x or x < 0: | ||||
|                 # print("over board") | ||||
|                 return False | ||||
|              | ||||
|  | ||||
|             for i, char in enumerate(word): | ||||
|                 char_x = x + i | ||||
|                 char_y = y | ||||
|                  | ||||
|  | ||||
|                 if not (grid[char_y, char_x] == " " or grid[char_y, char_x] == char): | ||||
|                     # print("not matching") | ||||
|                     return False | ||||
|                  | ||||
|  | ||||
|                 if grid[char_y, char_x] == " ": | ||||
|                     # check for vertical neighbors: | ||||
|                     if char_y - 1 >= 0 and grid[char_y - 1, char_x] != " ": | ||||
| @ -204,83 +237,106 @@ def create_word_grid(w: int, h: int, lang_code: str = "en", target_density = 0.5 | ||||
|                     if char_y + 1 < grid.shape[0] and grid[char_y + 1, char_x] != " ": | ||||
|                         # print("2") | ||||
|                         return False | ||||
|          | ||||
|  | ||||
|         return True | ||||
|          | ||||
|      | ||||
|  | ||||
|     def get_crossover(word: str): | ||||
|         # returns Tuple of: (y,x, is_vertical?) or None | ||||
|          | ||||
|  | ||||
|         shuffled_order = list(range(len(word))) | ||||
|         random.shuffle(shuffled_order) | ||||
|          | ||||
|  | ||||
|         for index in shuffled_order: | ||||
|             # check for existing locations | ||||
|             char = word[index] | ||||
|             if char in locations: | ||||
|                 char_locations = locations[char] | ||||
|                  | ||||
|  | ||||
|                 for char_loc in char_locations: | ||||
|                     # test vertical | ||||
|                     y = char_loc[0] - index | ||||
|                     x = char_loc[1] | ||||
|                      | ||||
|  | ||||
|                     if check_if_fits(word, y, x, vertical=True): | ||||
|                         return (y,x,True) | ||||
|                      | ||||
|                         return (y, x, True) | ||||
|  | ||||
|                     # test horizontal | ||||
|                     y = char_loc[0] | ||||
|                     x = char_loc[1] - index | ||||
|                      | ||||
|  | ||||
|                     if check_if_fits(word, y, x, vertical=False): | ||||
|                         return (y,x,False) | ||||
|          | ||||
|                         return (y, x, False) | ||||
|  | ||||
|         return None | ||||
|      | ||||
|     min_shape = min(w,h,30) | ||||
|      | ||||
|  | ||||
|     def get_solution_word(min_length=8, max_length=100): | ||||
|         word = get_word(min_length=min_length, max_length=max_length) | ||||
|  | ||||
|         # search for matching characters in locations | ||||
|         locations_cpy = dict(locations) | ||||
|         solution_locations = [] | ||||
|  | ||||
|         for char in word: | ||||
|             if char not in locations_cpy or len(locations_cpy[char]) == 0: | ||||
|                 # next try: | ||||
|                 get_solution_word(min_length=min_length, max_length=max_length) | ||||
|  | ||||
|             location_candidates = locations_cpy[char] | ||||
|  | ||||
|             n = len(location_candidates) | ||||
|  | ||||
|             i = random.randint(0, n-1) | ||||
|  | ||||
|             solution_locations.append(location_candidates[i]) | ||||
|             del(location_candidates[i]) | ||||
|  | ||||
|         return solution_locations | ||||
|  | ||||
|     min_shape = min(w, h, 30) | ||||
|  | ||||
|     # place first word: | ||||
|     first_word = get_word(max_length=min_shape, min_length=min(10,grid.shape[1] - 2)) | ||||
|      | ||||
|     first_word = get_word(max_length=min_shape, | ||||
|                           min_length=min(10, grid.shape[1] - 2)) | ||||
|  | ||||
|     # find random place: | ||||
|     x = random.randint(0, grid.shape[1] - len(first_word) - 1) | ||||
|     y = random.randint(0, grid.shape[0] - 1) | ||||
|      | ||||
|  | ||||
|     place_word(first_word, y, x, vertical=False) | ||||
|                  | ||||
|  | ||||
|     i = 0 | ||||
|      | ||||
|      | ||||
|  | ||||
|     current_density = density() | ||||
|      | ||||
|  | ||||
|     while current_density < target_density: | ||||
|         word = get_word(max_length=(1 - current_density ** 0.4) * min_shape, | ||||
|                         min_length=max(min(10, 0.5 * (1 - current_density ** 0.3) * min_shape), 2)) | ||||
|          | ||||
|  | ||||
|         normalized_word = normalize_word(word) | ||||
|          | ||||
|  | ||||
|         if normalized_word in word_hints: | ||||
|             continue | ||||
|          | ||||
|  | ||||
|         # check if matching characters exist: | ||||
|         crossover = get_crossover(normalized_word) | ||||
|          | ||||
|  | ||||
|         i += 1 | ||||
|         if i % 100000 == 0: | ||||
|             print(i) | ||||
|         if i > 100000: | ||||
|             break | ||||
|          | ||||
|  | ||||
|         if crossover == None: | ||||
|             current_density = density() | ||||
|             continue | ||||
|          | ||||
|         y,x,is_vertical = crossover | ||||
|          | ||||
|         place_word(word, y,x, is_vertical) | ||||
|          | ||||
|  | ||||
|         y, x, is_vertical = crossover | ||||
|  | ||||
|         place_word(word, y, x, is_vertical) | ||||
|  | ||||
|         current_density = density() | ||||
|      | ||||
|  | ||||
|     solution_word_locations = get_solution_word() | ||||
|  | ||||
|     logging.info("crossword generation done after %s iterations", str(i)) | ||||
|     return grid, word_hints | ||||
|          | ||||
|     return grid, word_hints, solution_word_locations | ||||
|  | ||||
							
								
								
									
										
											BIN
										
									
								
								server/de.json
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								server/de.json
									 (Stored with Git LFS)
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -36,13 +36,13 @@ class Session(object): | ||||
|     def get_datetime_created(self) -> dt.datetime: | ||||
|         return self.datetime_created | ||||
|  | ||||
|     def create_crossword(self, width: int = 30, height: int = 30): | ||||
|     def create_crossword(self, width: int = 20, height: int = 20, lang: str = "en"): | ||||
|         self.crossword = crossword.Crossword(width=width, | ||||
|                                              height=height, | ||||
|                                              lang_code="en") | ||||
|                                              lang_code=lang) | ||||
|  | ||||
|     def get_crossword(self) -> crossword.Crossword: | ||||
|     def get_crossword(self, lang: str = "en") -> crossword.Crossword: | ||||
|         if self.crossword is None: | ||||
|             self.create_crossword() | ||||
|             self.create_crossword(lang = lang) | ||||
|          | ||||
|         return self.crossword | ||||
|  | ||||
		Reference in New Issue
	
	Block a user