Constellations/js/Share/Encoder/Protocol.js

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