I’m trying to render a BitTorrent (transmission) bitfield into a chart like the following:
I’m getting my bitfield from the pieces
field of the Transmission RPC API.
My code right now looks like the following:
function renderPieces(pieces: string, pieceCount: number) {
const w = 100;
const h = 100;
const ppp = pieceCount / w; // pieceCount per pixel
pieces = Buffer.from(pieces, "base64").toString("utf8");
const cells = [];
let bitIndex = 0.0;
let sb, eb, db;
let b, c;
let j = 0;
for (let i = 0, len = pieces.length; i < len; ++i) {
b = (b << 8) | pieces.charCodeAt(i);
bitIndex += 8.0;
sb = Math.round(bitIndex);
while (bitIndex > ppp) {
bitIndex -= ppp;
eb = Math.round(bitIndex);
db = sb - eb;
c = b >> eb;
c <<= 32 - db;
c = c - ((c >> 1) & 0x55555555);
c = (c & 0x33333333) + ((c >> 2) & 0x33333333);
c = (((c + (c >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24;
cells.push({
alpha: c / db,
moveTo: [j, 0],
lineTo: [j++, h],
});
sb = eb;
}
}
return cells;
}
I’d like to then use the array of { alpha: number, moveTo: [number, number], lineTo: [number, number] }
to render an SVG:
const printTorrentDetails = (torrent: Torrent) => {
return `<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
${renderPieces(torrent.pieces, torrent.pieceCount)
.map(
({ moveTo, lineTo, alpha }) =>
`<line x1="${moveTo[0]}" y1="${moveTo[1]}" x2="${lineTo[0]}" y2="${lineTo[1]}" stroke="rgba(0, 0, 0, ${alpha})" />`
)
.join("")}
</svg>`;
}
The problem is that my code is only rendering a list of vertical lines instead of something resembling the image I posted.
This is my base64 encoded bitfield:
Ph/d7r/f/fN///xwVv///v///+/Y7///54QH///ePc///vt///D//3/8fgDvf/////8f3n+CH+f+TI///DwA//9MAGMAfB/P4BYAAcf2AaHjj//+D+eAAf/v/+HiAH4f/x/hAAP//8PEBkAAf8AxEEcAPwCMIEB4j4AFAQAAAQBDgAAAoAAATAAAsAAAAYAAAAAAAAAABAAAAACAAHgAAAAQAABAAJAAAAEAASAAAAACAAAYAAgAAAAAAmAAABAAAAgAAAAAAAAAEAgAAAAIACAAACEEAAAAAEwIAAABAAAAAAAQAAAARADIACAACCAgAgAAAQAAAABAIAACEBAAAAAAAAAAAEAAEAAAAEAgCAAAAAIIAAIAAAIAAAEIAAAAiBAAAAEAAAAAAAAAAAAAAAAAAAAAgAAAAAAAEgAAEQAAAoAAEAAEEAAAAAAAIAAAAoAIQgAAAAGBBAgAAAIABADABGAARAAIAAAABAAAEAAAAAAAAIAAAAAiAgABAAAAAAAAkQAECCBQAAAAAAAAAAAIAAAAABgAEAIwAAABBAIABABARQAAAAQAIgAgAAAQBEAAAAAgEAAABAAAAAAAgwAAEABBAIAAAAAAAAAAAAAAAAgABKAAAAAAAgACAAgIAQAAAAAAEBAAAAEAAAAADAAMAAAAAYAAAAABAAACAAAAEIQQIAAABAABAAAAAAAAAAAAAAEAAQAAgAAAQAAAAAAIBAAAAQEAAAAAgAQQAAAIAgAAAABAAAAAAAgAAAgAAAAAAAAAAACAAAAAACAAAAAAAAAAAAACAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAABSAAAAAAAAAAACAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA=