74 lines
1.9 KiB
JavaScript
74 lines
1.9 KiB
JavaScript
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));
|
|
}
|