#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require 'sqlite3'
require 'cgi'
require 'date'
require './sub.rb'
require 'net/http'

c = CGI.new(:tag_maker => "html5", :accept_charest => "UTF-8")
db = SQLite3::Database.new("sql/stamp.sq3")

id = c.cookies["id"][0].to_i
magic = c.cookies["magic"][0].to_i
err = 0                         # 不正な動きであれば負の値になる
sidesize = 3
message = "はりきって行きましょう!<br>"                    # ビンゴ用テキスト

print("Content-type: text/html; charset=UTF-8 \n\n")

### DROP TABLE ###

getcom = ARGV[0].to_s
drop = 'DROP TABLE main ;'
if getcom == 'ududlrllba'
  db.execute(drop)
end

######

### DELETE TABLE ###

del = 'DELETE FROM main WHERE id=?'
if getcom == 'ududlrlrba'
  db.execute(del, id)
end

######

##### CHECKING UID #####

sql = "SELECT stamp_status, stamp_img, name, job, sex, exp FROM main WHERE id=? AND magic=?"
begin
  user_data = db.execute(sql, id, magic)
rescue
  user_data = []
end

if user_data == []              # ログインエラー(-1)
  err -= 1
end

### LOGIN ERROR HTML ###

if err == -1
  print'
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="refresh" content="2.5;http://skip.koeki-prj.org/minato2014/account.html">
</head>
<title>たいとる</title>
<body>
'
print'
<p> ログインに失敗しました。 </p>
<p>
アカウント登録ページへ接続中…<br>
* 3秒経っても移動しない場合は<a href="account.html">こちら</a>から移動して下さい。
</p>
</body>
</html>
'
  exit
end

######

##########

##### RE-ARRAYING STAMP_STATUS AND STAMP_IMG #####

# stamp status
stamp_st = user_data[0][0]
stamp_st = stamp_st.split(//)   # 一文字ずつ分けて配列にする
stamp_st = stamp_st.map {|s| s.to_i} # 配列内の文字列を数列になおす

# stamp img
stamp_img = user_data[0][1]     
stamp_img = stamp_img.split(",") # 文字列を","で区切って配列にする

##########

##### STAMPPING #####

### Making randam number ###

def taiou(sidesize)
  srand(256788901)
  stamp = Hash.new("n")
  stamp_name = ["kamo", "kite", "mame", "mo2usa", "inuwasi", "hanabu", "be", "UMIMARU", "pero"]
  (sidesize**2).times do |n|
    stamp[rand(10000000)] = stamp_name[n]
  end
  stamp
end

######

##### Checking bingo method #####

def bingocheck(start, sidesize, stepon, stamp, decision, bingo)
  nbox = []
  setbox = Hash.new
  if sidesize == stepon
    x = sidesize
  else
    x = 1
  end
  x.times do |m|
    start.step(sidesize*sidesize - 1, stepon) do |n|
      nbox << n + m
      if nbox.length == sidesize
        dbox = Array.new(0)     # next bingo or reach numbers(bingoed -> nothing)
        for i in nbox
          if stamp[i] == 0
            dbox << i
          end
        end
        # sidesizeにdecisionの値を加えることで、ビンゴ、次ビンゴ、リーチをそれぞれdecisionに0,1,2を加えることで表現。
        if dbox.length == decision 
          setbox[dbox] = nbox
          bingo << setbox
          setbox = Hash.new
          nbox = []
        else
          nbox = []
        end
      end
    end
  end
end 
# bingo[{[ビンゴまたはリーチに必要な番号] => [ビンゴまたはリーチのラインを形成する番号]}]
##########

bingo =          # 現在のビンゴ数

### Checking Access Cord(AC) ###

getAC = ARGV[0].to_i            # URL?以降の引数を取得
rightAC = taiou(sidesize)       # taiouで生成したACのハッシュ
#p rightAC
rightAC = rightAC[getAC]        # ACが正しければスタンプ名が入り、異なる場合はn

##### ACCESS LOG #####
t = Time.now
time = (t.hour * 3600) + (t.min * 60) + t.sec

## Checking sql_master table. If sqlite_master don't have tablename, it create.

sql_master = "SELECT name FROM sqlite_master WHERE name='logs';"
check_master = db.execute(sql_master)
sql_logs = 'CREATE TABLE logs(
id INTEGER PRIMARY KEY AUTOINCREMENT,
uid INTEGER,
ac TEXT,
time INTEGER);
'
if check_master == []
  db.execute(sql_logs)
