import * as Encoder from Share.Encoder.Class; import {at, iter, square} 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 != undefined) { encodeBlock(encoder, block); } else { encodeSingleCell( encoder, getColorGradient(gradients, grid, cell) ); } } }); } function getLongestBlock(grid, origin) { var color = at(grid, origin); var longestDirection = findLongestDirection(grid, origin, color); var size = extend(grid, origin, color, longestDirection); if(size >= Protocol.MIN_BLOCK_SIZE) { return { direction: longestDirection.coordinate == 'row' ? 'vertical' : 'horizontal', size: size, color: color }; } } function findLongestDirection(grid, p, originColor) { var delta = 1; while(true) { var newRow = p.row + delta; var newColumn = p.column + delta; if(newRow >= grid.length || grid[newRow][p.column] != originColor) { return {coordinate: 'column', delta: delta}; } else if(newColumn >= grid[p.row].length || grid[p.row][newColumn] != originColor) { return {coordinate: 'row', delta: delta+1}; } delta++; } } function extend(grid, p, originColor, direction) { var origin = p[direction.coordinate]; p[direction.coordinate] += direction.delta; while(isSmaller(p, diagonal(grid.length)) && at(grid, p) == originColor) { p[direction.coordinate]++; } return p[direction.coordinate] - origin; } function encodeBlock(encoder, block) { encoder.push(1); encoder.push(block.direction == 'vertical'); encoder.variableLength6(block.size - Protocol.MIN_BLOCK_SIZE); encoder.int(3)(block.color); } function getColorGradient(gradients, grid, cell) { if(at(gradients, cell) == undefined) { } return at(gradients, cell); } function encodeSingleCell(encoder, direction) { encoder.push(0); encoder.int(2)(Protocol.directions.indexOf(direction)); }