#!/usr/bin/env ruby #「京都名所クイズ」デモプログラム # # で提供されている京都名所クイズサービスに #接続して、5択クイズで遊ぶためのサンプルです。 [RAA:SOAP4R]、[RAA:NQXML]が必要です。 # # 2001.06.17 Ruby/Tk で記述 by Noritsugu Nakamura # http://www.jin.gr.jp/~nahi/yarpc/?cmd=view;name=hippo5tq.rb # http://www.hippo2000.net/perl/Quiz/soapQuiz.htm # をマージしただけ # # 既知の不具合: # * wraplength の適切な値を設定するには? # * 接続などのタイミング # * ウィンドウマネージャーから close されたときの処理 # * proxy = ARGV.shift || nil require 'soap/driver' require 'kconv' require 'tk' # XML Schema Datatypesの1999版を指定(はよなくなってくれ) require 'soap/XMLSchemaDatatypes1999' # Wiredumpの出力先 def getWireDumpLogFile logFilename = File.basename( $0 ) + '.log' f = File.open( logFilename, 'w' ) f << "File: #{ logFilename } - Wiredumps for SOAP4R client / #{ $serverName } server.\n" f << "Date: #{ Time.now }\n\n" end class O5tqv def initialize(o5tq) Tk.root.title('SOAP de Quiz') @iNo = 0 # 使えないんだっけ? # @sQNo = TkVariable.new('') # @sQ = TkVariable.new('') # @sResult = TkVariable.new('') # @sPnt = TkVariable.new('') # @iSum = TkVariable.new('') cmd_nextq = proc { |o5tq| nextq(o5tq) } cmd_rep_btn = proc { |o5tq, i| rep_btn(o5tq, i) } cmd_set_btn_state = proc { |flag| set_btn_state(flag) } @sQNo = TkLabel.new { width 8 #textvariable @sQNo grid('row' => 0, 'column' => 0) } @sQ = TkLabel.new { height 3 width 30 justify 'left' anchor 'nw' # 適切な値を設定するには? #wraplength 320 wraplength 200 #textvariable @sQ grid('row' => 0, 'column' => 1) } @sResult = TkLabel.new { #textvariable @sResult width 6 grid('row' => 2, 'column' => 3) } @sPnt = TkLabel.new { #textvariable @sPnt grid('row' => 3, 'column' => 3) } @iSum = TkLabel.new { #textvariable @iSum grid('row' => 4, 'column' => 3) } @aBtnOpt = [] (1..5).each do |i| TkLabel.new { text "選択肢:#{i}" grid('row' => i, 'column' => 0) } @aBtnOpt[i] = TkButton.new { command { cmd_rep_btn.call(o5tq, i) cmd_nextq.call(o5tq) } width 30 justify 'left' anchor 'nw' state 'disabled' grid('row' => i, 'column' => 1) } end @btn_start = TkButton.new { text '開始' command { o5tq.get_quiz_all cmd_set_btn_state.call(0) # qvwm だとウィンドウマネージャが一度死ぬ(うちだけ?) # Tk.messageBox('type' => 'ok', # 'title' => '確認', # 'message' => 'さぁ始まります!準備はいいですか?') # あなたは誰? @iNo = 1 cmd_nextq.call(o5tq) } grid('row' => 0, 'column' => 2) } @btn_abort = TkButton.new { text '中止' command { puts "中断されました" o5tq.quit cmd_set_btn_state.call(1) } state 'disabled' grid('row' => 0, 'column' => 3) } TkLabel.new { text '結果' grid('row' => 2, 'column' => 2) } TkLabel.new { text '得点' grid('row' => 3, 'column' => 2) } TkLabel.new { text '合計' grid('row' => 4, 'column' => 2) } Tk.mainloop end def set_btn_state(flag) if flag == 0 sSt, sOt = 'disabled', 'normal' else sSt, sOt = 'normal', 'disabled' end # ボタンの設定 @btn_start.state sSt @btn_abort.state sOt (1..5).each do |i| @aBtnOpt[i].state sOt end # 表示をクリア @sQ.text '' @sQNo.text '' end def nextq(o5tq) quiz, *opt = o5tq.nextq if quiz @iNo += 1 @sQNo.text("問題:" + @iNo.to_s) @sQ.text quiz.toeuc 1.upto( opt.length ) do |i| @aBtnOpt[i].text(opt[i-1].toeuc) end else o5tq.quit @sQ.text '--終了--' set_btn_state(1) @iNo = 0 end end def rep_btn(o5tq, i) result, point, totalPoint = o5tq.answer(i) if result @sPnt.text point @sResult.text '正解!' @iSum.text totalPoint else @sPnt.text 0 @sResult.text 'ハズレ' @iSum.text totalPoint end end end class O5tq # サービス情報の登録(本来ならWSDLから作られるべきところ) Server = 'http://www.hippo2000.net/cgi-bin/soap5tq2.cgi' NS = 'urn:Soap5tq2' def initialize(proxy) @proxy = proxy @drv = SOAP::Driver.new( nil, 'hippo5tq', NS, Server, @proxy ) @drv.setWireDumpDev( getWireDumpLogFile ) @drv.addMethod( 'Init', 'UsrName', 'Passwd' ) # => [ sSession, sErr ] @drv.addMethod( 'End', 'sSsID' ) # => void @drv.addMethod( 'GetQuizAll', 'sSsId' ) # => [ sQuiz0, sOpt00, sOpt01, sOpt02, sOpt03, sOpt04, # ... # sQuiz9, sOpt90, sOpt91, sOpt92, sOpt93, sOpt94 ] @drv.addMethod( 'RepQuizAll', 'sSsID', 'iRes' ) # => [ iResult, iPoint ] @drv.addMethod( 'GetQuiz', 'sSsID' ) # => [ sQuiz, sOpt0, sOpt1, sOpt2, sOpt3, sOpt4 ] @drv.addMethod( 'ReqQuiz', 'sSsID', 'iRes' ) # => [ iResult, iPoint ] connect end def connect # クイズサービスへのログイン @sessionId, errInfo = @drv.Init( 'SOAP4R', '' ) @totalPoint = 0 end def get_quiz_all connect # 最初に一括してクイズを取得してしまう @quizAll = @drv.GetQuizAll( @sessionId ) end def nextq # クイズの残ってる間。。。 if !(@quizAll.length < 6) return @quizAll.slice!( 0..5 ) else return nil end end def answer(ans) # 回答を照合する result, point = @drv.RepQuizAll( @sessionId, ans - 1 ) # 判定結果は? unless result.zero? @totalPoint += point return true, point, @totalPoint else return false, point, @totalPoint end end def quit # ログオフ @drv.End( @sessionId ) end end o5tq = O5tq.new(proxy) O5tqv.new(o5tq) # # 中断時。。。 # trap( "INT" ) do | sig | # puts "中断されました" # o5tq.quit # exit( -1 ) # end