This demo shows a fictional group of people linked by their activity on various social media platforms.
When analysing connections, it is useful to resolve multiple identifiers (such as social media accounts) into a single entity (the account owner). This reveals interesting patterns without overwhelming the chart with the clutter of individual communications.
Combos can represent a single entity, but also enable analysts to drill down into detail and explore how information spreads between groups of people.
The 𝕏 logo is a trademark of X, Inc.
The ** logo is a trademark of Meta.
Key functions used:
import KeyLines from "keylines";
import { data, style } from "./data.js";
let chart;
let hoveredGlyph = null;
const expandLayoutOpts = {
fit: true,
name: "organic",
mode: "adaptive",
};
function getGlyphs(item) {
const isOpenCombo = chart.combo().isOpen(item.id);
return isOpenCombo ? item.oc.g : item.g;
}
function setGlyphs(id, glyphs, isOpenCombo = chart.combo().isOpen(id)) {
const g = isOpenCombo ? { oc: { g: glyphs } } : { g: glyphs };
chart.setProperties({ id, ...g });
}
function getHoveredGlyph(item, subId) {
if (item) {
if (item.d.type === "post" && item.g && item.g.length === 1) {
return 0;
}
const glyphs = getGlyphs(item);
if (glyphs) {
return glyphs.findIndex((g) => g.p.toString() === subId);
}
}
}
function chartHoverHandler({ id, subItem: { subId } }) {
const item = chart.getItem(id);
const index = getHoveredGlyph(item, subId);
const isOpenCombo = chart.combo().isOpen(id);
let glyphToHover = null;
// Work out if the cursor is over a glyph which is in the foreground to focus
// i.e. over an expand glyph on a node or a post node with an expand glyph
if (id && item && !item.bg && item.type === "node" && index >= 0) {
glyphToHover = item.id;
}
// Return any previously focussed glyph to normal
if (hoveredGlyph && hoveredGlyph.nodeId !== glyphToHover) {
setGlyphs(hoveredGlyph.nodeId, hoveredGlyph.originalGlyphs, hoveredGlyph.isOpenCombo);
hoveredGlyph = null;
}
// Focus any newly hovered glyph
if (!hoveredGlyph && glyphToHover) {
const originalGlyphs = getGlyphs(item);
const newGlyphs = originalGlyphs.map((g, i) => {
return i === index ? { ...g, c: style.hoverStyles[g.c] } : g;
});
hoveredGlyph = { nodeId: id, sub: subId, originalGlyphs, isOpenCombo };
setGlyphs(id, newGlyphs);
}
}
function getAllCombos() {
const combos = [];
// In this demo all top level items are combos and there are no nested combos
chart.each({ type: "node", items: "toplevel" }, (combo) => {
combos.push(combo.id);
});
return combos;
}
function enableInput(enabled) {
const buttons = ["openCombos", "closeCombos", "expandCombos"];
buttons.forEach((id) => {
const button = document.getElementById(id);
if (enabled) {
button.classList.remove("disabled");
button.removeAttribute("disabled");
} else {
button.classList.add("disabled");
button.setAttribute("disabled", "");
}
});
}
async function openCombos() {
enableInput(false);
await chart.combo().open(getAllCombos());
chart.layout("organic", { mode: "adaptive" });
enableInput(true);
}
async function closeCombos() {
enableInput(false);
await chart.combo().close(getAllCombos());
chart.layout("organic", { mode: "adaptive" });
enableInput(true);
}
async function expandAllCombos() {
enableInput(false);
let allOwners = [];
for (const owner in data.rawData.owners) {
const combo = createEntityCombo(owner);
allOwners.push(...combo);
}
await chart.expand(allOwners, {
layout: expandLayoutOpts,
time: 700,
arrange: { name: "lens" },
});
styleLinks();
enableInput(true);
}
function getRepostIds(platformInfo, postId) {
return data.rawData[platformInfo.data]
.filter((p) => p[platformInfo.copyOf] === postId)
.map((p) => p.id);
}
/* Create chart items */
function createPostNode(platformInfo, post, owner) {
const reposts = getRepostIds(platformInfo, post.id);
const colour =
post[platformInfo.copyOf] || reposts.length > 0
? platformInfo.colour
: platformInfo.fadedColour;
return {
id: post.id,
type: "node",
fi: { t: platformInfo.postIcon, c: colour },
e: 0.75,
d: {
type: "post",
platform: platformInfo.name,
idx: post.idx,
copyOf: post[platformInfo.copyOf],
reposts,
},
parentId: owner,
};
}
function createAuthoredByLink(platformInfo, post) {
return {
id: `${platformInfo.author}${post[platformInfo.author]} ${post.id}`,
type: "link",
id1: post[platformInfo.author],
id2: post.id,
a2: true,
c: platformInfo.colour,
d: { type: "authoredBy" },
};
}
function createRepostLink(platformInfo, repostId, postId) {
return {
id: repostId + platformInfo.copyOf + postId,
type: "link",
id1: repostId,
id2: postId,
a1: true,
c: platformInfo.colour,
d: { type: "repost" },
};
}
function createAccountNodes(owner, platformInfo) {
const ownerInfo = data.rawData.owners[owner];
const accountIcon =
platformInfo.name === "x" ? "/images/icons/x-logo-2023.svg" : "/images/icons/facebook-2023.svg";
return ownerInfo[`${platformInfo.name}Accounts`].map((account) => ({
id: account.id,
type: "node",
c: platformInfo.name === "x" ? "rgb(255, 255, 255)" : "transparent",
bw: 2,
b: "transparent",
e: 0.8,
fc: style.textColour,
fs: 16,
t: [
{
t: account.name,
borderRadius: 20,
bw: 0,
padding: "3 5 0 5",
fbc: "rgba(255, 255, 255, 0)",
b: "rgb(255, 255, 255)",
},
],
u: accountIcon,
parentId: owner,
d: { type: "account", platform: platformInfo.name },
}));
}
function getPlatformContentBy(owner, platform, links) {
const platformInfo = style.platformDetails[platform];
const platformPosts = data.rawData[platformInfo.data];
const accountNodes = createAccountNodes(owner, platformInfo);
const accounts = accountNodes.map((node) => node.id);
const posts = platformPosts
.filter((post) => accounts.includes(post[platformInfo.author]))
.map((post) => {
const node = createPostNode(platformInfo, post, owner);
links.push(createAuthoredByLink(platformInfo, post));
// Expand in all the copyOf links for this post
// If the other end isn't in the chart yet, they will automatically be filtered out
if (post[platformInfo.copyOf]) {
links.push(createRepostLink(platformInfo, post.id, post[platformInfo.copyOf]));
}
node.d.reposts.forEach((repost) => {
links.push(createRepostLink(platformInfo, repost, node.id));
});
return node;
});
return [...accountNodes, ...posts];
}
function getLinkSize(id) {
if (chart.combo().isCombo(id, { type: "link" })) {
// set the link thickness
return 3.5 * Math.sqrt(chart.combo().info(id).links.length);
}
return 3.5;
}
function createEntityCombo(owner) {
const ownerInfo = data.rawData.owners[owner];
const ownerImage = `/im/people/${owner}.png`;
const entityGlyph = {
u: ownerImage,
p: style.entityGlyphPos,
e: 3,
};
const label = {
t: `${ownerInfo.firstname} ${ownerInfo.surname}`,
fs: 16,
borderRadius: 8,
bw: 0,
b: "transparent",
fc: style.textColour,
fbc: "transparent",
position: "s",
padding: "3 5 0 5",
};
let nodes = [
{
id: owner,
type: "node",
e: 2,
fc: style.textColour,
fi: style.entityIcon,
fs: 16,
t: label,
u: ownerImage,
oc: {
bw: 4,
c: "rgba(21, 6, 28, 0.5)",
b: "rgb(255, 255, 255)",
g: [entityGlyph, style.closeComboGlyph],
t: label,
},
g: [style.openComboGlyph],
d: { type: "owner" },
},
];
const links = [];
["x", "fb"].forEach((platform) => {
nodes = nodes.concat(getPlatformContentBy(owner, platform, links));
});
return [...nodes, ...links];
}
/* END of functions to create chart items */
// Expand in the neighbours of item not already in the chart
// and if highlight is true, highlight all the neighbours of item
function getRepostsToExpandIn(postId, postData) {
let items = [];
const platformInfo = style.platformDetails[postData.platform];
const allPosts = data.rawData[platformInfo.data];
const reposts = postData.reposts.map((pId) => {
const id = pId.slice(platformInfo.identifier.length);
return { id, dir: "to" };
});
if (postData.copyOf) {
reposts.push({ id: postData.copyOf.slice(platformInfo.identifier.length), dir: "from" });
}
// Repost already in the chart => nothing to expand in => filter out
reposts
.filter((repost) => !chart.getItem(platformInfo.identifier + repost.id))
.forEach((repost) => {
const p = allPosts[repost.id];
const author = p[platformInfo.author];
const owner = data.rawData.accounts[postData.platform][author].owner;
// Include all the accounts of this owner
items = items.concat(createEntityCombo(owner));
const origPost = repost.dir === "from" ? p.id : postId;
const repostedTo = repost.id === "from" ? postId : p.id;
const repostLink = createRepostLink(platformInfo, repostedTo, origPost);
items.push(repostLink);
});
styleLinks();
return items;
}
// Update the expand glyphs on current chart items to correctly identify which can be expanded
function updateGlyphs() {
const props = [];
const expandableCombos = {};
const graphEngine = KeyLines.getGraphEngine();
graphEngine.load(chart.serialize());
const degrees = graphEngine.degrees();
chart.each({ type: "node" }, (node) => {
if (node.d && node.d.type === "post") {
let numReposts = node.d.reposts ? node.d.reposts.length : 0;
if (node.d.copyOf) numReposts++;
if (numReposts > 0) {
const inChart = degrees[node.id] - 1;
if (inChart !== numReposts) {
props.push({ id: node.id, g: [style.expandGlyph] });
const parentCombo = chart.getItem(node.parentId);
props.push({
id: node.parentId,
g: [style.openComboGlyph, style.expandGlyph],
oc: { ...parentCombo.oc, g: [...parentCombo.oc.g, style.expandGlyph] },
});
expandableCombos[node.parentId] = true;
} else {
props.push({ id: node.id, g: [] });
}
}
}
});
// Check if glyph needs removing from any combos
chart.each({ type: "node", items: "toplevel" }, (combo) => {
if (!expandableCombos[combo.id]) {
props.push({ id: combo.id, g: [combo.g[0]], oc: { g: combo.oc.g.slice(0, 2) } });
}
});
chart.setProperties(props);
}
async function loadStartingNode() {
// data is defined in socialmedia-data.js
chart.clear();
const startingCombo = createEntityCombo(data.initialEntity);
await chart.expand(startingCombo, {
layout: expandLayoutOpts,
time: 200,
arrange: { name: "lens" },
});
exploreOutwards(startingCombo[0]);
chart.selection([startingCombo[0].id]);
updateGlyphs();
styleLabels(chart.selection());
styleNodes(chart.selection());
styleLinks();
}
/**
* Get the items to expand into the chart so that all direct reposts or previous posts of
* postId (the data about which is in the postData object) are included in the chart
* (including the details of their containing combos)
*/
function getAllCopiesOfPost(postId) {
let origPostId = postId;
let origPost = chart.getItem(postId);
while (origPost.d.copyOf) {
origPost = chart.getItem(origPost.d.copyOf);
// Only store ID and continue search for original if node in the chart
if (origPost) origPostId = origPost.id;
else break;
}
let reposts = [origPostId];
for (let i = 0; i < reposts.length; i++) {
const repost = chart.getItem(reposts[i]);
if (repost) {
reposts = [...reposts, ...repost.d.reposts];
}
}
return reposts;
}
function isParentOpen(nodeId) {
return chart.combo().isOpen(chart.combo().find(nodeId));
}
/**
* Foreground the item defined by id and its linked items.
* For owners this is just their neighbours
* For accounts this is all accounts that have interacted with it and all posts by those accounts
* (including the original account)
* For posts this is all copies of the post and the accounts making those posts
*/
function revealAndForeground(linksToReveal, itemsToForeground, fgItems) {
const bgLinks = [];
// Only reveal links if at least one end inside an open combo
const toReveal = linksToReveal.filter((linkId) => {
const link = chart.getItem(linkId);
if (isParentOpen(link.id1) || isParentOpen(link.id2)) {
// Background any parent link unless it is explicitly set to be foregrounded
if (
link.parentId &&
chart.getItem(link.parentId).type === "link" &&
!itemsToForeground.includes(link.parentId)
) {
bgLinks.push(link.parentId);
}
return true;
}
return false;
});
chart.combo().reveal(toReveal);
chart.foreground((item) => itemsToForeground.includes(item.id), { type: "all", items: fgItems });
// background all combolinks of revealed links
chart.setProperties(bgLinks.map((linkId) => ({ id: linkId, bg: true })));
}
function highlightRelations(ids) {
const clickedNodes = chart.getItem(ids).filter((item) => item.type === "node");
let fgItems;
if (clickedNodes.length > 0) {
let nbrs;
let itemsToForeground = [...ids];
const linksToReveal = [];
const graphEngine = KeyLines.getGraphEngine();
graphEngine.load(chart.serialize());
clickedNodes.forEach((clicked) => {
if (clicked.d.type === "owner") {
fgItems = "toplevel";
nbrs = chart.graph().neighbours(clicked.id);
itemsToForeground = itemsToForeground.concat(nbrs.nodes, nbrs.links, [clicked.id]);
} else {
fgItems = "underlying";
if (clicked.d.type === "account") {
// Get the accounts that have interacted with this account
const nbrs3 = graphEngine.neighbours(clicked.id, { hops: 3 });
const connectedAccounts = nbrs3.nodes.filter((nodeId) => {
const isAccount = chart.getItem(nodeId).d.type === "account";
return isAccount;
});
connectedAccounts.push(clicked.id);
// Get the posts by these accounts (and links to them)
nbrs = graphEngine.neighbours(connectedAccounts);
// Get underlying links between the accounts
// (these won't be revealed but the combolink will be foregrounded)
const interAccountLinks = graphEngine.neighbours(clicked.id, { hops: 2 }).links;
itemsToForeground = itemsToForeground.concat(
nbrs.nodes,
nbrs.links,
connectedAccounts,
interAccountLinks
);
} else {
// clicked.d.type === 'post'
const copiesOfPost = getAllCopiesOfPost(clicked.id);
itemsToForeground = [...itemsToForeground, ...copiesOfPost];
chart.each({ type: "link" }, (link) => {
// Also foreground accounts which posted these posts
// (account is always id1 on a postedBy link)
if (copiesOfPost.includes(link.id2)) {
if (!copiesOfPost.includes(link.id1)) {
itemsToForeground.push(link.id1);
}
linksToReveal.push(link.id);
}
});
itemsToForeground = [...itemsToForeground, ...linksToReveal];
}
}
});
revealAndForeground(linksToReveal, itemsToForeground, fgItems);
} else {
chart.combo().reveal([]);
chart.foreground(() => true);
}
}
async function styleLabels(selections) {
const props = [];
const colourLabel = (item, colour) => {
let labels = item.t;
if (Array.isArray(labels)) {
labels = labels.map((label) => ({ ...label, fbc: colour }));
}
return { ...item, t: labels };
};
chart.each({ type: "node", items: "all" }, (item) => {
const { id, t, oc } = item;
const colour = selections.includes(id) ? style.selectionColour : "transparent";
props.push({ id, ...colourLabel({ t, oc }, colour) });
});
await chart.setProperties(props);
}
function styleNodes(selection) {
const propertiesToSet = [];
chart.each({ type: "node", items: "toplevel" }, (node) => {
let border;
if (selection.includes(node.id)) {
// hide border
border = "transparent";
} else {
// add border
border = "white";
}
propertiesToSet.push({
id: node.id,
...node,
oc: { ...node.oc, t: node.t, b: border },
});
});
chart.setProperties(propertiesToSet);
}
function styleLinks() {
const propertiesToSet = [];
chart.each({ type: "link", items: "toplevel" }, (link) => {
propertiesToSet.push({
id: link.id,
...link,
w: getLinkSize(link.id),
});
});
chart.setProperties(propertiesToSet);
}
function selectionchangeHandler() {
const selection = chart.selection();
if (selection.length === 0) {
highlightRelations(selection);
styleLabels(selection);
styleNodes(selection);
} else {
const items = chart.getItem(selection);
const nodeIds = items.filter((item) => item.type !== "link").map((item) => item.id);
highlightRelations(nodeIds);
styleLabels(nodeIds);
styleNodes(nodeIds);
}
}
async function exploreOutwards(item, highlight) {
let expandIn = [];
if (!item || !item.id || item.type !== "node" || !item.d) {
return;
}
if (item.d.type === "post") {
// Add in reposts
expandIn = getRepostsToExpandIn(item.id, item.d);
} else if (item.d.type === "owner") {
const content = chart.combo().info(item.id).nodes;
content.forEach((t) => {
if (t.d.type === "post") {
expandIn = expandIn.concat(getRepostsToExpandIn(t.id, t.d));
}
});
} else {
return;
}
// Prevent opening/closing of combos while data is being added to the chart
chart.on("double-click", ({ preventDefault }) => preventDefault());
await chart.expand(expandIn, {
layout: expandLayoutOpts,
arrange: { name: "lens" },
time: 700,
});
chart.off("double-click");
updateGlyphs();
if (highlight) highlightRelations([item.id]);
}
function toggleCombo(id) {
const isCombo = chart.combo().isCombo(id);
if (isCombo) {
const isOpen = chart.combo().isOpen(id);
if (isOpen) {
chart.combo().close(id);
} else {
chart.combo().open(id);
}
}
}
function chartClickHandler({ id, subItem: { subId } }) {
const item = chart.getItem(id);
// Only check for glyph clicks if in foreground
if (item && item.type === "node" && !item.bg) {
if (
subId === style.expandGlyphPos.toString() ||
(item.d.type === "post" && item.g && item.g.length === 1)
) {
// Ensure the expand glyph isn't re-added to this node
if (hoveredGlyph && hoveredGlyph.nodeId === id) {
hoveredGlyph = null;
}
exploreOutwards(item, true);
} else if (subId === style.openCloseGlyphPos.toString()) {
toggleCombo(id);
}
}
}
function initialiseInteractions() {
// Setup handlers
chart.on("hover", chartHoverHandler);
chart.on("click", chartClickHandler);
chart.on("selection-change", selectionchangeHandler);
document.getElementById("openCombos").addEventListener("click", openCombos);
document.getElementById("closeCombos").addEventListener("click", closeCombos);
document.getElementById("expandCombos").addEventListener("click", expandAllCombos);
document.getElementById("reset").addEventListener("click", loadStartingNode);
loadStartingNode();
}
async function startKeyLines() {
// Set offsets and enlargements for Font Icons
const imageAlignment = {
"fas fa-user": { dy: -12, e: 1.2 },
"fas fa-plus": { e: 1 },
"/images/icons/x-logo-2023.svg": { e: 0.5 },
};
const options = {
arrows: "large",
defaultStyles: {
comboGlyph: null,
comboLinks: { c: "rgb(201, 160, 217)" },
},
handMode: true,
navigation: false,
minZoom: -4,
hover: 0,
iconFontFamily: "Font Awesome 5 Brands",
imageAlignment,
selectionColour: style.selectionColour,
selectedLink: {},
gradient: {
stops: [
{ c: "#543c5e", r: 0 },
{ c: "#15001f", r: 1 },
],
},
};
chart = await KeyLines.create({ container: "klchart", options });
initialiseInteractions();
}
function loadKeyLines() {
Promise.all([
document.fonts.load('24px "Font Awesome 5 Free"'),
document.fonts.load('24px "Font Awesome 5 Brands"'),
]).then(startKeyLines);
}
window.addEventListener("DOMContentLoaded", loadKeyLines); import KeyLines from "keylines";
const data = {
rawData: {
owners: {
Person0: {
idx: 0,
id: "Person0",
firstname: "Diane",
surname: "Denman",
nickname: "Di",
fbAccounts: [
{
id: "Person0fb0",
name: "Di D",
owner: "Person0",
reposts: [1, 2, 3],
platform: "fb",
},
],
xAccounts: [
{
id: "Person0x0",
name: "@Di",
owner: "Person0",
reposts: [0, 1, 9],
platform: "x",
},
{
id: "Person0x1",
name: "@Di D",
owner: "Person0",
reposts: [0, 1, 9],
platform: "x",
},
],
},
Person1: {
idx: 1,
id: "Person1",
firstname: "Ophelia",
surname: "Winston",
fbAccounts: [
{
id: "Person1fb0",
name: "Ophelia W",
owner: "Person1",
reposts: [0, 2, 3, 12, 13, 14],
platform: "fb",
},
],
xAccounts: [
{
id: "Person1x0",
name: "@Ophelia",
owner: "Person1",
reposts: [0, 2, 12, 13, 14],
platform: "x",
},
],
},
Person2: {
idx: 2,
id: "Person2",
firstname: "Niall",
surname: "Milligan",
fbAccounts: [
{
id: "Person2fb0",
name: "Niall M",
owner: "Person2",
reposts: [0, 1, 3],
platform: "fb",
},
],
xAccounts: [
{
id: "Person2x0",
name: "@Niall",
owner: "Person2",
reposts: [0, 1, 2],
platform: "x",
},
{
id: "Person2x1",
name: "@Niall M",
owner: "Person2",
reposts: [0, 1, 2],
platform: "x",
},
],
},
Person3: {
idx: 3,
id: "Person3",
firstname: "Emanuela",
surname: "Cooper",
nickname: "Ella",
fbAccounts: [
{
id: "Person3fb0",
name: "Ella C",
owner: "Person3",
reposts: [0, 1, 2, 4, 5],
platform: "fb",
},
],
xAccounts: [],
},
Person4: {
idx: 4,
id: "Person4",
firstname: "Tammy",
surname: "McKendrick",
fbAccounts: [
{
id: "Person4fb0",
name: "Tammy McK",
owner: "Person4",
reposts: [3, 5],
platform: "fb",
},
],
xAccounts: [],
},
Person5: {
idx: 5,
id: "Person5",
firstname: "Malakai",
surname: "Janson",
fbAccounts: [
{
id: "Person5fb0",
name: "Malakai J",
owner: "Person5",
reposts: [3, 4],
platform: "fb",
},
],
xAccounts: [],
},
Person6: {
idx: 6,
id: "Person6",
firstname: "Delia",
surname: "Foster",
fbAccounts: [
{
id: "Person6fb0",
name: "Delia F",
owner: "Person6",
reposts: [4],
platform: "fb",
},
],
xAccounts: [
{
id: "Person6x0",
name: "@Delia",
owner: "Person6",
reposts: [6, 7],
platform: "x",
},
{
id: "Person6x1",
name: "@Delia F",
owner: "Person6",
reposts: [6, 7],
platform: "x",
},
],
},
Person7: {
idx: 7,
id: "Person7",
firstname: "Christie",
surname: "Sergeant",
nickname: "Chrissie",
fbAccounts: [],
xAccounts: [
{
id: "Person7x0",
name: "@Chrissie",
owner: "Person7",
reposts: [6],
platform: "x",
},
],
},
Person8: {
idx: 8,
id: "Person8",
firstname: "Coreen",
surname: "Reis",
fbAccounts: [],
xAccounts: [
{
id: "Person8x0",
name: "@Coreen",
owner: "Person8",
reposts: [6, 7, 8],
platform: "x",
},
{
id: "Person8x1",
name: "@Coreen R",
owner: "Person8",
reposts: [6, 7, 8],
platform: "x",
},
],
},
Person9: {
idx: 9,
id: "Person9",
firstname: "Vito",
surname: "Morello",
fbAccounts: [],
xAccounts: [
{
id: "Person9x0",
name: "@Vito",
owner: "Person9",
reposts: [0, 9, 10, 11],
platform: "x",
},
{
id: "Person9x1",
name: "@Vito M",
owner: "Person9",
reposts: [0, 9, 10, 11],
platform: "x",
},
],
},
Person10: {
idx: 10,
id: "Person10",
firstname: "Sebastian",
surname: "Fabian",
nickname: "Seb",
fbAccounts: [],
xAccounts: [
{
id: "Person10x0",
name: "@Seb",
owner: "Person10",
reposts: [9, 11],
platform: "x",
},
],
},
Person11: {
idx: 11,
id: "Person11",
firstname: "Jill",
surname: "Bukoski",
fbAccounts: [],
xAccounts: [
{
id: "Person11x0",
name: "@Jill",
owner: "Person11",
reposts: [0, 9, 10],
platform: "x",
},
],
},
Person12: {
idx: 12,
id: "Person12",
firstname: "Ashlea",
surname: "Coeman",
fbAccounts: [
{
id: "Person12fb0",
name: "Ashlea C",
owner: "Person12",
reposts: [1, 13, 14],
platform: "fb",
},
],
xAccounts: [
{
id: "Person12x0",
name: "@Ashlea",
owner: "Person12",
reposts: [1, 13, 14],
platform: "x",
},
],
},
Person13: {
idx: 13,
id: "Person13",
firstname: "Valerie",
surname: "Beaumont",
nickname: "Val",
fbAccounts: [
{
id: "Person13fb0",
name: "Val B",
owner: "Person13",
reposts: [1, 12, 14],
platform: "fb",
},
],
xAccounts: [
{
id: "Person13x0",
name: "@Val",
owner: "Person13",
reposts: [1, 12, 14],
platform: "x",
},
],
},
Person14: {
idx: 14,
id: "Person14",
firstname: "Tatiana",
surname: "Columbo",
fbAccounts: [
{
id: "Person14fb0",
name: "Tatiana C",
owner: "Person14",
reposts: [1, 12, 13, 15],
platform: "fb",
},
],
xAccounts: [
{
id: "Person14x0",
name: "@Tatiana",
owner: "Person14",
reposts: [1, 12, 13, 14],
platform: "x",
},
{
id: "Person14x1",
name: "@Tatiana C",
owner: "Person14",
reposts: [1, 12, 13, 14],
platform: "x",
},
],
},
Person15: {
idx: 15,
id: "Person15",
firstname: "Raegan",
surname: "Ready",
fbAccounts: [
{
id: "Person15fb0",
name: "Raegan R",
owner: "Person15",
reposts: [12, 14, 16, 17],
platform: "fb",
},
],
xAccounts: [],
},
Person16: {
idx: 16,
id: "Person16",
firstname: "Richard",
surname: "Gallo",
nickname: "Ricky",
fbAccounts: [
{
id: "Person16fb0",
name: "Ricky G",
owner: "Person16",
reposts: [],
platform: "fb",
},
],
xAccounts: [
{
id: "Person16x0",
name: "@Ricky",
owner: "Person16",
reposts: [],
platform: "x",
},
],
},
Person17: {
idx: 17,
id: "Person17",
firstname: "Madilyn",
surname: "Both",
nickname: "Maddy",
fbAccounts: [
{
id: "Person17fb0",
name: "Maddy B",
owner: "Person17",
reposts: [15, 16],
platform: "fb",
},
],
xAccounts: [
{
id: "Person17x0",
name: "@Maddy",
owner: "Person17",
reposts: [15, 16],
platform: "x",
},
],
},
Person18: {
idx: 18,
id: "Person18",
firstname: "Michael",
surname: "Burnham",
nickname: "Mike",
fbAccounts: [
{
id: "Person18fb0",
name: "Mike B",
owner: "Person18",
reposts: [2, 19],
platform: "fb",
},
],
xAccounts: [],
},
Person19: {
idx: 19,
id: "Person19",
firstname: "David",
surname: "Van Kann",
nickname: "Dave",
fbAccounts: [
{
id: "Person19fb0",
name: "Dave Van K",
owner: "Person19",
reposts: [18],
platform: "fb",
},
],
xAccounts: [],
},
},
accounts: {
fb: {
Person0fb0: {
id: "Person0fb0",
name: "Di D",
owner: "Person0",
reposts: [1, 2, 3],
platform: "fb",
},
Person1fb0: {
id: "Person1fb0",
name: "Ophelia W",
owner: "Person1",
reposts: [0, 2, 3, 12, 13, 14],
platform: "fb",
},
Person2fb0: {
id: "Person2fb0",
name: "Niall M",
owner: "Person2",
reposts: [0, 1, 3],
platform: "fb",
},
Person3fb0: {
id: "Person3fb0",
name: "Ella C",
owner: "Person3",
reposts: [0, 1, 2, 4, 5],
platform: "fb",
},
Person4fb0: {
id: "Person4fb0",
name: "Tammy McK",
owner: "Person4",
reposts: [3, 5],
platform: "fb",
},
Person5fb0: {
id: "Person5fb0",
name: "Malakai J",
owner: "Person5",
reposts: [3, 4],
platform: "fb",
},
Person6fb0: {
id: "Person6fb0",
name: "Delia F",
owner: "Person6",
reposts: [4],
platform: "fb",
},
Person12fb0: {
id: "Person12fb0",
name: "Ashlea C",
owner: "Person12",
reposts: [1, 13, 14],
platform: "fb",
},
Person13fb0: {
id: "Person13fb0",
name: "Val B",
owner: "Person13",
reposts: [1, 12, 14],
platform: "fb",
},
Person14fb0: {
id: "Person14fb0",
name: "Tatiana C",
owner: "Person14",
reposts: [1, 12, 13, 15],
platform: "fb",
},
Person15fb0: {
id: "Person15fb0",
name: "Raegan R",
owner: "Person15",
reposts: [12, 14, 16, 17],
platform: "fb",
},
Person16fb0: {
id: "Person16fb0",
name: "Ricky G",
owner: "Person16",
reposts: [],
platform: "fb",
},
Person17fb0: {
id: "Person17fb0",
name: "Maddy B",
owner: "Person17",
reposts: [15, 16],
platform: "fb",
},
Person18fb0: {
id: "Person18fb0",
name: "Mike B",
owner: "Person18",
reposts: [2, 19],
platform: "fb",
},
Person19fb0: {
id: "Person19fb0",
name: "Dave Van K",
owner: "Person19",
reposts: [18],
platform: "fb",
},
},
x: {
Person0x0: {
id: "Person0x0",
name: "@Di",
owner: "Person0",
reposts: [0, 1, 9],
platform: "x",
},
Person0x1: {
id: "Person0x1",
name: "@Di D",
owner: "Person0",
reposts: [0, 1, 9],
platform: "x",
},
Person1x0: {
id: "Person1x0",
name: "@Ophelia",
owner: "Person1",
reposts: [0, 2, 12, 13, 14],
platform: "x",
},
Person2x0: {
id: "Person2x0",
name: "@Niall",
owner: "Person2",
reposts: [0, 1, 2],
platform: "x",
},
Person2x1: {
id: "Person2x1",
name: "@Niall M",
owner: "Person2",
reposts: [0, 1, 2],
platform: "x",
},
Person6x0: {
id: "Person6x0",
name: "@Delia",
owner: "Person6",
reposts: [6, 7],
platform: "x",
},
Person6x1: {
id: "Person6x1",
name: "@Delia F",
owner: "Person6",
reposts: [6, 7],
platform: "x",
},
Person7x0: {
id: "Person7x0",
name: "@Chrissie",
owner: "Person7",
reposts: [6],
platform: "x",
},
Person8x0: {
id: "Person8x0",
name: "@Coreen",
owner: "Person8",
reposts: [6, 7, 8],
platform: "x",
},
Person8x1: {
id: "Person8x1",
name: "@Coreen R",
owner: "Person8",
reposts: [6, 7, 8],
platform: "x",
},
Person9x0: {
id: "Person9x0",
name: "@Vito",
owner: "Person9",
reposts: [0, 9, 10, 11],
platform: "x",
},
Person9x1: {
id: "Person9x1",
name: "@Vito M",
owner: "Person9",
reposts: [0, 9, 10, 11],
platform: "x",
},
Person10x0: {
id: "Person10x0",
name: "@Seb",
owner: "Person10",
reposts: [9, 11],
platform: "x",
},
Person11x0: {
id: "Person11x0",
name: "@Jill",
owner: "Person11",
reposts: [0, 9, 10],
platform: "x",
},
Person12x0: {
id: "Person12x0",
name: "@Ashlea",
owner: "Person12",
reposts: [1, 13, 14],
platform: "x",
},
Person13x0: {
id: "Person13x0",
name: "@Val",
owner: "Person13",
reposts: [1, 12, 14],
platform: "x",
},
Person14x0: {
id: "Person14x0",
name: "@Tatiana",
owner: "Person14",
reposts: [1, 12, 13, 14],
platform: "x",
},
Person14x1: {
id: "Person14x1",
name: "@Tatiana C",
owner: "Person14",
reposts: [1, 12, 13, 14],
platform: "x",
},
Person16x0: {
id: "Person16x0",
name: "@Ricky",
owner: "Person16",
reposts: [],
platform: "x",
},
Person17x0: {
id: "Person17x0",
name: "@Maddy",
owner: "Person17",
reposts: [15, 16],
platform: "x",
},
},
},
posts: [
{
idx: 0,
id: "xPost0",
xPostBy: "Person13x0",
xRepostOf: null,
},
{
idx: 1,
id: "xPost1",
xPostBy: "Person7x0",
xRepostOf: null,
},
{
idx: 2,
id: "xPost2",
xPostBy: "Person14x1",
xRepostOf: null,
},
{
idx: 3,
id: "xPost3",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 4,
id: "xPost4",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 5,
id: "xPost5",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 6,
id: "xPost6",
xPostBy: "Person9x0",
xRepostOf: "xPost5",
},
{
idx: 7,
id: "xPost7",
xPostBy: "Person9x1",
xRepostOf: "xPost5",
},
{
idx: 8,
id: "xPost8",
xPostBy: "Person10x0",
xRepostOf: "xPost5",
},
{
idx: 9,
id: "xPost9",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 10,
id: "xPost10",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 11,
id: "xPost11",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 12,
id: "xPost12",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 13,
id: "xPost13",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 14,
id: "xPost14",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 15,
id: "xPost15",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 16,
id: "xPost16",
xPostBy: "Person14x1",
xRepostOf: null,
},
{
idx: 17,
id: "xPost17",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 18,
id: "xPost18",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 19,
id: "xPost19",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 20,
id: "xPost20",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 21,
id: "xPost21",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 22,
id: "xPost22",
xPostBy: "Person1x0",
xRepostOf: "xPost21",
},
{
idx: 23,
id: "xPost23",
xPostBy: "Person2x0",
xRepostOf: "xPost21",
},
{
idx: 24,
id: "xPost24",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 25,
id: "xPost25",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 26,
id: "xPost26",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 27,
id: "xPost27",
xPostBy: "Person2x0",
xRepostOf: null,
},
{
idx: 28,
id: "xPost28",
xPostBy: "Person7x0",
xRepostOf: null,
},
{
idx: 29,
id: "xPost29",
xPostBy: "Person6x1",
xRepostOf: "xPost28",
},
{
idx: 30,
id: "xPost30",
xPostBy: "Person8x0",
xRepostOf: "xPost28",
},
{
idx: 31,
id: "xPost31",
xPostBy: "Person8x1",
xRepostOf: "xPost30",
},
{
idx: 32,
id: "xPost32",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 33,
id: "xPost33",
xPostBy: "Person8x0",
xRepostOf: "xPost32",
},
{
idx: 34,
id: "xPost34",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 35,
id: "xPost35",
xPostBy: "Person14x1",
xRepostOf: null,
},
{
idx: 36,
id: "xPost36",
xPostBy: "Person14x0",
xRepostOf: "xPost35",
},
{
idx: 37,
id: "xPost37",
xPostBy: "Person16x0",
xRepostOf: null,
},
{
idx: 38,
id: "xPost38",
xPostBy: "Person17x0",
xRepostOf: "xPost37",
},
{
idx: 39,
id: "xPost39",
xPostBy: "Person9x1",
xRepostOf: null,
},
{
idx: 40,
id: "xPost40",
xPostBy: "Person10x0",
xRepostOf: null,
},
{
idx: 41,
id: "xPost41",
xPostBy: "Person9x0",
xRepostOf: "xPost40",
},
{
idx: 42,
id: "xPost42",
xPostBy: "Person9x1",
xRepostOf: "xPost40",
},
{
idx: 43,
id: "xPost43",
xPostBy: "Person0x1",
xRepostOf: "xPost42",
},
{
idx: 44,
id: "xPost44",
xPostBy: "Person11x0",
xRepostOf: "xPost42",
},
{
idx: 45,
id: "xPost45",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 46,
id: "xPost46",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 47,
id: "xPost47",
xPostBy: "Person6x1",
xRepostOf: "xPost46",
},
{
idx: 48,
id: "xPost48",
xPostBy: "Person7x0",
xRepostOf: "xPost47",
},
{
idx: 49,
id: "xPost49",
xPostBy: "Person8x0",
xRepostOf: "xPost47",
},
{
idx: 50,
id: "xPost50",
xPostBy: "Person8x1",
xRepostOf: "xPost49",
},
{
idx: 51,
id: "xPost51",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 52,
id: "xPost52",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 53,
id: "xPost53",
xPostBy: "Person7x0",
xRepostOf: "xPost52",
},
{
idx: 54,
id: "xPost54",
xPostBy: "Person8x0",
xRepostOf: "xPost52",
},
{
idx: 55,
id: "xPost55",
xPostBy: "Person8x1",
xRepostOf: "xPost52",
},
{
idx: 56,
id: "xPost56",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 57,
id: "xPost57",
xPostBy: "Person1x0",
xRepostOf: "xPost56",
},
{
idx: 58,
id: "xPost58",
xPostBy: "Person2x0",
xRepostOf: "xPost56",
},
{
idx: 59,
id: "xPost59",
xPostBy: "Person2x0",
xRepostOf: null,
},
{
idx: 60,
id: "xPost60",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 61,
id: "xPost61",
xPostBy: "Person0x0",
xRepostOf: null,
},
{
idx: 62,
id: "xPost62",
xPostBy: "Person2x0",
xRepostOf: "xPost61",
},
{
idx: 63,
id: "xPost63",
xPostBy: "Person2x1",
xRepostOf: "xPost61",
},
{
idx: 64,
id: "xPost64",
xPostBy: "Person9x0",
xRepostOf: "xPost61",
},
{
idx: 65,
id: "xPost65",
xPostBy: "Person9x1",
xRepostOf: "xPost61",
},
{
idx: 66,
id: "xPost66",
xPostBy: "Person11x0",
xRepostOf: "xPost65",
},
{
idx: 67,
id: "xPost67",
xPostBy: "Person10x0",
xRepostOf: "xPost66",
},
{
idx: 68,
id: "xPost68",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 69,
id: "xPost69",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 70,
id: "xPost70",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 71,
id: "xPost71",
xPostBy: "Person2x0",
xRepostOf: "xPost70",
},
{
idx: 72,
id: "xPost72",
xPostBy: "Person16x0",
xRepostOf: null,
},
{
idx: 73,
id: "xPost73",
xPostBy: "Person9x1",
xRepostOf: null,
},
{
idx: 74,
id: "xPost74",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 75,
id: "xPost75",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 76,
id: "xPost76",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 77,
id: "xPost77",
xPostBy: "Person2x0",
xRepostOf: "xPost76",
},
{
idx: 78,
id: "xPost78",
xPostBy: "Person1x0",
xRepostOf: null,
},
{
idx: 79,
id: "xPost79",
xPostBy: "Person14x1",
xRepostOf: "xPost78",
},
{
idx: 80,
id: "xPost80",
xPostBy: "Person13x0",
xRepostOf: "xPost79",
},
{
idx: 81,
id: "xPost81",
xPostBy: "Person14x0",
xRepostOf: "xPost79",
},
{
idx: 82,
id: "xPost82",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 83,
id: "xPost83",
xPostBy: "Person14x0",
xRepostOf: "xPost82",
},
{
idx: 84,
id: "xPost84",
xPostBy: "Person14x1",
xRepostOf: "xPost82",
},
{
idx: 85,
id: "xPost85",
xPostBy: "Person1x0",
xRepostOf: "xPost84",
},
{
idx: 86,
id: "xPost86",
xPostBy: "Person13x0",
xRepostOf: "xPost84",
},
{
idx: 87,
id: "xPost87",
xPostBy: "Person10x0",
xRepostOf: null,
},
{
idx: 88,
id: "xPost88",
xPostBy: "Person0x0",
xRepostOf: null,
},
{
idx: 89,
id: "xPost89",
xPostBy: "Person9x0",
xRepostOf: null,
},
{
idx: 90,
id: "xPost90",
xPostBy: "Person9x0",
xRepostOf: null,
},
{
idx: 91,
id: "xPost91",
xPostBy: "Person10x0",
xRepostOf: null,
},
{
idx: 92,
id: "xPost92",
xPostBy: "Person11x0",
xRepostOf: "xPost91",
},
{
idx: 93,
id: "xPost93",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 94,
id: "xPost94",
xPostBy: "Person8x0",
xRepostOf: "xPost93",
},
{
idx: 95,
id: "xPost95",
xPostBy: "Person8x1",
xRepostOf: "xPost93",
},
{
idx: 96,
id: "xPost96",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 97,
id: "xPost97",
xPostBy: "Person1x0",
xRepostOf: "xPost96",
},
{
idx: 98,
id: "xPost98",
xPostBy: "Person14x1",
xRepostOf: "xPost97",
},
{
idx: 99,
id: "xPost99",
xPostBy: "Person2x0",
xRepostOf: "xPost96",
},
{
idx: 100,
id: "xPost100",
xPostBy: "Person0x1",
xRepostOf: null,
},
{
idx: 101,
id: "xPost101",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 102,
id: "xPost102",
xPostBy: "Person16x0",
xRepostOf: null,
},
{
idx: 103,
id: "xPost103",
xPostBy: "Person17x0",
xRepostOf: "xPost102",
},
{
idx: 104,
id: "xPost104",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 105,
id: "xPost105",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 106,
id: "xPost106",
xPostBy: "Person6x1",
xRepostOf: null,
},
{
idx: 107,
id: "xPost107",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 108,
id: "xPost108",
xPostBy: "Person0x1",
xRepostOf: "xPost107",
},
{
idx: 109,
id: "xPost109",
xPostBy: "Person0x0",
xRepostOf: "xPost107",
},
{
idx: 110,
id: "xPost110",
xPostBy: "Person9x1",
xRepostOf: "xPost108",
},
{
idx: 111,
id: "xPost111",
xPostBy: "Person1x0",
xRepostOf: "xPost110",
},
{
idx: 112,
id: "xPost112",
xPostBy: "Person2x0",
xRepostOf: "xPost110",
},
{
idx: 113,
id: "xPost113",
xPostBy: "Person2x1",
xRepostOf: "xPost110",
},
{
idx: 114,
id: "xPost114",
xPostBy: "Person9x0",
xRepostOf: "xPost110",
},
{
idx: 115,
id: "xPost115",
xPostBy: "Person10x0",
xRepostOf: "xPost114",
},
{
idx: 116,
id: "xPost116",
xPostBy: "Person13x0",
xRepostOf: null,
},
{
idx: 117,
id: "xPost117",
xPostBy: "Person12x0",
xRepostOf: "xPost116",
},
{
idx: 118,
id: "xPost118",
xPostBy: "Person14x0",
xRepostOf: "xPost116",
},
{
idx: 119,
id: "xPost119",
xPostBy: "Person14x1",
xRepostOf: "xPost118",
},
{
idx: 120,
id: "xPost120",
xPostBy: "Person1x0",
xRepostOf: "xPost119",
},
{
idx: 121,
id: "xPost121",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 122,
id: "xPost122",
xPostBy: "Person13x0",
xRepostOf: "xPost121",
},
{
idx: 123,
id: "xPost123",
xPostBy: "Person14x1",
xRepostOf: "xPost121",
},
{
idx: 124,
id: "xPost124",
xPostBy: "Person1x0",
xRepostOf: "xPost123",
},
{
idx: 125,
id: "xPost125",
xPostBy: "Person12x0",
xRepostOf: "xPost123",
},
{
idx: 126,
id: "xPost126",
xPostBy: "Person0x1",
xRepostOf: null,
},
{
idx: 127,
id: "xPost127",
xPostBy: "Person2x0",
xRepostOf: "xPost126",
},
{
idx: 128,
id: "xPost128",
xPostBy: "Person1x0",
xRepostOf: "xPost127",
},
{
idx: 129,
id: "xPost129",
xPostBy: "Person2x1",
xRepostOf: "xPost127",
},
{
idx: 130,
id: "xPost130",
xPostBy: "Person9x1",
xRepostOf: "xPost126",
},
{
idx: 131,
id: "xPost131",
xPostBy: "Person11x0",
xRepostOf: "xPost126",
},
{
idx: 132,
id: "xPost132",
xPostBy: "Person1x0",
xRepostOf: null,
},
{
idx: 133,
id: "xPost133",
xPostBy: "Person1x0",
xRepostOf: null,
},
{
idx: 134,
id: "xPost134",
xPostBy: "Person0x1",
xRepostOf: null,
},
{
idx: 135,
id: "xPost135",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 136,
id: "xPost136",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 137,
id: "xPost137",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 138,
id: "xPost138",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 139,
id: "xPost139",
xPostBy: "Person13x0",
xRepostOf: null,
},
{
idx: 140,
id: "xPost140",
xPostBy: "Person0x0",
xRepostOf: null,
},
{
idx: 141,
id: "xPost141",
xPostBy: "Person11x0",
xRepostOf: "xPost140",
},
{
idx: 142,
id: "xPost142",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 143,
id: "xPost143",
xPostBy: "Person11x0",
xRepostOf: null,
},
{
idx: 144,
id: "xPost144",
xPostBy: "Person9x0",
xRepostOf: "xPost143",
},
{
idx: 145,
id: "xPost145",
xPostBy: "Person9x1",
xRepostOf: "xPost143",
},
{
idx: 146,
id: "xPost146",
xPostBy: "Person10x0",
xRepostOf: "xPost143",
},
{
idx: 147,
id: "xPost147",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 148,
id: "xPost148",
xPostBy: "Person1x0",
xRepostOf: null,
},
{
idx: 149,
id: "xPost149",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 150,
id: "xPost150",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 151,
id: "xPost151",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 152,
id: "xPost152",
xPostBy: "Person8x1",
xRepostOf: "xPost151",
},
{
idx: 153,
id: "xPost153",
xPostBy: "Person13x0",
xRepostOf: null,
},
{
idx: 154,
id: "xPost154",
xPostBy: "Person1x0",
xRepostOf: "xPost153",
},
{
idx: 155,
id: "xPost155",
xPostBy: "Person2x0",
xRepostOf: "xPost154",
},
{
idx: 156,
id: "xPost156",
xPostBy: "Person2x1",
xRepostOf: "xPost155",
},
{
idx: 157,
id: "xPost157",
xPostBy: "Person12x0",
xRepostOf: "xPost154",
},
{
idx: 158,
id: "xPost158",
xPostBy: "Person14x0",
xRepostOf: "xPost157",
},
{
idx: 159,
id: "xPost159",
xPostBy: "Person14x1",
xRepostOf: "xPost158",
},
{
idx: 160,
id: "xPost160",
xPostBy: "Person2x0",
xRepostOf: null,
},
{
idx: 161,
id: "xPost161",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 162,
id: "xPost162",
xPostBy: "Person2x0",
xRepostOf: "xPost161",
},
{
idx: 163,
id: "xPost163",
xPostBy: "Person1x0",
xRepostOf: "xPost162",
},
{
idx: 164,
id: "xPost164",
xPostBy: "Person10x0",
xRepostOf: null,
},
{
idx: 165,
id: "xPost165",
xPostBy: "Person11x0",
xRepostOf: "xPost164",
},
{
idx: 166,
id: "xPost166",
xPostBy: "Person8x1",
xRepostOf: null,
},
{
idx: 167,
id: "xPost167",
xPostBy: "Person8x0",
xRepostOf: "xPost166",
},
{
idx: 168,
id: "xPost168",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 169,
id: "xPost169",
xPostBy: "Person2x0",
xRepostOf: "xPost168",
},
{
idx: 170,
id: "xPost170",
xPostBy: "Person1x0",
xRepostOf: "xPost169",
},
{
idx: 171,
id: "xPost171",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 172,
id: "xPost172",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 173,
id: "xPost173",
xPostBy: "Person8x0",
xRepostOf: null,
},
{
idx: 174,
id: "xPost174",
xPostBy: "Person6x0",
xRepostOf: null,
},
{
idx: 175,
id: "xPost175",
xPostBy: "Person12x0",
xRepostOf: null,
},
{
idx: 176,
id: "xPost176",
xPostBy: "Person14x1",
xRepostOf: "xPost175",
},
{
idx: 177,
id: "xPost177",
xPostBy: "Person2x0",
xRepostOf: null,
},
{
idx: 178,
id: "xPost178",
xPostBy: "Person13x0",
xRepostOf: null,
},
{
idx: 179,
id: "xPost179",
xPostBy: "Person14x0",
xRepostOf: "xPost178",
},
{
idx: 180,
id: "xPost180",
xPostBy: "Person14x1",
xRepostOf: "xPost178",
},
{
idx: 181,
id: "xPost181",
xPostBy: "Person2x1",
xRepostOf: null,
},
{
idx: 182,
id: "xPost182",
xPostBy: "Person2x0",
xRepostOf: "xPost181",
},
{
idx: 183,
id: "xPost183",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 184,
id: "xPost184",
xPostBy: "Person9x1",
xRepostOf: null,
},
{
idx: 185,
id: "xPost185",
xPostBy: "Person14x0",
xRepostOf: null,
},
{
idx: 186,
id: "xPost186",
xPostBy: "Person13x0",
xRepostOf: "xPost185",
},
{
idx: 187,
id: "xPost187",
xPostBy: "Person14x1",
xRepostOf: "xPost186",
},
{
idx: 188,
id: "xPost188",
xPostBy: "Person17x0",
xRepostOf: null,
},
{
idx: 189,
id: "xPost189",
xPostBy: "Person6x1",
xRepostOf: null,
},
],
fbPosts: [
{
idx: 0,
id: "fbPost0",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 1,
id: "fbPost1",
fbPostBy: "Person15fb0",
fbShareOf: null,
},
{
idx: 2,
id: "fbPost2",
fbPostBy: "Person2fb0",
fbShareOf: null,
},
{
idx: 3,
id: "fbPost3",
fbPostBy: "Person5fb0",
fbShareOf: null,
},
{
idx: 4,
id: "fbPost4",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost3",
},
{
idx: 5,
id: "fbPost5",
fbPostBy: "Person2fb0",
fbShareOf: "fbPost4",
},
{
idx: 6,
id: "fbPost6",
fbPostBy: "Person4fb0",
fbShareOf: "fbPost4",
},
{
idx: 7,
id: "fbPost7",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 8,
id: "fbPost8",
fbPostBy: "Person5fb0",
fbShareOf: "fbPost7",
},
{
idx: 9,
id: "fbPost9",
fbPostBy: "Person6fb0",
fbShareOf: "fbPost7",
},
{
idx: 10,
id: "fbPost10",
fbPostBy: "Person3fb0",
fbShareOf: null,
},
{
idx: 11,
id: "fbPost11",
fbPostBy: "Person5fb0",
fbShareOf: "fbPost10",
},
{
idx: 12,
id: "fbPost12",
fbPostBy: "Person4fb0",
fbShareOf: "fbPost11",
},
{
idx: 13,
id: "fbPost13",
fbPostBy: "Person15fb0",
fbShareOf: null,
},
{
idx: 14,
id: "fbPost14",
fbPostBy: "Person15fb0",
fbShareOf: null,
},
{
idx: 15,
id: "fbPost15",
fbPostBy: "Person17fb0",
fbShareOf: "fbPost14",
},
{
idx: 16,
id: "fbPost16",
fbPostBy: "Person3fb0",
fbShareOf: null,
},
{
idx: 17,
id: "fbPost17",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 18,
id: "fbPost18",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost17",
},
{
idx: 19,
id: "fbPost19",
fbPostBy: "Person14fb0",
fbShareOf: "fbPost18",
},
{
idx: 20,
id: "fbPost20",
fbPostBy: "Person1fb0",
fbShareOf: "fbPost19",
},
{
idx: 21,
id: "fbPost21",
fbPostBy: "Person12fb0",
fbShareOf: "fbPost19",
},
{
idx: 22,
id: "fbPost22",
fbPostBy: "Person13fb0",
fbShareOf: "fbPost21",
},
{
idx: 23,
id: "fbPost23",
fbPostBy: "Person13fb0",
fbShareOf: null,
},
{
idx: 24,
id: "fbPost24",
fbPostBy: "Person19fb0",
fbShareOf: null,
},
{
idx: 25,
id: "fbPost25",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 26,
id: "fbPost26",
fbPostBy: "Person18fb0",
fbShareOf: null,
},
{
idx: 27,
id: "fbPost27",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 28,
id: "fbPost28",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost27",
},
{
idx: 29,
id: "fbPost29",
fbPostBy: "Person2fb0",
fbShareOf: "fbPost28",
},
{
idx: 30,
id: "fbPost30",
fbPostBy: "Person18fb0",
fbShareOf: "fbPost29",
},
{
idx: 31,
id: "fbPost31",
fbPostBy: "Person19fb0",
fbShareOf: "fbPost30",
},
{
idx: 32,
id: "fbPost32",
fbPostBy: "Person5fb0",
fbShareOf: "fbPost28",
},
{
idx: 33,
id: "fbPost33",
fbPostBy: "Person6fb0",
fbShareOf: "fbPost27",
},
{
idx: 34,
id: "fbPost34",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 35,
id: "fbPost35",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost34",
},
{
idx: 36,
id: "fbPost36",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 37,
id: "fbPost37",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 38,
id: "fbPost38",
fbPostBy: "Person13fb0",
fbShareOf: null,
},
{
idx: 39,
id: "fbPost39",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 40,
id: "fbPost40",
fbPostBy: "Person16fb0",
fbShareOf: null,
},
{
idx: 41,
id: "fbPost41",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 42,
id: "fbPost42",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
{
idx: 43,
id: "fbPost43",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 44,
id: "fbPost44",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 45,
id: "fbPost45",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost44",
},
{
idx: 46,
id: "fbPost46",
fbPostBy: "Person2fb0",
fbShareOf: "fbPost45",
},
{
idx: 47,
id: "fbPost47",
fbPostBy: "Person5fb0",
fbShareOf: "fbPost45",
},
{
idx: 48,
id: "fbPost48",
fbPostBy: "Person6fb0",
fbShareOf: "fbPost44",
},
{
idx: 49,
id: "fbPost49",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 50,
id: "fbPost50",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 51,
id: "fbPost51",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
{
idx: 52,
id: "fbPost52",
fbPostBy: "Person2fb0",
fbShareOf: null,
},
{
idx: 53,
id: "fbPost53",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
{
idx: 54,
id: "fbPost54",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 55,
id: "fbPost55",
fbPostBy: "Person16fb0",
fbShareOf: null,
},
{
idx: 56,
id: "fbPost56",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost55",
},
{
idx: 57,
id: "fbPost57",
fbPostBy: "Person17fb0",
fbShareOf: "fbPost55",
},
{
idx: 58,
id: "fbPost58",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
{
idx: 59,
id: "fbPost59",
fbPostBy: "Person14fb0",
fbShareOf: "fbPost58",
},
{
idx: 60,
id: "fbPost60",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost58",
},
{
idx: 61,
id: "fbPost61",
fbPostBy: "Person15fb0",
fbShareOf: null,
},
{
idx: 62,
id: "fbPost62",
fbPostBy: "Person17fb0",
fbShareOf: "fbPost61",
},
{
idx: 63,
id: "fbPost63",
fbPostBy: "Person2fb0",
fbShareOf: null,
},
{
idx: 64,
id: "fbPost64",
fbPostBy: "Person18fb0",
fbShareOf: "fbPost63",
},
{
idx: 65,
id: "fbPost65",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 66,
id: "fbPost66",
fbPostBy: "Person1fb0",
fbShareOf: null,
},
{
idx: 67,
id: "fbPost67",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 68,
id: "fbPost68",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost67",
},
{
idx: 69,
id: "fbPost69",
fbPostBy: "Person14fb0",
fbShareOf: "fbPost68",
},
{
idx: 70,
id: "fbPost70",
fbPostBy: "Person13fb0",
fbShareOf: "fbPost69",
},
{
idx: 71,
id: "fbPost71",
fbPostBy: "Person2fb0",
fbShareOf: null,
},
{
idx: 72,
id: "fbPost72",
fbPostBy: "Person1fb0",
fbShareOf: "fbPost71",
},
{
idx: 73,
id: "fbPost73",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost71",
},
{
idx: 74,
id: "fbPost74",
fbPostBy: "Person4fb0",
fbShareOf: "fbPost73",
},
{
idx: 75,
id: "fbPost75",
fbPostBy: "Person6fb0",
fbShareOf: "fbPost74",
},
{
idx: 76,
id: "fbPost76",
fbPostBy: "Person5fb0",
fbShareOf: "fbPost73",
},
{
idx: 77,
id: "fbPost77",
fbPostBy: "Person18fb0",
fbShareOf: "fbPost71",
},
{
idx: 78,
id: "fbPost78",
fbPostBy: "Person19fb0",
fbShareOf: "fbPost77",
},
{
idx: 79,
id: "fbPost79",
fbPostBy: "Person19fb0",
fbShareOf: null,
},
{
idx: 80,
id: "fbPost80",
fbPostBy: "Person13fb0",
fbShareOf: null,
},
{
idx: 81,
id: "fbPost81",
fbPostBy: "Person6fb0",
fbShareOf: null,
},
{
idx: 82,
id: "fbPost82",
fbPostBy: "Person18fb0",
fbShareOf: null,
},
{
idx: 83,
id: "fbPost83",
fbPostBy: "Person19fb0",
fbShareOf: "fbPost82",
},
{
idx: 84,
id: "fbPost84",
fbPostBy: "Person18fb0",
fbShareOf: null,
},
{
idx: 85,
id: "fbPost85",
fbPostBy: "Person19fb0",
fbShareOf: "fbPost84",
},
{
idx: 86,
id: "fbPost86",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 87,
id: "fbPost87",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 88,
id: "fbPost88",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 89,
id: "fbPost89",
fbPostBy: "Person19fb0",
fbShareOf: null,
},
{
idx: 90,
id: "fbPost90",
fbPostBy: "Person5fb0",
fbShareOf: null,
},
{
idx: 91,
id: "fbPost91",
fbPostBy: "Person19fb0",
fbShareOf: null,
},
{
idx: 92,
id: "fbPost92",
fbPostBy: "Person18fb0",
fbShareOf: "fbPost91",
},
{
idx: 93,
id: "fbPost93",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 94,
id: "fbPost94",
fbPostBy: "Person16fb0",
fbShareOf: null,
},
{
idx: 95,
id: "fbPost95",
fbPostBy: "Person13fb0",
fbShareOf: null,
},
{
idx: 96,
id: "fbPost96",
fbPostBy: "Person1fb0",
fbShareOf: null,
},
{
idx: 97,
id: "fbPost97",
fbPostBy: "Person13fb0",
fbShareOf: "fbPost96",
},
{
idx: 98,
id: "fbPost98",
fbPostBy: "Person14fb0",
fbShareOf: "fbPost97",
},
{
idx: 99,
id: "fbPost99",
fbPostBy: "Person6fb0",
fbShareOf: null,
},
{
idx: 100,
id: "fbPost100",
fbPostBy: "Person3fb0",
fbShareOf: null,
},
{
idx: 101,
id: "fbPost101",
fbPostBy: "Person6fb0",
fbShareOf: null,
},
{
idx: 102,
id: "fbPost102",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 103,
id: "fbPost103",
fbPostBy: "Person2fb0",
fbShareOf: "fbPost102",
},
{
idx: 104,
id: "fbPost104",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost102",
},
{
idx: 105,
id: "fbPost105",
fbPostBy: "Person4fb0",
fbShareOf: null,
},
{
idx: 106,
id: "fbPost106",
fbPostBy: "Person3fb0",
fbShareOf: null,
},
{
idx: 107,
id: "fbPost107",
fbPostBy: "Person18fb0",
fbShareOf: null,
},
{
idx: 108,
id: "fbPost108",
fbPostBy: "Person0fb0",
fbShareOf: null,
},
{
idx: 109,
id: "fbPost109",
fbPostBy: "Person6fb0",
fbShareOf: null,
},
{
idx: 110,
id: "fbPost110",
fbPostBy: "Person15fb0",
fbShareOf: null,
},
{
idx: 111,
id: "fbPost111",
fbPostBy: "Person17fb0",
fbShareOf: "fbPost110",
},
{
idx: 112,
id: "fbPost112",
fbPostBy: "Person1fb0",
fbShareOf: null,
},
{
idx: 113,
id: "fbPost113",
fbPostBy: "Person13fb0",
fbShareOf: null,
},
{
idx: 114,
id: "fbPost114",
fbPostBy: "Person18fb0",
fbShareOf: null,
},
{
idx: 115,
id: "fbPost115",
fbPostBy: "Person14fb0",
fbShareOf: null,
},
{
idx: 116,
id: "fbPost116",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
{
idx: 117,
id: "fbPost117",
fbPostBy: "Person5fb0",
fbShareOf: null,
},
{
idx: 118,
id: "fbPost118",
fbPostBy: "Person1fb0",
fbShareOf: null,
},
{
idx: 119,
id: "fbPost119",
fbPostBy: "Person2fb0",
fbShareOf: "fbPost118",
},
{
idx: 120,
id: "fbPost120",
fbPostBy: "Person3fb0",
fbShareOf: "fbPost119",
},
{
idx: 121,
id: "fbPost121",
fbPostBy: "Person18fb0",
fbShareOf: "fbPost119",
},
{
idx: 122,
id: "fbPost122",
fbPostBy: "Person12fb0",
fbShareOf: "fbPost118",
},
{
idx: 123,
id: "fbPost123",
fbPostBy: "Person13fb0",
fbShareOf: "fbPost122",
},
{
idx: 124,
id: "fbPost124",
fbPostBy: "Person14fb0",
fbShareOf: "fbPost123",
},
{
idx: 125,
id: "fbPost125",
fbPostBy: "Person15fb0",
fbShareOf: "fbPost124",
},
{
idx: 126,
id: "fbPost126",
fbPostBy: "Person17fb0",
fbShareOf: "fbPost125",
},
{
idx: 127,
id: "fbPost127",
fbPostBy: "Person17fb0",
fbShareOf: null,
},
{
idx: 128,
id: "fbPost128",
fbPostBy: "Person16fb0",
fbShareOf: null,
},
{
idx: 129,
id: "fbPost129",
fbPostBy: "Person1fb0",
fbShareOf: null,
},
{
idx: 130,
id: "fbPost130",
fbPostBy: "Person12fb0",
fbShareOf: null,
},
],
},
initialEntity: "Person0",
};
const style = {
summaryLinkColor: "rgb(161, 156, 156)",
expandGlyphColour: "rgb(30, 148, 54)",
expandGlyphHoverColour: "rgb(53, 189, 80)",
selectionColour: "rgb(142, 62, 176)",
textColour: "rgb(240, 240, 240)",
entityIconColour: "rgb(120, 120, 120)",
glyphColour: "rgb(0, 153, 104)",
glyphHoverColour: "rgb(0, 201, 128)",
openCloseGlyphColour: "rgb(24, 120, 102)",
openCloseGlyphHoverColour: "rgb(40, 156, 134)",
expandIcon: {
t: "fas fa-plus",
ff: "Font Awesome 5 Free",
c: "white",
},
entityIcon: {
t: "fas fa-user",
c: "rgb(120, 120, 120)",
ff: "Font Awesome 5 Free",
},
expandGlyphPos: "ne",
entityGlyphPos: "nw",
openCloseGlyphPos: "se",
// Lookup for social media platform specific terms and styling
platformDetails: {
x: {
name: "x",
data: "posts",
identifier: "xPost",
backgroundColour: "black",
author: "xPostBy",
copyOf: "xRepostOf",
colour: "rgb(255, 255, 255)",
fadedColour: "rgba(255, 255, 255, 0.3)",
accountIconColour: "rgb(255, 255, 255)",
accountIcon: "\u{1D54F}",
postIcon: "\u{1D54F}",
},
fb: {
name: "fb",
data: "fbPosts",
identifier: "fbPost",
backgroundColour: "white",
author: "fbPostBy",
copyOf: "fbShareOf",
colour: "rgb(107, 174, 255)",
fadedColour: "rgba(107, 174, 255, 0.3)",
accountIcon: "fas fa-facebook-f",
accountIconColour: "rgb(107, 174, 255)",
postIcon: "fas fa-facebook-f",
},
},
};
style.expandGlyph = {
p: style.expandGlyphPos,
fi: style.expandIcon,
b: "transparent",
c: style.expandGlyphColour,
e: 1,
};
style.openComboGlyph = {
fi: {
t: "fas fa-expand-arrows-alt",
c: "white",
ff: "Font Awesome 5 Free",
},
c: style.openCloseGlyphColour,
b: "transparent",
p: style.openCloseGlyphPos,
};
style.closeComboGlyph = {
fi: {
t: "fas fa-compress-arrows-alt",
c: "white",
ff: "Font Awesome 5 Free",
},
c: style.openCloseGlyphColour,
b: "transparent",
p: style.openCloseGlyphPos,
};
style.hoverStyles = {
[style.openCloseGlyphColour]: style.openCloseGlyphHoverColour,
[style.expandGlyphColour]: style.expandGlyphHoverColour,
};
export { style, data }; <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Social Media Analysis</title>
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/keylines.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/minimalsdk.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/sdk-layout.css" />
<link rel="stylesheet" type="text/css" href="@ci/theme/kl/css/demo.css" />
<link
rel="stylesheet"
type="text/css"
href="@fortawesome/[email protected]/css/fontawesome.css"
/>
<link
rel="stylesheet"
type="text/css"
href="@fortawesome/[email protected]/css/solid.css"
/>
<link
rel="stylesheet"
type="text/css"
href="@fortawesome/[email protected]/css/brands.css"
/>
</head>
<body>
<div id="klchart" class="klchart"></div>
<script type="module" src="./code.js"></script>
</body>
</html>