class Ellington::Visualizer
Constants
- CLUSTER_COLOR
- CLUSTER_FILLCOLOR
- CLUSTER_PENCOLOR
- CLUSTER_STYLE
- EDGE_COLOR_PASSENGER_HIT
- EDGE_PENWIDTH_PASSENGER_HIT
- EDGE_STYLE_PASSENGER_MISS
- FONTNAME
- NODE_COLOR
- NODE_COLOR_LINE_GOAL
- NODE_COLOR_PASSENGER_HIT
- NODE_COLOR_ROUTE_GOAL
- NODE_COLOR_VIRTUAL
- NODE_FILLCOLOR
- NODE_FILLCOLOR_LINE_GOAL
- NODE_FILLCOLOR_ROUTE_GOAL
- NODE_FONTCOLOR_VIRTUAL
- NODE_PENWIDTH_PASSENGER_HIT
- NODE_SHAPE
- NODE_STYLE
- NODE_STYLE_VIRTUAL
- RANKSEP
Attributes
format[R]
route[R]
short_names[R]
Public Class Methods
new(route, format: :svg, short_names: true)
click to toggle source
# File lib/ellington/visualizer.rb, line 38 def initialize(route, format: :svg, short_names: true) @route = route @format = format @short_names = short_names end
Public Instance Methods
class_label(obj)
click to toggle source
# File lib/ellington/visualizer.rb, line 67 def class_label(obj) klass = obj klass = klass.class unless klass.is_a?(Class) return klass.name unless short_names klass.name.split("::").last end
graph_route(passenger=nil)
click to toggle source
# File lib/ellington/visualizer.rb, line 139 def graph_route(passenger=nil) g = Node.new(nil, GraphViz.new("GraphRoute")) set_graph_defaults g.viz g.viz[:label] = "#{class_label(route)} Lines" g.viz[:ranksep] = 0.8 route.lines.each_with_index do |line, index| line_cluster = g.add(Node.new(line, g.viz.add_graph("cluster#{index}"))) set_cluster_defaults line_cluster.viz line_cluster.viz[:label] = class_label(line) add_state_nodes_for_line line_cluster, line, passenger end viz = g.viz.add_nodes(route.initial_state, :label => state_label(route.initial_state)) rendered_edges = {} if passenger passenger_nodes = g.reduce([]) do |memo, line_cluster| line_cluster.children.each do |node| if node.viz[:color].to_s.gsub(/\W/, "") == NODE_COLOR_PASSENGER_HIT memo << node end end memo end previous_node = nil passenger_nodes.each do |node| from_viz = previous_node.nil? ? viz : previous_node.viz rendered_edges[from_viz.id + node.viz.id] = true edge = g.viz.add_edges(from_viz, node.viz) edge["color"] = EDGE_COLOR_PASSENGER_HIT edge["penwidth"] = EDGE_PENWIDTH_PASSENGER_HIT previous_node = node end end route.states.each do |from_state, to_states| (to_states || []).each do |to_state| from_line = route.lines.to_a.select{ |l| l.states.keys.include?(from_state) }.first from_node = g.find(from_line) if from_line from_viz = from_node.viz.get_node(from_state) if from_node from_viz ||= g.viz.get_node(from_state) to_line = route.lines.to_a.select{ |l| l.states.keys.include?(to_state) }.first to_node = g.find(to_line) if to_line to_viz = to_node.viz.get_node(to_state) if to_node to_viz ||= g.viz.get_node(to_state) if from_viz && to_viz && !rendered_edges[from_viz.id + to_viz.id] rendered_edges[from_viz.id + to_viz.id] = true edge = g.viz.add_edges( from_viz, to_viz ) edge[:style] = EDGE_STYLE_PASSENGER_MISS if passenger end end end g.viz.output(format => String) end
graph_route_basic(passenger=nil)
click to toggle source
# File lib/ellington/visualizer.rb, line 79 def graph_route_basic(passenger=nil) g = Node.new(nil, GraphViz.new("GraphRouteBasic")) set_graph_defaults g.viz g.viz[:ranksep] = 1 g.viz[:label] = "#{class_label(route)} Route - basic" route.lines.each_with_index do |line, index| line_cluster = g.add(Node.new(line, g.viz.add_graph("cluster#{index}"))) set_cluster_defaults line_cluster.viz line_cluster.viz[:label] = class_label(line) %w{PASS FAIL ERROR}.each do |state| state_node = line_cluster.add(Node.new(state, line_cluster.viz.add_nodes("#{line.class.name}#{state}", "label" => state))) states = line.stations.map{ |s| "#{state} #{s.name}" } style_node_for_line(state_node, line, *states) style_node_for_route(state_node, route, *states) style_node_for_passenger(state_node, passenger, *line.send("#{state.downcase}ed")) end end route.connections.each do |connection| to_node = g.find(connection.line) to_line = to_node.base combos = {} g.to_a.each do |node| states = node.base.state_names(connection.states) states.each do |state| (combos[state] ||= []) << node end end if connection.strict combos.each do |state, nodes| node_name = nodes.map{ |n| n.base.class.name }.join + state node_label = nodes.map{ |n| state_label(state) }.join("\n") viz = g.viz.add_nodes(node_name, :label => node_label) g.viz.add_edges( viz, to_node.viz.get_node("#{connection.line.class.name}#{state}"), "lhead" => to_node.viz.id ) end else combos.each do |state, nodes| nodes.each do |node| from_line = node.base g.viz.add_edges( node.viz.get_node("#{from_line.class.name}#{state}"), to_node.viz.get_node("#{to_line.class.name}PASS"), "lhead" => to_node.viz.id ) end end end end g.viz.output(format => String) end
state_label(state)
click to toggle source
# File lib/ellington/visualizer.rb, line 74 def state_label(state) return state unless short_names state.split(" ").map { |part| part.split("::").last }.join(" | ") end
Protected Instance Methods
add_state_nodes_for_line(cluster, line, passenger)
click to toggle source
# File lib/ellington/visualizer.rb, line 202 def add_state_nodes_for_line(cluster, line, passenger) line.states.keys.each do |state| node = cluster.add(Node.new(state, cluster.viz.add_nodes(state, :label => state_label(state)))) style_node_for_line(node, line, state) style_node_for_route(node, route, state) style_node_for_passenger(node, passenger, state) end end
color_name(graphviz_color)
click to toggle source
# File lib/ellington/visualizer.rb, line 233 def color_name(graphviz_color) graphviz_color.to_s.gsub("\"", "") end
set_cluster_defaults(cluster)
click to toggle source
# File lib/ellington/visualizer.rb, line 248 def set_cluster_defaults(cluster) cluster[:style] = CLUSTER_STYLE cluster[:color] = CLUSTER_COLOR cluster[:fillcolor] = CLUSTER_FILLCOLOR cluster[:pencolor] = CLUSTER_PENCOLOR end
set_graph_defaults(graph)
click to toggle source
# File lib/ellington/visualizer.rb, line 237 def set_graph_defaults(graph) graph[:compound] = true graph[:ranksep] = RANKSEP graph[:fontname] = FONTNAME graph.node[:fontname] = FONTNAME graph.node[:shape] = NODE_SHAPE graph.node[:style] = NODE_STYLE graph.node[:color] = NODE_COLOR graph.node[:fillcolor] = NODE_FILLCOLOR end
style_node(node, color)
click to toggle source
# File lib/ellington/visualizer.rb, line 211 def style_node(node, color) node.viz[:color] = color node.viz[:fillcolor] = color end
style_node_for_line(node, line, *states)
click to toggle source
# File lib/ellington/visualizer.rb, line 216 def style_node_for_line(node, line, *states) return if (line.goal & states).empty? style_node node, NODE_COLOR_LINE_GOAL end
style_node_for_passenger(node, passenger, *states)
click to toggle source
# File lib/ellington/visualizer.rb, line 226 def style_node_for_passenger(node, passenger, *states) return if passenger.nil? return if (passenger.state_history & states).empty? node.viz[:color] = NODE_COLOR_PASSENGER_HIT node.viz[:penwidth] = NODE_PENWIDTH_PASSENGER_HIT end
style_node_for_route(node, route, *states)
click to toggle source
# File lib/ellington/visualizer.rb, line 221 def style_node_for_route(node, route, *states) return if (route.goal & states).empty? style_node node, NODE_COLOR_ROUTE_GOAL end