#!/usr/bin/env ruby
# -*- coding: euc-jp -*-
#
#== TITLE
TITLE = "写真用 HTML 作成スクリプト"

#== MAINTAINERS
MAINTAINERS="Yasuhiro MORIKAWA"

#== VERSION
PACKAGE_NAME="dcreal"
URL='http://www.gfd-dennou.org/library/cc-env/dcreal'

CVSTAGNAME='$Name: dcreal-0_3_5-4 $'
CVSDATE='$Date: 2012-11-21 06:23:57 $'
CVSREVISION='$Revision: 1.4 $'

#== USAGE
USAGE = "
      dcreal-photo.rb

      まず, src というディレクトリを作成し, そのディレクトリに移動しま
      す. そこでプログラムを実行すると, dcreal-photo-make.rb という設
      定ファイルが作成されます. この設定ファイルを編集後, src/img-web/
      にデジカメで撮った画像 (JPG 形式のみ) を置き,

          ruby dcreal-photo-make.rb

      を実行すると, ../pub 以下に HTML ファイルが作成されます.
"

#== Acknowledgements
ACKNOWLEDGEMENTS = "
      本プログラムは, Chihiro MITSUDA 氏作成の
      dcphoto.pl <http://www.ep.sci.hokudai.ac.jp/~chihiro/computer/program/dcphoto/>
      および, このプログラムを ruby で写経した Yukiko YAMADA 氏作成の
      dcphoto-y.rb <非公開> を参照して作成されました.
"
#== Bugs
BUGS= "

      * $infofile の行数が ${file_num}*2 より小さいと動きません
"

#==COPYRIGHT 
#
COPYRIGHT =
  "Copyright (C) 2007 GFD Dennou Club"

#== History
#
#These entries is generated by CVS automatically.
#So don't add new information manually.
#(But please adjust old log format to latest log format manually,
#if format gap between them causes).
#
#$Log: dcreal-photo.rb,v $
#Revision 1.4  2012-11-21 06:23:57  murashin
#Ruby 1.9対応のためのマジックコメントの付加
#
#Revision 1.3  2007-02-24 02:41:32  morikawa
#* コメントに ":" がある場合に正常動作しないバグを修正.
#* HTML 内の < や > を &lt;, &gt; に変更.
#* 画像とコメントの間に挿入される改行の数を変更.
#
#Revision 1.2  2006/04/03 17:04:52  morikawa
#* jhead のみ動作させる -j, --jhead オプションを追加.
#
#Revision 1.1  2006/03/30 09:32:53  morikawa
#* セミナーの様子を収めた写真画像をサムネイル HTML 化するための Ruby
#  スクリプト.
#* dcphoto.pl (光田千紘氏作成) → dcphoto-y.rb (山田由貴子氏作成) を
#  取り込み, 少し修正を加えた.
#
#
#

############################################################
## config part

IMGDIR = "./img-web"
PUBDIR = "../pub"

## config part end
############################################################


# ---------------------------------------------------------
# required libraries
require 'date'
require 'optparse'
require 'etc'
require 'kconv'
require 'pathname'
$KCODE = "e"

