最近的task是将储存在类似于链表中的workflow转换成图。
图的信息存在于文件当中,格式是"前置事件","当前事件",第一个事件的前置事件是"0"。
例如 A -> B -> C 可以存储为
0,A
A,B
B,C
当这个workflow存在回路的时候是一件很头疼的事,自己想了好几个办法效果都不好,最后参考
http://topic.csdn.net/u/20071023/11/3edb81fc-37b2-4506-906e-44dc0fc521f2.html willshy回复中的方法终于可以找到图中的回路,方法如下……
首先定义一个类,用来储存workflow中每一个Event的信息。
class Event
attr_accessor :event_id, :parent_events, :child_events, :is_first_event, :is_last_event, :is_external, :ergodic_status
def initialize event_id
@event_id = event_id
@parent_events = []
@child_events = []
@is_first_event = false
@is_last_event = false
@is_external = false
@ergodic_status = 0 # 0 stand for scan not start, 1 stand for scan finished, -1 stand for scaning.
end
end
在找环操作中会用到的属性是@event_id,@child_events,@ergodic_status。
@event_id会用作hash的key,@child_events记录此event下一级的events,@ergodic_status就是willshy所提到的顶点的颜色。初始化为0表示还没有被遍历过,1表示此节点所有的子节点都被遍历过,-1表示此节点正在被遍历。
第一步是扫描文件,把所有事件都存到一个hash表中(下面方法中的@event_hash),扫描的同时也将每一个event的@child_events赋值完成。
遍历的方法如下:
def ergodic key
key = key.to_sym unless key.kind_of? Symbol # Check the key is 'Symbol' type.
return if @event_hash[key].ergodic_status == 1
@event_hash[key].ergodic_status = -1
unless @event_hash[key].is_last_event
@event_hash[key].child_events.each do |child_event|
child_key = child_event.to_sym
if @event_hash[child_key].ergodic_status == -1
@circles << "#{key.to_s},#{child_key.to_s}" unless @circles.include? "#{key.to_s},#{child_key.to_s}"
next
end
ergodic child_key
end
end
@event_hash[key].ergodic_status = 1
return
end
然后调用一次ergodic(第一个事件的key)就可以将所有形成回路的线记录到数组@circles中,从而得到没有环的文件。(因为画图的时候会用到许多递归,有环的话就意味着递归会成为一个死循环。)
下一步就是生成图,leader告诉我用svg格式的图,相关信息:
http://www.w3school.com.cn/svg/index.asp
Sample:
http://croczilla.com/bits_and_pieces/svg/samples/
可以看出svg还是很牛的,sample中居然有一个俄罗斯方块……
svg文件可以用Fire Fox直接打开,IE打开需要安装Adobe的SVGView。
目前为止我就会两个标签,一个画长方形,一个划线……
不过已经足够了,我需要做的事情就是计算出每个事件在图中的坐标,然后用线把他们连起来。
先来一个简单的sample(sample的源文件与生成图的文件在附件中):
简单的图效果还可以,复杂的我还不忍心贴出来……具体代码有不少繁琐的细节和需要调整的地方,有需要的请单独联系我吧