Newer
Older
WebSocketSample / quiz / qserv.rb
@HIROSE Yuuji HIROSE Yuuji on 4 Aug 3 KB Quiz mode initial
#!/usr/bin/env ruby
# -*- coding: utf-8 -*-
# EM Intro. - http://keijinsonyaban.blogspot.jp/2010/12/eventmachine.html
# irb to EM - https://keyesberry.hatenadiary.org/entry/20110929/p1
#
# Browser Settings:
# Chrome: https://blog.hello-world.jp.net/node-js/1821/

require 'em-websocket'
require 'json'
require 'csv'
PORT = 9124		# クイズよ
# TOKEN = "jugemujugemugokonosurikire"
TOKEN = "jugemu"
QUIZ  = "quiz.csv"
QJSON = CSV.read(QUIZ, headers:true).collect{|row| p row.to_h}


class QZ
  def jsonval(hash)
    JSON.generate(hash)
  end
  def sendinfo(client, msg)
    client.send(jsonval({info: msg}))
  end
  def initialize
    @client = Hash.new
    @currentQ = 0
  end
  def handleMessage(client, msg)
    begin
      json = JSON.parse(msg)
    rescue
      p "GYAA"
      return                    # Simply ignore it
    end
    p json
    json.each do |key, val|
      STDERR.printf("JSON:IN Handling key=[[%s]]\n", key)
      if key=="mode"
        if val == TOKEN
          @client[client][:master] = true
          STDERR.printf("Client %s set to master\n", client)
          client.send(jsonval({q: QJSON}))
        end
        next
      else
        @client[client][key] = val
        STDERR.printf("Set %s of %s to %s\n", key, @client[client]["name"], val)
      end
      @client.each do |c, prop|
        isMaster = @client[c][:master]
        STDERR.printf("isMaster=%s\n", isMaster)
        if c == client          # to packet sender
          if key == "getquiz"
            STDERR.printf("sent %s to %s\n", QJSON[@currentQ], @client[c][:name])
            c.send(jsonval({setquiz: QJSON[@currentQ]}))
          else
            sendinfo(c, "送信完了")
          end
        else
          STDERR.printf("notClient key=%s val=%s\n", key, val)
          case key
          when "name"
            sendinfo(c, "#{val}さんが入室しました")
          when "setquiz"
            @currentQ = val.to_i
            c.send(jsonval({setquiz: QJSON[@currentQ]}))
          when "select"
            if isMaster
              v = {             # クイズサーバのみに誰が何を選択したか送る
                "name"   => @client[client]["name"],
                "choice" => val
              }
              c.send(jsonval({select: v}))
            end
          when "check", "result"
            if !isMaster
              c.send(jsonval({key => val}))
            end
          end
        end
      end
    end
  end
  def start
    print("No @client yet...")
    EM::WebSocket.start({:host => "0.0.0.0", :port => PORT}) do |ws_conn|
      # クライアント接続がある度にその情報が ws_conn に入って来る
      ws_conn.onopen do		# そのクライアントが接続開始してきたとき
        @client[ws_conn] = {openat: Time.now}
        sendinfo(ws_conn, "うっす!")
        printf("%d guest(s)\n", @client.length)
      end
      ws_conn.onmessage do |message|	# クライアントから文字列が来たとき
        handleMessage(ws_conn, message)
      end
      ws_conn.onclose do			# クライアントが切断したとき
        @client.delete(ws_conn)		# そのクライアントを集合から削除
        # p "bye"+ws_conn.inspect
        printf("%d GUEST(s)\n", @client.length)
      end
      EM::defer do				# 共通で実行するスレッド
        # Thread.new do のほうがいいかも
        puts "..captured!"
        loop do
          print("Enter message for all @client: ")
          line = gets
          puts("Sending")
          @client.each{|conn| conn.send(line.chomp) }
        end
      end
    end
  end
end
QZ.new.start