# ---------------------------------------------------------
# バージョンナンバー整形
UPDATE=CVSDATE.sub(/\s*\$\w+: /, '').sub(/\s*\$$/, '')
FILE_VERSION=CVSREVISION.sub(/\s*\$\w+: /, '').sub(/\s*\$$/, '')
pver_tmp=CVSTAGNAME.sub(/\s*\$\w+: /, '').sub(/\s*\$$/, '').sub(/#{PACKAGE_NAME}\-/, '').gsub(/_/, '.').chomp.strip
PACKAGE_VERSION = pver_tmp == "" ? '(Latest CVS version)' : pver_tmp

# ---------------------------------------------------------
# options are parsed
opt = OptionParser.new
OPTS = {}
ARGV.options{|opt|

  opt.summary_width = 23
  opt.summary_indent = ' '*6

  opt.on_tail('-j', '--jhead', 
                              "#{IMGDIR} 以下の JPG ファイルの
                              リネームのみ行います.\n"
              ){|v| OPTS[:jhead] = v}

  opt.on_tail('-h', '--help', 
                             "ヘルプを出力します.\n"
              ){|v| OPTS[:help] = v}

  opt.on_tail('-H', '--help-detail',
                             "このプログラムに関する詳細情報を出力します.\n"
              ){|v| OPTS[:help_detail] = v}

  opt.parse!
}
n = nil

# ---------------------------------------------------------
# help
def help(opt)
  print <<-"EOF"

  #{File.basename($0.to_s)}: #{PACKAGE_NAME} #{PACKAGE_VERSION}
    <URL: #{URL}>
    Copyright: #{COPYRIGHT}

    TITLE: #{TITLE}

    USAGE: #{USAGE}

    OPTION: \n#{opt.to_a[1..-1].join("")}
    VERSION: 
      Version: #{FILE_VERSION}, Last Update: #{UPDATE}

EOF
end
private :help

def help_detail(opt)
  help(opt)
  print <<-"EOF"

    MAINTAINERS: #{MAINTAINERS}

    ACKNOWLEDGEMENTS: #{ACKNOWLEDGEMENTS}

    BUGS: #{BUGS}

EOF
end
private :help_detail

if OPTS[:help] then
  help(opt)
  exit
end

if OPTS[:help_detail] then
  help_detail(opt)
  exit
end


# 画像名変換
#
# jhead を用いて画像変換を行う.
def rename_images
  jhead_cmd = "jhead"
  jhead_cmd_check = "which #{jhead_cmd}"
  if !IO.popen(jhead_cmd_check).gets
    errmsg = <<-ERR


  Error : \"#{jhead_cmd}\": command not found.
          Please install \"jhead\".


ERR
    raise ArgumentError, errmsg
  end

  Dir.foreach(IMGDIR) { |file|
    next if file.to_s == ".." || file.to_s == "."
    next unless file.to_s =~ /\.jpe?g$/i
    next if file.to_s =~ /^\d{4}\-\d{2}\-\d{2}\-\d{6}\.jpg$/
    system("#{jhead_cmd} -nf%Y-%m-%d-%H%M%S #{IMGDIR}/#{file}")
  }
end
private :rename_images


if OPTS[:jhead] then
  rename_images
  exit
end

# ---------------------------------------------------------
# main()

def dcreal_photo_main
  print "#{relative_str(__FILE__, $0.to_s)} is required.\n"
  rename_images; print "rename images in #{IMGDIR} end\n"
  mkinfo       ; print "mkinfo end\n"
  makethum     ; print "mkthum end\n"
  mkminipic    ; print "makeminipic end\n"
  makehtml     ; print "makehtml end\n"
end


# ---------------------------------------------------------
# 以下サブルーチン群. 非公開属性を付加
private

# -------------------------
# 画像情報取得 (jpg ファイル名, 枚数, コメントファイル)

def mkinfo

  # img-web から画像ファイル名一覧をとりだし, 配列 imgfiles へ代入
  $imgfiles = []
  Dir.foreach(IMGDIR) { |item|
    $imgfiles.push(File.basename(item, ".jpg")) if item =~ /jpg$|JPG$/
  }

  # 画像ファイル数
  $file_num = $imgfiles.size

  $imgfiles = $imgfiles.sort

  # $infofile がなければ作成
  unless File.exist?($infofile) then
    ifile = open($infofile, "w")
    1.upto($file_num) { |num|
      ifile.print "%03d:\n" % num
#      ifile.print "#{$imgfiles[num]}:\n" % num
    }
    ifile.close
  end

  # $infofile からファイル名とコメントを取り出す
  # $info[true][0] にはファイル名, $info[0][true] にはコメントが入る
  $info = [] 
  ifile = open($infofile, "r")
  ifile.each { |line|
    $info.push(line.chomp.split(/:/, 2))
  }
  ifile.close

  # $infofile からファイル数を再定義
  $file_num = $info.size


end

# -------------------------
# 画像の大きさを変更し, PUBDIR へ格納する.

def mkminipic

  # ディレクトリの作成
  Dir.mkdir("#{PUBDIR}",0775) unless File.exist?("#{PUBDIR}") 
  Dir.mkdir("#{PUBDIR}/large",0775) unless File.exist?("#{PUBDIR}/large") 
  Dir.mkdir("#{PUBDIR}/small",0775) unless File.exist?("#{PUBDIR}/small") 

  # 画像の大きさ変更
  $file_num.times{ |num|
    picname = $info[num][0]
    print "  #{picname}.jpg is created.\n" unless File.exist?("#{PUBDIR}/large/#{picname}.jpg")
    `convert -geometry 640x480 #{IMGDIR}/#{$imgfiles[num]}.jpg  #{PUBDIR}/large/#{picname}.jpg` unless File.exist?("#{PUBDIR}/large/#{picname}.jpg") 
    `convert -geometry 240x180 #{IMGDIR}/#{$imgfiles[num]}.jpg #{PUBDIR}/small/#{picname}.jpg` unless File.exist?("#{PUBDIR}/small/#{picname}.jpg") 
#    `convert -geometry 100x75 #{IMGDIR}/#{$imgfiles[num]}.jpg #{PUBDIR}/small/#{picname}.jpg` unless File.exist?("#{PUBDIR}/small/#{picname}.jpg") 
  }
end


# -------------------------
# サムネイル $index の作成

def makethum

  # ディレクトリ作成, ファイル削除
  if File.exist?("#{PUBDIR}") then
    Dir.foreach("#{PUBDIR}") { |item|
      File.delete("#{PUBDIR}/" + item  ) if item =~ /.html$/
    }
  elsif
    Dir.mkdir("#{PUBDIR}",0775) 
  end
  
  # $index ページ数の計算
  if ($file_num % 18 ) == 0 then
    $thum_max =  $file_num /18 
  else
    $thum_max = ($file_num / 18) + 1
  end

  # $index ファイルナンバー初期化
  $thum_num = 1

  $file_num.times { |num|
    if (num % 18) == 0 then
      # 初期化
      $htmls = ""
      # ヘッダ部
      $htmls = htmlhead
      # 本文表題部
      $htmls << htmltitle
      # $index ページリンク
      unless ($file_num / 18) == 0 then 
	$htmls << htmlpage($thum_num) unless $file_num  == 18 
      end
    end

    # サムネイル部分作成 
    $htmls << htmlthum(num)

    if (num % 18) == 17 then
      # $index ページリンク
      unless $file_num  == 18 then
	$htmls << htmlpage($thum_num)
      end
      # フッタ処理
      $htmls << htmlfoot
      # ファイルの書きだし
      ifile = open("#{PUBDIR}/" + $index + $thum_num.to_s + ".html", "w")
      ifile.print $htmls
      ifile.close
      $thum_num += 1
    end
  }

  unless ($file_num % 18 ) == 0 then
    # table 末処理
    amari = ($file_num - 1 ) % 3
    amari.upto(1) { |num|
      $htmls << <<HTMLEOF
       <td align="center" width="20%" valign="top">
        &nbsp;
       </td>
HTMLEOF
    }
    $htmls << %|      </tr>\n| unless amari == 2

    # $index ページリンク
      unless ($file_num / 18) == 0 then 
	$htmls << htmlpage($thum_num)
      end
    # フッタ処理
    $htmls << htmlfoot

    # ファイルの書きだし
    ifile = open("#{PUBDIR}/" + $index + $thum_num.to_s + ".html", "w")
    ifile.print $htmls
    ifile.close
  end 

  # ファイル名変更 ${index} + "0.html" => ${index}".html"
  File.rename("#{PUBDIR}/" + $index + "1.html","#{PUBDIR}/" + $index + ".html" )

end


# -------------------------
# 各 HTML ファイル作成サブルーチン
def makehtml

  # ディレクトリ作成, ファイル削除
  if File.exist?("#{PUBDIR}/html") then
    Dir.foreach("#{PUBDIR}/html") { |item|
      File.delete("#{PUBDIR}/html/" + item  ) if item =~ /html$/
    }
  elsif
    Dir.mkdir("#{PUBDIR}/html",0775) 
  end

  # ファイル作成
  $file_num.times { |num|
    htmldetail(num)
  }
end

def htmldetail(num)

  prepic    = $info[num-1][0]  unless num == 0 
  picname   = $info[num][0]
  nextpic   = $info[num+1][0]  unless num == ( $file_num - 1 )
  comment   = $info[num][1] || ""
  
  # 標準出力 
  print "  #{num+1}: comment = #{comment}\n"

  htmls = ""
  htmls = htmlhead
  htmls << <<HTMLEOF
<body>
<center>
<table><tr><td align="center">
HTMLEOF

  # 画像貼りつけ部分, フッタの作成
  htmls << <<HTMLEOF
<img src="../large/#{picname}.jpg" >
<br>
#{comment}<br>
[ #{phototime(picname)}  ]
<br>&nbsp;
</td></tr></table>
HTMLEOF

  # 前後のページへのリンク, 現ページ/ページ総数, 小題の書き出し
  htmls << <<HTMLEOF
<table width="80%">
  <tr>
  <td bgcolor="#{$color_table}" align="center">
HTMLEOF

  # 最初のページと最後ページの場合はリンクを貼れないので
  # 条件分岐する.
  
  # 最初のページは [前頁] にリンクを貼らない
  if num == 0 then 
    htmls << %|      [ PRE ] &nbsp;&nbsp; |
  else
    htmls << %|      [ <A HREF="./#{prepic}.html">PRE</A> ] &nbsp;&nbsp;|
  end
  
  # リンクをはるべき $index の場所を計算
  if (num / 18) == 0 then 
    htmls << %|      [ <A HREF="../#{$index}.html">index</A> ] &nbsp;&nbsp;|
  else
    htmls << <<HTMLEOF 
     [ <A HREF="../#{$index}#{(num/18)+1}.html">index</A> ] &nbsp;&nbsp; 
HTMLEOF
  end

  # 最後のページは [後頁] にリンクを貼らない
  if num ==  ( $file_num - 1 ) then 
    htmls << %|      [ NEXT ]|
  else
    htmls << %|      [ <A HREF="./#{nextpic}.html"> NEXT </A>]|
  end

  # フッタ
  htmls << <<HTMLEOF
    </td>
  </tr>
</table>
</td></tr></table>
</center>
</body>
</html>
HTMLEOF

  # ファイルの書きだし
  ifile = open("#{PUBDIR}/html/" + picname + ".html", "w")
  ifile.print htmls
  ifile.close
end



#-------------------------------------------------------------
# サムネイル $index 用サブルーチン

# html ヘッダ部
def htmlhead
   htmls = <<HTMLEOF
<html lang="ja">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=x-euc-jp">
  <meta name="Author" content="#{username_from_gid}">
  <meta name="robots" content="noindex,nofollow">
  <meta name="robots" content="noarchive">
  <meta name="generator" content="#{File.basename(__FILE__)} ver #{FILE_VERSION} in #{PACKAGE_NAME} #{PACKAGE_VERSION} released in #{URL}">
  <title>#{$title}</title>
  <style type="text/css">
  <!--
    BODY { font-style:osaka;color:#{$color_font};}
    a:link { color:#{$color_link}; }
    a:visited { color:#{$color_visited}; }
    A{text-decoration:none; font-weight:bold; }
    A:hover {color:#{$color_hover}}
  -->
  </STYLE>
</head>
HTMLEOF
return htmls
end

# html thumnail 繰り返し部
def htmlthum(num)
  picname = $info[num][0]
  amari   = num % 3
  comment = $info[num][1]

  # テーブルの配置によって <tr> のつけたしをおこなう.
  # 左端 : 3n+1   ($amari == 0)
  # 右端 : 3n     ($amari == 2)

  htmls = ""
  htmls = %|      <tr align="center" VALIGN="bottom">\n| if amari == 0
  htmls << <<HTMLEOF    
       <td align="center" width="20%" valign="top">
         <A HREF="./html/#{picname}.html">
         <img src="./small/#{picname}.jpg" border="0">
        </A>
        <br>
        <small>
         #{comment}
        </small>
       </td>
HTMLEOF

  htmls << %|      </tr>\n| if amari == 2
  return htmls
end

# フッター
def htmlfoot
  htmls = <<HTMLEOF    
<tr><td colspan="3" bgcolor="#{$color_table}" align="center">
<B><small>#{$footer}</small></B>
</td></tr>

</table>

 </center>
 </body>
</html>
HTMLEOF
  return htmls
end

# 本文表題部
def htmltitle
  htmls = <<HTMLEOF
 <body>
  <center>
<table BORDER="0" cellspacing="10" width="80%" align="center">
<tr><td colspan="3" bgcolor="#{$color_table}" align="center">
&nbsp;
<br>
<B><big>&lt;&lt; #{$header1} &gt;&gt;</B></big><br>
<small>#{$header2}</small>
<br>&nbsp;
</td></tr>
HTMLEOF
return htmls
end

# サムネイルへのリンク
def htmlpage(num)
  htmls = <<HTMLEOF
<tr><td colspan="3" align="center"><small>
HTMLEOF
  1.upto($thum_max){ |numnum|
  # 自分にはリンクを貼らない
  if numnum == num then 
    htmls << %| &nbsp; [ PAGE#{numnum} ] |
  else
    if numnum == 1 then 
      htmls << <<HTMLEOF
&nbsp; [ <A HREF="./#{$index}.html">PAGE#{numnum}</A> ] 
HTMLEOF
    else
      htmls << <<HTMLEOF
&nbsp; [ <A HREF="./#{$index}#{numnum}.html">PAGE#{numnum}</A> ] 
HTMLEOF
    end
  end
  }
  htmls << %| &nbsp; </small></td></tr>\n|
return htmls
end

# 画像の時刻の取得
def phototime(picname)
  test = `jhead #{PUBDIR}/large/#{picname}.jpg`
  hoge = ""
  test.split(/\n/).size.times { |num|
    hoge = test.split(/\n/)[num]  if test.split(/\n/)[num] =~ /Date/
  }
  return hoge.split(/    : /)[1]
end

#
# 引数 uid に対応するユーザ名 (ログイン名) を返す。
# uid に nil を与えた場合はプロセスの uid に対応するユーザ名 (ログイン名)
# を返す。uid が無効なものである場合、エラーを返す。
#
def username_from_uid(uid=nil)
  unless uid
    pw = Etc.getpwuid(Process.uid) or return nil
  else
    pw = Etc.getpwuid(uid) or return nil
  end
  
  user_name = pw.name
  return user_name
end

#
# 引数 gid に対応するユーザ名 (ログイン名) を返す。
# gid に nil を与えた場合はプロセスの gid に対応するユーザ名 (ログイン名)
# を返す。gid が無効なものである場合、エラーを返す。
#
def username_from_gid(gid=nil)
  unless gid
    pw = Etc.getpwuid(Process.gid) or return nil
  else
    pw = Etc.getpwuid(gid) or return nil
  end
  
  user_name = pw.name
  return user_name
end

#
# target で与えられたパス (String オブジェクト) を from (String 
# オブジェクト) から見た相対パスとして String オブジェクトで返す。
# 内部で Pathname クラスを利用している。
# 与えられるパスは絶対パスでも相対パスでもかまわない。
#
def relative_str(target=nil, from=nil)
  return nil    unless str_and_notspace?(target)
  return target unless str_and_notspace?(from)
  
  from_dir     = File.dirname(from)
  target_dir   = File.dirname(target)
  target_base  = File.basename(target)
  
  from_ab_path   = Pathname.new(File.expand_path(from_dir))
  target_ab_path = Pathname.new(File.expand_path(target_dir))
  
  target_re_path = target_ab_path.relative_path_from(from_ab_path)
  
  result = target_re_path.to_s + "/" + target_base
  
  return result
end

#
# 代入された変数が、文字列で、且つ空白文字のみではないことを
# 調べるメソッド。日本語であっても、文字列が入っていれば true を返す。
#
def str_and_notspace?(obj)
  
  if !obj.instance_of?(String) then
    return false
  end
  
  # 日本語の文字列も対応できるように
  Kconv::toeuc(obj)
  
  if /\S+/e =~ obj.chomp.strip then
    return true
  else
    return false
  end
end



######################################################
if $0 == __FILE__

dcreal_photo = <<EOF
#!/usr/bin/env ruby
# -*- coding: euc-jp -*-
#= dcreal-photo configure file
#
#  Editor :: #{username_from_uid}
#  Created:: #{Time.now.strftime("%Y/%m/%d %H:%M:%S")}
#
#== Overview
#
#This file is generate by following ruby script automatically.
#
#      #{File.expand_path($0.to_s)}
#      version "#{FILE_VERSION}"
#
#Please edit this file according to your purpose.
#
########################################################
##  デフォルト設定値, ユーザ設定
########################################################

# 情報ファイル
$infofile = "comment.txt"

# インデックスファイル (拡張子は $index + ".html")
$index = "index"

# テーブル, フォントの色
$color_table   = "#ADD8E6" 
$color_font    = "#000080" 
$color_link    = "#269900" 
$color_visited = "#269900" 
$color_hover   = "#99FF33" 

# html ヘッダタイトル
$title  = "GFD Seminar #{Time.now.strftime("%Y")}"
\#$title  = "FDEPS #{Time.now.strftime("%Y")}"
\#$title  = "森羅万象学校 #{Time.now.strftime("%Y")}"

# サムネイルタイトル
$header1 = $title
$header2 = "#{Time.now.strftime("%Y/%m/%d")}--?? at Hokkaido Univ.";

# サムネイルフッタ ;
$footer = "Last update: \#\{Time.now\} <br> 
           #{COPYRIGHT}"

# ---------------------------------------------------------
# カレントディレクトリを変数にわたす.
require "#{File.expand_path($0.to_s)}"

# ---------------------------------------------------------
# main()

dcreal_photo_main

EOF

sample_file = "./dcreal-photo-make.rb"
existing_file = File.exist?(sample_file)
wfile = open(sample_file,"w")
wfile.print dcreal_photo
wfile.close

if existing_file
  print "\n  *** MESSAGE *** #{sample_file} is overwritten.\n"
else
  print "\n  *** MESSAGE *** #{sample_file} is created.\n"
end

print <<-"EOF"

  *** GUIDANCE *** 
  Please edit "#{sample_file}", and locate JPG files in "#{IMGDIR}".
  Then do 

    ruby #{sample_file}

  In the result, HTML files are generated in "#{PUBDIR}"

  If you want to know more information, add "-h" option.

EOF

end
