OSDN Git Service

Adds exception procedures
[dianzhuhui/site.git] / hanMorph / app / controllers / hanmorph_controller.rb
1 TBL_DIR = File.join(File.dirname(__FILE__), '..', '..', 'config', 'table')
2 XS = File.join(TBL_DIR, 'phonetic_components.yml')
3 MAX_NUM_FOR_MATCHED = 100
4
5 class HanmorphController < ApplicationController
6   layout "main"
7   caches_page :xiesheng, :rime_groups
8   caches_action :xiesheng, :rime_groups
9   
10   def index
11     if request.post? then
12       @errors = []
13       (@ucs, @char, @extext) = check_targets
14 #      raise Exception
15       if @errors.empty? then
16         begin
17           main_procedure_at_home
18         rescue StandardError => bang
19           @message = bang.message
20         end
21       end
22     else
23       char = params[:char]
24       (@ucs, @char) = process_char(char) if char
25       main_procedure_at_home
26     end
27   end
28   def rime_groups
29     @groups = Array.new
30     volumes = Volume.find(:all)
31     groups = RimeGroup.find(:all)
32     #groups.sort! {|a,b| a.num <=> b.num}
33     groups.each do |group|
34       sisheng = Array.new(4)
35       volumes.each do |volume|
36         rhymes = Rhyme.find(:all, :conditions => 
37                             ["rime_group_id = ? and volume_id = ?", group.id, volume.id])
38         volume
39         if volume.name =~ /[上下]平聲/u then
40           sisheng[0] = Array.new unless sisheng[0] 
41           sisheng[0] += rhymes
42         elsif volume.name =~ /上聲/u then
43           sisheng[1] = rhymes
44         elsif volume.name =~ /去聲/u then
45           sisheng[2] = rhymes
46         elsif volume.name =~ /入聲/u then
47           sisheng[3] = rhymes
48         end
49       end
50       @groups.push([group, sisheng])
51     end
52   end
53   def xiesheng
54     @doc = YAML.load(File.new(XS))
55 #    doc.each_key do |group|
56 #      doc[group].each_key do |xs|
57 #        doc[group][xs].each do |char|
58 #    end
59   end
60   def pcomponent
61     @group = params[:group]
62     @xiesheng = params[:xiesheng]
63     doc = YAML.load(File.new(XS))
64     @chars = doc[@group][@xiesheng]
65   end
66   def explanation
67   end
68   
69   private
70   def main_procedure_at_home
71     if @char then
72       process_unihan
73       process_sbgy
74       process_dianzhu
75       process_daxu
76     end
77     if @extext then
78       begin
79         search_daxu
80       rescue TooManyCandidatesError => bang
81         @errors << bang
82       end
83     end
84   end
85
86   # Validation Input Parameters
87   def check_targets
88     c = params[:char]
89     extext = params[:extext]
90     # TODO: 不正な文字のチェック
91     if extext and extext.size == 0 then
92       @errors << "検索する説解が入力されていません"
93     elsif ! extext and c and c.size == 0 then
94       @errors << "検索する文字が入力されていません"
95     elsif c =~/[0-9A-Fa-f]+/ and not c =~ /[0-9A-Fa-f]{4,5}/ then
96       @errors << "#{c}: 正しいコードポイントではありません"
97     else
98       (ucs, char) = process_char(c)
99       return [ucs, char, extext]
100     end
101   end
102
103   # Main Procesures
104   def process_unihan
105     cp = ucs2codepoint(@ucs)
106     ideograph = Ideograph.find(:first, :conditions => ["codepoint = ?", cp])
107     return nil unless ideograph
108     @sbgy = unihan_lookup(ideograph, 'kSBGY')
109     @hdz = unihan_lookup(ideograph, 'kHanYu')
110     @dkz = unihan_lookup(ideograph, 'kIRGDaiKanwaZiten')
111     @kx = unihan_lookup(ideograph, 'kIRGKangXi')
112     (@page, @appendix) = get_hdz_page(@hdz)
113   end
114   def process_sbgy
115     @chars = Array.new
116     wordheads = Wordhead.find(:all, :conditions => ["name = ?", @char])
117     wordheads.each do |wordhead|
118       voice = Voice.find(:first, :conditions => ["id = ?", wordhead.voice_id])
119       rhyme = Rhyme.find(:first, :conditions => ["id = ?", voice.rhyme_id])
120       rime_group = RimeGroup.find(:first, :conditions =>
121                                   ["id = ?", rhyme.rime_group_id])
122       volume = Volume.find(:first, :conditions => ["id = ?", rhyme.volume_id])
123       @chars.push([wordhead, voice, rhyme, rime_group, volume])
124     end
125   end
126   def process_dianzhu
127     @sw_chars = Array.new
128     wordheads = SwWordhead.find(:all, :conditions => ["name = ?", @char])
129     wordheads.each do |wordhead|
130       charid = wordhead.character_id
131       char = SwCharacter.find(:first, :conditions => ["id = ?", charid])
132       rad = SwRadical.find(:first, :conditions => ["id = ?", char.radical_id])
133       chap = SwChapter.find(:first, :conditions => ["id = ?", rad.chapter_id])
134       words = SwWordhead.find(:all, :conditions => ["character_id = ?", charid])
135       @sw_chars.push([chap, rad, char, words])
136     end
137   end
138   def process_daxu
139     @dx_words = Array.new
140     wordheads = DxWordhead.find(:all, :conditions => ["name = ?", @char])
141     wordheads.each do |word|
142       wordid = word.wordid
143       rad = DxRadical.find(:first, :conditions => ["id = ?", word.radical_id])
144       vol = DxVolume.find(:first, :conditions => ["id = ?", rad.volume_id])
145       @dx_words.push([vol, rad, word])
146     end
147   end
148   def search_daxu
149     @dxexp_words = Array.new
150     @pattern = sprintf("%%%s%%", @extext)
151     wordheads = DxWordhead.find_by_sql(["select * from dx_wordheads " +
152                                        "where exp like ?", @pattern])
153     searched = wordheads.size
154     if searched > MAX_NUM_FOR_MATCHED then
155       raise TooManyCandidatesError, "#{searched}件、見付かりました。検索条件を絞り込んでください。"
156     end
157     wordheads.each do |word|
158       wordid = word.wordid
159       rad = DxRadical.find(:first, :conditions => ["id = ?", word.radical_id])
160       vol = DxVolume.find(:first, :conditions => ["id = ?", rad.volume_id])
161       voltitle = get_voltitle(vol)
162       exp = hilighted_exp(word.exp, @extext)
163       @dxexp_words.push([voltitle, rad, word, exp])
164     end
165   end
166
167   # Utility Functions
168   def unihan_lookup(ideograph, field_name)
169     field = Field.find(:first, :conditions => ["name = ?", field_name])
170     property = Property.find(:first,
171                              :conditions => ["field_id = ? and ideograph_id = ?", field.id, ideograph.id])
172     return property
173   end
174   def get_hdz_page(property)
175     return nil unless property
176     if property.value =~ /([1-8])([0-9]{4})\.([0-3][0-9])[01]/ then
177       volume = $1
178       page = $2
179 #      num = $3.to_i
180       appendix = (volume == "8" ? true : false)
181       return [page, appendix, volume]
182     end 
183   end
184   def get_voltitle(vol)
185     return vol.title.sub(/說文解字第/u, "")
186   end
187   def hilighted_exp(exp, pattern)
188     regex = pattern.gsub(/%/, ".+")
189     # BUG: マッチした文字列が異なる場合、最初のものに置換される
190     if exp =~ /#{regex}/u then
191       span = "<span style='background-color:lightpink;'>#{$&}</span>"
192       return exp.gsub(/#{regex}/u, span)
193     else
194       return exp
195     end
196
197   end
198 end
199
200 class TooManyCandidatesError < RuntimeError
201 end