Newer
Older
Ruby / last / chinamini.rb
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

#ちなみに.rbです(ダジャレ?)
#お察しの通りかと思いますが。
#ちなみに100行越した方(つまり本当の現状)はこんなんです。っていうやつです。
#よかったら見てってほしいです

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
      return "q" if a == "q"
      return @@numbers[a].join.to_i  #アルファベットを対応表@@numbersを利用し2桁の整数にする
  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番号を入れてください\n")
  win.putSentakusi(menu_sentakusi.values)
  choice =  win.getAns
  win.setpos(0,0)
  case menu_sentakusi[choice]
   when "play"
    win.addstr("ジャンルを決めてください(複数選択可能、qで入力終了\n")
    win.addstr("もう一度選ぶと選択解除)\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" && type_list != []
      redo if choice.class == String
      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 do|type|
      sentaku = type.sub(/\(.*?\)/,"").to_s
      sentence_utu[sentaku]
    end.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(kaisu.to_s)
    win.addstr("\nなにか打つと開始!!\n")
    win.getAns
    refresh
                     #-=* タイピング本体 *=-#
    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.setpos(0,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]
          win.setpos(cury+1,curx)
          win.addstr(input)
          win.refresh
          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
                 #-=* 結果表示の準備 *=-#
    finish_time = Time.now.to_i
    keikajikan = finish_time - start_time
    miss_result = miss_all.tally
    miss = {syousai:{chars: miss_result.keys, kaisu: miss_result.values},
            kaisu: miss_all.length}
    utu  = {perfect: odai_utu_list.join.length,
            seitou: (odai_utu_list.join.length) - miss[:kaisu],
            kaisu: (odai_utu_list.join.length) + miss[:kaisu]}
    point = [(60*(utu[:perfect]-miss[:kaisu])/keikajikan).to_i,0].max #trr参考です。
    win.resize((lines)+5,60)
    win.clear
    win.setpos(1,10)
                     #-- 結果表示 --#
    win.addstr_sousyoku([A_BOLD],"結果\n")
    win.addstr("かかった時間: #{keikajikan}秒(1問あたり: #{keikajikan/kaisu}秒,1打あたり: #{(keikajikan/(utu[:kaisu].to_f)).truncate(3)}秒),\nミス: #{miss[:kaisu]}回,\n得点: #{point}点\n")
    miss_kaisu_with_unit = (miss[:syousai][:kaisu].join("回,").to_s)+"回"#String
    win.addstr("ミスの詳細: ")
    win.addstr_sousyoku([A_BOLD,A_UNDERLINE],"PERFECT!!\n")if miss[:kaisu] == 0
    unless miss[:kaisu] == 0
      win.addstr("\n")
      win.putSentakusi(miss_kaisu_with_unit.split(","), miss[:syousai][:chars])
    end
    win.refresh
    
  else #`case menu_sentakusi[choice]'のelse
    win.addstr("未実装か存在しない選択肢です。\n")
    win.refresh
  end
ensure
  close_screen
end