送受信_環境変数 ENV - 演習編

Problem2: カウンタ画像の桁数を URL からコントロールしてみよう

アクセス回数を、数字画像を連結された一つの画像として表示させる CGI は作成しました。数字画像を、アドレスに付加した情報からコントロールできるようにしてみてください。

例:6桁表示  http://〜略〜/count.cgi?6 12

できれば、枠もつけてみてください

例:枠幅5,桁数6  http://〜略〜/count.cgi?waku=5;kata=6 ○

⇒ ヒント

Hint

  1. 前章の「画像連結式カウンター」をわずかに書き換えるだけです
  2. クエリー(=アドレスの後ろに付加した「?」以降の部分)を取り出すには、ENV['QUERY_STRING']
  3. とくに、クエリーが無い場合は、3桁になるようにしておいてください
  4. "%03d" % count の部分の 3 を 6 に書き換えると6桁になります
  5. ダブルクオート"で挟まれた部分には、#{ }を使って代入ができます
    keta = 6
    "%0#{keta}d"
    は、"%06d"と、同じです

枠もつける場合

  1. 枠をつけるコマンド:count.gif に枠をつけて、count2.gif とする場合、
    convert -frame 64x32+8+4 -mattecolor teal count.gif count2.gif
    • の指定:(左右横幅)x(上下縦幅)+(外側稜線幅)+(内側稜線幅)
    • の指定:色の名前、又は、#16進数表記rgb(#aaf で藤色)
    • …こんなに太い枠をつけなくても良いですが…
    border_example
  2. 複雑なクエリーは、正規表現でパターンマッチを見た方が良いかもしれません
    str = "keta=5;waku=6"
    if /\bketa=(\d+)\b/ =~ str then
      puts $1
    end
    • if /正規表現/オプション =~ 文字列 then 動作 endという形でよく使います
    • 文字列の中に正規表現にマッチする部分が含まれていなければ、=~ の結果は true にならないので、動作しません
    • 正規表現の中で、括弧 ( ) で括った部分は、動作の中で前括弧( の順に、$1, $2, ... という変数名で取り出すことができます
    • \bは単語境界、\dは任意の数字一文字、\d+は一文字以上からなる任意の数字を表します
    • str の部分が文字列ではない(例えば、nil)と、例外が発生(=エラー)するので、=~ str.to_s の様にムリ繰り文字列に直した方が安全です
    • 正規表現
    ちなみに、よくやられている方法は、「;」又は「&」で切り分けて、ハッシュにまとめます
    str = "keta=5;waku=6"
    h = Hash.new
    for q in str.split(/[;&]/) do
      key,value = q.split(/=/,2)
      h[key] = value
    end
    • 一般的ですが、今回の目的には効率が悪い

⇒ 答え

Solution

画像連結式カウンターのプログラムを下記の様の書き直すだけで完成

#!/usr/local/bin/ruby
keta = 3
qs   = ENV['QUERY_STRING'].to_i
keta = qs if qs > 0
CounterIMG = "count.gif"
CountLOG   = "count.txt"
Fonts = Dir.glob("font/*.*").sort
count = File.open(CountLOG){|f| f.read.to_i } rescue 0
count += 1
a = ["convert","+append"]
for n in ("%0#{ keta }d" % count).split(//) do
  a += [ Fonts[n.to_i] ]
end
a += [CounterIMG]
system(*a)
Process.waitall
File.open(CountLOG,"w"){|f| f.print count }
print <<EOS
Content-Disposition: filename="#{ ("%0#{ keta }d" % count) }.gif"
Content-type:   image/gif
Content-Length: #{ File.size( CounterIMG ) }

EOS
f = File.open( CounterIMG ,"rb")
STDOUT.binmode
while line = f.gets do
  print line
end
f.close

さらに枠もつけてみると、(http://〜略〜/count.cgi?waku=5;keta=6 のように枠の太さと桁数を入力)

#!/usr/local/bin/ruby
keta = 3
if /\bketa=(\d+)\b/ =~ ENV['QUERY_STRING'].to_s then
  k = $1.to_i
  keta = k if k > 0
end

waku = 0
if /\bwaku=(\d+)\b/ =~ ENV['QUERY_STRING'].to_s then
  k = $1.to_i
  waku = k if k > 0
  futi = [(waku+1)/3,5].min
end

CounterIMG = "count.gif"
CountLOG   = "count.txt"
Fonts = Dir.glob("font/*.*").sort
count = File.open(CountLOG){|f| f.read.to_i } rescue 0
count += 1
a = ["convert","+append"]
for n in ("%0#{ keta }d" % count).split(//) do
  a += [ Fonts[n.to_i] ]
end
a += [CounterIMG]
system(*a)
Process.waitall
`convert -frame #{ waku }x#{ waku }+#{ futi }+#{ futi } \
-mattecolor #aaf #{ CounterIMG } #{ CounterIMG }` if waku > 0
Process.waitall


File.open(CountLOG,"w"){|f| f.print count }
print <<EOS
Content-Disposition: filename="#{ ("%0#{ keta }d" % count) }.gif"
Content-type:   image/gif
Content-Length: #{ File.size( CounterIMG ) }

EOS
f = File.open( CounterIMG ,"rb")
STDOUT.binmode
while line = f.gets do
  print line
end
f.close

さらに枠の色も指定できるようにします。枠の幅/色 という形として、(http://〜略〜/count.cgi?waku=5/f80;keta=6

#!/usr/local/bin/ruby
keta = 3
if /\bketa=(\d+)\b/ =~ ENV['QUERY_STRING'].to_s then
  k = $1.to_i
  keta = k if k > 0
end

waku = 0
if /\bwaku=(\d+)\b/ =~ ENV['QUERY_STRING'].to_s then
  k = $1.to_i
  waku = k if k > 0
  futi = [(waku+1)/3,5].min
end

mattecolor = "#aaf"
if /\bwaku=\d+\/([0-9a-f]{3,9})\b/ =~ ENV['QUERY_STRING'].to_s then
  mattecolor = "#" + $1
elsif /\bwaku=\d+\/([A-Za-z]+)\b/  =~ ENV['QUERY_STRING'].to_s then
  mattecolor = $1
end

CounterIMG = "count.gif"
CountLOG   = "count.txt"
Fonts = Dir.glob("font/*.*").sort
count = File.open(CountLOG){|f| f.read.to_i } rescue 0
count += 1
a = ["convert","+append"]
for n in ("%0#{ keta }d" % count).split(//) do
  a += [ Fonts[n.to_i] ]
end
a += [CounterIMG]
system(*a)
Process.waitall
`convert -frame #{ waku }x#{ waku }+#{ futi }+#{ futi } \
-mattecolor #{ mattecolor } #{ CounterIMG } #{ CounterIMG }` if waku > 0
Process.waitall


File.open(CountLOG,"w"){|f| f.print count }
print <<EOS
Content-Disposition: filename="#{ ("%0#{ keta }d" % count) }.gif"
Content-type:   image/gif
Content-Length: #{ File.size( CounterIMG ) }

EOS
f = File.open( CounterIMG ,"rb")
STDOUT.binmode
while line = f.gets do
  print line
end
f.close

⇒ 次の問題に進む

以上です。

Last updated 15.Sep.2006 [ Home ] [ Up ] [ 質問メール ]
Copyright © 2005-2006 Shigeru Konno All Rights Reserved..