end

##########

begin
  get_log = 'SELECT ac, time FROM logs WHERE uid=(SELECT MAX(id) FROM logs WHERE uid=?);' # ユーザーの最新のログ情報を取得
  log_check = db.execute(get_log, id)
rescue
  print'GETTING LOG ERROR!'
end
begin
  log = 'INSERT INTO logs(uid, ac, time) VALUES(?, ?, ?)'
  db.execute(log, id, rightAC, time)
rescue
  print'INSERT LOG ERROR!'
end
# /* memo: 再度同じようなシステムを作る際はスタンプ用のテーブルがほしい。 */ #

##########

### ビンゴしたラインを判定(decision = 0) ###
bingo = []
# 横
bingocheck(0, sidesize, 1, stamp_st, 0, bingo)
# 縦
bingocheck(0, sidesize, sidesize, stamp_st, 0, bingo)
# 左斜め
bingocheck(0, sidesize, sidesize+1, stamp_st, 0, bingo)
# 右斜め
bingocheck(sidesize-1, sidesize, sidesize-1, stamp_st, 0, bingo)
#######

bingo = bingo.length            # ビンゴの数
last_bingo = bingo

if rightAC != "n"               # rightACが正しければ
  
  ### Update Stamp_status And Stamp_img ###
  
  # Replacing Image #
  
  index_st = []
  stamp_st.length.times { |c|
    if stamp_st[c] == 0
      index_st << c
    end
  }
  
  ### リーチ（decision = 1）# [{[ビンゴの番号] => [リーチを構成する数]}]
  reach = []
  # 横 
  bingocheck(0, sidesize, 1, stamp_st, 1, reach)
  # 縦
  bingocheck(0, sidesize, sidesize, stamp_st, 1, reach)
  # 左斜め
  bingocheck(0, sidesize, sidesize+1, stamp_st, 1, reach)
  # 右斜め
  bingocheck(sidesize-1, sidesize, sidesize-1, stamp_st, 1, reach)
  #######
  
  begin
    reach = reach[0].flatten(2)[0] # ビンゴの番号のみ抽出
  rescue
    reach = []
  end
  
    ### ビンゴしたラインを判定(decision = 0) ###
  bingo = []
  # 横
  bingocheck(0, sidesize, 1, stamp_st, 0, bingo)
  # 縦
  bingocheck(0, sidesize, sidesize, stamp_st, 0, bingo)
  # 左斜め
  bingocheck(0, sidesize, sidesize+1, stamp_st, 0, bingo)
  # 右斜め
  bingocheck(sidesize-1, sidesize, sidesize-1, stamp_st, 0, bingo)
  #######
  
  bingo = bingo.length            # ビンゴの数
  
  # Updating stamp_st #  
  if stamp_img.include?(rightAC) == true          # 既に同名のスタンプが入っていたら
    if stamp_st[stamp_img.index(rightAC)] < 9
      stamp_st[stamp_img.index(rightAC)] += 1       # 対応するスタンプの位置に1足す
      message = "スタンプカウントが「1」増えました!(スタンプカウントは「9」が上限です)"
    else
      message="スタンプカウントMAX!!(※これ以上このスタンプのカウントは増えません)"
    end
  else
    if reach != [] && bingo == 0       # はじめのビンゴは必ず3回で完成
      stamp_st[reach] += 1# ビンゴになる数字を代入
      stamp_img[reach] = rightAC
      message = "新しいスタンプをGETしました!" # Top message
    else
      randam_number = index_st[rand(index_st.length)] # スタンプの入っていない個所のなかからランダムにひとつ選ぶ
      stamp_st[randam_number] += 1                  # 選ばれた個所に1足す
      stamp_img[randam_number] = rightAC # stamp_stと同じ個所にstamp_imgにスタンプの名前を代入
      message = "新しいスタンプをGETしました!" # Top message
    end
  end
  ##

  ### ビンゴしたラインを判定(decision = 0) ###
  bingo = []
  # 横
  bingocheck(0, sidesize, 1, stamp_st, 0, bingo)
  # 縦
  bingocheck(0, sidesize, sidesize, stamp_st, 0, bingo)
  # 左斜め
  bingocheck(0, sidesize, sidesize+1, stamp_st, 0, bingo)
  # 右斜め
  bingocheck(sidesize-1, sidesize, sidesize-1, stamp_st, 0, bingo)
  #######
  
  bingo = bingo.length            # ビンゴの数
  
  
  ##
  
  # Convert to string # 
  
  stamp_st_string = stamp_st.join
  stamp_img_string = stamp_img.join(",")
  
  ##

  sql_update = "UPDATE main SET stamp_status=?, stamp_img=? WHERE id=?;"
  db.execute(sql_update, stamp_st_string, stamp_img_string, id)
