add network.rb, kanjilist.rb, defkanji.rb, graphviz.rb,
authoreto <eto>
Tue, 11 Mar 2003 11:58:03 +0000 (11:58 +0000)
committereto <eto>
Tue, 11 Mar 2003 11:58:03 +0000 (11:58 +0000)
 makegraph.rb, tc_network.rb, tc_kanjilist.rb

src/chise.rb
src/defkanji.rb [new file with mode: 0755]
src/graphviz.rb [new file with mode: 0755]
src/kanjilist.rb [new file with mode: 0755]
src/makegraph.rb [new file with mode: 0755]
src/network.rb [new file with mode: 0755]
t/tc_kanjilist.rb [new file with mode: 0755]
t/tc_network.rb [new file with mode: 0755]
t/ts_chise.rb

index 8d302af..4eef060 100755 (executable)
@@ -1,5 +1,5 @@
-#!c:/ruby/bin/ruby.exe
-# Ruby/UTF-2000 module by eto 2002-1114
+#!/usr/bin/env ruby
+# Ruby/CHISE module by eto 2002-1114
 
 require 'bdb'
 require 'uconv'
diff --git a/src/defkanji.rb b/src/defkanji.rb
new file mode 100755 (executable)
index 0000000..038c5ab
--- /dev/null
@@ -0,0 +1,162 @@
+#!/usr/bin/env ruby
+# define local kanji features, by eto 2003-0305
+
+require 'singleton'
+
+module CHISE
+  class IDS_Definition #======================================================================
+    include Singleton
+
+    #●ids-element: stop-character。これ以上分割しない、基本要素文字。
+    #その文字自身を値として持つ。それ以外の値を持つ場合は、それを代りの値として使うことを意味する。
+    #つまり、101字の基本漢字は最小構成要素なので、それ以上分解しませんよ、ということ。
+    IDS_ELEMENT = "六百回交向歩考出書多少高可"
+    BASIC_KANJI = "人子女母父王口耳手足力目首毛心犬牛鳥貝角羽虫馬魚羊肉皮米竹木麦豆山川雨風水土石金田穴日月火音糸刀舟門戸衣矢弓車皿一二三四五六七八九十百千万寸尺上中下本玉立回食行止交向歩考入示走生出来書言大小白青多少高長"
+
+    AWASE_KANJI = "鳴名加品古知問間聞取兄見切分粉貧林森校東明住位好岩砂里男畑習休短空坂島倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守灰秋秒困国医包同合舌居右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣"
+
+    #●ids-meaning: 意味的に考えるところのIDS。形としてはつながらないが、意味としてはこう分割できるというものを表す。
+    IDS_MEANING = "
+見    ⿱目儿
+東    ⿻木日
+里    ⿱田土
+赤    ⿱大火
+舌    ⿱千口
+太    ⿻大丶
+#州   ⿻砂川
+#重   ⿱?土
+世    ⿺十⿰十十
+内    ⿵冂入
+谷    ⿱⿱八&CDP-8B5D;口
+半    ⿱八牛
+孝    ⿱老子
+島    ⿹鳥山
+美    ⿱羊大
+看    ⿸手目
+倉    ⿸食口
+強    ⿰弓⿱厶虫
+&#x4e51;       ⿲人人人
+果    ⿱田木
+比    ⿰匕匕
+鼓    ⿰&#x58f4;支
+#承
+鼻    &#x2ff3;自田廾
+風    &#x2ff5;几⿱丿虫
+#夜
+&CDP-8C47;     ⿰亡月
+黙    ⿺黒犬
+".split("\n")
+
+    #●ids-represent: これを持つもつ字は、それ以外の字を意味するということを意味する。
+    #例えば人偏は、人を意味する。これは再帰的に摘要する。
+    IDS_REPRESENT = "
+&#x4ebb;       人
+&CDP-8B5D;     人
+&#x8864;       衣
+&#x20086;      厂
+&#x20087;      厂
+&#x2ea1;       水
+&#x6c35;       水
+&CDP-8CCC;     羊
+&#x2634c;      羊
+&CDP-8B52;     老
+&CDP-8CBB;     鳥
+&CDP-8BEA;     刀
+&#x5202;       刀
+朩    木
+&#x2ea9;       王
+&#x571f;       土
+&#x2090e;      匕
+&CDP-8BC4;     泉
+&#x2ed7;       雨
+&CDP-8BE8;     申
+&#x7cf9;       糸
+&#x2eca;       足
+&J90-5469;     夂
+&CDP-8BD5;     西
+&CDP-8BA9;     牛
+&#x2eae;       竹
+&#x9ed1;       黒
+&CDP-8971;     冫
+".split("\n")
+
+    #●ids-link: 横列びの関係があるもの
+    IDS_LINK = "
+&#x826e;       &CDP-8B7C;
+&CDP-8B48;     四
+&#x5bf8;       &#x624d;
+&#x3405;       米
+#この部品はいろいろあるのだけど…。
+".split("\n")
+
+    def check
+      #show_ids(IDS_ELEMENT) #ar = BASIC_KANJI+IDS_ELEMENT
+      #show_ids(IDS_MEANING.join())
+      #show_ids(KanjiList.instance.joyo)
+      #show_ids(KanjiList.instance.awase(0))
+      #show_ids(open("0208-shell.txt").read)
+      #p "&U+2ff2;".de_er
+      #p "休".decompose.to_er
+      eval_print_loop
+    end
+    def show_ids(str)
+      str.de_er.to_a.sort.uniq.each {|ch|
+       char = ch.char
+       ids = char.decompose_all
+       print "#{char}  #{ids.map_ucs}\n" #できるだけucsに正規化するべし。
+      }
+    end
+    def eval_print_loop
+      while true
+       line = STDIN.gets
+       line.chomp!
+       exit if line.nil? || line =~ /end/
+       print "#{line.decompose}        #{line.decompose.to_er}\n"
+       print "#{line.decompose_all}    #{line.decompose_all.to_er}\n"
+      end
+    end
+
+    def define_all
+      define_ids_element
+      define_ids_meaning
+      define_ids_represent
+      define_ids_link
+    end
+    def define_ids_element
+      IDS_ELEMENT.each_char {|ch|
+       char = ch.char
+       char.ids_element = ch
+      }
+    end
+    def define_ids_meaning
+      IDS_MEANING.each {|line|
+       next if line.nil? || line == "" || line =~ /^#/
+       ch, ids = line.split
+       char = ch.de_er.char
+       char.ids_meaning = ids.de_er
+       print "#{ch}    #{ids}\n"
+      }
+    end
+    def define_ids_represent
+      IDS_REPRESENT.each {|line|
+       next if line.nil? || line == "" || line =~ /^#/
+       ch, rep = line.split
+       char = ch.de_er.char
+       char.ids_represent = rep.de_er
+       print "#{char.map_ucs}  #{rep}\n"
+      }
+    end
+    def define_ids_link
+      IDS_LINK.each {|line|
+       next if line.nil? || line == "" || line =~ /^#/
+       ch, rep = line.split
+       char = ch.de_er.char
+       char.ids_link = rep.de_er
+       print "#{char.map_ucs}  #{rep}\n"
+      }
+    end
+
+  end
+end
+
+#----------------------------------------------------------------------end.
diff --git a/src/graphviz.rb b/src/graphviz.rb
new file mode 100755 (executable)
index 0000000..0a37a83
--- /dev/null
@@ -0,0 +1,139 @@
+#!/usr/bin/env ruby
+# Graphiviz wrapper by eto 2003-0227
+
+class DotElement #======================================================================
+  def initialize()
+    @attr = Hash.new
+  end
+  def method_missing(mid, *args) #\8eQ\8dl:ostruct.rb
+    mname = mid.id2name
+    return @attr[mname] if args.length == 0
+    @attr[mname.chop] = args[0] if mname =~ /=$/ #\91ã\93ü
+  end
+  def to_s
+    str = "  #{mainstr()} "
+    str << "[" + @attr.map {|k, v| %Q|#{k}="#{v}"| }.join(" ") + "]" if 0 < @attr.length
+    str << ";\n"
+    str
+  end
+end
+
+class DotPage < DotElement #======================================================================
+  def initialize()
+    super()
+    @nodes = []
+    @edges = []
+  end
+  def mainstr() @name.to_s; end
+  def add_node(node)
+    return unless node.is_a? DotNode
+    @nodes << node
+  end
+  def add_edge(edge)
+    return unless edge.is_a? DotEdge
+    @edges << edge
+  end
+  def to_s()
+    str = "digraph G {\n"
+#    str << %Q|  size="6, 6"\n|
+    str << @attr.map {|k, v| %Q|  #{k}="#{v}"\n| }.join("")
+    @nodes.each {|node|
+      str << node.to_s
+    }
+    @edges.each {|edge|
+      str << edge.to_s
+    }
+    str << "}\n"
+    str
+  end
+end
+
+class DotNode < DotElement #======================================================================
+  def initialize(name)
+    @name = name
+    super()
+  end
+  def mainstr() @name.to_s; end
+end
+
+class DotEdge < DotElement #======================================================================
+  def initialize(from, to)
+    @from, @to = from, to
+    super()
+  end
+  def mainstr() "#{@from.to_s} -> #{@to.to_s}"; end
+end
+
+class Graphviz #======================================================================\92\8a\8fÛ\83N\83\89\83X
+  DOT = 0
+  TWOPI = 1
+  NEATO = 2
+  def initialize(type=DOT)
+    @type = type
+    @codepage = nil
+    @target = nil
+    @in = nil
+    @out = nil
+  end
+  attr_accessor :type, :codepage, :target, :in, :out
+  def post_process() #\93¯\82\83t\83@\83C\83\8b\82É\8fã\8f\91\82«\82É\82·\82é\81B
+    str = open(@out).read
+    str.gsub!(/&amp;#x/, '&#x')
+    #str.gsub!(/font-family:MS Gothic;/, '')
+    #str.gsub!(/font-family:MS Gothic;/, 'font-family:MS-Mincho;')
+    str.gsub!(/font-family:Times New Roman;/, '')
+    open(@out, "w"){|out| out.print str}
+  end
+end
+
+class GraphvizCLI < Graphviz  #====================================================================== Command Line Interface
+# COMMAND_DIR = "c:\Program Files\ATT\Graphviz\bin"
+  COMMAND_DIR = "" #PATH\82ª\82Æ\82¨\82Á\82Ä\82È\82¢\82Æ\82¾\82ß\82Ý\82½\82¢\81B
+  NAMES = "dot twopi neato".split
+  def generate(debug=false)
+    ar = []
+    #ar << COMMAND_DIR + NAMES[@type] + ".exe"
+    ar << COMMAND_DIR + NAMES[@type]
+    #ar << "-V"
+    #ar << "-Gpack"
+    ar << "-T#{@target}"
+    ar << "-o #{@out}"
+    ar << @in
+    cmd = ar.join(' ')
+    print cmd,"\n"
+    system cmd
+    if @target =~ /svg/i
+      post_process
+    end
+  end
+end
+
+class GraphvizOLE < Graphviz #====================================================================== Object Linking & Embedding
+  #NAMES = "DOT TWOPI NEATO".split
+  def generate(debug=false)
+    require 'win32ole' #\82±\82ñ\82È\82Æ\82±\82É\8e\9d\82Á\82Ä\82«\82½\81B
+    names = "DOT TWOPI NEATO".split
+    @ole = WIN32OLE.new("Wingraphviz." + names[@type])
+    @ole.codepage = cp if @codepage  #neato.codepage = 65001 #codepage: 65001 Unicode UTF-8 
+    @instr = open(@in).read
+    if @target =~ /svg/i
+      result = @ole.toSVG(@instr)
+      open(@out, "w"){|out| out.print result}
+      post_process
+    elsif @target =~ /svg/i
+      result = @ole.toPNG(@dot)
+      result.save(@out)
+    end
+  end
+  def nu_to_png(filename=nil)
+    return "" unless @dot.is_a?(String)
+    png = @ole.toPNG(@dot)
+    png.save(filename) unless filename.nil?
+    return png
+  end
+  #p neato.validate(str)
+  #ps = neato.toPS(str)
+  #open("test.ps", "w"){|out|  out.print ps  }
+end
+
+#----------------------------------------------------------------------end.
diff --git a/src/kanjilist.rb b/src/kanjilist.rb
new file mode 100755 (executable)
index 0000000..45469ee
--- /dev/null
@@ -0,0 +1,81 @@
+#!/usr/bin/env ruby
+# KanjiList, Joyo Kanji, Kyoiku Kanji by eto 2003-0305
+
+require 'singleton'
+
+module CHISE
+  class KanjiList #======================================================================
+    include Singleton
+
+    AWASE_KANJI_LIST = "鳴名加品古知問間聞取兄見切分粉貧林森校東明住位好岩砂里男畑習休短空坂島倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守灰秋秒困国医包同合舌居右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣
+鳴名
+鳴名加知医短男畑秋居古灰
+加知医短男畑秋居古灰
+品問間聞取兄見切分粉貧林森校東明住位好岩砂里習休空坂島
+倉美孝赤看光初努協解新歌語話張強忘悲答晴現正字安守秒困国包同合舌
+右左受友反道返迷花菜集机主太氷州点店庫仕帳幼防引配早直班筆重番北化比
+死夏後進酒福私家世内谷半原前寺思電雲気布旅衆泣".split
+
+    KYOIKU_KANJI_LIST = "愛悪圧安暗案以位囲委意易異移胃衣遺医域育一印員因引飲院右宇羽雨運雲営映栄永泳英衛液益駅円園延沿演遠塩央往応横王黄億屋恩温音下化仮何価加可夏家科果歌河火花荷課貨過我画芽賀会解回快改械海灰界絵開階貝外害街各拡格確覚角閣革学楽額割活株寒刊巻完官干幹感慣漢看管簡観間関館丸岸眼岩顔願危喜器基寄希揮机旗期機帰気汽季紀規記貴起技疑義議客逆久休吸宮弓急救求泣球究級給旧牛去居挙許漁魚京供競共協境強教橋胸興郷鏡業局曲極玉勤均禁筋近金銀九句区苦具空君訓群軍郡係兄型形径敬景系経計警軽芸劇激欠決潔穴結血月件健券建憲検権犬研絹県見険験元原厳減源現言限個古呼固己庫戸故湖五午後語誤護交候光公功効厚口向后好孝工幸広康校構港皇紅耕考航行講鉱鋼降高号合刻告国穀黒骨今困根混左差査砂座再最妻才採済災祭細菜裁際在材罪財坂作昨策桜冊刷察札殺雑皿三参山散産算蚕賛酸残仕使司史四士始姉姿子市師志思指支枝止死氏私糸紙至視詞詩試誌資飼歯事似児字寺持時次治磁示耳自辞式識七失室質実舎写射捨社者謝車借尺若弱主取守手種酒首受授樹収周宗就州修拾秋終習衆週集住十従縦重宿祝縮熟出術述春準純順処初所暑署書諸助女序除傷勝商唱将小少承招昭松消焼照省章笑証象賞障 上乗城場常情条状蒸植織職色食信心新森深申真神臣親身進針人仁図垂推水数寸世制勢性成政整星晴正清生盛精聖声製西誠青静税席昔石積績責赤切接折設節説雪絶舌先千宣専川戦泉浅洗染線船選銭前善然全祖素組創倉奏層想操早巣争相窓総草装走送像増臓蔵造側則息束測足速属族続卒存孫尊損村他多太打体対帯待態貸退隊代台大第題宅達谷単担探炭短誕団断暖段男談値知地池置築竹茶着中仲宙忠昼柱注虫著貯丁兆帳庁張朝潮町腸調長頂鳥直賃追痛通低停定底庭弟提程敵的笛適鉄典天展店転点伝田電徒登都努度土党冬刀島投東湯灯当等答糖統討豆頭働動同堂導童道銅得徳特毒独読届内南難二肉日乳入任認熱年念燃納能脳農波派破馬俳拝敗背肺配倍梅買売博白麦箱畑八発判半反板版犯班飯晩番否悲批比皮秘肥費非飛備美鼻必筆百俵標氷票表評病秒品貧不付夫婦富布府父負武部風副復服福腹複仏物分奮粉文聞兵平並閉陛米別変片編辺返便勉弁保歩補墓暮母包報宝放方法訪豊亡忘暴望棒貿防北牧本妹枚毎幕末万満味未密脈民務夢無名命明盟迷鳴綿面模毛木目問門夜野矢役約薬訳油輸優勇友有由遊郵夕予余預幼容曜様洋用羊葉要陽養欲浴翌来落乱卵覧利理裏里陸律率立略流留旅両料良量領力緑林臨輪類令例冷礼歴列練連路労朗老六録論和話"
+
+    KYOIKU_GAKUNEN_LIST = "一右雨円王音下火花学気休金九空月犬見五口校左三山四子糸字耳七車手十出女小上森人水正生青石赤先千川早足村大男中虫町天田土二日入年白八百文本名木目夕立力林六
+引雲遠黄何夏家科歌画会回海絵貝外楽間顔帰汽記牛魚京強教玉近形計元原古戸午後語交光工広考行高合国黒今才作算市思止紙寺時自室社弱首秋春書少場色食心新親図数星晴声西切雪船前組草走多太体台谷知地池竹茶昼朝長鳥通弟店点電冬刀東当答頭同道読南馬買売麦半番父風分聞米歩母方北妹毎明鳴毛門夜野友曜用来理里話
+悪安暗意医育員飲院運泳駅園横屋温化荷界開階角活寒感館岸岩期起客宮急球究級去橋業局曲銀苦具君係兄軽決血研県言庫湖公向幸港号根祭細坂仕使始指死詩歯事持次式実写者主取守酒受州拾終習週集住重所暑助勝商昭消章乗植深申神身進世整線全送息族他打対待代第題炭短着柱注丁帳調直追定庭鉄転登都度島投湯等動童内肉農波配畑発反板悲皮美鼻氷表病秒品負部服福物平返勉放万味命面問役薬油有由遊予様洋葉陽落流旅両緑礼列路和
+愛案以位囲委胃衣印栄英塩央億加課貨芽改械害各覚完官漢管観関願喜器希旗機季紀議救求給挙漁競共協鏡極区軍郡型景芸欠結健建験固候功康航告差最菜材昨刷察殺参散産残司史士姉氏試治辞失借種周宿順初唱焼照省象賞信真臣勢成清静席積折節説戦浅選然倉想争相側速続卒孫帯隊達単談置貯腸低停底的典伝徒努灯働堂毒熱念敗倍博飯費飛必筆標票不付夫府副粉兵別変辺便包法望牧末満脈民約勇要養浴利陸料良量輪類令例冷歴練連労老録
+圧易移因営永衛液益演往応恩仮価果河過賀解快格確額刊幹慣歓眼基寄規技義逆久旧居許境興均禁句訓群経潔件券検絹険減現限個故護効厚構耕講鉱混査再妻採災際在罪財雑蚕賛酸師志支資似児示識質舎謝授収修衆祝術述準序除承招称証常情条状織職制性政精製税績責接設絶舌銭善祖素総像増造則測属損態貸退団断築張提程敵適統導銅得徳特独任燃能破判版犯比肥非備俵評貧婦富布武復複仏編弁保墓報豊暴貿防未務無迷綿輸余預容率略留領
+異遺域壱宇羽映延沿可我灰街拡閣革割株勧巻干看簡丸危揮机貴疑吸弓泣供胸郷勤筋径敬系警劇穴兼憲権厳源呼己誤后好孝皇紅鋼降刻穀骨困砂座済裁策冊姿私至視詞誌磁射捨尺釈若樹需宗就従縦縮熟純処署諸傷将笑障城蒸針仁垂推寸是聖誠宣専泉洗染創奏層操窓臓蔵俗存尊宅担探暖段値仲宙忠著兆庁潮頂賃痛展党糖討届難弐乳認納脳派俳拝背肺班晩否批秘腹奮閉陛片補宝訪亡忘棒枚幕密盟模矢訳優郵幼羊欲翌乱卵覧裏律臨朗論".split
+
+    SHOUKEI = 0 #象形文字
+    SHIJI   = 1 #指事文字
+    KAII    = 2 #会意文字
+    KEISEI  = 3 #形声文字
+
+    #0文字の行もあるため、漢字列の最後に-を入れた。利用するときにはchopすること。
+    KYOIKU_KUBUN_LIST = "
+右雨王音火貝九玉金月犬見口左山子糸耳車手十女人水夕石川早足大竹虫天田土日年白文木目立力六-
+一二三四五下七小上生中入八本-
+円休出森正赤千男町名林-
+花学気空校字青先草村百-
+羽雲夏画回会外角弓牛魚京兄原戸古午工交行高黄才止矢自首心西長鳥弟刀東肉馬米歩母方北万毛門用来-
+-
+科楽岩顔汽教計公谷黒今思春少声雪走多太台直電内売半番父明鳴友里-
+引園遠何家歌海絵活間丸記帰強近形元言後語広光考合国細作算市姉紙寺時室社弱配秋週書場色食新親図数星晴切船線前組体地池茶昼朝通店点冬当答頭同道読南買麦風分聞毎妹夜野曜理話-
+向皿主州章申身丁豆平面由予羊両業曲-
+-
+悪安飲運央屋化開客究級宮去橋区血決県庫幸港祭仕死使者守取酒集重宿暑助乗植神真深世整全想息族他対第調庭投農畑皮悲美氷秒品福物辺勉牧命役有遊葉陽流旅-
+晴医委育員院泳駅横温荷界階寒感漢館岸起期急球局銀苦具君係軽研湖号根始指歯詩次事持式実写受拾終習住所昭消商勝進昔相送速打待代題炭短談着注柱帳追定笛鉄転都度島湯登等動童波配倍箱発反坂板鼻筆表病負部服味問薬油洋様落録礼列練路和-
+衣栄果求士氏臣巣束単兆飛必不包未無要良老-
+卒末-
+以位胃印加官希器共競好告最刷殺参史児祝初信折争倉孫帯典働毒夫付兵別脈民利料令連労-
+愛案囲英塩億貨課芽改械害街各覚完管関観願季紀喜旗機議泣救給挙漁協鏡極訓軍郡径型景芸欠結建健験固功候航康差菜材昨札察産散残司試治辞失借種周順松笑唱焼照賞成省清静席積節説浅戦選然側続隊達置仲貯帳低底停的伝徒努灯堂特得熱念敗梅博飯費票標府副粉辺変便法望牧満約勇養浴陸量輸類冷例歴録-
+易益再率-
+久支非-
+因永衛採示授制性製則断燃弁保綿-
+圧移営液演応往桜恩可仮価河過賀快解格確額刊幹慣眼基寄規技義逆旧居許境均禁句群経潔件券検限現減個護効厚耕鉱構興講混査災妻際在財罪雑酸賛志枝師資飼似識質舎謝政勢精税責績接設舌絶銭祖素総造像増測属損退貸態団築張提程適敵統銅導徳独任能破犯判版比肥備俵評貧布婦富武復複仏編墓報豊防貿暴務夢迷輸余預容略留領-
+異我革系千己后冊至尺泉片卵並-
+寸-
+域看危郷筋孝皇降刻穀骨困砂座 裁策蚕私姿射宗衆従仁染善奏尊段難乳脳拝班奮亡牧郵幼-
+遺宇映延沿灰拡閣割株巻簡机揮貴疑吸供胸勤敬警劇激穴絹権憲源厳呼誤紅鋼済視詞誌磁捨若樹収就縦縮熟純処署諸除将傷障城蒸針垂推盛聖誠宣専洗窓創装層操蔵臓存宅担探誕暖値宙忠著庁頂潮賃痛展討党糖届認納派背肺俳晩否批秘腹陛閉補暮宝訪忘棒幕密盟模訳優欲翌乱覧裏律臨朗論-
+".split
+
+    JOYO_KANJI_LIST = "亜哀愛悪握圧扱安暗案以位依偉囲委威尉意慰易為異移維緯胃衣違遺医井域育一壱逸稲芋印員因姻引飲院陰隠韻右宇羽雨渦浦運雲営影映栄永泳英衛詠鋭液疫益駅悦謁越閲円園宴延援沿演炎煙猿縁遠鉛塩汚凹央奥往応押横欧殴王翁黄沖億屋憶乙卸恩温穏音下化仮何価佳加可夏嫁家寡科暇果架歌河火禍稼箇花荷華菓課貨過蚊我画芽賀雅餓介会解回塊壊快怪悔懐戒拐改械海灰界皆絵開階貝劾外害慨概涯街該垣嚇各拡格核殻獲確穫覚角較郭閣隔革学岳楽額掛潟割喝括活渇滑褐轄且株刈乾冠寒刊勘勧巻喚堪完官寛干幹患感慣憾換敢棺款歓汗漢環甘監看管簡緩缶肝艦観貫還鑑間閑関陥館丸含岸眼岩頑顔願企危喜器基奇寄岐希幾忌揮机旗既期棋棄機帰気汽祈季紀規記貴起軌輝飢騎鬼偽儀宜戯技擬欺犠疑義議菊吉喫詰却客脚虐逆丘久休及吸宮弓急救朽求泣球究窮級糾給旧牛去居巨拒拠挙虚許距漁魚享京供競共凶協叫境峡強恐恭挟教橋況狂狭矯胸脅興郷鏡響驚仰凝暁業局曲極玉勤均斤琴禁筋緊菌襟謹近金吟銀九句区苦駆具愚虞空偶遇隅屈掘靴繰桑勲君薫訓群軍郡係傾刑兄啓型契形径恵慶憩掲携敬景渓系経継茎蛍計警軽鶏芸迎鯨劇撃激傑欠決潔穴結血月件倹健兼券剣圏堅嫌建憲懸検権犬献研絹県肩見謙賢軒遣険顕験元原厳幻弦減源玄現言限個古呼固孤己庫弧戸故枯湖誇雇顧鼓五互午呉娯後御悟碁語誤護交侯候光公功効厚口向后坑好孔孝工巧幸広康恒慌抗拘控攻更校構江洪港溝甲皇硬稿紅絞綱耕考肯航荒行衡講貢購郊酵鉱鋼降項香高剛号合拷豪克刻告国穀酷黒獄腰骨込今困墾婚恨懇昆根混紺魂佐唆左差査砂詐鎖座債催再最妻宰彩才採栽歳済災砕祭斎細菜裁載際剤在材罪財坂咲崎作削搾昨策索錯桜冊刷察撮擦札殺雑皿三傘参山惨散桟産算蚕賛酸暫残仕伺使刺司史嗣四士始姉姿子市師志思指支施旨枝止死氏祉私糸紙紫肢脂至視詞詩試誌諮資賜雌飼歯事似侍児字寺慈持時次滋治璽磁示耳自辞式識軸七執失室湿漆疾質実芝舎写射捨赦斜煮社者謝車遮蛇邪借勺尺爵酌釈若寂弱主取守手朱殊狩珠種趣酒首儒受寿授樹需囚収周宗就州修愁拾秀秋終習臭舟衆襲週酬集醜住充十従柔汁渋獣縦重銃叔宿淑祝縮粛塾熟出術述俊春瞬准循旬殉準潤盾純巡遵順処初所暑庶緒署書諸助叙女序徐除傷償勝匠升召商唱奨宵将小少尚床彰承抄招掌昇昭晶松沼消渉焼焦照症省硝礁祥称章笑粧紹肖衝訟証詔詳象賞鐘障上丈乗冗剰城場壌嬢常情条浄状畳蒸譲醸錠嘱飾植殖織職色触食辱伸信侵唇娠寝審心慎振新森浸深申真神紳臣薪親診身辛進針震人仁刃尋甚尽迅陣酢図吹垂帥推水炊睡粋衰遂酔錘随髄崇数枢据杉澄寸世瀬畝是制勢姓征性成政整星晴正清牲生盛精聖声製西誠誓請逝青静斉税隻席惜斥昔析石積籍績責赤跡切拙接摂折設窃節説雪絶舌仙先千占宣専川戦扇栓泉浅洗染潜旋線繊船薦践選遷銭銑鮮前善漸然全禅繕塑措疎礎祖租粗素組訴阻僧創双倉喪壮奏層想捜掃挿操早曹巣槽燥争相窓総草荘葬藻装走送遭霜騒像増憎臓蔵贈造促側則即息束測足速俗属賊族続卒存孫尊損村他多太堕妥惰打駄体対耐帯待怠態替泰滞胎袋貸退逮隊代台大第題滝卓宅択拓沢濯託濁諾但達奪脱棚谷丹単嘆担探淡炭短端胆誕鍛団壇弾断暖段男談値知地恥池痴稚置致遅築畜竹蓄逐秩窒茶嫡着中仲宙忠抽昼柱注虫衷鋳駐著貯丁兆帳庁弔張彫徴懲挑朝潮町眺聴脹腸調超跳長頂鳥勅直朕沈珍賃鎮陳津墜追痛通塚漬坪釣亭低停偵貞呈堤定帝底庭廷弟抵提程締艇訂逓邸泥摘敵滴的笛適哲徹撤迭鉄典天展店添転点伝殿田電吐塗徒斗渡登途都努度土奴怒倒党冬凍刀唐塔島悼投搭東桃棟盗湯灯当痘等答筒糖統到討謄豆踏逃透陶頭騰闘働動同堂導洞童胴道銅峠匿得徳特督篤毒独読凸突届屯豚曇鈍内縄南軟難二尼弐肉日乳入如尿任妊忍認寧猫熱年念燃粘悩濃納能脳農把覇波派破婆馬俳廃拝排敗杯背肺輩配倍培媒梅買売賠陪伯博拍泊白舶薄迫漠爆縛麦箱肌畑八鉢発髪伐罰抜閥伴判半反帆搬板版犯班畔繁般藩販範煩頒飯晩番盤蛮卑否妃彼悲扉批披比泌疲皮碑秘罷肥被費避非飛備尾微美鼻匹必筆姫百俵標氷漂票表評描病秒苗品浜貧賓頻敏瓶不付夫婦富布府怖扶敷普浮父符腐膚譜負賦赴附侮武舞部封風伏副復幅服福腹複覆払沸仏物分噴墳憤奮粉紛雰文聞丙併兵塀幣平弊柄並閉陛米壁癖別偏変片編辺返遍便勉弁保舗捕歩補穂募墓慕暮母簿倣俸包報奉宝峰崩抱放方法泡砲縫胞芳褒訪豊邦飽乏亡傍剖坊妨帽忘忙房暴望某棒冒紡肪膨謀貿防北僕墨撲朴牧没堀奔本翻凡盆摩磨魔麻埋妹枚毎幕膜又抹末繭万慢満漫味未魅岬密脈妙民眠務夢無矛霧婿娘名命明盟迷銘鳴滅免綿面模茂妄毛猛盲網耗木黙目戻問紋門匁夜野矢厄役約薬訳躍柳愉油癒諭輸唯優勇友幽悠憂有猶由裕誘遊郵雄融夕予余与誉預幼容庸揚揺擁曜様洋溶用窯羊葉要謡踊陽養抑欲浴翌翼羅裸来頼雷絡落酪乱卵欄濫覧利吏履理痢裏里離陸律率立略流留硫粒隆竜慮旅虜了僚両寮料涼猟療糧良量陵領力緑倫厘林臨輪隣塁涙累類令例冷励礼鈴隷零霊麗齢暦歴列劣烈裂廉恋練連錬炉路露労廊朗楼浪漏老郎六録論和話賄惑枠湾腕"
+
+    JINMEI_KANJI_LIST = "丑丞乃之也亘亥亦亨亮伊伍伎伶伽佑侃侑倖倭偲允冴冶凌凜凪凱勁匡卯叡只叶吾呂哉唄啄喬嘉圭尭奈奎媛嬉孟宏宥寅峻崚嵐嵩嵯嶺巌巳巴巽庄弘弥彗彦彪彬怜恕悌惇惟惣慧憧拳捷捺敦斐於旦旭旺昂昌昴晃晋晏晟晨智暉暢曙朋朔李杏杜柊柚柾栗栞桂桐梓梢梧梨椋椎椰椿楊楓楠榛槙槻樺橘檀欣欽毅毬汀汐汰沙洲洵洸浩淳渚渥湧滉漱澪煕熊燎燦燿爽爾猪玖玲琢琳瑚瑛瑞瑠瑶瑳璃甫皐皓眉眸睦瞭瞳矩碧碩磯祐禄禎秦稀稔稜穣竣笙笹紗紘紬絃絢綜綸綺綾緋翔翠耀耶聡肇胡胤脩舜艶芙芹苑茉茄茅茜莉莞菖菫萌萩葵蒔蒼蓉蓮蔦蕉蕗藍藤蘭虎虹蝶衿袈裟詢誼諄諒赳輔辰迪遥遼邑那郁酉醇釆錦鎌阿隼雛霞靖鞠須頌颯馨駒駿魁鮎鯉鯛鳩鳳鴻鵬鶴鷹鹿麟麿黎黛亀"
+
+    def awase(num=0)
+      AWASE_KANJI_LIST[num]
+    end
+    def kyoiku(gakunen=nil, kubun=nil)
+      return KYOIKU_KANJI_LIST if gakunen.nil?
+      return gakunen.map {|nen| kyoiku(nen) }.join('') if gakunen.is_a?(Range) && kubun.nil?
+      return KYOIKU_GAKUNEN_LIST[gakunen-1] if gakunen.is_a?(Integer) && kubun.nil? #1引いてます
+      return gakunen.map {|nen| kyoiku(nen, kubun) }.join('') if gakunen.is_a?(Range) && (! kubun.nil?)
+      return KYOIKU_KUBUN_LIST[(gakunen-1)*4+kubun].chop if gakunen.is_a?(Integer) && (! kubun.nil?)
+      return ""
+    end
+    def joyo() JOYO_KANJI_LIST; end
+    def jinmei() JINMEI_KANJI_LIST; end
+  end
+end
+
+#----------------------------------------------------------------------end.
diff --git a/src/makegraph.rb b/src/makegraph.rb
new file mode 100755 (executable)
index 0000000..3341749
--- /dev/null
@@ -0,0 +1,107 @@
+#!/usr/bin/env ruby
+# MakeGraph routine by eto 2003-0305
+
+require 'network'
+
+module CHISE
+  class MakeGraph #======================================================================実務的な処理を引き受ける。
+    #GRAPHVIZ_CMD = 0 # CLI
+    GRAPHVIZ_CMD = 1 # OLE
+    GRAPHVIZ_TYPE = Graphviz::TWOPI
+    #GRAPHVIZ_TYPE = Graphviz::NEATO
+    START_GAKUNEN = 1
+    END_GAKUNEN = 6
+    
+    def initialize()
+      @kl = KanjiList.instance
+      @hn = KanjiNetwork.new
+    end
+    def go()
+      make_min
+      #make_html_all
+      #make_svg_all
+    end
+    def make_html_all()
+      open("gakunen.html", "w"){|out|
+       out.print %Q|<pre>\n|
+         (1..2).each {|type|
+         typestr = type.to_s
+         out.print %Q|#{typestr}グラフ\n|
+           (1..6).each {|gakunen|
+           out.print %Q|小学#{gakunen}年生 |
+             base = "han-#{type}-#{gakunen}-all"
+           out.print %Q|<a href="#{base}.svg">all</a> |
+             (0..3).each {|kubun|
+             base = "han-#{type}-#{gakunen}-#{kubun}"
+             out.print %Q|<a href="#{base}.svg">#{kubun}</a> |
+           }
+           out.print %Q|\n|
+         }
+       }
+       out.print %Q|</pre>\n|
+      }
+    end
+    def make_min
+      @hn.reset()
+      @hn.make_network(@kl.awase(0))
+      # @hn.make_network(@kl.awase(1))
+      @hn.out("min.dot") #途中状態を保存
+      #graphviz(Graphviz::NEATO, "min.dot", "min.svg")
+      graphviz(GRAPHVIZ_TYPE, "min.dot", "min.svg")
+    end
+    def make_svg_all()
+      (START_GAKUNEN..END_GAKUNEN).each {|gakunen|
+       (0..3).each {|kubun|
+         make_dot(gakunen, kubun)
+         (2..2).each {|type|
+           make_svg(type, gakunen, kubun)
+         }
+       }
+       make_dot(gakunen, nil)
+       (2..2).each {|type|
+         unless type == 2 && 5 <= gakunen
+           make_svg(type, gakunen, nil)
+         end
+       }
+      }
+    end
+    def gaku_name(gakunen, kubun=nil)
+      return "#{gakunen}nen-all" if kubun.nil?
+      return "#{gakunen}nen-#{kubun}"
+    end
+    def make_dot(gakunen, kubun=nil) #Graphvizのtype, 学年, 象形、指示などの区分
+      @hn.reset()
+      list = @kl.kyoiku(1..gakunen, kubun)
+      @hn.make_network(list)
+      dotf = "list-"+gaku_name(gakunen, kubun)+".dot"
+      @hn.out(dotf) #途中状態を保存する
+      p [dotf, "done"]
+    end
+    def make_svg(type, gakunen, kubun=nil) #Graphvizのtype, 学年, 象形、指示などの区分
+      g = gaku_name(gakunen, kubun)
+      dotf = "list-"+g+".dot"
+      svgf = "han-"+g+"-"+GraphvizCLI::NAMES[type]+".svg"
+      graphviz(type, dotf, svgf)
+    end
+    def dot2svg(dir)
+      Dir.chdir(dir)
+      Dir.glob("*.dot").each {|inf|
+       out = inf.sub(/.dot$/, '.svg')
+       type = 1 if inf =~ /^han-1/
+       type = 2 if inf =~ /^han-2/
+       graphviz(type, inf, out)
+      }
+    end
+    def graphviz(type, inf, out)
+      gv = GraphvizCLI.new() if GRAPHVIZ_CMD == 0
+      gv = GraphvizOLE.new() if GRAPHVIZ_CMD == 1
+      gv.type = type
+      gv.target = 'svg'
+      gv.in  = inf
+      gv.out = out
+      gv.generate()
+    end
+  end
+end
+
+#----------------------------------------------------------------------end.
diff --git a/src/network.rb b/src/network.rb
new file mode 100755 (executable)
index 0000000..882f53b
--- /dev/null
@@ -0,0 +1,145 @@
+#!/usr/bin/env ruby
+# calc KanjiNetwork by eto 2003-0305
+
+require 'kanjilist'
+require 'defkanji'
+require 'graphviz'
+
+module CHISE
+  class KanjiNetwork #======================================================================漢字間のネットワークを計算する。
+    def initialize()
+      reset()
+      @formatter = GraphvizFormatter.new(self)
+      # @formatter = XSpringiesFormatter.new(self)
+    end
+    attr_reader :h, :list
+    def reset
+      @h = Hash.new
+      @done = Hash.new
+      @list = []
+    end
+    def make_network(list) #@h, @listに結果を入れていく。
+      list.each_char {|ch|
+       make_network_one(ch)
+      }
+    end
+    
+    def make_network_one(ch) #実質的にこれが本体。再帰で呼ばれる。
+      return if @done[ch]
+      
+      @h[ch] = []
+      @list << ch #登場文字リストに追加
+      
+      char = ch.char
+      ids = char.decompose
+      if ids.char_length == 1 #分割できない文字は、リンクを探す。
+       link = char.ids_represent if char.ids_represent
+       link = char.ids_link if char.ids_link
+       return if link.nil?
+       @h[ch] << link #親字に追加する。
+       @list << link
+       return
+      end
+      
+      ids.each_char {|idsch|
+       idschar = idsch.char
+       next if idschar.is_ids?
+       @h[ch] << idsch #親字に追加する。
+       @list << idsch
+       make_network_one(idsch) #再帰する。
+      }
+      @done[ch] = true
+    end
+    
+    def nodes_and_edges() #これを二つのarrayで返す
+      nodear = []
+      nodeh  = Hash.new
+      @list.sort.uniq.each_with_index {|ch, index|
+       nodear[index] = ch
+       nodeh[ch] = index
+      }
+      edgear = []
+      @h.each {|ch, ar|
+       ar.each {|idsch|
+         edgear << [nodeh[ch], nodeh[idsch]]
+       }
+      }
+      return nodear, edgear
+    end
+
+    def out(filename)
+      open(filename, "w"){|out| out.print to_s }
+    end
+    def to_s() @formatter.to_s; end
+  end
+
+  class GraphvizFormatter #====================================================================== Graphviz関係
+    def initialize(network)
+      @network = network
+    end
+    def to_s() #Graphvizのフォーマット、dotフォーマットに変換する。
+      page = DotPage.new
+      page.size = "5.5, 5.5"
+      #page.pack = "true"
+      #page.epsilon = 0.001
+      #page.epsilon = 0.01
+      #page.overlap = false
+      #page.overlap = scale
+      #page.spline = true
+
+      #p @network.list
+      @network.list.sort.uniq.each {|ch|
+       char = ch.char
+       node = DotNode.new(char.to_i)
+       node.label = char.map_ucs_er #node.label = char.to_utf8
+       node.fontsize = (node.label =~ /^&#/) ? 12 : 6
+       #node.fontsize = (node.label =~ /^&#/) ? 24 : 6
+       node.shape = "plaintext"
+       node.fontname = "MS-Mincho" #呪われてるがしかたがない
+       #node.fontname = "Arial-Unicode-MS" #ダメ
+       page.add_node(node)
+      }
+
+      @network.h.each {|ch, ar|
+       char = ch.char
+       ar.each {|idsch|
+         idschar = idsch.char
+         edge = DotEdge.new(char.to_i, idschar.to_i)
+         #edge.len = 4
+         #edge.len = 2
+         #edge.color = "gray"
+         edge.color = "lightgray"
+         page.add_edge(edge)
+       }
+      }
+      return page.to_s
+    end
+  end
+
+  class XSpringiesFormatter #======================================================================
+    def initialize(network)
+      @network = network
+    end
+    def to_s # #1.0 *** XSpringies data file
+      str = ""
+      @network.list.sort.uniq.each {|ch|
+       char = ch.char
+       num = char.to_i
+       label = char.map_ucs_er
+       str << "mass #{num}\n"
+      }
+      @network.h.each {|ch, ar|
+       char = ch.char
+       ar.each {|idsch|
+         idschar = idsch.char
+         from = char.to_i
+         to = idschar.to_i
+         str << "spng #{from} #{to}\n"
+       }
+      }
+      str
+    end
+  end
+end
+
+#----------------------------------------------------------------------end.
diff --git a/t/tc_kanjilist.rb b/t/tc_kanjilist.rb
new file mode 100755 (executable)
index 0000000..cdbbb87
--- /dev/null
@@ -0,0 +1,37 @@
+#!/usr/bin/env ruby
+# testcase for KanjiNetwork by eto 2003-0227
+
+require 'test/unit'
+$LOAD_PATH << '../src'
+require 'chise'
+require 'kanjilist'
+include CHISE
+
+class TC_KanjiList < Test::Unit::TestCase
+  def setup
+    @kl = KanjiList.instance
+  end
+  def test_kyoiku_kanji_list #範囲指定が複雑なのでtestするべし。
+    assert_equal("愛悪圧安暗案以位囲委意易異移胃衣遺医域育一印員因引飲院右宇羽雨運雲営映栄永泳英衛液益駅円園延沿演遠塩央往応横王黄億屋恩温音下化仮何価加可夏家科果歌河火花荷課貨過我画芽賀会解回快改械海灰界絵開階貝外害街各拡格確覚角閣革学楽額割活株寒刊巻完官干幹感慣漢看管簡観間関館丸岸眼岩顔願危喜器基寄希揮机旗期機帰気汽季紀規記貴起技疑義議客逆久休吸宮弓急救求泣球究級給旧牛去居挙許漁魚京供競共協境強教橋胸興郷鏡業局曲極玉勤均禁筋近金銀九句区苦具空君訓群軍郡係兄型形径敬景系経計警軽芸劇激欠決潔穴結血月件健券建憲検権犬研絹県見険験元原厳減源現言限個古呼固己庫戸故湖五午後語誤護交候光公功効厚口向后好孝工幸広康校構港皇紅耕考航行講鉱鋼降高号合刻告国穀黒骨今困根混左差査砂座再最妻才採済災祭細菜裁際在材罪財坂作昨策桜冊刷察札殺雑皿三参山散産算蚕賛酸残仕使司史四士始姉姿子市師志思指支枝止死氏私糸紙至視詞詩試誌資飼歯事似児字寺持時次治磁示耳自辞式識七失室質実舎写射捨社者謝車借尺若弱主取守手種酒首受授樹収周宗就州修拾秋終習衆週集住十従縦重宿祝縮熟出術述春準純順処初所暑署書諸助女序除傷勝商唱将小少承招昭松消焼照省章笑証象賞障 上乗城場常情条状蒸植織職色食信心新森深申真神臣親身進針人仁図垂推水数寸世制勢性成政整星晴正清生盛精聖声製西誠青静税席昔石積績責赤切接折設節説雪絶舌先千宣専川戦泉浅洗染線船選銭前善然全祖素組創倉奏層想操早巣争相窓総草装走送像増臓蔵造側則息束測足速属族続卒存孫尊損村他多太打体対帯待態貸退隊代台大第題宅達谷単担探炭短誕団断暖段男談値知地池置築竹茶着中仲宙忠昼柱注虫著貯丁兆帳庁張朝潮町腸調長頂鳥直賃追痛通低停定底庭弟提程敵的笛適鉄典天展店転点伝田電徒登都努度土党冬刀島投東湯灯当等答糖統討豆頭働動同堂導童道銅得徳特毒独読届内南難二肉日乳入任認熱年念燃納能脳農波派破馬俳拝敗背肺配倍梅買売博白麦箱畑八発判半反板版犯班飯晩番否悲批比皮秘肥費非飛備美鼻必筆百俵標氷票表評病秒品貧不付夫婦富布府父負武部風副復服福腹複仏物分奮粉文聞兵平並閉陛米別変片編辺返便勉弁保歩補墓暮母包報宝放方法訪豊亡忘暴望棒貿防北牧本妹枚毎幕末万満味未密脈民務夢無名命明盟迷鳴綿面模毛木目問門夜野矢役約薬訳油輸優勇友有由遊郵夕予余預幼容曜様洋用羊葉要陽養欲浴翌来落乱卵覧利理裏里陸律率立略流留旅両料良量領力緑林臨輪類令例冷礼歴列練連路労朗老六録論和話", @kl.kyoiku())
+    assert_equal("一右雨円王音下火花学気休金九空月犬見五口校左三山四子糸字耳七車手十出女小上森人水正生青石赤先千川早足村大男中虫町天田土二日入年白八百文本名木目夕立力林六", @kl.kyoiku(1))
+    assert_equal("引雲遠黄何夏家科歌画会回海絵貝外楽間顔帰汽記牛魚京強教玉近形計元原古戸午後語交光工広考行高合国黒今才作算市思止紙寺時自室社弱首秋春書少場色食心新親図数星晴声西切雪船前組草走多太体台谷知地池竹茶昼朝長鳥通弟店点電冬刀東当答頭同道読南馬買売麦半番父風分聞米歩母方北妹毎明鳴毛門夜野友曜用来理里話", @kl.kyoiku(2))
+    assert_equal("一右雨円王音下火花学気休金九空月犬見五口校左三山四子糸字耳七車手十出女小上森人水正生青石赤先千川早足村大男中虫町天田土二日入年白八百文本名木目夕立力林六引雲遠黄何夏家科歌画会回海絵貝外楽間顔帰汽記牛魚京強教玉近形計元原古戸午後語交光工広考行高合国黒今才作算市思止紙寺時自室社弱首秋春書少場色食心新親図数星晴声西切雪船前組草走多太体台谷知地池竹茶昼朝長鳥通弟店点電冬刀東当答頭同道読南馬買売麦半番父風分聞米歩母方北妹毎明鳴毛門夜野友曜用来理里話", @kl.kyoiku(1..2))
+
+    assert_equal("右雨王音火貝九玉金月犬見口左山子糸耳車手十女人水夕石川早足大竹虫天田土日年白文木目立力六", @kl.kyoiku(1, KanjiList::SHOUKEI))
+    assert_equal("一二三四五下七小上生中入八本", @kl.kyoiku(1, KanjiList::SHIJI))
+    assert_equal("円休出森正赤千男町名林", @kl.kyoiku(1, KanjiList::KAII))
+    assert_equal("花学気空校字青先草村百", @kl.kyoiku(1, KanjiList::KEISEI))
+
+    assert_equal("羽雲夏画回会外角弓牛魚京兄原戸古午工交行高黄才止矢自首心西長鳥弟刀東肉馬米歩母方北万毛門用来", @kl.kyoiku(2, KanjiList::SHOUKEI))
+    assert_equal("", @kl.kyoiku(2, KanjiList::SHIJI))
+    assert_equal("科楽岩顔汽教計公谷黒今思春少声雪走多太台直電内売半番父明鳴友里", @kl.kyoiku(2, KanjiList::KAII))
+    assert_equal("引園遠何家歌海絵活間丸記帰強近形元言後語広光考合国細作算市姉紙寺時室社弱配秋週書場色食新親図数星晴切船線前組体地池茶昼朝通店点冬当答頭同道読南買麦風分聞毎妹夜野曜理話", @kl.kyoiku(2, KanjiList::KEISEI))
+
+    assert_equal("右雨王音火貝九玉金月犬見口左山子糸耳車手十女人水夕石川早足大竹虫天田土日年白文木目立力六羽雲夏画回会外角弓牛魚京兄原戸古午工交行高黄才止矢自首心西長鳥弟刀東肉馬米歩母方北万毛門用来", @kl.kyoiku(1..2, KanjiList::SHOUKEI))
+    assert_equal("一二三四五下七小上生中入八本", @kl.kyoiku(1..2, KanjiList::SHIJI))
+    assert_equal("円休出森正赤千男町名林科楽岩顔汽教計公谷黒今思春少声雪走多太台直電内売半番父明鳴友里", @kl.kyoiku(1..2, KanjiList::KAII))
+    assert_equal("花学気空校字青先草村百引園遠何家歌海絵活間丸記帰強近形元言後語広光考合国細作算市姉紙寺時室社弱配秋週書場色食新親図数星晴切船線前組体地池茶昼朝通店点冬当答頭同道読南買麦風分聞毎妹夜野曜理話", @kl.kyoiku(1..2, KanjiList::KEISEI))
+  end
+end
+
+#----------------------------------------------------------------------end.
diff --git a/t/tc_network.rb b/t/tc_network.rb
new file mode 100755 (executable)
index 0000000..b0519d1
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env ruby
+# testcase for KanjiNetwork by eto 2003-0227
+
+require 'test/unit'
+$LOAD_PATH << '../src'
+require 'chise'
+require 'network'
+include CHISE
+
+class TC_KanjiNetwork < Test::Unit::TestCase
+  def test_network
+    @kl = KanjiList.instance
+    @kn = KanjiNetwork.new
+    @kn.make_network(@kl.awase(0))
+    @kn.out("min.dot") #途中状態を保存
+
+    @gv = GraphvizOLE.new() #OLE version
+    @gv.type = Graphviz::TWOPI
+    @gv.target = 'svg'
+    @gv.in  = "min.dot"
+    @gv.out = "min.svg"
+    @gv.generate()
+  end
+end
+
+#----------------------------------------------------------------------end.
index 1c68bed..53a0f44 100755 (executable)
@@ -7,5 +7,7 @@ require 'tc_char'
 require 'tc_str'
 require 'tc_db'
 require 'tc_ids'
+require 'tc_kanjilist'
+#require 'tc_network' #Graphvizが必要なため、普段は実行しない
 
 #----------------------------------------------------------------------end.