Constellations/js/Share/Encoder/Protocol.js
2022-08-11 09:58:57 +02:00

81 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));
}