end

######

##########

##### HTML #####
print'
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>たいとる</title>
<link rel="stylesheet" type="text/css" href="Bingo.css">
</head>
<body>
'
### TOP ###

sql_rank = 'select rank from main where id=?;'
rank = db.execute(sql_rank, id).flatten(2)[0].to_i

print'
<div class="outflam">
'
if rank > 0
  print'<div class="top" style="background: red;">'
else
  print'<div class="top">'
end
# - ビンゴステータス処理 - #

if rank > 0
  printf("<h1>おめでとうございます!!<br>☆ %d等 ☆が当選しました!!</h1>", rank)
  # print'<p>抽選は終了しましたが、引続きゆる☆スタをお楽しみ下さい!!</p>'
end 

# End of top 
print'
</div>
'
# Top message #

bc = bingo.to_i - last_bingo.to_i

if bc > 0
  message += '<br>おめでとう!' + bc.to_s
  message += 'ビンゴ揃いました!!<br>'
end

if rank > 0
  printf("<p style=\"background:red; color:white;\">%sおめでとうございます!☆ %d等 ☆が当選しました!!</p>", message, rank)
else
  printf("<p style=\"background:#136cf9;\">%s</p>", message)
end

##

######

### CENTER ###
print'
<div class="center">
<table border=1>
'
for i in 0..2
  print'<tr>'
  3.times do |n|
    if stamp_st[3*i+n].to_i > 0
      printf("<td width=170 height=170><img src=\"png/%s.png\" alt=\"stamped\" width=\"160\" height=\"160\"><span style=\"color: green; font-weight: 900;\">%d</span></td>\n", stamp_img[3*i+n], stamp_st[3*i+n])
    else
      print"<td width=170 height=170></td>\n" 
    end
  end
  print'<tr>'
end
# End of center 
print'
</table>
</div>
'
######

### BOTTOM ###
print'
<div class="bottom">
'
# - RPGの表示 - #

name = user_data[0][2]
job = user_data[0][3]
sex = user_data[0][4]
exp = user_data[0][5]

## GETTING EXP SUM ##

sum_sql = 'SELECT SUM(exp)  FROM main  WHERE rank=0;'
sumexp = db.execute(sum_sql).flatten(2)[0]

####

stamp = stamp_st.inject(:+)                 # 配列内の値を全て足す

charST = rpg(job, sex, stamp, bingo, sumexp)      # ユーザーのキャラクタステータス

## UPDATE EXP ##

update_exp = 'UPDATE main SET exp=? WHERE id=?;'
db.execute(update_exp, charST[2], id)

####

## GETTING EXP SUM ##

sum_sql = 'SELECT SUM(exp) FROM main WHERE rank=0;'
sumexp = db.execute(sum_sql).flatten(2)[0]

####

stamp = stamp_st.inject(:+)                 # 配列内の値を全て足す

charST = rpg(job, sex, stamp, bingo, sumexp)      # ユーザーのキャラクタステータス

printf("
<!-- キャラクターイメージの設定 -->
<div class=\"charIMG\">
<img src=\"png/%s.png\">
</div>
<div class=\"charSTATUS\">
ID:%04d<br>
NAME:%s<br>
あなたのLv: %d / 全員のLv: %d<br>
当選確率: %3.3f \%
<div>
", charST[0], id-1,  name, charST[2],sumexp , charST[1])

# End of bottom
print'</div>'
# End of outflam
print'</div>'
######

print'
</body>
</html>
'
##########
