It can often be difficult to see the important information in your data, even when everything presented is related. This demo shows just a few techniques for visualising insurance fraud data to get a better understanding of what insights can be found.
The data is a fictional representation of typical insurance claim data.
Each view combines multiple filters and data manipulations, taking advantage of KeyLines' extensive functionality to create a visualisation that shows different anomalies in the data to help detect fraud. Select a different view from the drop-down menu to see what insights remodelling can reveal.
To visualise data on a map, we integrate KeyLines with ESRI Leaflet and the ArcGIS mapping platform.
Key functions used:
import KeyLines from "keylines";
import {
data,
defaultStyle,
defaultNodeStyle,
defaultLinkStyle,
mapNodeStyle,
mapLinkStyle,
comboStyle,
comboGlyphStyle,
selectedNodeStyle,
defaultLabelStyle,
} from "./data.js";
// Returns colour for betweenness sizing
function getColour(value) {
if (value < 0.25) {
return "#A674BA";
}
if (value < 0.5) {
return "#844C9A";
}
if (value < 0.75) {
return "#583267";
}
return "#2C1933";
}
let chart;
let underlyingGraph;
const modelElement = document.getElementById("model");
const descriptorElements = Array.from(document.querySelectorAll(".model-text"));
let singleGarageMode = false;
/* Create chart items helpers */
// Returns the current model
function getSelectedModel() {
return { model: modelElement.value };
}
// Changes the base map layer
function mapBaseLayer() {
const leafletMap = chart.map().leafletMap();
const basemap = L.esri.basemapLayer("Topographic");
basemap.addTo(leafletMap);
}
// Returns array of all combo node ids
function getComboIds() {
const comboIds = [];
chart.each({ type: "node", items: "toplevel" }, (item) => {
comboIds.push(item.id);
});
return comboIds;
}
// Returns the single selected id or null
function getSelection() {
const selection = chart.selection();
if (selection.length === 0) {
return null;
}
return selection[0];
}
// Returns array of items excluding selected item and its neighbours
function getUnrelatedItems(nodes, selectedId) {
const unrelatedItems = [];
chart.each({ type: "node" }, (item) => {
if (!nodes.includes(item.id) && item.id !== selectedId) {
unrelatedItems.push(item.id);
}
});
return unrelatedItems;
}
// Return nodes based on their d.kind property
function getNodesByKind(kind) {
const nodes = [];
chart.each({ type: "node" }, (n) => {
if (n.d && n.d.kind === kind) {
nodes.push(n);
}
});
return nodes;
}
// Return font icon from item property
function getIconByKind(kind) {
return defaultStyle.kindIcons[kind];
}
// Returns neighbours of an item filtered by kind
function getNeighboursByKind(id, kind, hops = 1) {
const neighbourIds = chart.graph().neighbours(id, { hops }).nodes.concat(id);
const neighbours = chart.getItem(neighbourIds);
const neighboursOfKind = neighbours.filter((n) => n.d && n.d.kind === kind);
return neighboursOfKind.map((node) => node.id);
}
// Get the paths for a model
function findNetworkSelection(id) {
let selectedId = id;
// If we've selected one of the 4 nodes to do with a policy,
// then pretend we selected the claim instead
const item = chart.getItem(id);
if (item.d.kind === "person") {
const policies = getNeighboursByKind(id, "policy");
if (policies.length === 1) {
selectedId = policies[0];
}
} else if (["address", "telephone"].includes(item.d.kind)) {
selectedId = getNeighboursByKind(id, "policy", 2)[0];
}
// Find the neighbouring claims to our selection.
const claims = getNeighboursByKind(selectedId, "claim");
if (claims.length === 0) {
return chart
.graph()
.neighbours(selectedId, { hops: 2 })
.nodes.concat(selectedId);
}
const neighbourIds = [...chart.graph().neighbours(claims).nodes, ...claims];
// Fill in the policy data - next to the person who took the policy
const policies = getNeighboursByKind(claims.concat(selectedId), "policy");
const policyTakers = getNeighboursByKind(policies, "person");
const policyData = [
...chart.graph().neighbours(policyTakers).nodes,
...policyTakers,
];
return [...neighbourIds, ...policyData];
}
function styleSuspiciousItems(linkId) {
let comboId;
if (!chart.combo().isCombo(linkId)) {
comboId = chart.combo().find(linkId);
} else {
comboId = linkId;
}
const underlyingLinks = chart.combo().info(comboId).links;
// Highlight items where there is a large proportion of the same repairs
if (underlyingLinks.length > 12) {
const propLink = {
id: linkId,
w: 10,
c: defaultStyle.linkColours.suspiciousConnection,
};
const propNode = {
id: chart.getItem(linkId).id1,
fi: {
c: defaultStyle.nodeColours.suspiciousGarage,
t: getIconByKind("garage"),
},
};
return [propLink, propNode];
}
return [];
}
// Get colour of link based on distance between person and garage
function getMapLinkColour(link) {
const id1 = chart.getItem(link.id1);
const id2 = chart.getItem(link.id2);
const xDist = id1.x - id2.x;
const yDist = id1.y - id2.y;
const distanceSquared = xDist * xDist + yDist * yDist;
// Recolour longer distances
if (distanceSquared > 210 * 210) {
return defaultStyle.linkColours.suspiciousConnection;
}
return defaultStyle.linkColours.normalDistance;
}
/* END of helper functions to create chart items */
function applyMapStyling() {
const props = [];
// Styling of nodes in map mode.
chart.each({ type: "node" }, (item) => {
if (defaultStyle.nodeColours[item.d.kind]) {
props.push(
Object.assign({}, mapNodeStyle, {
id: item.id,
g: {
p: "ne",
fi: {
t: getIconByKind(item.d.kind),
c: defaultStyle.nodeColours[item.d.kind],
},
e: 2,
},
}),
);
}
});
// Styling of links
chart.each({ type: "link" }, (item) => {
props.push(
Object.assign({}, mapLinkStyle, {
id: item.id,
c: getMapLinkColour(item),
}),
);
});
chart.animateProperties(props, { time: 250 });
}
/* Controls the chart selection behaviour */
// Default selection foregrounds neighbours of selection
function defaultOnSelect(id) {
const item = chart.getItem(id);
if (id === null) {
// clicked on background - restore all the elements in the foreground
chart.foreground(() => true, { type: "all" });
chart.selection([]);
} else if (item && item.type === "node") {
// show only direct neighbours of nodes
const result = chart.graph().neighbours(id).nodes.concat(item.id);
chart.foreground((node) => result.includes(node.id), { type: "node" });
chart.selection([id]);
}
}
// Network selection foregrounds neighbours of nearest claim
function networkOnSelect(id) {
const item = chart.getItem(id);
if (id === null) {
// clicked on background - restore all the elements in the foreground
chart.foreground(() => true, { type: "all" });
chart.selection([]);
} else if (item && item.type === "node") {
const result = findNetworkSelection(id);
chart.foreground((node) => result.includes(node.id), { type: "node" });
chart.selection([id]);
}
}
// In 'garage-repair' view, we hide items that are not neighbours
async function garageOnSelect(id) {
const selectedModel = getSelectedModel();
if (singleGarageMode) {
// If background selected then return to full garage-damages model
if (id === null) {
const filterOptions = {
hideSingletons: true,
};
// Filters the chart to include all previously hidden items for the model
await chart.filter(
(node) => node.d.models.includes(selectedModel.model),
filterOptions,
);
singleGarageMode = false;
chart.combo().reveal([]);
chart.layout("standard", { consistent: true });
}
return;
}
const selectedItem = chart.getItem(id);
if (!(selectedItem && selectedItem.d && selectedItem.d.kind === "garage")) {
return;
}
// Return underlying graph from graph engine
underlyingGraph = KeyLines.getGraphEngine();
underlyingGraph.load(chart.serialize());
// Find neighbours of selected item and hide items that are not
const garageUnderlyingNeighbours = underlyingGraph.neighbours(
selectedItem.id,
);
const garageComboNeighbours = chart.graph().neighbours(selectedItem.id);
chart.combo().close(garageComboNeighbours.nodes);
await chart.hide(
getUnrelatedItems(garageUnderlyingNeighbours.nodes, selectedItem.id),
);
singleGarageMode = true;
await chart.layout("radial", { top: selectedItem.id });
chart.combo().reveal(garageUnderlyingNeighbours.links);
let props = [];
garageUnderlyingNeighbours.links.forEach((linkId) => {
const linkProps = styleSuspiciousItems(linkId);
props = props.concat(linkProps);
});
chart.setProperties([
...garageComboNeighbours.links.map((comboLinkId) => ({
id: comboLinkId,
hi: true,
})),
...props,
]);
}
/* END chart selection functions */
// Damages are combined with links to garages
async function combineDamages() {
const garages = getNodesByKind("garage");
const damages = getNodesByKind("damage");
const damagesGroup = damages.reduce((groupBy, damage) => {
groupBy[damage.d.subkind] = (groupBy[damage.d.subkind] || []).concat(
damage,
);
return groupBy;
}, {});
let props = [];
const comboDefinition = Object.keys(damagesGroup).map((subkind) => ({
ids: damagesGroup[subkind].map((damage) => damage.id),
style: {
...comboStyle,
t: {
...defaultLabelStyle,
t: subkind,
},
},
open: false,
}));
const comboOptions = { arrange: "concentric", select: false };
await chart.combo().combine(comboDefinition, comboOptions);
// Highlight suspicious activity between neighbours
garages.forEach((g) => {
const linkIds = chart.graph().neighbours(g.id).links;
linkIds.forEach((linkId) => {
const linkProps = styleSuspiciousItems(linkId);
props = props.concat(linkProps);
});
// Resize the garages to scale with combos
props.push({ id: g.id, e: 10 });
});
// Apply properties and run layout
await chart.setProperties(props, false);
await chart.layout("standard", { consistent: true });
}
/* Transition functions for each model */
async function fullNetworkTransition(props, options) {
await chart.animateProperties(props, options);
chart.layout("organic", { tightness: 4, consistent: true });
}
async function peopleTransition(props, options) {
chart.foreground(() => true, { type: "all" });
await chart.animateProperties(props, options);
await chart.layout("organic", { consistent: true, packing: "circle" });
}
async function personGarageTransition(props, options) {
chart.foreground(() => true, { type: "all" });
await chart.animateProperties(props, options);
await chart.map().show();
await chart.zoom("fit");
}
async function garageDamagesTransition(props, options) {
chart.foreground(() => true, { type: "all" });
chart.selection([]);
singleGarageMode = false;
await chart.animateProperties(props, options);
combineDamages();
}
/* END Transition functions for each model */
// Define model object properties
const models = {
none: {
transition: fullNetworkTransition,
onSelect: networkOnSelect,
},
"garage-damages": {
// Return to default settings to avoid unnecessary behaviour on item selection
transition: garageDamagesTransition,
onSelect: garageOnSelect,
},
people: {
transition: peopleTransition,
onSelect: defaultOnSelect,
},
"person-garage": {
transition: personGarageTransition,
onSelect: defaultOnSelect,
},
};
/* Styling for each model view */
async function getStyling() {
const selectedModel = getSelectedModel();
const props = [];
// Apply styling to nodes and make sure all items transition from centre of chart
chart.each({ type: "node" }, (item) => {
if (defaultStyle.nodeColours[item.d.kind]) {
props.push(
Object.assign({}, defaultNodeStyle, {
id: item.id,
t: {
...defaultLabelStyle,
t: item.d.label,
},
b: defaultStyle.nodeColours[item.d.kind],
fi: {
c: defaultStyle.nodeColours[item.d.kind],
t: item.d.subkindperson
? getIconByKind(item.d.subkindperson)
: getIconByKind(item.d.kind),
},
}),
);
} else {
props.push({ id: item.id, x: 0, y: 0 });
}
});
// Style links
chart.each({ type: "link" }, (item) => {
props.push(Object.assign({}, defaultLinkStyle, { id: item.id }));
});
if (selectedModel.model === "people") {
// Calculate betweenness between components
const betweenness = await chart
.graph()
.betweenness({ normalization: "component" });
// Adjust size and colour of node based on betweenness in component
const adjustments = {};
chart
.graph()
.components()
.forEach((component) => {
const length = component.nodes.length;
component.nodes.forEach((node) => {
const enlargement = ((betweenness[node] - 0.5) * length) ** 0.6;
const size = enlargement >= 1 ? enlargement : 1;
const colour = getColour(betweenness[node]);
adjustments[node] = { size, colour };
});
props.forEach((item, index) => {
if (adjustments[item.id]) {
props[index].e = adjustments[item.id].size;
props[index].fi.c = adjustments[item.id].colour;
props[index].b = adjustments[item.id].colour;
}
});
});
}
return props;
}
/* Chart filter and model transition */
async function showSelectedModel() {
const selectedModel = getSelectedModel();
if (selectedModel.model !== "garage-damages") {
// Make sure to uncombine combos and to reveal all links
chart.combo().reveal([]);
chart.combo().uncombine(getComboIds(), { time: 0, select: false });
}
// Update the chart options select node property
chart.options({ selectedNode: selectedNodeStyle[selectedModel.model] });
const transitionOptions = { time: 200 };
const filterOptions = {
time: 500,
hideSingletons: true,
};
// Filter the items for the selected model
await chart.filter(
(node) => node.d.models.includes(selectedModel.model),
filterOptions,
);
// Transition to the selected model after collecting styling
const props = await getStyling();
await models[selectedModel.model].transition(props, transitionOptions);
modelElement.disabled = false;
models[selectedModel.model].onSelect(getSelection());
}
/* END Chart filter and Transition */
// Controls the item selection behaviour
function onSelection() {
chart.off("click");
chart.on("click", ({ id }) => {
models[getSelectedModel().model].onSelect(id);
});
}
function onMap({ type }) {
if (type === "showend") {
mapBaseLayer();
applyMapStyling();
}
}
function preventCombosOpening() {
if (!chart) return;
chart.on("double-click", ({ id, preventDefault }) => {
if (chart.combo().isCombo(id)) {
preventDefault();
}
});
}
async function startKeyLines() {
const chartOptions = {
logo: { u: "/public/images/Logo.png" },
iconFontFamily: "Font Awesome 5 Free",
imageAlignment: {
"fas fa-user": { e: 1.0, dy: -5 },
"fas fa-car": { e: 0.9, dy: -4 },
"fas fa-wrench": { e: 0.9, dy: -2 },
"fas fa-cogs": { e: 0.9, dx: -5 },
"fas fa-phone": { e: 0.9, dy: 5, dx: 3 },
"fas fa-file-invoice-dollar": { e: 0.9, dy: 0 },
"fas fa-file-contract": { e: 0.9, dy: 0 },
"fas fa-user-md": { dy: -3 },
},
selectionColour: defaultStyle.selectionColour,
selectionFontColour: defaultStyle.selectionFontColour,
defaultStyles: {
comboGlyph: comboGlyphStyle,
},
handMode: true,
arrows: "small",
minZoom: 0.02,
backColour: "#F0F8FF",
linkEnds: { avoidLabels: false },
};
chart = await KeyLines.create({
container: "klchart",
options: chartOptions,
});
// Reduce chart zoom for smoother load & initial layout animation
chart.viewOptions({ zoom: 0.05 });
// Set map options for map view
chart.map().options({
time: 250,
tiles: null, // Remove the default tile layer
transition: "restore",
leaflet: {
minZoom: 10,
},
});
chart.on("map", onMap);
onSelection();
// Load the data to the chart component
chart.load(data);
preventCombosOpening();
// Update view and selection behaviour on dropdown change
modelElement.addEventListener("change", async () => {
modelElement.disabled = true;
const modeltype = modelElement.value;
descriptorElements.forEach((element) => element.classList.add("hide"));
document.getElementById(modeltype).classList.remove("hide");
onSelection();
await chart.map().hide();
showSelectedModel();
});
// Run initial full network layout
showSelectedModel();
}
function loadKeyLines() {
document.fonts.load("24px 'Font Awesome 5 Free'").then(startKeyLines);
}
window.addEventListener("DOMContentLoaded", loadKeyLines); import KeyLines from "keylines";
export const data = {
type: "LinkChart",
items: [
{
type: "link",
id: "23-21",
id1: "23",
id2: "21",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "27-25",
id1: "27",
id2: "25",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "32-30",
id1: "32",
id2: "30",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "37-35",
id1: "37",
id2: "35",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "42-40",
id1: "42",
id2: "40",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "47-45",
id1: "47",
id2: "45",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "52-50",
id1: "52",
id2: "50",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "57-55",
id1: "57",
id2: "55",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "62-60",
id1: "62",
id2: "60",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "67-65",
id1: "67",
id2: "65",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "72-70",
id1: "72",
id2: "70",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "77-75",
id1: "77",
id2: "75",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "82-80",
id1: "82",
id2: "80",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "87-85",
id1: "87",
id2: "85",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "92-90",
id1: "92",
id2: "90",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "97-95",
id1: "97",
id2: "95",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "102-100",
id1: "102",
id2: "100",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "107-105",
id1: "107",
id2: "105",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "112-110",
id1: "112",
id2: "110",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "117-115",
id1: "117",
id2: "115",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "122-120",
id1: "122",
id2: "120",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "127-125",
id1: "127",
id2: "125",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "137-135",
id1: "137",
id2: "135",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "142-140",
id1: "142",
id2: "140",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "147-145",
id1: "147",
id2: "145",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "152-150",
id1: "152",
id2: "150",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "157-155",
id1: "157",
id2: "155",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "162-160",
id1: "162",
id2: "160",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "167-165",
id1: "167",
id2: "165",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "172-170",
id1: "172",
id2: "170",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "177-175",
id1: "177",
id2: "175",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "182-180",
id1: "182",
id2: "180",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "187-185",
id1: "187",
id2: "185",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "192-190",
id1: "192",
id2: "190",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "197-195",
id1: "197",
id2: "195",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "202-200",
id1: "202",
id2: "200",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "207-205",
id1: "207",
id2: "205",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "212-210",
id1: "212",
id2: "210",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "217-215",
id1: "217",
id2: "215",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "222-220",
id1: "222",
id2: "220",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "227-225",
id1: "227",
id2: "225",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "232-230",
id1: "232",
id2: "230",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "237-235",
id1: "237",
id2: "235",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "242-240",
id1: "242",
id2: "240",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "247-245",
id1: "247",
id2: "245",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "252-250",
id1: "252",
id2: "250",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "257-255",
id1: "257",
id2: "255",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "262-260",
id1: "262",
id2: "260",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "267-265",
id1: "267",
id2: "265",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "272-270",
id1: "272",
id2: "270",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "277-275",
id1: "277",
id2: "275",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "282-280",
id1: "282",
id2: "280",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "293-291",
id1: "293",
id2: "291",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "23-20",
id1: "23",
id2: "20",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "27-8",
id1: "27",
id2: "8",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "32-29",
id1: "32",
id2: "29",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "37-34",
id1: "37",
id2: "34",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "42-39",
id1: "42",
id2: "39",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "47-44",
id1: "47",
id2: "44",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "52-49",
id1: "52",
id2: "49",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "57-54",
id1: "57",
id2: "54",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "62-59",
id1: "62",
id2: "59",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "67-64",
id1: "67",
id2: "64",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "72-69",
id1: "72",
id2: "69",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "77-74",
id1: "77",
id2: "74",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "82-79",
id1: "82",
id2: "79",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "87-84",
id1: "87",
id2: "84",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "92-89",
id1: "92",
id2: "89",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "97-94",
id1: "97",
id2: "94",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "102-99",
id1: "102",
id2: "99",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "107-104",
id1: "107",
id2: "104",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "112-109",
id1: "112",
id2: "109",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "117-114",
id1: "117",
id2: "114",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "122-119",
id1: "122",
id2: "119",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "127-124",
id1: "127",
id2: "124",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "137-134",
id1: "137",
id2: "134",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "142-139",
id1: "142",
id2: "139",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "147-144",
id1: "147",
id2: "144",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "152-149",
id1: "152",
id2: "149",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "157-154",
id1: "157",
id2: "154",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "162-159",
id1: "162",
id2: "159",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "167-164",
id1: "167",
id2: "164",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "172-169",
id1: "172",
id2: "169",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "177-174",
id1: "177",
id2: "174",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "182-179",
id1: "182",
id2: "179",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "187-184",
id1: "187",
id2: "184",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "192-189",
id1: "192",
id2: "189",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "197-194",
id1: "197",
id2: "194",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "202-199",
id1: "202",
id2: "199",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "207-204",
id1: "207",
id2: "204",
c: "#c0c0c0",
w: 3,
d: {
models: ["none"],
},
},
{
type: "link",
id: "212-209",
id1: "212",
id2: "209",
c: "#c0c0c0",
// ...truncated 20691 lines <!doctype html>
<html lang="en" style="background-color: #2d383f">
<head>
<meta charset="utf-8" />
<title>Insurance Fraud 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="leaflet/dist/leaflet.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"
/>
</head>
<body>
<div id="klchart" class="klchart"></div>
<script src="leaflet" defer type="text/javascript"></script>
<script src="esri-leaflet" defer type="text/javascript"></script>
<script src="esri-leaflet-geocoder" defer type="text/javascript"></script>
<script type="module" src="./code.js"></script>
</body>
</html>