| 1 | # ktai_db.rb - ktai database |
|---|
| 2 | # |
|---|
| 3 | # Author:: MIZOGUCHI Coji <mizoguchi.coji at gmail.com> |
|---|
| 4 | # License:: Distribute under the same terms as Ruby |
|---|
| 5 | # |
|---|
| 6 | # $Id$ |
|---|
| 7 | # |
|---|
| 8 | require 'csv' |
|---|
| 9 | require 'nkf' |
|---|
| 10 | |
|---|
| 11 | module SSB |
|---|
| 12 | class KtaiDB |
|---|
| 13 | COLUMN_MAP = { |
|---|
| 14 | '連番' => :id, |
|---|
| 15 | 'メーカ名' => :carrier, |
|---|
| 16 | '機種名' => :name, |
|---|
| 17 | '機種略名' => :name_abbr, |
|---|
| 18 | 'ユーザエージェント' => :useragent, |
|---|
| 19 | 'タイプ1' => :generation, |
|---|
| 20 | 'タイプ2' => :generation_ver, |
|---|
| 21 | 'ブラウザ幅(x)' => :screen_width, |
|---|
| 22 | 'ブラウザ高さ(y)' => :screen_height, |
|---|
| 23 | '表示カラー数' => :colors, |
|---|
| 24 | 'ブラウザキャッシュ' => :cache_size, |
|---|
| 25 | 'GIF' => :gif, |
|---|
| 26 | 'JPG' => :jpg, |
|---|
| 27 | 'PNG' => :png, |
|---|
| 28 | 'FLASH' => :flash, |
|---|
| 29 | 'FLASHバージョン' => :flash_ver, |
|---|
| 30 | 'FLASHワークメモリ' => :flash_work_memory, |
|---|
| 31 | 'Javaアプリ' => :java, |
|---|
| 32 | 'BREW' => :brew, |
|---|
| 33 | 'HTML' => :html, |
|---|
| 34 | 'SSL' => :ssl, |
|---|
| 35 | 'ログイン' => :login, |
|---|
| 36 | 'クッキー' => :cookie, |
|---|
| 37 | '備考' => :note, |
|---|
| 38 | '更新日' => :lastupdate, |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | def initialize(do_load = false, filename = nil) |
|---|
| 42 | @cols = Array.new |
|---|
| 43 | @list = Array.new |
|---|
| 44 | |
|---|
| 45 | if filename.nil? |
|---|
| 46 | filename = File.join(SSB::CONFIG[:config_dir], 'ke-tai_list.csv') |
|---|
| 47 | end |
|---|
| 48 | |
|---|
| 49 | if do_load |
|---|
| 50 | load_from_csv(filename) |
|---|
| 51 | end |
|---|
| 52 | end |
|---|
| 53 | |
|---|
| 54 | def search(query) |
|---|
| 55 | real_search(@list, query) |
|---|
| 56 | end |
|---|
| 57 | |
|---|
| 58 | def self.load(force_load = false) |
|---|
| 59 | |
|---|
| 60 | end |
|---|
| 61 | |
|---|
| 62 | private |
|---|
| 63 | def load_from_csv(filename) |
|---|
| 64 | state = :start |
|---|
| 65 | CSV.open(filename, 'r') do |csv| |
|---|
| 66 | csv = csv.map{|e| NKF::nkf('-w', e)} |
|---|
| 67 | case state |
|---|
| 68 | when :start |
|---|
| 69 | state = :columns |
|---|
| 70 | when :columns |
|---|
| 71 | state = :body |
|---|
| 72 | @cols = csv.map{ |e| COLUMN_MAP[e] } |
|---|
| 73 | when :body |
|---|
| 74 | add_item combine(csv) |
|---|
| 75 | end |
|---|
| 76 | end |
|---|
| 77 | end |
|---|
| 78 | |
|---|
| 79 | def real_search(list, query) |
|---|
| 80 | cond = query.shift |
|---|
| 81 | # キャリア名の変動対応(ThirdForce等) |
|---|
| 82 | cond[1] = remap_carrier(cond[1]) if cond[0] == :carrier |
|---|
| 83 | |
|---|
| 84 | # 前方一致で探す |
|---|
| 85 | ret = list.select {|e| e[cond[0]] =~ Regexp.new("^#{cond[1]}.*", Regexp::IGNORECASE) } |
|---|
| 86 | if query.size == 0 |
|---|
| 87 | ret |
|---|
| 88 | else |
|---|
| 89 | real_search(ret, query) # 再帰 |
|---|
| 90 | end |
|---|
| 91 | end |
|---|
| 92 | |
|---|
| 93 | # 同一キャリアの別名を許容する |
|---|
| 94 | def remap_carrier(source) |
|---|
| 95 | remap_table = [ |
|---|
| 96 | 'DoCoMo', |
|---|
| 97 | 'au|KDDI|Tu-ka', |
|---|
| 98 | 'Vodafone|SoftBank|ThirdForce', # ディズニーとか... |
|---|
| 99 | ] |
|---|
| 100 | |
|---|
| 101 | for cond in remap_table do |
|---|
| 102 | if source =~ Regexp.new(cond, Regexp::IGNORECASE) |
|---|
| 103 | source = cond |
|---|
| 104 | break |
|---|
| 105 | end |
|---|
| 106 | end |
|---|
| 107 | source |
|---|
| 108 | end |
|---|
| 109 | |
|---|
| 110 | def add_item(ktai) |
|---|
| 111 | @list << ktai |
|---|
| 112 | end |
|---|
| 113 | |
|---|
| 114 | def combine(data) |
|---|
| 115 | t = Hash.new |
|---|
| 116 | @cols.size.times do |i| |
|---|
| 117 | t[@cols[i]] = data[i] |
|---|
| 118 | end |
|---|
| 119 | t |
|---|
| 120 | end |
|---|
| 121 | |
|---|
| 122 | def method_missing(msg, *arg) |
|---|
| 123 | @list.send(msg, *arg) |
|---|
| 124 | end |
|---|
| 125 | end |
|---|
| 126 | end |
|---|