add network.rb, kanjilist.rb, defkanji.rb, graphviz.rb,
[chise/ruby.git] / src / network.rb
1 #!/usr/bin/env ruby
2 # calc KanjiNetwork by eto 2003-0305
3
4 require 'kanjilist'
5 require 'defkanji'
6 require 'graphviz'
7
8 module CHISE
9   class KanjiNetwork #======================================================================漢字間のネットワークを計算する。
10     def initialize()
11       reset()
12       @formatter = GraphvizFormatter.new(self)
13       # @formatter = XSpringiesFormatter.new(self)
14     end
15     attr_reader :h, :list
16     def reset
17       @h = Hash.new
18       @done = Hash.new
19       @list = []
20     end
21     def make_network(list) #@h, @listに結果を入れていく。
22       list.each_char {|ch|
23         make_network_one(ch)
24       }
25     end
26     
27     def make_network_one(ch) #実質的にこれが本体。再帰で呼ばれる。
28       return if @done[ch]
29       
30       @h[ch] = []
31       @list << ch #登場文字リストに追加
32       
33       char = ch.char
34       ids = char.decompose
35       if ids.char_length == 1 #分割できない文字は、リンクを探す。
36         link = char.ids_represent if char.ids_represent
37         link = char.ids_link if char.ids_link
38         return if link.nil?
39         @h[ch] << link #親字に追加する。
40         @list << link
41         return
42       end
43       
44       ids.each_char {|idsch|
45         idschar = idsch.char
46         next if idschar.is_ids?
47         @h[ch] << idsch #親字に追加する。
48         @list << idsch
49         make_network_one(idsch) #再帰する。
50       }
51       @done[ch] = true
52     end
53     
54     def nodes_and_edges() #これを二つのarrayで返す
55       nodear = []
56       nodeh  = Hash.new
57       @list.sort.uniq.each_with_index {|ch, index|
58         nodear[index] = ch
59         nodeh[ch] = index
60       }
61       edgear = []
62       @h.each {|ch, ar|
63         ar.each {|idsch|
64           edgear << [nodeh[ch], nodeh[idsch]]
65         }
66       }
67       return nodear, edgear
68     end
69
70     def out(filename)
71       open(filename, "w"){|out| out.print to_s }
72     end
73     def to_s() @formatter.to_s; end
74   end
75
76   class GraphvizFormatter #====================================================================== Graphviz関係
77     def initialize(network)
78       @network = network
79     end
80     def to_s() #Graphvizのフォーマット、dotフォーマットに変換する。
81       page = DotPage.new
82       page.size = "5.5, 5.5"
83       #page.pack = "true"
84       #page.epsilon = 0.001
85       #page.epsilon = 0.01
86       #page.overlap = false
87       #page.overlap = scale
88       #page.spline = true
89
90       #p @network.list
91       @network.list.sort.uniq.each {|ch|
92         char = ch.char
93         node = DotNode.new(char.to_i)
94         node.label = char.map_ucs_er #node.label = char.to_utf8
95         node.fontsize = (node.label =~ /^&#/) ? 12 : 6
96         #node.fontsize = (node.label =~ /^&#/) ? 24 : 6
97         node.shape = "plaintext"
98         node.fontname = "MS-Mincho" #呪われてるがしかたがない
99         #node.fontname = "Arial-Unicode-MS" #ダメ
100         page.add_node(node)
101       }
102
103       @network.h.each {|ch, ar|
104         char = ch.char
105         ar.each {|idsch|
106           idschar = idsch.char
107           edge = DotEdge.new(char.to_i, idschar.to_i)
108           #edge.len = 4
109           #edge.len = 2
110           #edge.color = "gray"
111           edge.color = "lightgray"
112           page.add_edge(edge)
113         }
114       }
115       return page.to_s
116     end
117   end
118
119   class XSpringiesFormatter #======================================================================
120     def initialize(network)
121       @network = network
122     end
123     def to_s # #1.0 *** XSpringies data file
124       str = ""
125       @network.list.sort.uniq.each {|ch|
126         char = ch.char
127         num = char.to_i
128         label = char.map_ucs_er
129         str << "mass #{num}\n"
130       }
131       @network.h.each {|ch, ar|
132         char = ch.char
133         ar.each {|idsch|
134           idschar = idsch.char
135           from = char.to_i
136           to = idschar.to_i
137           str << "spng #{from} #{to}\n"
138         }
139       }
140       str
141     end
142   end
143 end
144
145 #----------------------------------------------------------------------end.