Browse Source

graf: sila tahnouci nody dolu, pokud maji hodne zavislosti

mj-deploy
Vašek Šraier 4 years ago
parent
commit
102c0677ed
  1. 2
      frontend/src/Editor.svelte
  2. 6
      frontend/src/Graph.svelte
  3. 5
      frontend/src/GraphEdge.svelte
  4. 50
      frontend/src/task-force.ts

2
frontend/src/Editor.svelte

@ -7,7 +7,7 @@
export let tasks: TasksFile; export let tasks: TasksFile;
let repulsionForce: number = -600; let repulsionForce: number = -1000;
let clicked: string[] = []; let clicked: string[] = [];
let graph: Graph; let graph: Graph;
let currentTask: TaskDescriptor | null = null; let currentTask: TaskDescriptor | null = null;

6
frontend/src/Graph.svelte

@ -5,10 +5,11 @@
import * as d3 from "d3"; import * as d3 from "d3";
import type { TasksFile, TaskDescriptor } from "./task-loader"; import type { TasksFile, TaskDescriptor } from "./task-loader";
import { createNodesAndEdges } from "./graph-types"; import { createNodesAndEdges } from "./graph-types";
import { taskForce } from "./task-force";
export let tasks: TasksFile; export let tasks: TasksFile;
let hoveredTask: null | string = null; let hoveredTask: null | string = null;
export let repulsionForce: number = -600; export let repulsionForce: number = -1000;
// Svelte automatically fills these with a reference // Svelte automatically fills these with a reference
let container: HTMLElement; let container: HTMLElement;
@ -61,7 +62,8 @@
) )
.force("charge", d3.forceManyBody().strength(repulsionForce)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength .force("charge", d3.forceManyBody().strength(repulsionForce)) // This adds repulsion between nodes. Play with the -400 for the repulsion strength
.force("x", d3.forceX()) // attracts elements to the zero X coord .force("x", d3.forceX()) // attracts elements to the zero X coord
.force("y", d3.forceY()) // attracts elements to the zero Y coord .force("y", d3.forceY().strength(0.5)) // attracts elements to the zero Y coord
.force("dependencies", taskForce())
.on("tick", ticked) .on("tick", ticked)
.on("end", ticked); .on("end", ticked);

5
frontend/src/GraphEdge.svelte

@ -10,5 +10,8 @@
$: y2 = edge === undefined || edge.target === undefined || edge.target.y === undefined ? 0 : edge.target.y; $: y2 = edge === undefined || edge.target === undefined || edge.target.y === undefined ? 0 : edge.target.y;
</script> </script>
<line {x1} {x2} {y1} {y2} style="stroke: #aaa" /> <line x1={x1+10} y1={y1} {x2} {y2} style="stroke: #aaa" />
<line x1={x1} y1={y1+10} {x2} {y2} style="stroke: #aaa" />
<line x1={x1-10} y1={y1} {x2} {y2} style="stroke: #aaa" />
<line x1={x1} y1={y1-10} {x2} {y2} style="stroke: #aaa" />

50
frontend/src/task-force.ts

@ -0,0 +1,50 @@
import type { TaskId } from "./graph-types";
/* copied from graph-types.ts */
function toMapById(nodes: TaskId[]): Map<string, TaskId> {
let nodeMap = new Map<string, TaskId>();
for (let task of nodes) {
if (task.id in nodeMap)
throw 'duplicate IDs';
nodeMap.set(task.id, task);
}
return nodeMap;
}
export function taskForce(): d3.Force<TaskId, undefined> {
let myNodes: TaskId[] | null = null;
let deps: Map<string, number> = new Map();
let idMap: Map<string, TaskId> = new Map();
function getNumberOfDeps(task: TaskId): number {
if (deps.has(task.id)) return deps.get(task.id)!;
if (task.task.requires.length == 0) return 0;
let res = 0;
for (let r of task.task.requires) {
res += getNumberOfDeps(idMap.get(r)!) + 1;
}
deps.set(task.id, res);
return res;
}
let force: d3.Force<TaskId, undefined> = function(alpha: number) {
if (myNodes == null) throw 'nodes not initialized';
for (let task of myNodes) {
if (task.vy == null) {
task.vy = 0
}
task.vy += getNumberOfDeps(task) * 25 * alpha;
}
}
force.initialize = function(nodes: TaskId[]) {
myNodes = nodes;
idMap = toMapById(myNodes);
}
return force;
}