`
piecehealth
  • 浏览: 46577 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Ruby实现有向图找回路,以及生成workflow图。

阅读更多
最近的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的源文件与生成图的文件在附件中):

简单的图效果还可以,复杂的我还不忍心贴出来……具体代码有不少繁琐的细节和需要调整的地方,有需要的请单独联系我吧
  • 大小: 17.7 KB
2
2
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics