#!/usr/bin/env ruby #-*- coding: utf-8 -*- #csquizのやばくなった方です。いつか絶対動かす!! #なんでやばくなった、って、、3択未満でも動くようにしたいじゃないですかぁ #そしてnil対応が間に合わなかった((泣))のコードですす、、書き換えかけ 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 def makeNumbers(santaku) #三択未満の場合に備え、割り振る番号の調整 santaku = santaku.compact numbers = [] (santaku.length).times do |num| numbers << (num+1).to_s end return numbers # 1 => "選択肢1",2 => "選択肢3" とか end # 1 => "選択肢2" とかに対応する番号の配列 # ans = answer,opt = row["オプション"],san = santaku,seikai = row["答え"],fu = fuseikaiと書きたいけど無理だった def isRightAns(ans,opt,san,seikai,fu) alreadySantaku = (fu >= 3) ansAry = ans.chars ansLength = ans.length santakuNumbers = makeNumbers(san) santakuTotalLength = san.join.length if san[0] #でえきたあ(?) aboutAnsA ={ansIsIt: (ans == san[0]), ansHasIt: (Regexp.new(san[0]) =~ ans), ansIsNum: (ans == "1"), ansHasNum: (Regexp.new( "1") =~ ans)} end # sanにnilがあるとinclude?で if san[1] # エラーになるのでこうなった aboutAnsB ={ansIsIt: (ans == san[1]), ansHasIt: (Regexp.new(san[1]) =~ ans), ansIsNum: (ans == "2"), ansHasNum: (Regexp.new( "2") =~ ans)} end if san[2] aboutAnsC ={ansIsIt: (ans == san[2]), ansHasIt: (Regexp.new(san[2]) =~ ans), ansIsNum: (ans == "3"), ansHasNum: (Regexp.new( "3") =~ ans)} end aboutAns = [aboutAnsA,aboutAnsB,aboutAnsC].compact ansHasAll = [] # 判断材料を集めるために一時的に配列にしている ansIsAll = [] doreka = [] aboutAns.each do |aa| ansHasAll << aa[:ansHasIt] doreka << (aa[:ansIsNum]&& alreadySantaku) || aa[:ansIsIt] end ansHasAll = ansHasAll.compact.all? doreka = doreka.compact.one? jyunfudou_AnsIsAll = san.permutation.zip(santakuNumbers.permutation) do |p,n| ansIsAll << (ans == p.join || ans == n.join || ans == p.join(",") || ans == n.join(",") || ans == p.join(" ") || ans == n.join(" ") || ans == p.join("、")|| ans == n.join("、")) end ansIsAll = (ansIsAll.one?) || (ansHasAll && ansLength == santakuTotalLength) aboutAllAns = {ansHasAll: ansHasAll, ansIsAllNumbers: (ansAry + santakuNumbers).tally == {}, ansIsAll: ansIsAll } #ansIs順不同 selectNumber = (ans.to_i)-1 select = san[selectNumber] #文字で答えた場合 || 番号で答えた場合 if opt =~/(すべて)/ return (aboutAllAns[:ansIsAll]) || (aboutAllAns[:ansIsAllNumbers] && alreadySantaku) elsif opt =~ /(どれかひとつ)/ return doreka 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すべてでした。\n",*santaku) return elsif row["オプション"] =~ /(どれかひとつ)/ # 正解表示(どれか) printf("正解は%sの中からひとつでした。\n",*santaku) return end end def makeSelectHash(keyAry,valAry) keyAry.compact! valAry.compact! newHash = {} newAry = [] keyAry.zip(valAry).each do|key,val| newAry << [key,val]if key && val # なんかちゃう? end newAry.compact.to_h end setumei = ["カスタムクイズ", " 説明", "専用のodsを使うことで、自由にクイズを作ることができます。", "ですが今回は私についてのクイズになっています。", "特別版ということです。といっても実はquiz2102を書き換えればカスタマイズ可能です。", "特別版だからってodsからの設定ではできないことをやるのは個人的に嫌なので、", "「この説明文」と「呼び出すodsファイルの名前」以外は通常版と全く同じものになっています。", "調整中。。。" ] 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"]] sanHash = makeSelectHash([:'1',:'2',:'3'],santaku,) santaku.compact! 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") #何個でもいい仕切りの機能 } if false # 終了時演出の変数の準備 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 # おつかれさまでした!! end