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

require 'curses'; include Curses
require 'csv'

sentence    = CSV.read("typing-texts.csv" , :headers => true)#タイピング本文
sentence_utu= CSV.read("typing-texts-utu.csv",:headers => true)
menu_sentakusi ={1=>"play",2=>"option",3=>"practice"}
play_sentakusi =sentence.headers
type_list =[] #打つ内容を呼び出すための文字列を格納する
kaisu = 0   # 問題数を指定
miss_now = nil      # 各文字でミスったか否か
miss_all = []      # 全部で何回、どの字でミスったか
class Window
  @@numbers = CSV.read("futaketa-alpha.csv",:headers => true)
def putSentakusi(nani,zip = @@numbers.headers)
  for na,s in nani.zip(zip)
    self.addstr(sprintf("%s => %s\n",s,na))
  end
  self.refresh
end
def getAns()
  self.addstr("入力:")
  self.refresh
  while true
    a = getch 
    if a == "q"
      return "q"
    elsif @@numbers[a]
      return @@numbers[a].join.to_i
   end
  end
end
def addstr_sousyoku(nani,str)
  nani.each{|n|self.attron(n)}
               self.addstr(str)
  nani.each{|n|self.attroff(n)}        
end
end
init_screen
noecho
cbreak
begin
  win = Window.new(32,60,10,10)
  win.addstr("タイピングです。\n番号を入れてください\n")
    win.addstr("ジャンルを決めてください(複数選択可能、qで入力終了\nもう一度選ぶと選択解除)\n")#refreshはquestionに
    cursor_position =[win.cury,win.curx]
    while true
      win.setpos(*cursor_position) ##* s e t "p  o" s *##setopsって書くとそのエラーすっごく見つけづらい
      win.putSentakusi(play_sentakusi)
      choice = win.getAns
      break if choice == "q"
      play_choice = play_sentakusi[choice-1]
      already_chosen = type_list.include?(play_choice)
      if play_choice
        type_list << play_choice #打つ内容に紐付いた文字を格納
        type_list.delete(play_choice)if already_chosen
      end
      win.addstr(sprintf("\n選択済み:%s\n",type_list.join(",")) ); win.refresh
    end
    odai_display_list = type_list.collect{|type|sentence[type]}.flatten.compact
    odai_utu_list = type_list.collect{|type|sentaku = type.sub(/\(.*?\)/,"").to_s;sentence_utu[sentaku]}.flatten.compact
    odai_length = odai_display_list.length  # 問題数を拾っている
    win.clear
    win.addstr(sprintf("何問やりますか(最大%d問)\n",odai_length))
    until kaisu != "q" && kaisu >= 1 && kaisu <= odai_length 
      kaisu = win.getAns
      win.setpos(1,0)
    end                  
    win.addstr("\nなにか打つと開始!!\n")
    win.getAns; refresh; win.setpos(0,0)
    number = 0  #お題の番号 #文字の様子 -> 入力前太字。入力後普通、ミス下線
    start_time = Time.now.to_i
    kaisu.times do
      number  = rand(0..(odai_length-1) )                   #この回のループで出すお題の番号
      odai = {display: odai_display_list[number],utu: odai_utu_list[number]}#この回のループで出すお題のハッシュ
      ch_count = 0 
      win.addstr_sousyoku([A_BOLD],odai[:display]+"\n")
      cursor_position =[win.cury,win.curx]
      win.addstr_sousyoku([A_DIM,A_BOLD],odai[:utu])
      while odai[:utu].length > ch_count
        win.setpos(cursor_position[0],(cursor_position[1])+ch_count);win.refresh
        input = getch 
        if input == odai[:utu][ch_count]
          win.addch(odai[:utu][ch_count])unless miss_now
          win.addstr_sousyoku([A_UNDERLINE],odai[:utu][ch_count])if miss_now
          ch_count += 1 ;miss_now = false ; win.refresh
        else
          miss_all << odai[:utu][ch_count] ; miss_now = true
        end
      end
      win.clear ; odai_length -= 1
      odai_display_list.delete_at(number)#2回出題を防ぐ
      odai_utu_list.delete_at(number)##for最終行##
    end
    keikajikan = (Time.now.to_i) - start_time
    miss = miss_all.tally
    win.addstr_sousyoku([A_BOLD],"結果\n")
    win.addstr(sprintf("かかった時間: %d秒(1問あたり: %d秒),ミス: %d回\nミスの詳細\n",keikajikan,keikajikan/kaisu,miss_all.length))
    win.putSentakusi(miss.values,miss.keys); refresh
ensure
  close_screen
end
