예제 #1
0
// handle a Start message. We set a lock when someone clicks Start
// to prevent race conditions.
func handleStart(table channels.Realm, user string, wc WebolithCommunicator,
	sender channels.SocketMessageSender) {
	log.Println("[DEBUG] In handleStart....")
	sendFail := func(errorCode string) {
		sender.BroadcastMessage(table, FailMT, errorCode)
	}
	// XXX: Set a lock for this table on start.
	st := gameStates.getState(table)
	st.Lock()
	defer st.Unlock()

	if st.options == nil {
		// XXX: This should always be really quick but maybe once in a
		// while it'll fail; should prompt user to try again
		log.Println("[ERROR] Settings for this table do not yet exist!")
		sendFail(FailureSettingsDoNotExist)
		return
	}
	users.wantsToPlay(table, user)
	if !users.allowStart(table) {
		log.Println("[DEBUG] Start not yet allowed.")
		sendFail(FailureNotAllowed)
		return
	}

	if st.going != GameDone {
		log.Println("[DEBUG] This game is going or about to start.")
		sendFail(FailureGameGoing)
		return
	}
	st.going = GameInitializing
	wordList := getWordList(wc, st.options.WordListID)
	if wordList == nil {
		log.Println("[ERROR] Got nil word list, error!")
		sendFail(FailureNullWordList)
		return
	}
	st.setList(wordList)
	qToSend := st.nextQuestionSet(st.options.QuestionsToPull)
	// Turn the raw alphagrams into full question objects.
	fullQResponse, err := getFullQInfo(wc, qToSend, wordList.Lexicon)
	if err != nil {
		log.Println("[ERROR] Error getting full Q response!", err)
		sendFail(FailureQuestionInfo)
		return
	}
	log.Println("[DEBUG] Got full Q response:", string(fullQResponse))
	countdown := time.NewTimer(time.Second * time.Duration(CountdownTime))
	st.setCountdownTimer(countdown)
	st.going = GameCountingDown
	sender.BroadcastMessage(table, CountdownMT, strconv.Itoa(CountdownTime))
	// Countdown before starting game.
	// We should not accept guesses until the game has started.
	go handleGameTimer(table, countdown, string(fullQResponse), sender)
	log.Println("[DEBUG] Leaving start, mutex should unlock.")
}
예제 #2
0
func handleGuess(data string, table channels.Realm, user string,
	sender channels.SocketMessageSender) {

	if gameStates.getGameGoing(table) != GameStarted {
		log.Println("[DEBUG] Got a guess when game had not started.")
		return
	}

	answer := gameStates.guess(data, table, user)
	if answer == nil {
		return
	}
	// Otherwise, broadcast correct guess and score!
	msg, err := json.Marshal(answer)
	if err != nil {
		log.Println("[ERROR] Marshalling answer", answer, err)
	}
	sender.BroadcastMessage(table, ScoreMT, string(msg))
}
예제 #3
0
func handleGameTimer(table channels.Realm, countdown *time.Timer,
	questionsToSend string, sender channels.SocketMessageSender) {

	<-countdown.C
	log.Println("[DEBUG] Finished counting down! About to send qs...")
	st := gameStates.getState(table)
	st.Lock()
	defer st.Unlock()
	st.going = GameStarted
	sender.BroadcastMessage(table, QuestionsMT, questionsToSend)
	sender.BroadcastMessage(table, TimerMT, strconv.Itoa(st.options.TimerSecs))
	// Start another nested goroutine here for game over. This looks
	// messy, but it seems easy enough to do.
	gameOver := time.NewTimer(time.Second * time.Duration(st.options.TimerSecs))
	st.setGameTimer(gameOver)
	go func() {
		<-gameOver.C
		log.Println("[DEBUG] This game is over!")
		st := gameStates.getState(table)
		st.Lock()
		defer st.Unlock()
		st.going = GameDone
		sender.BroadcastMessage(table, GameOverMT, "")
	}()
}