#! usr/bin/env ruby                                 #Rubyのインタプリタの指定
# -*- coding: utf-8 -*-                             #文字コードの設定

def now                                             #メソッド"now"を指定
  if Time.now.hour <= 6                             #もし現在の時間が6時以前だったら
    puts "まだ夜だよ。寝ようよ。"                   #"まだ夜だよ。寝ようよ。"と表示
  elsif Time.now.hour >= 7 && Time.now.hour <= 9    #もし現在の時間が7時以降で9時以前だったら
    puts "おはようございます。"                     #"おはようございます。"と表示
  elsif Time.now.hour >= 10 && Time.now.hour <= 18  #もし現在の時間が10時以降で18時(午後6時)以前だったら
    puts "こんにちは。"                             #"こんにちは。"と表示
  else                                              #それ以外だったら
    puts "こんばんは。"                             #"こんばんは。"と表示
  end                                               #ifのend
end                                                 #メソッド"now"を抜けるend

def loading(time)                                   #メソッド"loading"と仮引数"time"を指定
  if time == 2                                      #もし仮引数"time"が2だったら
    printf("\e[%dmloading",90)                      #"\e[90m"で色を灰色に指定し、"loading"と表示する
    2.times do                                      #2回繰り返す
      sleep(0.3)                                    #0.3秒待つ
      print "."                                     #"."と表示
    end                                             #doのend
    puts ""                                         #改行する
    sleep(0.4)                                      #0.4秒待つ
    print "\e[0m"                                   #"\e[0m"で色をもとに戻す
  else                                              #それ以外だったら
    printf("\e[%dmloading",90)                      #"\e[90m"で色を灰色に指定し、"loading"と表示する
    3.times do                                      #3回繰り返す
      sleep (0.3)                                   #0.3秒待つ
      print "."                                     #"."と表示する
    end                                             #doのend
    puts ""                                         #改行する
    sleep(0.4)                                      #0.4秒待つ
    print "\e[0m"                                   #"\e[0m"で色をもとに戻す
  end                                               #ifのend
end                                                 #メソッド"loading"を抜けるend

def levenshtein_distance(divide_input)              #メソッド"levenshtein_distance"と仮引数"divide_input"を指定
  distance = []                                     #配列"distance"を作成
  distance1 = 0                                     #変数"distance1"を0にする
  distance2 = 0                                     #変数"distance2"を0にする
  order = 0                                         #変数"order"を0にする
  rap = 1                                           #変数"rap"を1にする
  comparison_ziten_mini = []                        #配列"comparison_ziten_mini"を作成
  comparison_input_mini = []                        #配列"comparison_input_mini"を作成
  ziten = []                                        #配列"ziten"を作成
  File.readlines("j2106_intro_ziten.txt").each do |line|  #テキストファイルの文章をファイルから読み込み、
    ziten << line.chomp                                   #改行文字を切り取り、順に配列"ziten"に保存
  end                                                     #doのend
  if divide_input.length == 0                           #1.もし仮引数"divide_input"の長さが0なら
    shortest = ziten.sort_by(&:length).first              #配列"ziten"の要素の中で一番文字数が少ない語を変数"shortest"に代入
    distance << shortest.length                           #配列"distance"に変数"shortest"の文字列の長さを代入
  else                                                    #それ以外だったら
    for divide_ziten in ziten                             #配列"ziten"の要素を順にdivide_zitenに代入
      comparison_ziten = divide_ziten.split("")           #変数"divide_ziten"を一文字ずつに分解し、comparison_zitenに代入
      comparison_input = divide_input.split("")           #変数"divide_input"を一文字ずつに分解し、comparison_inputに代入
      if rap == 1                                         #もし変数"rap"が1だったら
        comparison_ziten.shift                            #変数comparison_zitenの先頭の要素を取り除く
        rap = 0                                           #変数"rap"を0にする
      end                                                 #ifのend
      if comparison_ziten.length > comparison_input.length  #もし変数"comparison_ziten"の長さがcomparison_inputの長さより長ければ
        distance1 += comparison_ziten.length - comparison_input.length  #変数"distance1"に変数"comparison_ziten"の長さから変数"comparison_input"の長さを引いた値を足す(代入演算)
        time = comparison_input.length    #変数"time"にcomparison_inputの長さを代入
      elsif comparison_input.length > comparison_ziten.length  #もし変数"comparison_input"の長さがcomparison_zitenの長さより長ければ
        distance1 += comparison_input.length - comparison_ziten.length  #変数"distance1"に変数"comparison_input"の長さから変数"comparison_ziten"の長さを引いた値を足す(代入演算)
        time = comparison_ziten.length    #変数"time"にcomparison_zitenの長さを代入
      else                                #それ以外だったら
        time = comparison_ziten.length    #変数"time"にcomparison_zitenの長さを代入
      end                                 #ifのend
      time. times do                      #変数"time"回繰り返す
        comparison_ziten_mini << comparison_ziten[order]   #変数"comparison_ziten"の変数"order"番目を配列"comparison_ziten_mini"に保存
        comparison_input_mini << comparison_input[order]   #変数"comparison_input"の変数"order"番目を配列"comparison_input_mini"に保存
        if comparison_ziten_mini != comparison_input_mini  #4.もし配列"comparison_ziten_mini"が配列"comparison_mini"と等しくなければ
          distance2 += 1                                   #変数"distance2"に1を足す(代入演算)
        end                                                #ifのend
        comparison_ziten_mini.slice!(0,comparison_ziten.length)  #配列"comparison_ziten_mini"を空にする
        comparison_input_mini.slice!(0,comparison_input.length)  #配列"comparison_input_mini"を空にする
        order += 1                                               #変数"order"に1を足す(代入演算)
      end                                                        #doのend
      distance << distance1 + distance2                          #変数"distance1"と変数"distance2"を足した値を配列"distance"に代入
      distance1 = 0                                              #変数"distance1"の初期化
      distance2 = 0                                              #変数"distance2"の初期化
      order = 0                                                  #変数"order"の初期化
    end                                                          #forのend
    return distance.min                                          #配列"distance"の要素の中で一番小さい要素を返す
  end                                                            #ifのend
