chocolog
Version:
A highlighted android-style logger
298 lines • 27.8 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const canvas_1 = require("canvas");
const emoji_unicode_1 = __importDefault(require("emoji-unicode"));
const fs_extra_1 = __importDefault(require("fs-extra"));
const image_size_1 = __importDefault(require("image-size"));
const minda_ts_1 = require("minda-ts");
const node_fetch_1 = __importDefault(require("node-fetch"));
const sharp_1 = __importDefault(require("sharp"));
const snowconfig_1 = require("../snow/config/snowconfig");
async function renderBoard(board, pallate = {}, sideinfo = {}) {
// load font
const ttf = `${snowconfig_1.debugPath}/res/NanumSquareRoundR.ttf`;
canvas_1.registerFont(ttf, { family: "NanumSquareRound" });
// define size
const hexagonSize = 1500;
const frameWidth = Math.floor(hexagonSize * 1.2211);
const circleFR = Math.floor(frameWidth * 1.1);
const canvas = canvas_1.createCanvas(circleFR, circleFR, "PDF");
// load frame
const frameBuffer = await fs_extra_1.default.readFile(`${snowconfig_1.debugPath}/res/board.png`);
const frameSizeI = image_size_1.default(frameBuffer);
const scaledFrameH = Math.floor(frameSizeI.height / frameSizeI.width * frameWidth);
const frame = await sharp_1.default(frameBuffer)
.resize(frameWidth, scaledFrameH, { fit: "inside" })
.toBuffer().then(loadImage);
const ctx = canvas.getContext("2d");
// draw circle
ctx.beginPath();
const r = circleFR / 2;
ctx.arc(r, r, r, 0, 2 * Math.PI, false);
ctx.fillStyle = "#f9edca";
ctx.fill();
// draw frame
ctx.drawImage(frame, (circleFR - frameWidth) / 2, (circleFR - scaledFrameH) / 2);
await drawHexagon(ctx, [Math.floor(circleFR / 2), Math.floor(circleFR / 2)], hexagonSize, "#2c2c2a", {
board,
blackImage: pallate.black,
whiteImage: pallate.white,
noStoneImage: pallate.default,
});
// draw userinfo
const infoSize = Math.floor(hexagonSize / 8);
const defaultPic = await fs_extra_1.default.readFile(`${snowconfig_1.debugPath}/res/placeHolderProfileImage.png`);
// copy
if (sideinfo.black != null) {
if (sideinfo.black.image == null) {
sideinfo.black.image = defaultPic;
}
await drawPicture(ctx, "left", {
at: [(circleFR - infoSize * 3) / 2, 0],
size: infoSize,
backColor: "#222222",
textColor: "#eeeeee",
stone: sideinfo.black.stone,
maxStone: sideinfo.maxstone,
}, sideinfo.black.image, sideinfo.black.username);
}
// paste
if (sideinfo.white != null) {
if (sideinfo.white.image == null) {
sideinfo.white.image = defaultPic;
}
await drawPicture(ctx, "right", {
at: [(circleFR - infoSize * 3) / 2, circleFR - infoSize],
size: infoSize,
backColor: "#eeeeee",
textColor: "#222222",
stone: sideinfo.white.stone,
maxStone: sideinfo.maxstone,
}, sideinfo.white.image, sideinfo.white.username);
}
const buffer = canvas.toBuffer();
return buffer;
}
exports.renderBoard = renderBoard;
/**
* Draw hexagon
* @param ctx Context
* @param centerPoint Center point of hexagon
* @param hexaLength Hexagon's longest width
* @param bgColor Background color
* @param params Original parameters
*/
async function drawHexagon(ctx, centerPoint, hexaLength, bgColor, params) {
// 0. config (0 < x <= 1/2)
const elSize = 2 / 5;
const { board, blackImage, whiteImage, noStoneImage } = params;
/* first: parse color */
const parseColor = (str, fault) => {
if (str != null && str.startsWith("#") && /^#[0-9A-Fa-f]{6}$/ig.test(str)) {
return str.toUpperCase();
}
else {
return fault.toUpperCase();
}
};
const colors = {
black: parseColor(blackImage, "#eeeeee"),
white: parseColor(whiteImage, "#111111"),
default: parseColor(noStoneImage, "#ffefbc"),
};
/* and draw background */
if (bgColor != null) {
ctx.fillStyle = bgColor;
ctx.beginPath();
const [cx, cy] = centerPoint;
ctx.moveTo(Math.floor(cx - hexaLength / 2), cy);
ctx.lineTo(Math.floor(cx - hexaLength / 4), Math.floor(cy - Math.sqrt(3) * hexaLength / 4));
ctx.lineTo(Math.floor(cx + hexaLength / 4), Math.floor(cy - Math.sqrt(3) * hexaLength / 4));
ctx.lineTo(Math.floor(cx + hexaLength / 2), cy);
ctx.lineTo(Math.floor(cx + hexaLength / 4), Math.floor(cy + Math.sqrt(3) * hexaLength / 4));
ctx.lineTo(Math.floor(cx - hexaLength / 4), Math.floor(cy + Math.sqrt(3) * hexaLength / 4));
ctx.lineTo(Math.floor(cx - hexaLength / 2), cy);
ctx.closePath();
ctx.fill();
}
/* second: define constans */
hexaLength = Math.floor(hexaLength * board.sqaureSize / (board.sqaureSize + Math.sqrt(2) - 1));
// 1 * l / (2n)
const oneX = hexaLength / (2 * board.sqaureSize);
// 3^(1/2)l / (2n)
const oneY = Math.sqrt(3) * hexaLength / (2 * board.sqaureSize);
// stone/image width (not radios but width)
const elementWidth = 2 * hexaLength * elSize / board.sqaureSize;
/* third: draw */
// load image
const getImage = async (url) => {
if (url == null || !url.startsWith("http")) {
return null;
}
let binary = await node_fetch_1.default(url).then((v) => v.buffer());
const roundedCorners = Buffer.from(`<svg><rect x="0" y="0" width="${elementWidth}" height="${elementWidth}" rx="${elementWidth}" ry="${elementWidth}"/></svg>`
// `<svg><circle cx="${elementWidth / 2} cy="${elementWidth / 2}" r="${elementWidth / 2}"/></svg>`
);
binary = await sharp_1.default(binary)
.resize(Math.ceil(elementWidth))
.overlayWith(roundedCorners, { cutout: true })
.toBuffer();
return new Promise((res, rej) => {
const img = new canvas_1.Image();
img.onload = () => res(img);
img.onerror = (err) => { res(null); };
img.src = binary;
});
};
const images = {
black: await getImage(blackImage),
white: await getImage(whiteImage),
default: await getImage(noStoneImage),
};
/**
* Get XY, draw image or circle to position.
*/
const grid = board.decodedGrid;
for (let row = 0; row < grid.length; row += 1) {
for (let column = 0; column < grid[row].length; column += 1) {
const stone = grid[row][column];
const x = Math.floor(centerPoint[0] +
(Math.abs(board.centerPosition - row) + 2 * (column - board.centerPosition)) * oneX);
const y = Math.floor(centerPoint[1] + (row - board.centerPosition) * oneY);
const drawCircle = (fillColor, r) => {
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI, false);
ctx.fillStyle = fillColor;
ctx.fill();
};
const drawImage = (fillImage, cornerColor, r) => {
ctx.drawImage(fillImage, Math.floor(x - r), Math.floor(y - r), Math.round(r * 2), Math.round(r * 2));
ctx.beginPath();
ctx.arc(x, y, r, 0, 2 * Math.PI, false);
ctx.strokeStyle = cornerColor;
ctx.lineWidth = Math.min(3, Math.floor(r / 20));
ctx.stroke();
};
const draw = (fillImage, fillColor, smallsize) => {
let r = elementWidth / 2;
if (smallsize) {
r *= 0.7;
r = Math.round(r);
}
if (fillImage != null) {
drawImage(fillImage, "#333333", r);
}
else {
drawCircle(fillColor, r);
}
};
switch (stone) {
case minda_ts_1.StoneType.black:
{
draw(images.black, colors.black, false);
}
break;
case minda_ts_1.StoneType.white:
{
draw(images.white, colors.white, false);
}
break;
case minda_ts_1.StoneType.void:
{
draw(images.default, colors.default, true);
}
break;
}
}
}
}
async function drawPicture(ctx, align, params, image, username) {
const alignLeft = align === "left";
const { at, size, backColor, textColor } = params;
let [x, y] = at;
x = Math.floor(x);
y = Math.floor(y);
const tagWidth = Math.floor(size * 3);
const tagHeight = Math.floor(size);
const padding = Math.floor(size * 0.1);
const pos = [x, y];
// background
ctx.fillStyle = backColor;
ctx.fillRect(x, y, tagWidth, tagHeight);
const padPicSize = tagHeight - 2 * padding;
// move poistion
if (alignLeft) {
pos[0] += padding;
pos[1] += padding;
}
else {
pos[0] += tagWidth - padding - padPicSize;
pos[1] += padding;
}
// image
const picture = await sharp_1.default(image)
.resize(padPicSize, padPicSize, { fit: "contain", position: "center", background: { r: 0, g: 0, b: 0, alpha: 0 } })
.toBuffer().then(loadImage);
ctx.drawImage(picture, pos[0], pos[1]);
// image stroke
ctx.strokeStyle = textColor;
ctx.lineWidth = 3;
ctx.fillStyle = "#111111";
ctx.strokeRect(pos[0], pos[1], padPicSize, padPicSize);
// ctx.fillRect(x + padPicture, y + padPicture, padPicSize, padPicSize)
// move position
const textWidth = Math.floor(tagWidth - (padPicSize + padding * 3));
const fontSize = Math.floor((tagHeight - 3 * padding) / 2);
if (alignLeft) {
pos[0] += padding + padPicSize;
}
else {
pos[0] -= padding;
}
pos[1] += fontSize;
if (!alignLeft) {
ctx.textAlign = "right";
}
// nickname
ctx.fillStyle = textColor;
ctx.font = `${fontSize}px NanumSquareRound`;
ctx.fillText(username, pos[0], pos[1], Math.floor(tagWidth - (padPicSize + padding * 3)));
// thinking
pos[1] = y + tagHeight - 2 * padding;
const getNum = (num) => {
if (num == null || num < 0) {
return "?";
}
else {
return num.toString();
}
};
ctx.fillText(`\u{25EF} ${getNum(params.stone)}/${getNum(params.maxStone)}`, pos[0], pos[1], Math.floor(tagWidth - (padPicSize + padding * 3)));
return [tagWidth, tagHeight];
}
function loadImage(url) {
return new Promise((res, rej) => {
const img = new canvas_1.Image();
img.onload = () => res(img);
img.onerror = (err) => {
console.log(err);
res(null);
};
img.src = url;
});
}
function emojiAsSVG(emoji) {
return `https://cdnjs.cloudflare.com/ajax/libs/twemoji/11.2.0/2/svg/${emoji_unicode_1.default(emoji).toLowerCase()}.svg`;
}
exports.emojiAsSVG = emojiAsSVG;
function getFillString(str, length) {
let s = "";
for (let i = 0; i < length; i += 1) {
s += str;
}
return s;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9hcmRyZW5kZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvY2hhdGJvdC9ib2FyZHJlbmRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQUFBLG1DQUFxRTtBQUNyRSxrRUFBd0M7QUFDeEMsd0RBQXlCO0FBQ3pCLDREQUErQjtBQUMvQix1Q0FBb0Q7QUFDcEQsNERBQThCO0FBQzlCLGtEQUF5QjtBQUN6QiwwREFBcUQ7QUFJOUMsS0FBSyxVQUFVLFdBQVcsQ0FBQyxLQUFZLEVBQUUsVUFJM0MsRUFBRSxFQUFFLFdBSUosRUFBRTtJQUNILFlBQVk7SUFDWixNQUFNLEdBQUcsR0FBRyxHQUFHLHNCQUFTLDRCQUE0QixDQUFBO0lBQ3BELHFCQUFZLENBQUMsR0FBRyxFQUFFLEVBQUUsTUFBTSxFQUFFLGtCQUFrQixFQUFFLENBQUMsQ0FBQTtJQUNqRCxjQUFjO0lBQ2QsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFBO0lBQ3hCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxDQUFBO0lBQ25ELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQyxDQUFBO0lBQzdDLE1BQU0sTUFBTSxHQUFHLHFCQUFZLENBQ3ZCLFFBQVEsRUFDUixRQUFRLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDcEIsYUFBYTtJQUNiLE1BQU0sV0FBVyxHQUFHLE1BQU0sa0JBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxzQkFBUyxnQkFBZ0IsQ0FBQyxDQUFBO0lBQ25FLE1BQU0sVUFBVSxHQUFHLG9CQUFNLENBQUMsV0FBVyxDQUFDLENBQUE7SUFDdEMsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQyxLQUFLLEdBQUcsVUFBVSxDQUFDLENBQUE7SUFDbEYsTUFBTSxLQUFLLEdB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