F#
HTML
Result
Hosted on
Try WebSharper
<
>
namespace Dijkstra open WebSharper open WebSharper.JavaScript open WebSharper.UI open WebSharper.UI.Html open WebSharper.UI.Client open WebSharper.UI.Notation open WebSharper.Cytoscape [<JavaScript>] module Dijkstra = let Nodes = ['A'; 'B'; 'C'; 'D'; 'E'] let Edges = [ 'A', 'B', 6 'A', 'D', 1 'D', 'E', 1 'B', 'D', 2 'B', 'E', 2 'B', 'C', 5 'C', 'E', 5 ] let createNode (c: char) = ElementObject(Data = ElementData(Id = string c)) let createEdge (c1: char, c2: char, i: int) = ElementObject(Data = ElementData(Id = sprintf "%c%c" c1 c2, Source = string c1, Target = string c2, Weight = float i)) let lm = ListModel.Create (fun (node: char, prevNode: char, weight: int) -> node) [] type State = | NonStarted | Processing | Finished static member IsDisabled state = state = Processing static member Text state = match state with | NonStarted -> "Start" | Processing -> "..." | Finished -> "Reset" let graph = div [attr.id "graph"; attr.style "height:90vh; width:50vw;"] [] let buttonState = Var.Create State.NonStarted let fst3 (a, _, _) = a let Dijkstra (vertices: char list) (edges: (char * char * int) list) (startingNode: char) (cy: Cytoscape) = async { Var.Set buttonState State.Processing let initWeigths = vertices |> List.map(fun x -> if x = startingNode then lm.Add(x, x, 0) x, 0, x else lm.Add(x, x, System.Int32.MaxValue) x, System.Int32.MaxValue, x ) do! Async.Sleep 1000 let rec inner (weights: (char * int * char) list) (selectedNodes: (char * int * char) list) = async { if List.length weights = 0 then return selectedNodes else let (minNode, minW, prev) = weights |> List.minBy (fun (n, w, _) -> w, n) cy.Elements(sprintf "#%c" minNode).Select() |> ignore if prev = minNode then () // starting node, do nothing elif prev < minNode then cy.Elements(sprintf "#%c%c" prev minNode).Select() |> ignore else cy.Elements(sprintf "#%c%c" minNode prev).Select() |> ignore let weights = weights |> List.filter (fst3 >> ((<>) minNode)) |> List.map (fun (node, weight, prev) -> let neighbour = edges |> List.tryFind (fun (n1, n2, w) -> n1 = node && n2 = minNode || n1 = minNode && n2 = node) match neighbour with | None -> node, weight, prev | Some (_, _, w) -> if minW + w < weight then lm.Add(node, minNode, minW + w) node, minW + w, minNode else node, weight, prev ) do! Async.Sleep 1000 return! inner weights ([minNode, minW, prev]@selectedNodes) } let! res = inner initWeigths [] Var.Set buttonState State.Finished return () } let nodes (cy: Cytoscape) = Dijkstra Nodes Edges 'A' cy let cytoscape = Var.Create None let combined = View.Map2 (fun a b -> a,b) cytoscape.View buttonState.View div [] [ button [ attr.disabledDynPred (View.Const "disabled") (buttonState.View.Map(State.IsDisabled)) on.clickView combined (fun _ _ (cy, button) -> match cy, button with | None, _ -> () | Some cy, State.NonStarted -> nodes cy |> Async.Start |> ignore | Some cy, State.Finished -> cy.Elements().Unselect() |> ignore lm.Clear() Var.Set buttonState State.NonStarted | _, _ -> () ) ] [textView <| buttonState.View.Map(State.Text)] div [attr.style "display: flex;"] [ graph div [] [ p [] [text "Table"] table [] [ thead [] [ th [] [text "Node"] th [] [text "Weight"] th [] [text "Previous Node"] ] tbody [] [ lm.View.Doc(fun items -> items |> Seq.map(fun (node, prevNode, weight) -> if weight = System.Int32.MinValue then tr [] [ td [] [text <| string node] td [] [] td [] [text "Inf"] ] else tr [] [ td [] [text <| string node] td [] [text <| string weight] td [] [text <| string prevNode] ] ) |> Doc.Concat ) ] ] ] ] ] |> Doc.RunById "main" let cy = Cytoscape( CytoscapeOptions( Container = JS.Document.GetElementById("graph"), Elements = [| yield! Nodes |> List.map createNode yield! Edges |> List.map createEdge |], Style = [| StyleConfig( selector = "node", style = New [ "background-color" => "#666" "label" => "data(id)" ] ) StyleConfig( selector = "edge", style = New [ "width" => "3" "line-color" => "#ccc" "curve-style" => "bezier" "label" => "data(weight)" ] ) StyleConfig( selector = ":selected", style = New [ "background-color" => "#070" "line-color" => "#070" "text-outline-color" => "#000" ] ) |], Layout = LayoutOptions( Name = "grid", Rows = 2, Directed = false ) ) ) cy.Autounselectify false |> ignore Var.Set cytoscape (Some cy)
<html> <head> <title></title> <style> table, th, td { border: 1px solid black; } </style> </head> <body> <div id="main"></div> <!--[BODY]--> </body> </html>