From cc4050e87e3bf73845fd6827135797dfeca73520 Mon Sep 17 00:00:00 2001 From: Andreas Neue Date: Sat, 19 Mar 2016 23:51:15 +0100 Subject: [PATCH] Added quiz module. --- modules/quiz.go | 182 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 modules/quiz.go diff --git a/modules/quiz.go b/modules/quiz.go new file mode 100644 index 0000000..10aa87a --- /dev/null +++ b/modules/quiz.go @@ -0,0 +1,182 @@ +// vi:ts=4:sts=4:sw=4:noet:tw=72 + +package modules + +import ( + "bufio" + "flokatirc/util" + "fmt" + "os" + "regexp" + "strings" + "time" + + "github.com/sorcix/irc" + + "code.dnix.de/an/xlog" +) + +type quizQuestion struct { + category, question, answer, regexp string +} + +var ( + quizCtrlCh = make(chan string, 1024) + quizAnswerCh = make(chan *irc.Message, 1024) + quizQuestions []quizQuestion +) + +func init() { + MsgFuncs["quiz"] = quizHandleMessage + RunFuncs["quiz"] = quiz + quizQuestions = quizLoadQuestions("./modules/quiz/questions.de") +} + +func quizHandleMessage(m *irc.Message) { + tok := strings.Split(m.Trailing, " ") + if len(tok) < 1 { + return + } + switch tok[0] { + case "!quizstart": + quizCtrlCh <- "start" + break + case "!quizstop": + quizCtrlCh <- "stop" + break + default: + quizAnswerCh <- m + break + } +} + +func quiz() { + SayCh <- fmt.Sprintf("%s\nquiz mod test. !quizstart to start, !quizstop to end.", "*") + for { + time.Sleep(1 * time.Millisecond) + select { + case s := <-quizCtrlCh: + if s == "start" { + quizRun() + } + default: + break + } + } +} + +func quizRun() { + for { + if !quizAskQuestion() { + return + } + } +} + +func quizAskQuestion() bool { + q := quizQuestions[util.Random(0, len(quizQuestions))] + SayCh <- fmt.Sprintf("%s\n%s (Kategorie: %s)", "*", q.question, q.category) + m, solved, cont := quizWaitForAnswer(q) + if solved { + SayCh <- fmt.Sprintf("%s\n%s hat die Frage beantwortet.", "*", m.Prefix) + } else { + SayCh <- fmt.Sprintf("%s\nNiemand konnte die Frage beantworten.", "*") + SayCh <- fmt.Sprintf("%s\nDie richtige Antwort wäre gewesen:", "*") + SayCh <- fmt.Sprintf("%s\n%s", "*", q.answer) + } + time.Sleep(5 * time.Second) + return cont +} + +func quizWaitForAnswer(q quizQuestion) (*irc.Message, bool, bool) { + i := 0 + t := 0 + for { + select { + case m := <-quizAnswerCh: + re, err := regexp.Compile(q.regexp) + if err != nil { + xlog.Error(err.Error()) + return nil, false, false + } + if re.MatchString(strings.ToLower(util.ReplaceUmlauts(m.Trailing))) { + return m, true, true + } + break + case s := <-quizCtrlCh: + if s == "stop" { + return nil, false, false + } + break + default: + time.Sleep(1 * time.Millisecond) + t++ + if t > 20000 { + t = 0 + i++ + if i > 3 { + return nil, false, true + } else { + quizGiveHint(q) + } + } + } + } +} + +func quizGiveHint(q quizQuestion) { + //SayCh <- fmt.Sprintf("%s\nHint: %s | %s", "*", q.answer, q.regexp) +} + +func quizLoadQuestions(path string) []quizQuestion { + file, err := os.Open(path) + if err != nil { + xlog.Fatal(err.Error()) + } + defer file.Close() + + questions := make([]quizQuestion, 0) + q := quizQuestion{"", "", "", ""} + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if len(line) == 0 || line[0] == '#' || line[0] == '\n' { + if q.category != "" { + questions = append(questions, q) + q = quizQuestion{"", "", "", ""} + } + } else { + tok := strings.Split(line, ": ") + switch tok[0] { + case "Category": + q.category = tok[1] + break + case "Question": + q.question = tok[1] + break + case "Answer": + q.answer = strings.Replace(tok[1], "#", "", -1) + q.answer = util.ReplaceUmlauts(q.answer) + regexp := strings.Split(tok[1], "#") + if q.regexp == "" { + if len(regexp) > 1 { + q.regexp = strings.ToLower(regexp[1]) + } else { + q.regexp = strings.ToLower(regexp[0]) + } + } + break + case "Regexp": + q.regexp = util.ReplaceUmlauts(tok[1]) + break + } + } + } + + if err := scanner.Err(); err != nil { + xlog.Fatal(err.Error()) + } + + return questions +}