end                                                              #メソッド"levenshtein_distance"を抜けるend
#参考にした"レーベンシュタイン距離のアルゴリズム"
#1.AとBのどちらかが空なら、もう一方の長さを編集距離に足して終了
#2.AとBの1文字目を比べる
#3.同じなら次の文字に進んで、1へ戻る
#4.異なるなら編集距離に1を足す
#5.分岐:
#  Bから1文字を削除(=挿入)し、1へ戻る
#  Aから1文字を削除(=挿入)し、1へ戻る
#  AとBから1文字を削除(=挿入)し、1へ戻る

def search(search_word)                    #メソッド"search"と仮引数"search_word"を指定
  search = Regexp.new(search_word)         #仮引数"search_word"を正規表現に変換して、変数"search"に代入
  File.readlines("j2106_intro_ziten.txt").each do |line|  #テキストファイルの文章をファイルから読み込み、
    ziten = line.chomp                                    #改行文字を切り取り、順に変数"ziten"に保存
    if search =~ ziten                                    #もし変数"search"がzitenの中の要素とマッチしたら
      return ziten                                        #その要素を返す
    end                                                   #ifのend
  end                                                     #doのend
end                                                       #メソッド"search"を抜けるend

now                                                       #メソッド"now"の参照
puts "土門侑生とは\n何について見る?"                      #説明
while true                                                #ループに入る
  puts "番号を入力してね.\n1.土門侑生とは\n2.好きなもの\n3.my厨二病語一覧\n" #選択肢の提示
  choice = gets.chomp       #打ち込んだ文字を取得し、改行文字を切り取り、変数"choice"に代入
  if choice == "1"          #もし変数"choice"が"1"ならば
    loading(3)              #メソッド"loading"の参照 実引数に"3"を入れる
    puts "土門侑生とは\n山形県酒田市立第六中学校の2年生。部活?そんなもの知らないね。\nかわりに勉強頑張ってるからいいんだよ。\nあとは...自作PCを持っている。\nそれぐらいかなぁ。\nじゃあクイズ出します。\n番号で入力してね。\n正解か不正解かは言わない。あえてね。\n"         #自己紹介
    sleep(10)               #10秒待つ
    
    require 'curses'        #Cursesライブラリの呼び出し
    include Curses          #Cursesモジュールをincludeする

    init_screen             #Cursesの初期化
    cbreak                  #入力を即座に処理
    noecho                  #入力した文字を画面に表示しない
    begin                   #処理の開始
      correct = 0           #変数"correct"を0にする
      quiz_number = ["1","2","3"]          #配列"quiz_number"を作成
      while 0 < quiz_number.length         #配列"quiz_number"の長さが0より大きい間繰り返す
        srand()                            #乱数の種を初期化
        number = rand(quiz_number.length)  #配列"quiz_number"の中の要素をランダムに変数"number"に代入
        quiz = quiz_number[number]         #取り出した値を変数"quiz"に代入
        quiz_number.shift[number]          #取り出した値を配列"quiz_number"の中から取り除く
        if quiz == "1"          #もし変数"quiz"が"1"だったら
          setpos(0,0)           #文字を表示する場所の指定
          addstr("私はなんと呼ばれているでしょうか。\n1.MP3\n2.ZIP\n3.PDF\n") #問題
          refresh               #画面の更新
          answer1 = getch       #入力した1文字を取得し、変数"answer1"に代入
          if answer1 == "3"     #もし変数"answer1"が"3"ならば
            correct += 1        #変数"correct"に1を足す(代入演算)
          end                   #ifのend
        elsif quiz == "2"       #もし変数"quiz"が"2"だったら
          setpos(0,0)           #文字を表示する場所の指定
          addstr("私の得意な教科は何でしょうか。\n1.国語\n2.数学\n3.英語\n")                                     #問題
          refresh               #画面の更新
          answer2 = getch       #入力した1文字を取得し、変数"answer2"に代入
          if answer2 == "2"     #もし変数"answer2"が"2"ならば
            correct += 1        #変数"correct"に1を足す(代入演算)
          end                   #ifのend
        else                    #それ以外だったら
          setpos(0,0)           #文字を表示する場所の指定
          addstr("私が寝る前に必ず行うことは何でしょうか。\n1.音楽を聴く\n2.アニメを見る\n3.漫画を読む\n")      #問題
          refresh               #画面の更新
          answer3 = getch       #入力した1文字を取得し、変数"answer3"に代入
          if answer3 == "1"     #もし変数"answer3"が"1"ならば
            correct += 1        #変数"correct"に1を足す(代入演算)
            setpos(0,0)         #文字を表示する場所の指定
            addstr("walkmanを使っています。そんなに高くないしおすすめ。\n")  #表示する文字
            refresh             #画面の更新
            picture = spawn "display -geometry +0+0 walkman1.jpg" #画像の表示
            sleep(3)                                              #3秒待つ
            Process.kill(:INT,picture)                            #画像の削除
          end                   #ifのend
        end                     #ifのend
      end                       #whileのend
    ensure                      #例外処理
      close_screen              #画面をもとに戻す
    end                         #beginを抜けるend
    printf("正答数:%d\n",correct)                  #文字と変数"correct"の値を表示
    correct_percent = correct * 100 * 1/3           #変数"correct"に100と1/3をかけて変数"correct_percent"に代入
    printf("正答率:%dパーセント\n",correct_percent) #文字と変数"correct_percent"の値を表示
    break                                           #ループを抜ける
  elsif choice == "2"                               #もし変数"choice"が"2"なら
    loading(3)                                      #メソッド"loading"の参照 実引数に"3"を入れる
    require 'csv'                                   #CSVライブラリの呼び出し
    like = CSV.read("j2106_intro_like.csv", :headers => true)  #CSVファイルの読み込みとHash化をしてlikeに代入
    lank = 1                                        #変数"lank"を0にする
    puts "好きなもの\n私の好きなものをランキングにしたよ。\nどれ見る?\n1.音楽(アーティスト)\n2.ゲーム\n3.漫画\n"                    #選択肢の提示
    while true                                      #ループに入る
      choice2 = gets.chomp                          #打ち込んだ文字を取得し、改行文字を切り取り、変数"choice2"に代入
      if choice2 == "1"                             #もし変数"choice2"が"1"ならば
        like.each{|row|                             #変数"like"の要素を順に変数"row"に格納
          printf("%d.%s\n",lank,row["音楽(アーティスト)"]) #"音楽(アーティスト)"キーでバリューの値を持ってきて出力
          lank += 1                                 #変数"lank"に1を足す(代入演算)
        }
        break                                       #ループを抜ける
      elsif choice2 == "2"                          #もし変数"choice2"が"2"ならば
        like.each{|row|                             #変数"like"の要素を順に変数"row"に格納
          printf("%d.%s\n",lank,row["ゲーム"])      #"ゲーム"キーでバリューの値を持ってきて出力
          lank += 1                                 #変数"lank"に1を足す(代入演算)
        }
        puts"slither.ioはフリーのブラウザゲームだからすぐに遊べるよ。\nやってみる?\nはいかいいえで答えてね。"                        #選択肢の提示
        while true                                  #ループに入る
          yesno = gets.chomp                        #打ち込んだ文字を取得し、改行文字を切り取り、変数"yesno"に代入
          if yesno == "はい"                        #もし変数"yesno"が"はい"ならば
            system("firefox","http://slither.io")
            break                                   #ループを抜ける
          elsif yesno == "いいえ"                   #もし変数"yesno"が"いいえ"ならば
            puts "今度やってみてね。"               #文字を出力
            break                                   #ループを抜ける
          else                                      #それ以外なら
            puts "もう一回入力してください"         #文字を出力
            redo                                    #ループの最初から処理を始める
          end                                       #ifのend
        end                                         #whileのend
        break                                       #ループを抜ける
      elsif choice2 == "3"                          #もし変数"choice2"が"3"ならば
        like.each{|row|                             #変数"like"の要素を順に変数"row"に格納
          printf("%d.%s\n",lank,row["漫画"])        #"漫画"キーでバリューの値を持ってきて出力
          lank += 1                                 #変数"lank"に1を足す(代入演算)
        }
      else                                          #それ以外なら
        puts "もう一回入力してください"             #文字を出力
        redo                                        #ループの最初から処理を始める
      end                                           #ifのend
    end                                             #whileのend
    break                                           #ループを抜ける
  elsif choice == "3"                               #もし変数"choice"が"3"なら
    loading(3)                                      #メソッド"loading"の参照 実引数に"3"を入れる
    number = 0                                      #変数"number"を0にする
    ziten = []                                      #配列"ziten"を作る
    p "my厨二病語一覧"                              #タイトルの表示
    puts "my厨二病語一覧とは?\n---私の好きな厨二病語が載ってるで。なんで厨二病語にしたかって?\nうーんいま私が中2だから。\nいやしょうもなとか言わないで。\n最初は言葉の意味をつけようかと思って辞典にしてたけど、ちょっと冷めたのでやめた。\nというか意味なんて気にせず使うでしょ。\n1.語を見る\n2.語や意味を調べる\n番号を入力してな。"                                               #選択肢の表示
    while true                                      #ループに入る
      choice2 = gets.chomp                          #打ち込んだ文字を取得し、改行文字を切り取り、変数"choice2"に代入
      if choice2 == "1"                             #もし変数"choice2"が"1"ならば
        File.readlines("j2106_intro_ziten.txt").each do |line|  #テキストファイルの文章をファイルから読み込み、
          ziten << line.chomp                       #改行文字を切り取り、順に配列"ziten"に保存
        end                                         #doのend
        puts "どういう順番で見る?\n1.昇順で見る(あ → ん)\n2.降順で見る(ん → あ)"                                                   #選択肢の提示
        while true                                  #ループに入る
          answer = gets.chomp                       #打ち込んだ文字を取得し、改行文字を切り取り、変数"answer"に代入
          if answer == "1"                          #もし変数"answer"が"1"ならば
            while number < ziten.length             #変数"number"が配列"ziten"の要素の数未満の間
              printf("%d.%s\n",number + 1,ziten.sort[number]) #配列"ziten"を辞書順に並べ、変数"number"番目の要素を取り出す
              number += 1                           #変数"number"に1を足す(代入演算)
            end                                     #whileのend
            break                                   #ループを抜ける
          elsif answer == "2"                       #もし変数"answer"が"2"ならば
            while number < ziten.length             #変数"number"が配列"ziten"の要素の数未満の間
              printf("%d.%s\n",number + 1,ziten.sort.reverse[number])  #配列"ziten"を辞書順に並べ、それを逆にし、変数"number"番目の要素を取り出す
              number += 1                           #変数"number"に1を足す(代入演算)
            end                                     #whileのend
            break                                   #ループを抜ける
          else                                      #それ以外だったら
            puts "もう一回入力してください"         #文字を出力
            redo                                    #ループの最初から処理を始める
          end                                       #ifのend
        end                                         #whileのend
        break                                       #ループを抜ける
      elsif choice2 == "2"                          #もし変数"choice2"が"2"なら、
        printf "まだ試作なのでうまくいかないことがあるかもしれない...\n入力してください:"                                            #説明
        search_word = gets.chomp                    #打ち込んだ文字を取得し、改行文字を切り取り、変数"search_word"に代入
        levenshtein_distance(search_word)           #メソッド"levenshtein_distance"の参照 実引数に"search_wold"を入れる
        loading(2)                                  #メソッド"loading"の参照 実引数に"2"を入れる
        printf("一覧にある一番近い単語との遠さ(編集距離):%s\n",levenshtein_distance(search_word))                                    #returnされた値を出力
        search(search_word)                         #メソッド"search"の参照 実引数に"search_word"を入れる
        puts "検索結果(一番近いもの)↓"             #文字の出力
        printf("%s\n",search(search_word))          #returnされた値を出力
        break                                       #ループを抜ける
      else                                          #それ以外なら
        puts "もう一回入力してください"             #文字の出力
        redo                                        #ループの最初から処理を始める
      end                                           #ifのend
      break                                         #ループを抜ける
    end                                             #whileのend
  else                                              #それ以外なら
    puts "もう一回入力してください"                 #文字を出力
    redo                                            #ループの最初から処理を始める
  end                                               #ifのend
  break                                             #ループを抜ける
end                                                 #whileのend
