Published
Edited
Apr 18, 2022
2 forks
28 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { viewof visualization } with { chartData as data } from "@tomlarkworthy/ego-graph"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function step() {
if (unvisited.size > 0) {
console.log("step...");

function findNearestUnvisited(v) {
var current = stepDijkstra({
seed: { id: v, distance: 0 },
adjacent: (u) =>
[...(edges.get(u)?.keys() || [])]
.map((v) => ({
id: v,
distance: edgeDistance(u, v)
}))
.filter((e) => !exclude.has(e.id))
});

while (current.lastVertex && !unvisited.has(current.lastVertex.id)) {
current = stepDijkstra(current);
}
return current.lastVertex?.id;
}

const u = findNearestUnvisited(initialTerm);

unvisited.delete(u);

const neighbours = await suggestionsFromGoogle({
term: u
});
for (let edge of neighbours) {
if (!edges.has(edge.source)) {
edges.set(edge.source, new Map());
}
const outgoingEdges = edges.get(edge.source);

let v = edge.target;
outgoingEdges.set(v, {
source: edge.source,
target: edge.target,
weight: edge.weight
});
const alt =
distance.get(edge.source) + edgeDistance(edge.source, edge.target);

if (distance.get(v) === undefined) {
distance.set(v, alt);
if (alt < maxDistance) unvisited.add(v);
} else if (alt < distance.get(v)) {
distance.set(v, alt);
}
}

console.log("step: notify epoch");
try {
viewof epoch.value = viewof epoch.value + 1;
viewof epoch.dispatchEvent(new Event("input", { bubbles: true }));
} catch (err) {
console.log(err);
}

if (unvisited.size == 0) {
console.log("step: nearly ending, notify latest version");
viewof version.value = viewof version.value + 1;
viewof version.dispatchEvent(new Event("input", { bubbles: true }));
} else {
if (viewof autoRun.value) {
// continue
setTimeout(step, 100);
}
}
} else {
console.log("step: ending, no unvisted nodes");
}
}
Insert cell
Insert cell
Insert cell
onPageLoadInitialTerm = {
if (!window.didPageLoad && viewof initialTermRaw.value === undefined) {
viewof initialTermRaw.value = "poodle";
viewof initialTermRaw.dispatchEvent(new Event("input", { bubbles: true }));
}
}
Insert cell
Insert cell
Insert cell
allEdges
Insert cell
allEdges.filter((e) => e.target === "loveramics")
Insert cell
Insert cell
Insert cell
defaultSuggestionsFilter = (suggestions, { term, seperator } = {}) => {
term = term.toLowerCase();
let w = MAX_RESULTS;
return suggestions.reduce((suggestions, suggestion) => {
if (
suggestions.length < MAX_RESULTS &&
suggestion.startsWith(term + " " + seperator + " ", "")
) {
// Trim "term VS" repeated prefix
suggestion = suggestion.replace(term + " " + seperator + " ", "");

// If SINGLE_RESULTS_ONLY we check for a single term
if (!SINGLE_RESULTS_ONLY || suggestion.split(" ").length === 1) {
// There may be several alternatives (e.g. covid vs flu vs cold
const alternatives = suggestion.split(` ${seperator} `);
alternatives.forEach((alternative) => {
suggestions.push({
source: term,
target: alternative,
weight: w--
});
});
}
}
return suggestions;
}, []);
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// This is a specialist proxy that does some black magic to avoid rate limits,
// but also it caches responses so we do not hit google with the same query twice.
// It does not work with anything else other than suggestqueries.google.com
proxy = "https://europe-west1-endpointservice.cloudfunctions.net/proxy"
Insert cell
Insert cell
googleResponse = fetch(url, {
headers: {
Authorization: `Bearer ${await user.getIdToken()}`
}
})
Insert cell
googleResponseBody = {
if (googleResponse.status == 200) {
return googleResponse.text();
} else {
const err = new Error(await googleResponse.text());
viewof suggestionsFromGoogleParams.reject(err);
throw err;
}
}
Insert cell
googleResponseDoc = parser.parseFromString(googleResponseBody, "text/xml")
Insert cell
Insert cell
filteredSuggestions = suggestionsFromGoogleParams.filter(
unfilteredSuggestions,
{
term: suggestionsFromGoogleParams.term,
seperator: suggestionsFromGoogleParams.seperator
}
)
Insert cell
viewof suggestionsFromGoogleParams.respond(filteredSuggestions)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// https://stackoverflow.com/a/30800715/862295
function downloadObjectAsJson(exportObj, exportName) {
var dataStr =
"data:text/json;charset=utf-8," +
encodeURIComponent(JSON.stringify(exportObj));
var downloadAnchorNode = document.createElement("a");
downloadAnchorNode.setAttribute("href", dataStr);
downloadAnchorNode.setAttribute("download", exportName + ".json");
document.body.appendChild(downloadAnchorNode); // required for firefox
downloadAnchorNode.click();
downloadAnchorNode.remove();
}
Insert cell
Insert cell
Insert cell
<style>
form.${ns} {
width: inherit;
}
</style>
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more