/ Published in: TCL
                    
                                        
here is a little update for the popular moxquizz script for eggdrop i wrote
you can download the script here: http://moxquiz.bplaced.net/homepage/?seite=download
an also see a list of the new features there
                you can download the script here: http://moxquiz.bplaced.net/homepage/?seite=download
an also see a list of the new features there
                            
                                Expand |
                                Embed | Plain Text
                            
                        
                        Copy this code and paste it in your HTML
##
### moxquizz.tcl -- quizzbot for eggdrop 1.6.9+
##
### Author: Moxon <[email protected]> (AKA Sascha Lüdecke)
##
### Credits:
## - Artwork was done with heavy support of Michee <[email protected]>
## - Julika loved to discuss and suggested many things.
## - Imran Ghory provided more than 600 english questions.
## - Questions have been edited by Michee, Julika, Tobac, Imran and
## Klinikai_Eset
## - ManInBlack for supplemental scripting
## - numerous others, see the README for a more complete list.
## If you are missing, please tell me!
##
### Copyright (C) 2000 Moxon AKA Sascha Lüdecke
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
##
###
## $Id: moxquizz.tcl,v 1.175 2002/07/05 19:21:26 chat Exp $
###########################################################################
###########################################################################
###########################################################################
########################
### typ's mod config ###
########################
#Wieviel Sekunden sollen Schätzfragen offen sein?
set schaetztime 15
#Soll !vok erlaubt sein? (1=ja,2=nein)
set allow_vok 1
#Soll !halt erlaubt sein? (1=ja,2=nein)
set allow_halt 1
#Soll das Anti-Highlighting aktiviert sein? (1=ja,2=nein)
set allow_antihl 1
#Soll das gelbe Design aktiviert sein? (1=ja,2=nein)
set go_yellow 0
#Sollen statistische Daten im Web veröffentlicht werden? (1=ja,2=nein)
set allow_web 1
#Sollen Zeitrekorde gespeichert werden? (1=ja,2=nein)
set allow_rec 1
#Soll der Bot jeden Tag einmal neu starten? (1=ja,2=nein)
set daily_restart 0
########################
### typ's mod info ###
########################
# 1. Schätzfragen
# Schätzfragen müssen als Kategorie "Category: Schätzfragen" haben, ansonsten werden sie wie normale Quizfragen behandelt.
# Die Antworten dürfen lediglich aus arabischen Zahlen (ohne Trennpunkte) sein.
# 2. Ratefragen
# Ratefragen müssen als Kategorie "Category: Ratefragen" haben, ansonsten werden sie wie normale Quizfragen behandelt.
# Die Antworten müssen folgendes Format haben: Antwort1*Antwort2*Antwort3
# Das Ratefragen-Script basiert auf dem KAOS-Script von Mark A. Day.
# 3. A/M
# A/M steht für Anschläge pro Minute
# 4. Web-Statistiken
# Soweit von Dir erlaubt, sendet der QuizBot informationen an http://moxquiz.bplaced.net/homepage/
# 5. Support
# Support gibt es im MoxQuizz-Forum unter http://www.moxquizz.de/forum oder im #quiz.de @ irc.gamesurge.net
########################
### new commands ###
########################
#!vok - Zeigt die Antwort ohne Vokale
#!halt - Hält den Bot an
#!alltimes - Zeigt die ewige Rangliste an
#!server - Zeigt den Server, zu dem der Bot verbunden ist
#!time - Zeigt Deine Spieldauer
#!rehash - OPs only
#!restart - OPs only
###########################################################################
###########################################################################
###########################################################################
## Version:
set version_moxquizz "0.8.1 {type:mod von http://moxquiz.bplaced.net/homepage/}"
package require msgcat
package require http
namespace import -force msgcat::*
###########################################################################
##
## ATTENTION:
##
## Defaults for bot configuration. Don't edit here, edit the file
## moxquizz.rc instead!
##
###########################################################################
# system stuff
variable quizbasedir moxquizz
variable datadir $quizbasedir/quizdata
variable configfile $quizbasedir/moxquizz.rc
variable intldir $quizbasedir/intl
variable rankfile $datadir/rank.data
variable allstarsfile $datadir/rankallstars.data
variable statsfile $datadir/stats.data
variable userqfile $datadir/questions.user.new
variable commentsfile $datadir/comments.txt
variable quizhelp
# these will be searched in $intldir/$quizconf(language)
variable channeltipfile channeltips.txt
variable channelrulesfile channelrules.txt
variable pricesfile prices.txt
variable helpfile help.txt
#
# Configuration map
#
variable quizconf
set quizconf(quizchannel) "#quiz"
set quizconf(quizloglevel) 1
# several global numbers
set quizconf(maxranklines) 100
set quizconf(tipcycle) 5
set quizconf(useractivetime) 240
set quizconf(userqbufferlength) 20
set quizconf(winscore) 30
set quizconf(overrunlimit) 29
# timer delays in seconds
set quizconf(askdelay) 12
set quizconf(tipdelay) 14
# safety features and other configs
set quizconf(lastwinner_restriction) no
set quizconf(lastwinner_max_games) 4
set quizconf(overrun_protection) no
set quizconf(colorize) yes
set quizconf(monthly_allstars) no
set quizconf(channeltips) yes
set quizconf(pausemoderated) no
set quizconf(userquestions) yes
set quizconf(msgwhisper) no
set quizconf(channelrules) yes
set quizconf(prices) yes
set quizconf(stripumlauts) no
set quizconf(statslog) no
set quizconf(aftergameaction) newgame
set quizconf(language) de
##
###########################################################################
##
## stuff for the game state
##
#typ
set ctcp-version "MoxQuizz für #Quiz.de @ irc.GameSurge.net"
variable answerarray
variable schaetzarray
variable schaetzend ""
variable schaetzwert ""
variable timetypasked [clock clicks -milliseconds]
variable subexp ""
variable bestscore 0
# values = stopped, paused, asked, waittoask, halted
variable quizstate "halted"
variable statepaused ""
variable statemoderated ""
variable usergame 0
variable timeasked [unixtime]
variable revoltmax 0
# values = newgame, stop, halt, exit
variable aftergame $quizconf(aftergameaction)
variable channeltips ""
variable channelrules ""
variable prices ""
#
# variables for the ranks and user handling
#
variable timerankreset [unixtime]
variable userlist
variable allstarsarray
variable revoltlist ""
variable lastsolver ""
variable lastsolvercount 0
variable lastwinner ""
variable lastwinnercount 0
variable allstars_starttime 0
variable ignore_for_userquest ""
#
# stuff for the question
#
variable tiplist ""
variable theq
variable qnumber 0
variable qnum_thisgame 0
variable userqnumber 0
variable tipno 0
variable qlist ""
variable qlistorder ""
variable userqlist ""
#
# doesn't fit elsewhere
#
variable whisperprefix "NOTICE"
variable statsfilefd "closed"
##################################################
## bindings
# bot running status
bind dcc P !init moxquiz_init
bind dcc P !stop moxquiz_stop
bind dcc P !halt moxquiz_halt
bind dcc P !pause moxquiz_pause
bind dcc P !cont moxquiz_cont
bind dcc P !reset moxquiz_reset
bind dcc m !exit moxquiz_exit
bind dcc m !aftergame moxquiz_aftergame
# bot speaking and hopping stuff
bind dcc P !say moxquiz_say
bind dcc P !act moxquiz_action
bind dcc m !allsay moxquiz_say_everywhere
bind dcc m !allact moxquiz_action_everywhere
bind dcc Q !join moxquiz_join
bind dcc Q !part moxquiz_part
bind dcc Q !quizto moxquiz_quizto
bind dcc Q !quizleave moxquiz_quizleave
# commands for the questions
bind dcc P !solve moxquiz_solve
bind dcc P !tip moxquiz_tip
bind dcc P !skipuserquest moxquiz_skipuserquest
bind dcc Q !setscore moxquiz_set_score
bind dcc m !qsave moxquiz_saveuserquests
bind dcc Q !reload moxquiz_reload
# status and configuration
bind dcc P !status moxquiz_status
bind dcc m !load moxquiz_config_load
bind dcc m !save moxquiz_config_save
bind dcc m !set moxquiz_config_set
# userquest and other user (public) commands
bind pubm - * moxquiz_pubm
bind pub - !ask moxquiz_ask
bind pub - .ask moxquiz_ask
bind pub - !quiz moxquiz_ask
bind pub - .quiz moxquiz_ask
bind pub - !start moxquiz_ask
bind pub - .start moxquiz_ask
bind pub - !revolt moxquiz_user_revolt
bind pub - !end moxquiz_user_revolt
bind msg - !userquest moxquiz_userquest
bind msg - !usercancel moxquiz_usercancel
bind msg - !usertip moxquiz_usertip
bind msg - !usersolve moxquiz_usersolve
bind pub P !nuq moxquiz_userquest_ignore
bind pub P !uq moxquiz_userquest_unignore
bind pub P !listnuq moxquiz_userquest_listignores
bind pub P !clearnuq moxquiz_userquest_clearignores
bind msg - !qhelp moxquiz_help
bind pub - !qhelp moxquiz_pub_help
bind pub - !score moxquiz_pub_score
bind pub - !rank moxquiz_pub_rank
bind pub - !allstars moxquiz_pub_allstars
bind pub - !comment moxquiz_pub_comment
bind pub - !fehler moxquiz_pub_comment
bind dcc - !comment moxquiz_dcc_comment
bind msg - !rules moxquiz_rules
bind pub - !rules moxquiz_pub_rules
bind msg - !version moxquiz_version
bind pub - !version moxquiz_pub_version
# mini funstuff
bind pub - !hi moxquiz_pub_hi
#bind ctcp - action moxquiz_purr
# commands to manage players and rank
bind dcc P !allstars moxquiz_allstars
bind dcc m !allstarssend moxquiz_allstars_send
bind dcc m !allstarsload moxquiz_allstars_load
bind dcc P !rank moxquiz_rank
bind dcc Q !rankdelete moxquiz_rank_delete
bind dcc m !rankload moxquiz_rank_load
bind dcc m !ranksave moxquiz_rank_save
bind dcc Q !rankreset moxquiz_rank_reset
bind dcc Q !rankset moxquiz_rank_set
# Some events the bot reacts on
bind nick - * moxquiz_on_nickchanged
bind join - * moxquiz_on_joined
bind mode - "*m" moxquiz_on_moderated
bind evnt - prerehash mx_event
bind evnt - rehash mx_event
## DEBUG
bind dcc n !colors moxquiz_colors
###########################################################################
#
# bot running commands
#
###########################################################################
## reset game
proc moxquiz_reset {handle idx arg} {
global quizstate
moxquiz_stop $handle $idx $arg
moxquiz_rank_reset $handle $idx $arg
moxquiz_init $handle $idx $arg
}
## initialize
proc moxquiz_init {handle idx arg} {
global qlist version_moxquizz banner bannerspace quizstate
global quizconf aftergame
set quizstate "halted"
set aftergame $quizconf(aftergameaction)
if {$quizconf(quizchannel) != ""} {
mxirc_say $quizconf(quizchannel) [mc "%sHello! I am a MoxQuizz version %s and ready to squeeze your brain!" "[banner] [botcolor txt]" "[col bold]$version_moxquizz[col bold][botcolor txt]"]
mxirc_say $quizconf(quizchannel) [mc "%s%d questions in database, just %s!ask%s. Report bugs and suggestions to [email protected]" "[bannerspace] [botcolor txt]" [llength $qlist] [col bold] "[col bold][botcolor txt]"]
mx_log "--- Game initialized"
} else {
mxirc_dcc $idx "ERROR: quizchannel is set to an empty string, use .!quizto to set one."
}
return 1
}
## stop
## stop everything and kill all timers
proc moxquiz_stop {handle idx arg} {
global quizstate banner bannerspace
global quizconf
variable t
variable prefix [banner]
## called directly?
if {[info level] != 1} {
set prefix [bannerspace]
} else {
set prefix [banner]
}
set quizstate "stopped"
## kill timers
foreach t [utimers] {
if {[lindex $t 1] == "mx_timer_ask" || [lindex $t 1] == "mx_timer_tip"} {
killutimer [lindex $t 2]
}
}
mx_log "--- Game stopped."
mxirc_say $quizconf(quizchannel) [mc "%s %sQuiz stopped." $prefix [botcolor boldtxt]]
return 1
}
## halt
## halt everything and kill all timers
proc moxquiz_halt {handle idx arg} {
global quizstate banner bannerspace
global quizconf
variable t
variable prefix [banner]
## called directly?
if {[info level] != 1} {
set prefix [bannerspace]
} else {
set prefix [banner]
}
set quizstate "halted"
## kill timers
foreach t [utimers] {
if {[lindex $t 1] == "mx_timer_ask" || [lindex $t 1] == "mx_timer_tip"} {
killutimer [lindex $t 2]
}
}
mx_log "--- Game halted."
mxirc_say $quizconf(quizchannel) [mc "%s %sQuiz halted. Say !ask for new questions." $prefix [botcolor boldtxt]]
utimer 5 mx_restart
return 1
}
## reload questions
proc moxquiz_reload {handle idx arg} {
global qlist quizconf
global datadir
variable alist ""
variable banks
variable suffix
set arg [string trim $arg]
if {$arg == ""} {
# get question files
set alist [glob -nocomplain "$datadir/questions.*"]
# get suffixes
foreach file $alist {
regexp "^.*\\.(\[^\\.\]+)$" $file foo suffix
set banks($suffix) 1
}
# report them
mxirc_dcc $idx "There are the following question banks available (current: $quizconf(questionset)): [lsort [array names banks]]"
} else {
if {[mx_read_questions $arg] != 0} {
mxirc_dcc $idx "There was an error reading files for $arg."
mxirc_dcc $idx "There are [llength $qlist] questions available."
} else {
mxirc_dcc $idx "Reloaded database, [llength $qlist] questions."
set quizconf(questionset) $arg
}
}
return 1
}
## pause
proc moxquiz_pause {handle idx arg} {
global quizstate statepaused banner timeasked
global quizconf
variable qwasopen "."
if {[regexp "(halted|paused)" $quizstate]} {
mxirc_dcc $idx "Quiz state is $quizstate. Command ignored."
} else {
if {$quizstate == "asked"} {
foreach t [utimers] {
if {[lindex $t 1] == "mx_timer_tip"} {
killutimer [lindex $t 2]
}
}
set qwasopen [mc " after %s." [mx_duration $timeasked]]
} elseif {$quizstate == "waittoask"} {
foreach t [utimers] {
if {[lindex $t 1] == "mx_timer_ask"} {
killutimer [lindex $t 2]
}
}
}
set statepaused $quizstate
set quizstate "paused"
mx_log "--- Game paused$qwasopen Quiz state was: $statepaused"
mxirc_say $quizconf(quizchannel) [mc "%sQuiz paused%s" "[banner] [botcolor boldtxt]" $qwasopen]
}
return 1
}
## continue
proc moxquiz_cont {handle idx arg} {
global quizstate banner bannerspace timeasked
global theq statepaused usergame statemoderated
global quizconf
if {$quizstate != "paused"} {
mxirc_dcc $idx "Game not paused, command ignored."
} else {
if {$statepaused == "asked"} {
if {$usergame == 1} {
set txt [mc "%sQuiz continued. The user question open since %s, worth %d point(s):" "[banner] [botcolor boldtxt]" [mx_duration $timeasked] $theq(Score)]
} else {
set txt [mc "%sQuiz continued. The question open since %s, worth %d point(s):" "[banner] [botcolor boldtxt]" [mx_duration $timeasked] $theq(Score)]
}
mxirc_say $quizconf(quizchannel) $txt
mxirc_say $quizconf(quizchannel) "[bannerspace] [botcolor question]$theq(Question)"
utimer $quizconf(tipdelay) mx_timer_tip
} else {
mxirc_say $quizconf(quizchannel) [mc "%sQuiz continued. Since there is no open question, a new one will be asked." "[banner] [botcolor boldtxt]"]
utimer 3 mx_timer_ask
}
set quizstate $statepaused
set statepaused ""
set statemoderated ""
mx_log "--- Game continued."
}
return 1
}
## show module status
proc moxquiz_status {handle idx arg} {
global quizstate statepaused qlist banner version_moxquizz userlist
global timeasked uptime
global usergame userqlist theq qnumber
global qnum_thisgame aftergame
global quizconf
variable askleft 0 rankleft 0 tipleft 0
variable txt
variable chansjoined ""
## banner and where I am
set txt "I am [mx_strip_colors [banner]] version $version_moxquizz, up for [mx_duration $uptime]"
if {$quizconf(quizchannel) == ""} {
set txt "$txt, not quizzing on any channel."
} else {
set txt "$txt, quizzing on channel \"$quizconf(quizchannel)\"."
}
mxirc_dcc $idx $txt
mxirc_dcc $idx "I know the channels [channels]."
foreach chan [channels] {
if {[botonchan $chan]} {
set chansjoined "$chansjoined $chan"
}
}
if {$chansjoined == ""} {
set chansjoined " none"
}
mxirc_dcc $idx "I currently joined:$chansjoined."
if {$quizstate == "asked" || $statepaused == "asked"} {
## Game running? User game?
set txt "There is a"
if {$usergame == 1} {
set txt "$txt user"
}
set txt "$txt game running."
if {[mx_userquests_available]} {
set txt "$txt [mx_userquests_available] user quests scheduled."
} else {
set txt "$txt No user quest is scheduled."
}
set txt "$txt Quiz state is: $quizstate."
mxirc_dcc $idx $txt
## Open question? Quiz state?
set txt "The"
if {[info exists theq(Level)]} {
set txt "$txt level $theq(Level)"
}
set txt "$txt question no. $qnum_thisgame is:"
if {[info exists theq(Category)]} {
set txt "$txt ($theq(Category))"
}
mxirc_dcc $idx "$txt \"$theq(Question)\" open for [mx_duration $timeasked], worth $theq(Score) points."
} else {
## no open question, no game running
set txt "There is no question open."
set txt "$txt Quiz state is: $quizstate."
if {[mx_userquests_available]} {
set txt "$txt [mx_userquests_available] user quests scheduled."
} else {
set txt "$txt No user quest is scheduled."
}
mxirc_dcc $idx $txt
}
mxirc_dcc $idx "Action after game won: $aftergame"
foreach t [utimers] {
if {[lindex $t 1] == "mx_timer_ask"} {
set askleft [lindex $t 0]
}
if {[lindex $t 1] == "mx_timer_tip"} {
set tipleft [lindex $t 0]
}
}
mxirc_dcc $idx "Tipdelay: $quizconf(tipdelay) ($tipleft) Askdelay: $quizconf(askdelay) ($askleft) Tipcycle: $quizconf(tipcycle)"
mxirc_dcc $idx "I know about [llength $qlist] normal and [llength $userqlist] user questions. Question number is $qnumber."
mxirc_dcc $idx "There are [llength [array names userlist]] known people, winscore is $quizconf(winscore)."
mxirc_dcc $idx "Game row restriction: $quizconf(lastwinner_restriction), row length: $quizconf(lastwinner_max_games)"
return 1
}
## exit -- finish da thing and logoff
proc moxquiz_exit {handle idx arg} {
global rankfile uptime botnick statsfilefd
global quizconf
mx_log "--- EXIT requested."
mxirc_say $quizconf(quizchannel) [mc "%sI am leaving now, after running for %s." "[banner] [botcolor boldtxt]" [mx_duration $uptime]]
if {$arg != ""} {
mxirc_say $quizconf(quizchannel) "[bannerspace] $arg"
}
# moxquiz_quizleave $handle $idx $arg
moxquiz_rank_save $handle $idx {}
moxquiz_saveuserquests $handle $idx "all"
moxquiz_config_save $handle $idx {}
if {$statsfilefd != "closed"} { close $statsfilefd }
mxirc_dcc $idx "$botnick now exits."
mx_log "--- $botnick exited"
mx_log "**********************************************************************"
utimer 10 die
}
## aftergame -- what to do if the game is over (won or desert detection)
proc moxquiz_aftergame {handle idx arg} {
global aftergame quizstate
variable thisnext "this"
if {$quizstate == "stopped" || $quizstate == "halted"} {
set thisnext "next"
}
if {$arg == ""} {
mxirc_dcc $idx "After $thisnext game I am planning to: \"$aftergame\"."
mxirc_dcc $idx "Possible values are: exit, halt, stop, newgame."
} else {
switch -regexp $arg {
"(exit|halt|stop|newgame)" {
set aftergame $arg
mxirc_dcc $idx "After $thisnext game I now will: \"$aftergame\"."
}
default {
mxirc_dcc $idx "Invalid action. Chosse from: exit, halt, stop and newgame."
}
}
}
return 1
}
####################
# bot control stuff
####################
## echo a text send by /msg
proc moxquiz_say {handle idx arg} {
global funstuff_enabled botnick
global quizconf
variable channel
set arg [string trim $arg]
if {[regexp -nocase "^(#\[^ \]+)( +.*)?" $arg foo channel arg]} {
## check if on channel $channel
if {[validchan $channel] && ![botonchan $channel]} {
mxirc_dcc $idx "Sorry, I'm not on channel \"$channel\"."
return
}
} else {
set channel $quizconf(quizchannel)
}
set arg [string trim $arg]
mxirc_say $channel "$arg"
variable unused "" cmd "" rest ""
# if it was a fun command, execute it with some delay
if {$funstuff_enabled &&
[regexp "^(!\[^ \]+)(( *)(.*))?" $arg unused cmd waste spaces rest] &&
[llength [bind pub - $cmd]] != 0} {
if {$rest == ""} {
set rest "{}"
} else {
set rest "{$rest}"
}
eval "[bind pub - $cmd] {$botnick} {} {} {$channel} $rest"
}
}
## say something on al channels
proc moxquiz_say_everywhere {handle idx arg} {
if {$arg != ""} {
mxirc_say_everywhere $arg
} else {
mxirc_dcc $idx "What shall I say on every channel?"
}
}
## act as sent by /msg
proc moxquiz_action {handle idx arg} {
global quizconf
variable channel
set arg [string trim $arg]
if {[regexp -nocase "^(#\[^ \]+)( +.*)?" $arg foo channel arg]} {
## check if on channel $channel
if {[validchan $channel] && ![botonchan $channel]} {
mxirc_dc $idx "Sorry, I'm not on channel \"$channel\"."
return
}
} else {
set channel $quizconf(quizchannel)
}
set arg [string trim $arg]
mxirc_action $channel "$arg"
}
## say something on al channels
proc moxquiz_action_everywhere {handle idx arg} {
if {$arg != ""} {
mxirc_action_everywhere $arg
} else {
mxirc_dcc $idx "What shall act like on every channel?"
}
}
## hop to another channel
proc moxquiz_join {handle idx arg} {
global quizconf
if {[regexp -nocase "^(#\[^ \]+)( +.*)?" $arg foo channel arg]} {
set channel [string tolower $channel]
if {[validchan $channel] && [botonchan $channel]} {
set txt "I am already on $channel."
if {$channel == $quizconf(quizchannel)} {
set txt "$txt It's the quizchannel."
}
mxirc_dcc $idx $txt
} else {
channel add $channel
channel set $channel -inactive
mxirc_dcc $idx "Joined channel $channel."
}
} else {
mxirc_dcc $idx "Please specify channel I shall join. \"$arg\" not recognized."
}
}
## part an channel
proc moxquiz_part {handle idx arg} {
global quizconf
if {[regexp -nocase "^(#\[^ \]+)( +.*)?" $arg foo channel arg]} {
set channel [string tolower $channel]
if {[validchan $channel]} {
if {$channel == $quizconf(quizchannel)} {
mxirc_dcc $idx "Cannot leave quizchannel via part. User !quizleave or !quizto to do this."
} else {
channel set $channel +inactive
mxirc_dcc $idx "Left channel $channel."
}
} else {
mxirc_dcc $idx "I am not on $channel."
}
} else {
mxirc_dcc $idx "Please specify channel I shall part. \"$arg\" not recognized."
}
}
## quiz to another channel
proc moxquiz_quizto {handle idx arg} {
global quizconf
if {[regexp "^#.*" $arg] == 0} {
mxirc_dcc $idx "$arg not a valid channel."
} else {
if {$quizconf(quizchannel) != ""} {
# channel set $quizconf(quizchannel) +inactive
mxirc_say $quizconf(quizchannel) [mc "Quiz is leaving to %s. Goodbye!" $arg]
}
set quizconf(quizchannel) [string tolower $arg]
channel add $quizconf(quizchannel)
channel set $quizconf(quizchannel) -inactive
mxirc_say $quizconf(quizchannel) [mc "Quiz is now on this channel. Hello!"]
mxirc_dcc $idx "quiz to channel $quizconf(quizchannel)."
mx_log "--- quizto channel $quizconf(quizchannel)"
}
return 1
}
## quiz leave a channel
proc moxquiz_quizleave {handle idx arg} {
global quizconf banner
if {$arg == ""} {
mxirc_say $quizconf(quizchannel) [mc "%s Goodbye." [banner]]
} else {
mxirc_say $quizconf(quizchannel) "[banner] $arg"
}
if {$quizconf(quizchannel) != ""} {
channel set $quizconf(quizchannel) +inactive
mx_log "--- quizleave channel $quizconf(quizchannel)"
mxirc_dcc $idx "quiz left channel $quizconf(quizchannel)"
set quizconf(quizchannel) ""
} else {
mxirc_dcc $idx "I'm not quizzing on any channel."
}
return 1
}
###########################################################################
#
# commands for the questions
#
###########################################################################
## something was said. Solution?
proc moxquiz_pubm {nick host handle channel text} {
global quizstate banner bannerspace
global timeasked theq aftergame
global usergame revoltlist
global lastsolver lastsolvercount
global lastwinner lastwinnercount
global botnick bestscore
global userlist channeltips prices
global quizconf
variable bestscore 0 lastbestscore 0 lastbest ""
variable userarray
variable authorsolved 0 waitforrank 0 gameend 0
## only accept chatter on quizchannel
if {![mx_str_ieq $channel $quizconf(quizchannel)]} {
return
}
## record that the $nick spoke and create entries for unknown people
mx_getcreate_userentry $nick $host
array set userarray $userlist($nick)
set hostmask $userarray(mask)
## not in asking state?
if {$quizstate != "asked"} {
return
}
# nick has revolted
#if {[lsearch -exact $revoltlist $hostmask] != -1} {
# return
#}
# tweak umlauts in input
set text [mx_tweak_umlauts $text]
global answerarray
set regohneleerzeichen $theq(Regexp)
regsub -all " " $regohneleerzeichen "" regohneleerzeichen
if {[regexp -nocase -- $theq(Regexp) $text] || [regexp -nocase -- $regohneleerzeichen $text]} {
foreach name [array names answerarray] {
unset answerarray($name)
}
## ignore games_max in a row winner
if {[mx_str_ieq [maskhost $host] $lastwinner]
&& $lastwinnercount >= $quizconf(lastwinner_max_games)
&& $quizconf(lastwinner_restriction) == "yes"} {
mxirc_notc $nick [mc "No, you've won the last %d games." $quizconf(lastwinner_max_games)]
return
}
# nick is author of userquest
#if {([info exists theq(Author)] && [mx_str_ieq $nick $theq(Author)])
#|| ([info exists theq(Hostmask)] && [mx_str_ieq [maskhost $host] $theq(Hostmask)])} {
# set authorsolved 1
#}
## return if overrunprotection set and limit reached
#if {$quizconf(overrun_protection) == "yes"
# && $userarray(score) == 0
# && [mx_users_in_rank] > 2
# && [mx_overrun_limit_reached]} {
# # [pending] TRANSLATE!
# mxirc_notc $nick [mc "Sorry, overrun protection enabled. Wait till end of game."]
# return
#}
## reset quiz state related stuff (and save userquestions)
mx_answered
set duration [mx_duration $timeasked]
set recdiff ""
global timetypasked schaetzend allow_rec
if {$schaetzend != "" && $schaetzend > 0} {
set typdur $schaetzend
set schaetzend ""
} else {
set typdur [expr ([clock clicks -milliseconds] - $timetypasked) * 0.001]
if {$typdur < "10.000" &&$allow_rec} {
set record [mx_read_record $text]
if {$record == ""} {
mx_save_record $nick $typdur $text
} else {
set recholder [lindex [split $record] 0]
set rectime [lindex [split $record] 1]
if {$rectime > $typdur} {
mx_save_record $nick $typdur $text
}
set recdiff [expr $typdur - $rectime]
if {$recdiff > 0} {set recdiff "+${recdiff}"} else {set recdiff "\002$recdiff\002"}
set recdiff "\(${recdiff} Sek. zu [mx_nickobf $recholder]\) "
}
}
}
# if it wasn't the author
if {!$authorsolved} {
## save last top score for the test if reset is near (later below)
set lastbest [lindex [lsort -command mx_sortrank [array names userlist]] 0]
if {$lastbest == ""} {
set lastbestscore 0
} else {
array set aa $userlist($lastbest)
set lastbestscore $aa(score)
}
## record nick for bonus points
if {[mx_str_ieq [maskhost $host] $lastsolver]} {
incr lastsolvercount
} else {
set lastsolver [maskhost $host]
set lastsolvercount 1
}
## save score (set started time to time of first point)
incr userarray(score) $theq(Score)
if {$userarray(score) == 1} {
set userarray(started) [unixtime]
}
set userlist($nick) [array get userarray]
## tell channel, that the question is solved
mx_log "--- solved after $duration by $nick with \"$text\", now $userarray(score) points"
set daten [mx_incr_qnr]
global vokspamvar hintmax hintlist
set vokspamvar 0
set hintmax 0
set hintlist ""
mx_statslog "solved" [list [unixtime] $nick $duration $userarray(score) $theq(Score)]
#mxirc_say $channel [mc "%s solved after %s and now has %s<%d>%s points (+%d) on rank %d." "[banner] [botcolor nick]$nick[botcolor txt]" $duration [botcolor nick] $userarray(score) [botcolor txt] $theq(Score) [mx_get_rank_pos $nick]]
set answrnr [mx_answ_user $nick 1]
set total [regexp -all -nocase {[A-Z]|[0-9]|[ ]} $text]
#bugfix:
if {$typdur <= 0 || $typdur == ""} { set typdur $duration }
set speed [expr $total / $typdur * 60]
mxirc_rsay $channel [mc "%s löst nach %s Sek. ${recdiff}seine %d. Frage und hat %s<%d>%s Punkte (+%d), Platz 9,1~%d~1,11.%s %sA/M: %3.0f" "[banner] [botcolor nick]$nick[botcolor txt]" $typdur $answrnr [botcolor nick] $userarray(score) [botcolor txt] $theq(Score) [mx_get_rank_pos $nick] [botcolor norm] [botcolor question] $speed]
# remove area of tip generation tags
regsub -all "\#(\[^\#\]*\)\#" $theq(Answer) "\\1" answer
global schaetzwert subexp
if {$schaetzwert != ""} {
set showanswer $answer
set schaetzwert [commas $schaetzwert]
set stotal [regexp -all -nocase {[A-Z]|[0-9]|[ ]} $subexp]
if {$stotal > 4} {
regsub -all $subexp $showanswer [commas $subexp] showanswer
}
set showanswer "$showanswer \(Abweichung: ${schaetzwert}\)"
set schaetzwert ""
} else {
set showanswer $answer
}
mxirc_say $channel [mc "%sThe answer was:%s%s" "[bannerspace] [botcolor txt]" "[botcolor norm] [botcolor answer]" $showanswer]
## honor good games!
if {$lastsolvercount == 3} {
mxirc_say $channel [mc "%sThree in a row!" "[bannerspace] [botcolor txt]"]
mx_log "--- $nick has three in a row."
mx_statslog "tiar" [list [unixtime] $nick 3 0]
} elseif {$lastsolvercount == 5} {
mxirc_say $channel [mc "%sCongratulation, five in a row! You receive an extra point." "[bannerspace] [botcolor txt]"]
mx_log "--- $nick has five in a row. score++"
mx_statslog "tiar" [list [unixtime] $nick 5 1]
moxquiz_rank_set $botnick 0 "$nick +1"
} elseif {$lastsolvercount == 10} {
mxirc_say $channel [mc "%sTen in a row! This is really rare, so you get 3 extra points." "[bannerspace] [botcolor txt]"]
mx_log "--- $nick has ten in a row. score += 3"
mx_statslog "tiar" [list [unixtime] $nick 10 3]
moxquiz_rank_set $botnick 0 "$nick +3"
} elseif {$lastsolvercount == 20} {
mxirc_say $channel [mc "%sTwenty in a row! This is extremely rare, so you get 5 extra points." "[bannerspace] [botcolor txt]"]
mx_log "--- $nick has twenty in a row. score += 5"
mx_statslog "tiar" [list [unixtime] $nick 20 5]
moxquiz_rank_set $botnick 0 "$nick +5"
}
## rankreset, if above winscore
# notify if this comes near
set best [lindex [lsort -command mx_sortrank [array names userlist]] 0]
if {$best == ""} {
set bestscore 0
} else {
array set aa $userlist($best)
set bestscore $aa(score)
}
set waitforrank 0
if {[mx_str_ieq $best $nick] && $bestscore > $lastbestscore} {
array set aa $userlist($best)
# tell the end is near
if {$bestscore >= $quizconf(winscore)} {
mx_web $daten $nick
set price "."
if {$quizconf(prices) == "yes"} {
set price " [lindex $prices [rand [llength $prices]]]"
}
mxirc_say $channel [mc "%s%s reaches %d points and wins%s" "[bannerspace] [botcolor txt]" $nick $quizconf(winscore) $price]
set now [unixtime]
if {[mx_str_ieq [maskhost $host] $lastwinner]} {
incr lastwinnercount
if {$lastwinnercount >= $quizconf(lastwinner_max_games)
&& $quizconf(lastwinner_restriction) == "yes"} {
mxirc_say $channel [mc "%s: since you won %d games in a row, you will be ignored for the next game." $nick $quizconf(lastwinner_max_games)]
}
} else {
set lastwinner [maskhost $host]
set lastwinnercount 1
}
# save $nick in allstars table
mx_saveallstar $now [expr $now - $aa(started)] $bestscore $nick [maskhost $host]
mx_statslog "gamewon" [list $now $nick $bestscore $quizconf(winscore) [expr $now - $aa(started)]]
moxquiz_alltimestars_load $botnick 0 $nick
#mxsave_alltimestars
moxquiz_rank $botnick 0 {}
moxquiz_rank_reset $botnick {} {}
set gameend 1
set waitforrank 15
} elseif {$bestscore == [expr $quizconf(winscore) / 2]} {
mxirc_say $channel [mc "%sHalftime. Game is won at %d points." \
"[bannerspace] [botcolor txt]" $quizconf(winscore)]
} elseif {$bestscore == [expr $quizconf(winscore) - 10]} {
mxirc_say $channel [mc "%s%s has 10 points to go." "[bannerspace] [botcolor txt]" $best]
} elseif {$bestscore == [expr $quizconf(winscore) - 5]} {
mxirc_say $channel [mc "%s%s has 5 points to go." "[bannerspace] [botcolor txt]" $best]
} elseif {$bestscore >= [expr $quizconf(winscore) - 3]} {
mxirc_say $channel [mc "%s%s has %d point(s) to go." \
"[bannerspace] [botcolor txt]" $best [expr $quizconf(winscore) - $bestscore]]
}
# show rank at 1/3, 2/3 of and 5 before winscore
set spitrank 1
foreach third [list [expr $quizconf(winscore) / 3] [expr 2 * $quizconf(winscore) / 3] [expr $quizconf(winscore) - 5]] {
if {$lastbestscore < $third && $bestscore >= $third && $spitrank} {
moxquiz_rank $botnick 0 {}
set spitrank 0
set waitforrank 15
}
}
}
} else {
## tell channel, that the question is solved by author
mx_log "--- solved after $duration by $nick with \"$text\" by author"
mxirc_say $channel [mc "%s solved own question after %s and gets no points, keeping %s<%d>%s points on rank %d." \
"[banner] [botcolor nick]$nick[botcolor txt]" $duration [botcolor nick] $userarray(score) [botcolor txt] [mx_get_rank_pos $nick]]
# remove area of tip generation tags
regsub -all "\#(\[^\#\]*\)\#" $theq(Answer) "\\1" answer
mxirc_say $channel [mc "%sThe answer was:%s%s" "[bannerspace] [botcolor txt]" "[botcolor norm] [botcolor answer]" $answer]
}
## Give some occasional tips
if {$quizconf(channeltips) == "yes" && [rand 30] == 0} {
mxirc_say $channel [mc "%sHint: %s" "[bannerspace] [botcolor txt]" [lindex $channeltips [rand [llength $channeltips]]]]
}
## check if game has ended and react
if {!$gameend || $aftergame == "newgame"} {
# set up ask timer
utimer [expr $waitforrank + $quizconf(askdelay)] mx_timer_ask
} else {
mx_aftergameaction
}
} elseif {[info exists theq(Category)]} {
if {$theq(Category) == "Schätzfragen"} {
set text [lindex [split $text] 0]
if {![regexp "\[0-9\]+" $text]} { return }
if {[regexp "\[A-Z\]" $text]} { return }
if {[regexp "\[a-z\]" $text]} { return }
if {[regexp -all -nocase {[A-Z]|[0-9]|[ ]} $text] > 12} {}
global schaetzarray timetypasked subexp
regsub -all \[{',.!}] $subexp "" subexp
set entry schaetzarray($nick)
set text [expr $text - $subexp]
if {$text < 0} {
set text [expr $text * -1]
}
set typdur [expr ([clock clicks -milliseconds] - $timetypasked) * 0.001]
set schaetzarray($nick) [list $text $typdur]
}
} else {
if {$text==""||$text==" "} { return }
if {[info exists answerarray($nick)]} {
set textzwei [lindex $answerarray($nick) 1]
if {$textzwei==$text||$textzwei=="$text "} { return }
regsub "\{" $textzwei "" textzwei
regsub "\}" $textzwei "" textzwei
regsub " " $textzwei "" textzwei
if {$textzwei==$text||$textzwei=="$text "} { return }
set textzwei "$textzwei $text"
regsub "\{" $textzwei "" textzwei
regsub "\}" $textzwei "" textzwei
regsub " " $textzwei "" textzwei
set entry $answerarray($nick)
set answerarray($nick) [list \
$nick \
$textzwei \
]
moxquiz_pubm $nick $host $handle $channel $textzwei
} else {
set answerarray($nick) [list \
$nick \
$text \
]
}
}
}
## Tool function to get the question introduction text
proc mx_get_qtext {complete} {
global theq qnum_thisgame timeasked usergame qlist
set qtext [list "Die Frage Nr. %d (aus [commas [llength $qlist]] Fragen) ist" \
"The question no. %d is worth %d points" \
"The question no. %d by %s is" \
"The question no. %d by %s is worth %d points" \
"The user question no. %d is" \
"The user question no. %d is worth %d points" \
"The user question no. %d by %s is" \
"The user question no. %d by %s is worth %d points" \
"The level %s question no. %d is" \
"The level %s question no. %d is worth %d points" \
"The level %s question no. %d by %s is" \
"The level %s question no. %d by %s is worth %d points" \
"The level %s user question no. %d is" \
"The level %s user question no. %d is worth %d points" \
"The level %s user question no. %d by %s is" \
"The level %s user question no. %d by %s is worth %d points" ]
## game runs, tell user the question via msg
set qtextnum 0
set txt [list $qnum_thisgame]
if {[info exists theq(Level)]} {
incr qtextnum 8
set txt [linsert $txt 0 $theq(Level)]
}
if {$usergame == 1} { incr qtextnum 4 }
if {[info exists theq(Author)]} {
incr qtextnum 2
lappend txt [mx_nickobf $theq(Author)]
}
if {$theq(Score) > 1} {
incr qtextnum 1
lappend txt $theq(Score)
}
set txt [linsert $txt 0 mc [lindex $qtext $qtextnum]]
set txt [eval $txt]
if {$complete == "long"} {
set txt [mc "%s, open for %s:" $txt [mx_duration $timeasked]]
if {[info exists theq(Category)]} {
set txt "$txt \($theq(Category)\)"
}
set txt "$txt $theq(Question)"
} else {
set txt "$txt:"
}
global datadir
set fname "$datadir/qnr.data"
if {[file exists $fname] && [file readable $fname]} {
set fp [open $fname "r"]
set daten [read -nonewline $fp]
close $fp
} else {
set daten 0
global statsfile
set fp [open $statsfile "r"]
set data [read $fp]
close $fp
foreach line [split $data "\n"] {
if {[lindex [split $line] 0] == "solved"} {
incr daten
}
}
set file [open $fname w]
puts $file $daten
close $file
}
#return [eval $txt]
set pre "[banner] [botcolor boldtxt]"
return "${pre}($daten.) $txt"
}
## ask a question, start game
proc moxquiz_ask {nick host handle channel arg} {
global qlist quizstate botnick banner bannerspace
global tipno tiplist
global userqnumber usergame userqlist
global timeasked qnumber theq
global qnum_thisgame
global userlist timerankreset
global quizconf schaetztime subexp
variable anum 0
variable txt
## only accept chatter on quizchannel
if {![mx_str_ieq $channel $quizconf(quizchannel)]} {
return
}
switch -exact $quizstate {
"paused" {
mxirc_notc $nick [mc "Game is paused."]
return 1
}
"stopped" {
mxirc_notc $nick [mc "Game is stopped."]
return 1
}
}
## record that $nick spoke (prevents desert detection from stopping,
## when an user joins and starts the game with !ask)
if {![mx_str_ieq $nick $botnick]} {
mx_getcreate_userentry $nick $host
}
## any questions available?
if {[llength $qlist] == 0 && [mx_userquests_available] == 0} {
mxirc_say $channel [mc "%sSorry, my database is empty." "[banner] [botcolor boldtxt]"]
} elseif {$quizstate == "asked"} {
mxirc_notc $nick [mx_get_qtext "long"]
} elseif {$quizstate == "waittoask" && ![mx_str_ieq $nick $botnick]} {
## no, user has to be patient
mxirc_notc $nick [mc "Please stand by, the next question comes in less than %d seconds." $quizconf(askdelay)]
} else {
##
## ok, now lets see, which question to ask (normal or user)
##
## clear old question
foreach k [array names theq] {
unset theq($k)
}
if {[mx_userquests_available]} {
## select a user question
array set theq [lindex $userqlist $userqnumber]
set usergame 1
incr userqnumber
mx_log "--- asking a user question: $theq(Question)"
} else {
variable ok 0
global bestscore
while {!$ok} {
array set theq [lindex $qlist [mx_next_qnumber]]
set usergame 0
# skip question if author is about to win
if {[info exists theq(Author)] && [info exists userlist($theq(Author))]} {
array set auser $userlist($theq(Author))
if {$auser(score) >= [expr $quizconf(winscore) - 5]} {
mx_log "--- skipping question number $qnumber, author is about to win"
} else {
mx_log "--- asking question number $qnumber: $theq(Question)"
set ok 1
}
} else {
mx_log "--- asking question number $qnumber: $theq(Question)"
set ok 1
}
if {[info exists theq(Category)]} {
if {$theq(Category) == "Ratefragen" && $bestscore > 24} {
set ok 0
} elseif {$theq(Category) == "Schätzfragen"} {
if {[mx_quizzer_count] < 3} {
set ok 0
}
}
}
if {!$ok} {
foreach k [array names theq] {
unset theq($k)
}
}
incr qnumber
}
}
incr qnum_thisgame
if {$qnum_thisgame == 1} {
set timerankreset [unixtime]
mx_log "---- it's the no. $qnum_thisgame in this game, rank timer started at: [unixtime]"
mx_statslog "gamestart" [list $timerankreset]
} else {
mx_log "---- it's the no. $qnum_thisgame in this game."
}
if {[info exists theq(Category)]} {
if {$theq(Category) == "Schätzfragen"} {
global schaetzarray
foreach name [array names schaetzarray] {
unset schaetzarray($name)
}
utimer $schaetztime mx_schaetz_end
} elseif {$theq(Category) == "Ratefragen"} {
Rate_Start $nick $host $handle $channel $arg
return
}
}
##
## ok, set some minimal required fields like score, regexp and the tiplist.
##
## set regexp to match
if {![info exists theq(Regexp)]} {
## mask all regexp special chars except "."
set aexp [mx_tweak_umlauts $theq(Answer)]
regsub -all "(\\+|\\?|\\*|\\^|\\$|\\(|\\)|\\\[|\\\]|\\||\\\\)" $aexp "\\\\\\1" aexp
# get #...# area tags for tipgeneration as regexp
regsub -all ".*\#(\[^\#\]*\)\#.*" $aexp "\\1" aexp
set theq(Regexp) $aexp
} else {
set theq(Regexp) [mx_tweak_umlauts $theq(Regexp)]
}
set subexp $theq(Answer)
# protect embedded numbers
if {[regexp "\[0-9\]+" $theq(Regexp)]} {
set newexp ""
set oldexp $theq(Regexp)
set theq(Oldexp) $oldexp
while {[regexp -indices "(\[0-9\]+)" $oldexp pair]} {
set subexp [string range $oldexp [lindex $pair 0] [lindex $pair 1]]
set newexp "${newexp}[string range $oldexp -1 [expr [lindex $pair 0] - 1]]"
if {[regexp -- $theq(Regexp) $subexp]} {
set newexp "${newexp}(^|\[^0-9\])${subexp}(\$|\[^0-9\])"
} else {
set newexp "${newexp}${subexp}"
}
set oldexp "[string range $oldexp [expr [lindex $pair 1] + 1] [string length $oldexp]]"
}
set newexp "${newexp}${oldexp}"
set theq(Regexp) $newexp
#mx_log "---- replaced regexp '$theq(Oldexp)' with '$newexp' to protect numbers."
}
## set score
if {![info exists theq(Score)]} {
set theq(Score) 1
}
## obfs question (answer script stopper)
# [pending] done elsewhere
##set theq(Question) [mx_obfs $theq(Question)]
## set category
## set anum [lsearch -exact $alist "Category"]
## if {![info exists theq(Category)} {
## set theq(Category) "unknown"
##}
## initialize tiplist
set anum 0
set tiplist ""
while {[info exists theq(Tip$anum)]} {
lappend tiplist $theq(Tip$anum)
incr anum
}
# No tips found? construct standard list
if {$anum == 0} {
set add "·"
# extract area of tip generation tags (side effect sets answer)
if {![regsub -all ".*\#(\[^\#\]*\)\#.*" $theq(Answer) "\\1" answer]} {
set answer $theq(Answer)
}
## use tipcycle from questions or
## generate less tips if all words shorter than $tipcycle
if {[info exists theq(Tipcycle)]} {
set limit $theq(Tipcycle)
} else {
set limit $quizconf(tipcycle)
## check if at least one word long enough
set tmplist [lsort -command mx_cmp_length -decreasing [split $answer " "]]
# not a big word
if {[string length [lindex $tmplist 0]] < $quizconf(tipcycle)} {
set limit [string length [lindex $tmplist 0]]
}
}
for {set anum 0} {$anum < $limit} {incr anum} {
set tiptext ""
set letterno 0
for {set i 0} {$i < [string length $answer]} {incr i} {
if {([expr [expr $letterno - $anum] % $quizconf(tipcycle)] == 0) ||
([regexp "\[- \.,`'\"\]" [string range $answer $i $i] foo])} {
set tiptext "$tiptext[string range $answer $i $i]"
if {[regexp "\[- \.,`'\"\]" [string range $answer $i $i] foo]} {
set letterno -1
}
} else {
set tiptext "$tiptext$add"
}
incr letterno
}
lappend tiplist $tiptext
}
# reverse tips for numeric questions
if {[regexp "^\[0-9\]+$" $answer]} {
set foo ""
for {set i [expr [llength $tiplist] - 1]} {$i >= 0} {set i [expr $i - 1]} {
lappend foo [lindex $tiplist $i]
}
set tiplist $foo
}
}
##
## Now print question header and question
##
mxirc_serv $channel [mx_get_qtext "short"]
set txt "[bannerspace] [botcolor question]"
if {[info exists theq(Category)]} {
set txt "$txt\($theq(Category)\) $theq(Question)"
if {[info exists theq(Category)]} {
if {$theq(Category) == "Schätzfragen"} {
set txt "$txt \[\00306Ihr habt\00310 $schaetztime \00306Sekunden, um eine Schätzung in arabischen Zahlen abzugeben.\]\003"
}
}
} else {
set txt "$txt$theq(Question)"
}
mxirc_serv $channel $txt
set quizstate "asked"
set tipno 0
set timeasked [unixtime]
global timetypasked
set timetypasked [clock clicks -milliseconds]
## set up tip timer
utimer $quizconf(tipdelay) mx_timer_tip
}
}
proc mx_quizzer_count {} {
global quizconf userlist
set qnow [unixtime]
set usermax 0
foreach u [lsort -command mx_sortrank [array names userlist]] {
array set aa $userlist($u)
if {[expr $qnow - $aa(lastspoken)] <= $quizconf(useractivetime)} {
incr usermax
}
}
return $usermax
}
## A user dislikes the question
proc moxquiz_user_revolt {nick host handle channel text} {
global revoltlist revoltmax tipno botnick quizstate
global userlist RateRunning raterevolt
global quizconf
## only accept revolts on the quizchannel
if {![mx_str_ieq $channel $quizconf(quizchannel)]} {
return
}
if {$quizstate == "asked" || $RateRunning == 1} {
if {$tipno < 1&&$RateRunning!=1} {
mxirc_action $channel [mc "does not react on revolts before at least one tip was given."]
return
}
## ensure that the revolting user has an entry
if {![info exists userlist($nick)]} {
mx_getcreate_userentry $nick $host
}
## calculate people needed to make a revolution (50% of active users)
mx_log "--- a game runs, !revolt. revoltmax = $revoltmax"
if {$revoltmax == 0} {
set now [unixtime]
foreach u [array names userlist] {
array set afoo $userlist($u)
if {[expr $now - $afoo(lastspoken)] <= $quizconf(useractivetime)} {
incr revoltmax
}
}
mx_log "---- active people are $revoltmax"
# one and two player shoud revolt "both"
if {$revoltmax > 2} {
set revoltmax [expr int(ceil(double($revoltmax) / 2))]
}
mx_log "---- people needed for a successful revolution: $revoltmax"
}
# records known users dislike
if {[info exists userlist($nick)]} {
array set anarray $userlist($nick)
set hostmask $anarray(mask)
if {[lsearch -exact $revoltlist $hostmask] == -1} {
#mxirc_quick_notc $nick [mc "Since you are revolting, you will be ignored for this question."]
if {[llength $revoltlist] < $revoltmax && $revoltmax > 0} {
mxirc_quick_action $channel [mc "sees that %s and %d other dislike the question, you need %d people." \
$nick [llength $revoltlist] $revoltmax]
}
lappend revoltlist $hostmask
set anarray(lastspoken) [unixtime]
set userlist($nick) [array get anarray]
mx_log "--- $nick is revolting, revoltmax is $revoltmax"
mx_statslog "revolt" [list [unixtime] $nick [llength $revoltlist] $revoltmax]
}
}
if {[llength $revoltlist] >= $revoltmax} {
set revoltmax 0
mx_log "--- solution forced by revolting."
mx_statslog "revoltsolve" [list [unixtime] $revoltmax]
#mxirc_action $channel [mc "will solve the question immediately."]
if {$RateRunning != 0} {
foreach t [utimers] {
set tname [lindex $t 1]
if {[lindex $t 1] == "RateTimeUp"||[lindex $t 1] == "RateDisplayRemainingTime"||[lindex $t 1] == "Rate_ShowResults"||[regexp $tname "Rate"]} {
killutimer [lindex $t 2]
}
}
RateTimesUp
set revoltlist ""
set revoltmax 0
set vokspamvar 0
set raterevolt 1
} else {
moxquiz_solve $botnick 0 {}
}
}
}
}
## solve question
proc moxquiz_solve {handle idx arg} {
global quizstate theq banner bannerspace
global botnick lastsolvercount lastsolver timeasked
global quizconf
variable txt
variable answer
if {$quizstate != "asked"} {
mxirc_dcc $idx "There is no open question."
} else {
mx_answered
set lastsolver ""
set lastsolvercount 0
if {[mx_str_ieq $botnick $handle]} {
set txt [mc "%sAutomatically solved after %s." \
"[banner] [botcolor boldtxt]" [mx_duration $timeasked]]
} else {
set txt [mc "%sManually solved after %s by %s" \
"[banner] [botcolor boldtxt]" [mx_duration $timeasked] $handle]
}
mxirc_serv $quizconf(quizchannel) $txt
# remove area of tip generation tags
regsub -all "\#(\[^\#\]*\)\#" $theq(Answer) "\\1" answer
mxirc_say $quizconf(quizchannel) [mc "%sThe answer is:%s%s" \
"[bannerspace] [botcolor txt]" "[botcolor norm] [botcolor answer]" $answer]
# remove protection of numbers from regexp
if {[info exists theq(Oldexp)]} {
set theexp $theq(Oldexp)
} else {
set theexp $theq(Regexp)
}
#if {$answer != $theexp} {
# mxirc_say $quizconf(quizchannel) [mc "%sAnd should match:%s%s" \
# "[bannerspace] [botcolor txt]" "[botcolor norm] [botcolor answer]" $theexp]
#}
mx_log "--- solved by $handle manually."
# schedule ask
utimer $quizconf(askdelay) mx_timer_ask
}
return 1
}
## show a tip
proc moxquiz_tip {handle idx arg} {
global tipno quizstate banner bannerspace
global botnick tiplist
global quizconf theq
if {[info exists theq(Category)]} {
if {$theq(Category) == "Schätzfragen"} {
return
}
}
if {$quizstate == "asked"} {
if {$arg != ""} {
mxirc_dcc $idx "Extra tip \'$arg\' will be given."
set tiplist [linsert $tiplist $tipno $arg]
}
if {$tipno == [llength $tiplist]} {
# enough tips, solve!
set tipno 0
moxquiz_solve $botnick 0 {}
} else {
set tiptext [lindex $tiplist $tipno]
mxirc_say $quizconf(quizchannel) [mc "%sHint %d:" "[banner] [botcolor boldtxt]" [expr $tipno + 1]]
mxirc_say $quizconf(quizchannel) "[bannerspace] [botcolor tip]$tiptext"
foreach j [utimers] {
if {[lindex $j 1] == "mx_timer_tip"} {
killutimer [lindex $j 2]
}
}
mx_log "----- Tip number $tipno: $tiptext"
# only short delay after last tip
incr tipno
if {$tipno == [llength $tiplist]} {
utimer 15 mx_timer_tip
} else {
utimer $quizconf(tipdelay) mx_timer_tip
}
}
} else {
mxirc_dcc $idx "Sorry, no question is open."
}
return 1
}
## schedule a userquest
proc moxquiz_userquest {nick host handle arg} {
global userqlist ignore_for_userquest
global quizconf usebadwords badwords
variable uanswer "" uquestion "" umatch ""
variable tmptext ""
if {$quizconf(userquestions) == "no"} {
mxirc_notc $nick [mc "Sorry, userquestions are disabled."]
return
}
if {[lsearch $ignore_for_userquest [string tolower $nick]] != -1 || [lsearch $ignore_for_userquest [maskhost $host]] != -1} {
mxirc_notc $nick "Sorry, you are not allowed to post userquestions at this time."
return
}
if {![onchan $nick $quizconf(quizchannel)]} {
mxirc_notc $nick [mc "Sorry, you MUST be in the quizchannel to ask questions."]
} else {
if {[mx_userquests_available] >= $quizconf(userqbufferlength)} {
mxirc_notc $nick [mc "Sorry, there are already %d user questions scheduled. Try again later." $quizconf(userqbufferlength)]
} elseif {[info exists usebadwords] && $usebadwords && [regexp -nocase "([join $badwords, "|"])" $arg]} {
mxirc_notc $nick [mc "Sorry, your userquest would trigger the badwords detection and will not be asked."]
} else {
set arg [mx_strip_colors $arg]
if {$quizconf(stripumlauts) == "yes"} {
set arg [mx_tweak_umlauts $arg]
}
if {[regexp "^(.+)::(.+)::(.+)$" $arg foo uquestion uanswer umatch] || \
[regexp "(.+)::(.+)" $arg foo uquestion uanswer]} {
set uquestion [string trim $uquestion]
set uanswer [string trim $uanswer]
set alist [list "Question" "$uquestion" "Answer" "$uanswer" "Author" "$nick" "Date" [ctime [unixtime]] "TipGiven" "no"]
if {$umatch != ""} {
set umatch [string trim $umatch]
lappend alist "Regexp" "$umatch"
set tmptext [mc " (regexp \"%s\")" $umatch]
}
lappend userqlist $alist
mxirc_notc $nick [mc "Your quest \"%s\" is scheduled with answer \"%s\"%s and will be asked after %d questions." \
$uquestion $uanswer $tmptext [expr [mx_userquests_available] - 1]]
mx_log "--- Userquest scheduled by $nick: \"$uquestion\"."
} else {
mxirc_notc $nick [mc "Wrong number of parameters. Use alike <question>::<answer>::<regexp>. The regexp is optional and used with care."]
mxirc_notc $nick [mc "You said: \"%s\". I recognize this as: \"%s\" and \"%s\", regexp: \"%s\"." \
$arg $uquestion $uanswer $umatch]
mx_log "--- userquest from $nick failed with: \"$arg\""
}
}
}
return
}
## usertip
proc moxquiz_usertip {nick host handle arg} {
global quizstate usergame theq
global quizconf
if {[onchan $nick $quizconf(quizchannel)]} {
mx_log "--- Usertip requested by $nick: \"$arg\"."
if {$quizstate == "asked" && $usergame == 1} {
if {[info exists theq(Author)] && ![mx_str_ieq $nick $theq(Author)]} {
mxirc_notc $nick [mc "No, only %s can give tips here!" $theq(Author)]
} else {
moxquiz_tip $nick 0 $arg
if {$arg != ""} {
set theq(TipGiven) "yes"
}
}
} else {
mxirc_notc $nick [mc "No usergame running."]
}
} else {
mxirc_notc $nick [mc "Sorry, you MUST be in the quizchannel to give tips."]
}
return 1
}
## usersolve
proc moxquiz_usersolve {nick host handle arg} {
global quizstate usergame theq
mx_log "--- Usersolve requested by $nick."
if {$quizstate == "asked" && $usergame == 1} {
if {[info exists theq(Author)] && ![mx_str_ieq $nick $theq(Author)]} {
mxirc_notc $nick [mc "No, only %s can solve this question!" $theq(Author)]
} else {
moxquiz_solve $nick 0 {}
}
} else {
mxirc_notc $nick [mc "No usergame running."]
}
return 1
}
bind msg - !adver mx_adver
## advertisement
proc mx_adver {nick host handle arg} {
global botnick
global quizconf
mxirc_say $quizconf(quizchannel) "[bannerspace] and can be downloaded from http://meta-x.de/moxquizz"
return 0
}
## usercancel
proc moxquiz_usercancel {nick host handle arg} {
global quizstate usergame theq userqnumber userqlist
mx_log "--- Usercancel requested by $nick."
if {$quizstate == "asked" && $usergame == 1} {
if {[info exists theq(Author)] && ![mx_str_ieq $nick $theq(Author)]} {
mxirc_notc $nick [mc "No, only %s can cancel this question!" $theq(Author)]
} else {
mxirc_notc $nick [mc "Your question is canceled and will be solved."]
set theq(Comment) "canceled by user"
moxquiz_solve "user canceling" 0 {}
}
} elseif {[mx_userquests_available]} {
array set aq [lindex $userqlist $userqnumber]
if {[mx_str_ieq $aq(Author) $nick]} {
mxirc_notc $nick [mc "Your question \"%s\" will be skipped." $aq(Question)]
set aq(Comment) "canceled by user"
set userqlist [lreplace $userqlist $userqnumber $userqnumber [array get aq]]
incr userqnumber
} else {
mxirc_notc $nick [mc "Sorry, the next question is by %s." $aq(Author)]
}
} else {
mxirc_notc $nick [mc "No usergame running."]
}
return 1
}
## ignore nick!*@* and *!ident@*.subdomain.domain for userquests for 45 minutes
proc moxquiz_userquest_ignore {nick host handle channel arg} {
global quizconf ignore_for_userquest
regsub -all " +" [string trim $arg] " " arg
variable nicks [split $arg]
variable n
for {set pos 0} {$pos < [llength $nicks]} {incr pos} {
set n [string tolower [lindex $nicks $pos]]
mxirc_notc $nick "Ignoring userquestions from $n for 45 minutes."
lappend ignore_for_userquest $n
if {[onchan $n $quizconf(quizchannel)]} {
lappend ignore_for_userquest [maskhost [getchanhost $n $quizconf(quizchannel)]]
} else {
lappend ignore_for_userquest "-!-@-"
}
}
timer 45 mx_timer_userquest_ignore_expire
return 1
}
## unignore nick!*@* and *!ident@*.subdomain.domain for userquests for 45 minutes
proc moxquiz_userquest_unignore {nick host handle channel arg} {
## replace each [split $arg] and associated hostmask with some impossible values
global quizconf ignore_for_userquest
regsub -all " +" [string trim $arg] " " arg
variable nicks [split $arg]
variable n
for {set pos 0} {$pos < [llength $nicks]} {incr pos} {
set n [string tolower [lindex $nicks $pos]]
set listpos [lsearch -exact $ignore_for_userquest $n]
if {$listpos != -1} {
set ignore_for_userquest [lreplace $ignore_for_userquest $listpos [expr $listpos + 1] "@" "-!-@-"]
mxirc_notc $nick "User $n removed from ignore list for userquestions."
} else {
mxirc_notc $nick "User $n was not in the ignore list for userquestions."
}
}
return 1
}
## lists current names on ignore for userquestions
proc moxquiz_userquest_clearignores {nick host handle channel arg} {
variable ignore_for_userquest
for {set pos 0} {$pos < [llength $ignore_for_userquest]} {incr pos 2} {
set ignore_for_userquest [lreplace $ignore_for_userquest $pos [expr $pos + 1] "@" "-!-@-"]
}
mxirc_notc $nick "Cleared ignore list for userquestions."
return 1
}
## lists current names on ignore for userquestions
proc moxquiz_userquest_listignores {nick host handle channel arg} {
variable ignore_for_userquest
variable nicks ""
for {set pos 0} {$pos < [llength $ignore_for_userquest]} {incr pos 2} {
if {[lindex $ignore_for_userquest $pos] != "@"} {
lappend nicks [lindex $ignore_for_userquest $pos]
}
}
if {$nicks != ""} {
mxirc_notc $nick "Currently ignored for userquestions: $nicks"
} else {
mxirc_notc $nick "Currently ignoring nobody for userquestions."
}
return 1
}
## removes the first two elements from ignore_for_userquest (nick and mask)
proc mx_timer_userquest_ignore_expire {} {
global ignore_for_userquest
set ignore_for_userquest [lreplace $ignore_for_userquest 0 1]
}
## pubm !score to report scores
proc moxquiz_pub_score {nick host handle channel arg} {
global alltimestarsarray allstarsarray userlist
global quizconf
variable allstarspos
variable pos 0
variable target
variable self 0
if {![mx_str_ieq $channel $quizconf(quizchannel)]} {
return 0
} else {
set arg [string trim "$arg"]
if {$arg != "" && $arg != $nick} {
set target $arg
} else {
set target $nick
set self 1
}
# report rank entries
if {[info exists userlist($targ
Comments
 Subscribe to comments
                    Subscribe to comments
                
                