import {diagonal, isSmaller, plus} from Geometry.Vector; import * as Vector from Geometry.Vector; import * as Encoder from Share.Encoder.Class; import {at, iter, square} from Grid.Util; import * as Grid from Grid.Util; import * as Protocol from Share.Protocol; return { grid: encodeGrid }; function encodeGrid(grid) { var encoder = Encoder.make(); var done = square(grid.length, false); var gradients = square(grid.length); iter(grid, function(_, cell) { if(!at(done, cell)) { let block = getLongestBlock(grid, cell); if(block.size >= Protocol.MIN_BLOCK_SIZE) { encodeBlock(encoder, done, block); } else { encodeSingleCell( encoder, getColorGradient(gradients, grid, done, cell) ); } } }); return encoder.output(); } function getLongestBlock(grid, origin) { var color = at(grid, origin); var hSize = getStreak(Grid.row(grid, origin.row), origin.column, color); var vSize = getStreak(Grid.column(grid, origin.column), origin.row, color); return { isVertical: vSize > hSize, size: Math.max(hSize, vSize), color: color, origin: origin }; } function getStreak(t, firstIndex, color) { var fromFirst = t.slice(firstIndex); var index = fromFirst.findIndex( function(x) {return x != color;} ); return index >= 0 ? index : fromFirst.length; } function encodeBlock(encoder, done, block) { encoder.push(1); encoder.push(block.isVertical); encoder.variableLength6(block.size - Protocol.MIN_BLOCK_SIZE); encoder.int(3)(block.color); var cell = Vector.make(block.origin.row, block.origin.column); for(var i = 0; i < block.size; i++) { Grid.set(done, cell, true); cell[block.isVertical ? 'row' : 'column']++; } } function getColorGradient(gradients, grid, done, cell) { if(at(gradients, cell) == undefined) { } return at(gradients, cell); } function encodeSingleCell(encoder, direction) { encoder.push(0); encoder.int(2)(Protocol.directions.indexOf(direction)); }