82 lines
2.1 KiB
JavaScript
82 lines
2.1 KiB
JavaScript
|
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));
|
||
|
}
|