--- /dev/null
+TBL_DIR = File.join(File.dirname(__FILE__), '..', '..', 'config', 'table')
+XS = File.join(TBL_DIR, 'phonetic_components.yml')
+
+class HanmorphController < ApplicationController
+ layout "main"
+ caches_page :xiesheng, :rime_groups
+ caches_action :xiesheng, :rime_groups
+
+ def index
+ c = params[:char]
+ @extext = params[:extext]
+ if c then
+ (@ucs, @char) = process_char(c)
+ process_unihan
+ process_sbgy
+ process_dianzhu
+ process_daxu
+ end
+ if @extext then
+ search_daxu
+ end
+ end
+ def rime_groups
+ @groups = Array.new
+ volumes = Volume.find(:all)
+ groups = RimeGroup.find(:all)
+ #groups.sort! {|a,b| a.num <=> b.num}
+ groups.each do |group|
+ sisheng = Array.new(4)
+ volumes.each do |volume|
+ rhymes = Rhyme.find(:all, :conditions =>
+ ["rime_group_id = ? and volume_id = ?", group.id, volume.id])
+ volume
+ if volume.name =~ /[上下]平聲/u then
+ sisheng[0] = Array.new unless sisheng[0]
+ sisheng[0] += rhymes
+ elsif volume.name =~ /上聲/u then
+ sisheng[1] = rhymes
+ elsif volume.name =~ /去聲/u then
+ sisheng[2] = rhymes
+ elsif volume.name =~ /入聲/u then
+ sisheng[3] = rhymes
+ end
+ end
+ @groups.push([group, sisheng])
+ end
+ end
+ def xiesheng
+ @doc = YAML.load(File.new(XS))
+# doc.each_key do |group|
+# doc[group].each_key do |xs|
+# doc[group][xs].each do |char|
+# end
+ end
+ def pcomponent
+ @group = params[:group]
+ @xiesheng = params[:xiesheng]
+ doc = YAML.load(File.new(XS))
+ @chars = doc[@group][@xiesheng]
+ end
+ def explanation
+ end
+
+ private
+ # Main Procesures
+ def process_unihan
+ cp = ucs2codepoint(@ucs)
+ ideograph = Ideograph.find(:first, :conditions => ["codepoint = ?", cp])
+ return nil unless ideograph
+ @sbgy = unihan_lookup(ideograph, 'kSBGY')
+ @hdz = unihan_lookup(ideograph, 'kHanYu')
+ @dkz = unihan_lookup(ideograph, 'kIRGDaiKanwaZiten')
+ @kx = unihan_lookup(ideograph, 'kIRGKangXi')
+ (@page, @appendix) = get_hdz_page(@hdz)
+ end
+ def process_sbgy
+ @chars = Array.new
+ wordheads = Wordhead.find(:all, :conditions => ["name = ?", @char])
+ wordheads.each do |wordhead|
+ voice = Voice.find(:first, :conditions => ["id = ?", wordhead.voice_id])
+ rhyme = Rhyme.find(:first, :conditions => ["id = ?", voice.rhyme_id])
+ rime_group = RimeGroup.find(:first, :conditions =>
+ ["id = ?", rhyme.rime_group_id])
+ volume = Volume.find(:first, :conditions => ["id = ?", rhyme.volume_id])
+ @chars.push([wordhead, voice, rhyme, rime_group, volume])
+ end
+ end
+ def process_dianzhu
+ @sw_chars = Array.new
+ wordheads = SwWordhead.find(:all, :conditions => ["name = ?", @char])
+ wordheads.each do |wordhead|
+ charid = wordhead.character_id
+ char = SwCharacter.find(:first, :conditions => ["id = ?", charid])
+ rad = SwRadical.find(:first, :conditions => ["id = ?", char.radical_id])
+ chap = SwChapter.find(:first, :conditions => ["id = ?", rad.chapter_id])
+ words = SwWordhead.find(:all, :conditions => ["character_id = ?", charid])
+ @sw_chars.push([chap, rad, char, words])
+ end
+ end
+ def process_daxu
+ @dx_words = Array.new
+ wordheads = DxWordhead.find(:all, :conditions => ["name = ?", @char])
+ wordheads.each do |word|
+ wordid = word.wordid
+ rad = DxRadical.find(:first, :conditions => ["id = ?", word.radical_id])
+ vol = DxVolume.find(:first, :conditions => ["id = ?", rad.volume_id])
+ @dx_words.push([vol, rad, word])
+ end
+ end
+ def search_daxu
+ @dxexp_words = Array.new
+ @pattern = sprintf("%%%s%%", @extext)
+ wordheads = DxWordhead.find_by_sql(["select * from dx_wordheads " +
+ "where exp like ?", @pattern])
+ wordheads.each do |word|
+ wordid = word.wordid
+ rad = DxRadical.find(:first, :conditions => ["id = ?", word.radical_id])
+ vol = DxVolume.find(:first, :conditions => ["id = ?", rad.volume_id])
+ voltitle = get_voltitle(vol)
+ exp = hilighted_exp(word.exp, @extext)
+ @dxexp_words.push([voltitle, rad, word, exp])
+ end
+ end
+
+ # Utility Functions
+ def unihan_lookup(ideograph, field_name)
+ field = Field.find(:first, :conditions => ["name = ?", field_name])
+ property = Property.find(:first,
+ :conditions => ["field_id = ? and ideograph_id = ?", field.id, ideograph.id])
+ return property
+ end
+ def get_hdz_page(property)
+ return nil unless property
+ if property.value =~ /([1-8])([0-9]{4})\.([0-3][0-9])[01]/ then
+ volume = $1
+ page = $2
+# num = $3.to_i
+ appendix = (volume == "8" ? true : false)
+ return [page, appendix, volume]
+ end
+ end
+ def get_voltitle(vol)
+ return vol.title.sub(/說文解字第/u, "")
+ end
+ def hilighted_exp(exp, pattern)
+# span = "<span style='background-color:peachpuff;'>%s</span>"
+ span = "<span style='background-color:lightpink;'>%s</span>"
+ replaced = sprintf(span, pattern)
+ return exp.sub(/#{pattern}/u, replaced)
+ end
+end
--- /dev/null
+ <% if @char and @char.size > 0 then %>
+ <% unihan_r = "http://www.unicode.org/cgi-bin/GetUnihanData.pl?codepoint=" %>
+ <h3>辞書情報
+ <%= link_to_function "▲▼", "new Effect.toggle('charinfo', 'blind')" %>
+ </h3>
+ <div id="charinfo">
+ <span style="font-size:200%"><%= @char %></span>
+ <% unihan_ref = unihan_r + @char %>
+ <a href="<%= unihan_ref %>" title="Unihan Lookup"
+ target="_blank"><%= @ucs %></a>
+ <ul>
+ <% if @hdz then %>
+ <li>漢語大字典 <%= link_to(@hdz.value, :controller => "unihan",
+ :action => "hdz", :char => @char) %></li>
+ <% end %>
+ <% if @dkz then %><li>大漢和辞典 <%= @dkz.value %></li><% end %>
+ <% if @kx then %><li>康煕字典 <%= @kx.value %></li><% end %>
+ </ul>
+ </div><!-- charinfo -->
+ <% end %>
--- /dev/null
+ <% if @char and @char.size > 0 and @dx_words then %>
+ <h2>
+ 説文解字(大徐本)
+
+ <%= link_to_function "▲▼", "new Effect.toggle('sw', 'blind')" %>
+ </h2>
+ <div id="sw">
+ <% @dx_words.each do |wordinfo| %>
+ <% (vol, rad, word) = wordinfo %>
+ <!--
+ <%= vol.title %>
+ <%= link_to(rad.name + "部", :controller => "daxu",
+ :action => "radical", :id => rad.id) %>
+ <br />
+ -->
+ <span class="s"><%= word.sw %></span>(<%= word.name %>)
+ <span style="font-size: 120%"><%= word.exp %></span>
+ [<%= word.fanqie %> <%= word.pinyin %>]
+ <br />
+ <% end %>
+ </div><!-- sw -->
+ <% end %>
--- /dev/null
+ <% if @extext then %>
+ <h2>説解検索結果
+ <span style="">
+ <%= link_to_function "▲▼", "new Effect.toggle('result', 'blind')" %>
+ 「<%= @extext %>」
+ <%= @dxexp_words.size %> Found
+ </span>
+ </h2>
+ <div id="result">
+ <ol>
+ <% @dxexp_words.each do |wordinfo|%>
+ <li><% (voltitle, rad, word, exp) = wordinfo %>
+ <%= voltitle %>
+ <%= link_to(rad.name + "部", :controller => "daxu",
+ :action => "radical", :id => rad.id) %>
+ <span class="swlist"><%= word.sw %></span>
+ <span style="font-size: 100%">
+ (<%= link_to(word.name, :controller => "hanmorph",
+ :action => "index", :char => word.name) %>)
+ </span>
+ <span style="font-size: 110%"><%= exp %></span>
+ [<%= word.fanqie %> <%= word.pinyin %>]
+ </li>
+ <% end %>
+ </ol>
+ </div> <!-- swresult -->
+ <% end %>
--- /dev/null
+<!--
+ <% if @sbgy or @chars then %><h3>宋本廣韻</h3><% end %>
+ <% if @sbgy then %>[<%= @sbgy.value %>]<% end %>
+-->
+
+ <% if @sbgy or (@chars and @chars.size > 0) then %>
+ <h3>宋本廣韻
+ <%= link_to_function "▲▼", "new Effect.toggle('sbgy', 'blind')" %>
+ </h3>
+ <% end %>
+
+ <div id="sbgy">
+ <% if @sbgy then %>
+ <span style="font-size:150%"><%= @char %></span> <%= @sbgy.value %>
+ <% end %>
+
+ <% if @chars then %>
+ <% @chars.each do |char| %>
+ <ul>
+ <li>
+ <span style="font-size:120%">
+ <% (wordhead, voice, rhyme, rime_group, volume) = char %>
+ <%= volume.name %>
+ <%= link_to(rhyme.name, :controller => "sbgy",
+ :action => "rhyme", :id => rhyme.id) %><span style="font-size:70%">(<%= rime_group.title %>)</span>
+ <%= link_to(
+ "小韻「" + voice.name + "」", :controller => "sbgy",
+ :action => "xiaoyun", :id => voice.id) %>
+ </span>
+ <%= voice.fanqie %>
+ <!-- %= wordhead.note % -->
+ </li>
+ </ul>
+ <% end %>
+ <% end %>
+ </div><!-- sbgy -->
--- /dev/null
+ <h3>検索
+ <%= link_to_function "▲▼", "new Effect.toggle('searchmenu', 'blind')" %>
+ </h3>
+
+ <div id="searchmenu">
+ <ul>
+ <li>
+ <% form_tag(:controller => "hanmorph", :action => "index", :method => "get") do %>
+ <%= label_tag(:char, "親字:") %>
+ <%= text_field_tag(:char, "", :size => "5") %>
+ <%= submit_tag("search") %>
+ <% end %>
+ </li>
+ <li>
+ <% form_tag(:controller => "hanmorph", :action => "index", :method => "get") do %>
+ <%= hidden_field_tag(:char, @char) %>
+ <%= label_tag(:extext, "説解:") %>
+ <%= text_field_tag(:extext, "", :size => "8") %>
+ <%= submit_tag("search") %>
+ <% end %>
+ </li>
+ </ul>
+ </div>
--- /dev/null
+<div id="menu">
+ <ul>
+ <li><%= link_to("大徐本", :controller => "daxu", :action => "index") %></li>
+ <li><%= link_to("段注", :controller => "shuowen", :action => "index") %></li>
+ <li><%= link_to("廣韻", :controller => "sbgy", :action => "index") %></li>
+ <li><%= link_to("漢語大字典", :controller => "unihan", :action => "hdz") %></li>
+ <li><%= link_to("十七部表", :controller => "kanjidb", :action => "rime_groups") %></li>
+ <li><%= link_to("諧聲表", :controller => "kanjidb", :action => "xiesheng") %></li>
+ <li></li>
+ <li><%= link_to("説明", :controller => "kanjidb", :action => "explanation") %></li>
+ </ul>
+</div>
+
+<div id="sidebar">
+ <%= render :partial => "dxsearch" %>
+ <%= render :partial => "charinfo" %>
+ <%= render :partial => "sbgy" %>
+</div><!-- layout: sidebar -->
+
+<div id="content">
+ <%= render :partial => "dxsearch_result" %>
+ <%= render :partial => "daxu" %>
+
+<% kdbimgdir="http://kanji-database.sourceforge.net/dict/swjz/swjz-img/" %>
+<% if @sw_chars then %>
+ <% @sw_chars.each do |sw_char| %>
+ <% (chap, rad, char, words) = sw_char %>
+ <h2>
+ <%= chap.name %>
+ <%= link_to(rad.name + "部", :controller => "shuowen",
+ :action => "radical", :id => rad.id) %>
+ </h2>
+ <% words.each do |word| %>
+ <p>
+ <% swimg=format(kdbimgdir+"%ss.png", word.img) %>
+ <img src=<%= swimg %> width="5%" height="6%" />
+ <!-- %= image_tag(swimg) % -->
+ <!-- span style="font-size:200%"><%= word.name %></span -->
+ <!-- span class="s"><%= word.sw %></span -->
+ <span style="font-size:100%">(<%= word.name %>)</span>
+ <%= word.note %>(<%= word.img %>)
+ </p>
+ <% end %>
+ <% end %>
+ <% end %>
+
+<% unless @char then %>
+ <h2>ようこそ</h2>
+ <h3>簡単な使用法</h3>
+ <p>
+ まずは左の検索メニューからお使い下さい。
+ 漢字についての情報を知りたい場合には、「親字:」の右にその文字を、
+ 説解について全文検索したい場合には、「説解:」の右にその語句を入力して下さい。
+ 詳細についてはメニューバーの「説明」をご覧下さい。
+ </p>
+<% end %>
+
+</div><!-- layout: content -->
+<div style="clear: both;"> </div>
--- /dev/null
+<html>
+<head>
+ <title>Han Morphism ver.0.3</title>
+ <META http-equiv="Content-Type" content="text/html; charset=utf8">
+ <%= stylesheet_link_tag("937316282/940") %>
+ <%= stylesheet_link_tag("sw") %>
+ <%= javascript_include_tag :defaults %>
+</head>
+<body>
+<div id="wrap">
+ <div id="header">
+ <h1><a href=".">汉态射
+ <span style="font-size:60%"><%= yield :head %></span>
+ <span style="font-size:90%;font-style:italic">Han Morphism System</span>
+ <span style="font-size:60%">Ver.0.3.0</span></a>
+ </h1>
+ </div>
+
+ <%= yield %>
+
+ <div id="footer">© Copyright 2011 SHIRASU Hiroyuki | Design by Blog Liber, Free Layouts World</div>
+</div>
+</body>
--- /dev/null
+ActionController::Routing::Routes.draw do |map|
+ # The priority is based upon order of creation: first created -> highest priority.
+
+ # Sample of regular route:
+ # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
+ # Keep in mind you can assign values other than :controller and :action
+
+ # Sample of named route:
+ # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
+ # This route can be invoked with purchase_url(:id => product.id)
+
+ # Sample resource route (maps HTTP verbs to controller actions automatically):
+ # map.resources :products
+
+ # Sample resource route with options:
+ # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
+
+ # Sample resource route with sub-resources:
+ # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller
+
+ # Sample resource route with more complex sub-resources
+ # map.resources :products do |products|
+ # products.resources :comments
+ # products.resources :sales, :collection => { :recent => :get }
+ # end
+
+ # Sample resource route within a namespace:
+ # map.namespace :admin do |admin|
+ # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb)
+ # admin.resources :products
+ # end
+
+ # You can have the root of your site routed with map.root -- just remember to delete public/index.html.
+ map.root :controller => "hanmorph"
+
+ # See how all your routes lay out with "rake routes"
+
+ # Install the default routes as the lowest priority.
+ # Note: These default routes make all actions in every controller accessible via GET requests. You should
+ # consider removing or commenting them out if you're using named routes and resources.
+ map.connect ':controller/:action/:id'
+ map.connect ':controller/:action/:id.:format'
+end
--- /dev/null
+body {
+font-family: "Trebuchet MS", sans-serif;
+line-height: 1.5;
+font-size: 14px;
+background: #36393D;
+margin: 0;
+padding: 0;
+}
+
+a { color: #0066cc; text-decoration: none;}
+a:hover { color: #880000; }
+
+h1 {
+margin: 0;
+padding-left: 20px;
+}
+h1 a { text-decoration: none; color: #F9F7ED; }
+h1 a:hover { border-bottom: 1px solid #F9F7ED; color: #F9F7ED; }
+
+#wrap {
+width: 940px;
+margin: 20px auto;
+background: #fff;
+padding: 20px;
+}
+
+#header {
+background: #2C2D2F;
+height: 100px;
+line-height: 100px;
+}
+
+#menu {
+background: #356AA0;
+height: 30px;
+line-height: 30px;
+}
+
+#menu ul {
+list-style-type: none;
+margin: 0;
+padding-left: 0px;
+}
+#menu ul li {
+display: block;
+float: left;
+}
+#menu ul li a {
+display: block;
+padding: 0 10px 0 10px;
+text-decoration: none;
+color: #fff;
+font-size: 13px;
+font-weight: 600;
+}
+#menu ul li a:hover {
+color: #fff;
+background: #CF4D4F;
+}
+
+#content {
+float: right;
+/* width: 620px; */
+width: 640px;
+background: #F9F7ED;
+margin-top: 20px;
+}
+#content h2 {
+margin: 0;
+color: #F9F7ED;
+height: 30px;
+line-height: 30px;
+background: #2C2D2F;
+padding: 0 0 0 10px;
+font-size: 16px;
+}
+
+#content p { padding: 0 10px 10px 10px; color: #232323;}
+#content ul { padding: 0 20px 10px 30px; }
+
+#sidebar {
+float: left;
+margin-top: 20px;
+/* width: 300px; */
+width: 280px;
+background: #eee;
+border-bottom: 5px solid #36393D;
+}
+
+#sidebar h3 {
+background: #2C2D2F;
+height: 30px;
+line-height: 30px;
+font-weight: 600;
+font-size: 14px;
+margin: 0; padding: 0 0 0 10px;
+color: #F9F7ED;
+}
+
+#sidebar p { padding: 0 10px 10px 10px; color: #232323; }
+
+#sidebar ul {
+padding: 10px 0 20px 30px;
+margin: 0;
+}
+
+#sidebar ul li {
+padding: 0;
+margin: 0;
+}
+
+#sidebar ul ul { padding: 2px 0 2px 20px; }
+
+#columns p { padding: 0 10px 10px 10px; color: #232323; }
+
+#columns h3 {
+background: #2C2D2F;
+height: 30px;
+line-height: 30px;
+font-weight: 600;
+font-size: 14px;
+margin: 0 0 0 0; padding: 0 0 0 10px;
+color: #F9F7ED;
+}
+
+#columns ul {
+padding: 15px 0 20px 30px;
+margin: 0;
+}
+
+#columns ul li {
+padding: 0;
+margin: 0;
+}
+
+#column1 {
+float: left;
+width: 300px;
+background: #FFFF88;
+margin-top: 20px;
+}
+#column2 {
+float: left;
+margin-left: 20px;
+width: 300px;
+background: #CDEB8B;
+margin-top: 20px;
+}
+#column3 {
+float: left;
+margin-left: 20px;
+width: 300px;
+background: #C3D9FF;
+margin-top: 20px;
+}
+
+#footer {
+background: #2C2D2F;
+padding: 10px 0;
+text-align: center;
+color: #fff;
+margin-top: 20px;
+}
+#footer p { padding: 0; margin: 0; }
+#footer a { color: #fff; }
+#footer a:hover { text-decoration: underline; }
--- /dev/null
+@font-face {
+ font-family: "SW";
+ src: url('http://www.wenzi.cn/shuzi/shuowen/download/SW.ttf') format("truetype");
+ /* src: url('./SW.ttf') format("truetype"); */
+}
+
+.s { font-family: SW, 'MS 明朝', serif; font-size: 300%; }
+.swlist { font-family: SW, 'MS 明朝', serif; font-size: 150%; }
+
+
+/* SBGY */
+.original { text-decoration: line-through; }
+.rewrite { background-color: plum; }
+.added { background-color: plum; }
+
+/* Shuowen */
+.explanation { font-size: 150%; }
+.duan_note { }
\ No newline at end of file