mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-08 10:56:15 -08:00
143 lines
3.8 KiB
Plaintext
143 lines
3.8 KiB
Plaintext
const fs = require('fs');
|
|
const assert = require('assert');
|
|
|
|
function parseLine(line) {
|
|
line = line.replace(/#.*/, '');
|
|
line = line.trim();
|
|
if (line.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
let parts = line.split(';').map(s => s.trim());
|
|
|
|
if (/\.\./.test(parts[0])) {
|
|
const range = parts[0].split('..');
|
|
return { from: parseInt(range[0], 16), to: parseInt(range[1], 16), type: parts[1] };
|
|
}
|
|
|
|
return { from: parseInt(parts[0], 16), to: parseInt(parts[0], 16), type: parts[1] };
|
|
}
|
|
|
|
function parseFile(filename) {
|
|
const fileContents = fs.readFileSync(filename).toString('utf8');
|
|
const lines = fileContents.split('\n');
|
|
const result = [];
|
|
for (let i = 0; i < lines.length; i++) {
|
|
let line = parseLine(lines[i]);
|
|
if (line) {
|
|
result.push(line);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const typeToInt = {
|
|
'Prepend': 1,
|
|
'CR': 2,
|
|
'LF': 3,
|
|
'Control': 4,
|
|
'Extend': 5,
|
|
'Regional_Indicator': 6,
|
|
'SpacingMark': 7,
|
|
'L': 8,
|
|
'V': 9,
|
|
'T': 10,
|
|
'LV': 11,
|
|
'LVT': 12,
|
|
'ZWJ': 13,
|
|
'Extended_Pictographic': 14
|
|
}
|
|
|
|
const tuples = [];
|
|
parseFile('./GraphemeBreakProperty.txt').forEach(item => tuples.push({ from:item.from, to:item.to, type: typeToInt[item.type] }));
|
|
parseFile('./emoji-data.txt').filter(item => item.type === 'Extended_Pictographic').forEach(item => tuples.push({ from:item.from, to:item.to, type: typeToInt[item.type] }));
|
|
tuples.sort((t1, t2) => t1.from - t2.from);
|
|
|
|
function pow2smallereq(n) {
|
|
let pow = 0;
|
|
let r = 1;
|
|
while (r <= n) {
|
|
r = r << 1;
|
|
pow++;
|
|
}
|
|
return pow;
|
|
}
|
|
|
|
let tuplesTree = [];
|
|
function buildTree(fromIndex, toIndex, outIndex) {
|
|
const elementCount = toIndex - fromIndex + 1;
|
|
|
|
let midIndex;
|
|
if (elementCount === 1) {
|
|
midIndex = fromIndex;
|
|
} else if (elementCount === 2) {
|
|
midIndex = fromIndex + 1;
|
|
} else {
|
|
const subtreeDepth = pow2smallereq(elementCount) - 1;
|
|
const minRightCount = (1 << (subtreeDepth - 1)) - 1;
|
|
const idealLeftCount = (1 << subtreeDepth) - 1;
|
|
const leftCount = Math.min(idealLeftCount, elementCount - 1 - minRightCount);
|
|
// console.log(`elementCount: ${elementCount}, subtreeDepth: ${subtreeDepth}, idealLeftCount: ${idealLeftCount}, minRightCount: ${minRightCount} ==> leftCount: ${leftCount}`);
|
|
midIndex = fromIndex + leftCount;
|
|
}
|
|
|
|
tuplesTree[outIndex] = tuples[midIndex];
|
|
|
|
// if (outIndex !== 1) {
|
|
// const parentIndex = (outIndex / 2) | 0;
|
|
// if (outIndex === 2 * parentIndex) {
|
|
// // I am left node
|
|
// if (tuplesTree[outIndex].to >= tuplesTree[parentIndex].from) {
|
|
// console.log(`illegal tree 1!`);
|
|
// }
|
|
// } else {
|
|
// // I am right node
|
|
// if (tuplesTree[outIndex].from <= tuplesTree[parentIndex].to) {
|
|
// console.log(`illegal tree 2!`);
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
if (fromIndex < midIndex) {
|
|
// left subtree
|
|
buildTree(fromIndex, midIndex - 1, 2 * outIndex);
|
|
}
|
|
if (midIndex < toIndex) {
|
|
// right subtree
|
|
buildTree(midIndex + 1, toIndex, 2 * outIndex + 1);
|
|
}
|
|
}
|
|
buildTree(0, tuples.length - 1, 1);
|
|
|
|
// for (let i = 1; i < tuplesTree.length; i++) {
|
|
// if (tuplesTree[i]) {
|
|
// console.log(`${i} - ${tuplesTree[i].from},${tuplesTree[i].to},${tuplesTree[i].type}`);
|
|
// } else {
|
|
// console.log(`${i} - undefined`);
|
|
// }
|
|
// }
|
|
|
|
function validateNode(nodeIndex) {
|
|
const node = tuplesTree[nodeIndex];
|
|
|
|
const leftChildIndex = 2 * nodeIndex;
|
|
if (leftChildIndex < tuplesTree.length) {
|
|
const leftChild = tuplesTree[leftChildIndex];
|
|
assert.ok(leftChild.to < node.from);
|
|
validateNode(leftChildIndex);
|
|
}
|
|
|
|
const rightChildIndex = 2 * nodeIndex + 1;
|
|
if (rightChildIndex < tuplesTree.length) {
|
|
const rightChild = tuplesTree[rightChildIndex];
|
|
assert.ok(rightChild.from > node.to);
|
|
validateNode(rightChildIndex);
|
|
}
|
|
}
|
|
validateNode(1);
|
|
|
|
let result = [0,0,0];
|
|
tuplesTree.forEach(t => result.push(t.from, t.to, t.type));
|
|
|
|
console.log(JSON.stringify(result));
|