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

# 通常バージョンです
# 改良しようとしたけどやばいことになったのでやばい方は避難させといた


require 'csv'
require 'roo'

ods = Roo::Spreadsheet.open("quizod.ods")        #odsをもってくる
neta = CSV.parse(ods.to_csv, :headers => true)   #odsをcsvにする

fuseikai = 0
def wrong()
  puts"不正解!"
  sleep(0.5)

end

              # ans = answer,opt = row["オプション"],san = santaku,seikai = row["答え"],fu = fuseikaiと書きたいけど無理だった
def isRightAns(ans,opt,san,seikai,fu)

  ansIsA = (ans == san[0])       # この変数群
  ansIsB = (ans == san[1])       # カッコ付きはTF、カッコ無しはその他の値
  ansIsC = (ans == san[2])       # A,B,Cは選択肢の文字を仮で表している

  alreadySantaku = (fu >= 3)
  ansIs1 = (ans == "1")
  ansIs2 = (ans == "2")
  ansIs3 = (ans == "3")
  
  ansAry = ans.chars
  ansIsEmpty = (ansAry.empty?)
  ansLength = ans.length
  santakuNumbers = ["1","2","3"]
  santakuTotalLength = san.join.length

  ansHasA = (ans.include?(san[0]))if san[0] # sanにnilがあるとinclude?で
  ansHasB = (ans.include?(san[1]))if san[1] # エラーになるのでこうなった
  ansHasC = (ans.include?(san[2]))if san[2]

  # ansIs123わかりにくくてすいません。回答に123が1個ずつあればOKを表しています
  ansIs123 = ((ansAry + santakuNumbers).tally == {"1" =>2,"2" =>2,"3" =>2})
  ansIsABC = (ansHasA && ansHasB && ansHasC && ansLength == santakuTotalLength)
  #ansIs順不同

  selectNumber = (ans.to_i)-1
  select = san[selectNumber]
  
  #文字で答えた場合 || 番号で答えた場合
  if opt =~/(すべて)/
    return  (ansIsABC) ||
            (ansIs123 && alreadySantaku)

  elsif opt =~ /(どれかひとつ)/
    return ([ansIsA,ansIsB,ansIsC].one?) ||
           ([ansIs1,ansIs2,ansIs3].one?)

  else    #通常の三択
    return false if ans == ""
    return (ans == seikai) || (select == seikai && alreadySantaku)

  end        
    
end


def putAnswer(row,santaku)
  if row["答え"] != nil      # 正解表示(通常)
    printf("正解は%sでした。\n",row["答え"])
    return
  end
  # 以下では row["答え"] = nil
  if    row["オプション"] =~ /(すべて)/  # 正解表示(すべて)
    printf("正解は%s,%s,%sすべてでした。\n",santaku[0],santaku[1],santaku[2])
    return
    
  elsif row["オプション"] =~ /(どれかひとつ)/ # 正解表示(どれか)
    printf("正解は%s,%s,%sの中からひとつでした。\n",santaku[0],santaku[1],santaku[2])
    return
  end  
end


setumei = ["カスタムクイズ",
           "              説明",
           "専用のodsを使うことで、自由にクイズを作ることができます。",
           "odsでつくったクイズが出題されるクイズです。",
           "選択肢を出す場合、今は出せる選択肢は3つのみとなっております。",
           "odsでの操作はodsに書いているのでそちらを見てください。",
           "enterを押すと始まります。"
          ]

for i in setumei
  puts i
end
gets

countAns = 0
countRight = 0

count = 0                       # 今何問目なのか
print("\e[2J")
print("\e[H")

startTime = Time.now.to_i
neta.each{|row|

          if row["オプション"] == "表示物"
            printf("%s\n",row["問題"])
            gets
            print("--------------------------\n")
            next
          end
              count += 1
              dasita = 0
              comeback = 0
             printf("第%d問\n",count) 
             printf("%s\n", row["問題"])
             santaku = [row["三択1"], row["三択2"], row["三択3"]]
             fuseikai = 0   # fuseikai >= 3で三択表示
             kaitou = nil
            
          while true
                       
               #入力と三択システム
              if comeback == 1
                wrong
                
              end
              if row["オプション"] =~ /(三択なし)/ # 意地悪問題がいい人へ
                dasita = 1
                
              elsif ( fuseikai == 3 || row["オプション"] =~ /(三択)/ ) &&
                    dasita   != 1
                if row["オプション"] =~ /(三択)/
                  fuseikai = 3
                end
                num = 1         # 選択肢の番号
                for i in santaku
                  printf("%d => %s\n",num,i)
                  num += 1
                end
                dasita = 1   # dasitaが1 =「三択出した」 2回以上の三択表示を防ぐ
              end
              
              print"答えを入力..."
              kaitou = gets.chomp
              countAns += 1

             if row["オプション"] !~ /(判定なし)/
              if isRightAns(kaitou,row["オプション"],santaku,row["答え"],fuseikai)
                puts"正解!!"
                countRight += 1
                sleep(0.5)
                break
              else
                fuseikai += 1
                wrong
                if row["オプション"] !~ /(1回だけ)/
                 print("\e[2A")      # 2行上
                 print("\e[J")        # 下のやつを消す
                end
              end
             end
              if row["オプション"] =~ /(正解を出す)/
                putAnswer(row,santaku)
              end
              if row["オプション"] =~ /(1回だけ|判定なし)/
                break
              end
                
          end
          if row["解説"]
            printf("%s\n",row["解説"])
            gets
            print"\e[1A"
          end
 
            print("--------------------------\n") #何個でもいい仕切りの機能
          }

# 終了時演出の変数の準備
finishTime = Time.now.to_i

text = neta["変更テキスト"][0]
finish = neta["終了時演出"][0]

seitouritu = (((countRight.to_f)/(countAns.to_f))*100).truncate(1)
keikajikan = (finishTime - startTime)
heikinjikan = ((keikajikan.to_f)/(count.to_f)).truncate(1)


# 終了時演出の表示
  printf("正解数: %d回/%d回中     ",countRight,countAns)if finish =~ /(結果表示)/

  printf("正答率: #{seitouritu}%%     ")if finish =~ /(正答率)/
print"\n" if finish =~ /(正解表示|正答率)/
  printf("経過時間: %d秒     ",keikajikan)if finish =~ /(経過時間)/

  printf("平均回答時間: #{heikinjikan}秒     ")if finish =~ /(平均時間)/

print"\n"
if text
  printf("%s\n",text)if text != "なし"
else
  puts"終了!!おつかれさまでした!"
end
# おつかれさまでした!!