###################################
## The #Homicide Efnet Trivia Bot #
###################### Ophmisu ####
############ by WSergio ###########



#########################################################
##################### Ophmisu's Settings
#########################################################
set team(dir) "Ophmisu"
set team(Version) "1.0.8 (beta)"
# verbosity
set team(verbose) 1
# tracing procs execution
set team(Trace) 0
set logo "\[\002Ophmisu\002\]"
# MAIN TRIVIA CHANNEL - YOU'LL WANT TO CHANGE THIS!
set team(chan) "#ophmisu"
# other channels where the trivia commands will be also available
set team(otherchans) ""
# topic_change: should the bot control the main channel's topic? [1: YES 0: NO]
set team(topic_change) 0
set team(char) "!"
set team(prefix) "team_"
set team(flags) "-|-"
set team(path,dir_teams) "$team(dir)/Teams"
set team(path,dir_questions) "$team(dir)/intrebari"
set team(path,dir_backups) "$team(dir)/.backups"
set team(path,file_teams) "$team(path,dir_teams)/TEAMS"
set team(path,file_individuals) "$team(path,dir_teams)/INDIVIDUALS"
set team(path,file_ranks) "$team(path,dir_teams)/RANKS"
set team(path,file_ranksPersonal) "$team(path,dir_teams)/RANKSPERSONALS"
set team(path,file_requests) "$team(path,dir_teams)/REQUESTS"
# for TEST purpose only: set team(path,file_web) "/var/www/html/public/ophmisu/index.html"
set team(path,file_web) "$team(dir)/index.html"
set team(trigger,pubm,team_create) "R|- creare*;create*;formeaza*;formatie*;creeaza* create"
set team(trigger,pubm,team_view) "R|- profil*;scor*;view* view"
set team(trigger,pubm,multi_view) "R|- echipa*;team*;tot*;all*;indiv* multi_view"
set team(trigger,pubm,team_delete) "Cn|- delete*;desfiint* delete"
set team(trigger,pubm,team_rename) "C|- nume*;rename* rename"
set team(trigger,pubm,addmember) "n|- forceadd* addmember"
set team(trigger,pubm,request) "T|- invita*;add* request"
set team(trigger,pubm,delmember) "C|- exclude* delmember"
set team(trigger,pubm,selfexclude) "T|- paraseste* selfexclude"
set team(trigger,pubm,selfadd) "n|- alatur* selfadd"
set team(trigger,pubm,register) "-|- inreg* Inregistrare"
set team(trigger,pubm,top) "R|- top* Top"
set team(trigger,pubm,ptop) "R|- personaltop*;ptop* PersonalTop"
set team(trigger,pubm,erase) "n|- erase* erase"
set team(trigger,pubm,grade) "R|- grade g:pubShow"
set team(trigger,pubm,genstats) "o|- genstats Stats:Gen"
set team(trigger,pubm,etapa) "oR|- etapa* Etapa"
set team(trigger,pubm,time) "TIC|- timp time"
set team(trigger,pubm,modall) "n|- modall*;ModAll* ModAll"
set team(trigger,pubm,request_clean) "n|- requests* Request:Setup"
# TEST trigger, REMOVE before publishing!
# set team(trigger,test) "n|- test* Test"
set team(trigger,msg,RequestAnswer) "TIC|- invitatie onRequestAnswer"
set team(trigger,msg,Confirmation) "-|- confirma onConfirmation"
set team(trigger,msg,auth) "-|- auth onAuth"
set team(trigger,msg,newpass) "R|- newpass onNewpass"
set team(clockformat) "%R %d/%m/%y"
# types using for columns code/name conversion
set team(Request) "request"
set team(Member) "membru"
set team(Teams) "echipe"
set team(Team) "echipa"
# 1st Ranking Table's name
set team(General) "General"
# 2nd Ranking Table's name
set team(Personal) "Personal"
set team(Individual) "individual"
set team(Individuals) "individuali"
set team(Grad) "grad"
set team(Rank) "rank"
set team(Web) "Web"
# columns codes/names lists
set team(sets,all) [split "all everyone everybody everything tot toti toate" " "]
set team(sets,Member,codes) [split "0 1 2 3 4 5 6 7 8 9 10 11 12 13" " "]
set team(sets,Member,names) [split "team nick grad scor correct joined last joins kicks speed consec rank time uptime" " "]
set team(sets,Member,friendly) [split "echipa nick grad scor corecte inregistrare ultima_vizita intrari kickuri viteza consecutive subrank timp" " "]
set team(sets,Team,codes) [split "0 1 2 3 4 5" " "]
set team(sets,Team,names) [split "team capitan total scor rank created" " "]
set team(sets,Grad,codes) [split "0 1 2 3 4 5 6 7 8 9 10" " "]
set team(sets,Grad,names) [split "undefined Junior Fulger Senior Geniu Lider Veteran undefined undefined undefined Capitan"  " "]
# help messages
set team(help,0) "(inregistrarea se face cu comanda <<!inregistrare>>)"
set team(help,1) "(comanda <<<|!paraseste|>>>)"
set team(help,2) "(comanda <<<|!desfiinteaza <nume-echipa>|>>>)"
# columns codes/names lists
set team(sets,Individual,codes) [split "0 1 2 3 4 5 6 7 8 9 10 11 12 13 " " "]
set team(sets,Individual,names) [split "nick scor correct joined last joins kicks speed consec rank time uptime" " "]
set team(sets,Individual,friendly) [split "nick scor corecte inregistrare ultima_vizita intrari kickuri viteza consecutive rank timp" " "]
set individuals(name1) "jucator individual"
set individuals(name2) "jucatori individuali"
# requests (invitations) states
set requests(expiration) "48 hours"
set requests(0) "in_asteptare"
set requests(1) "refuzata"
set requests(2) "acceptata"
set requests2(1) "REFUZ"
set requests2(2) "ACCEPT"
# globals for few of most used vars
set Total(General) 0
set Total(Personal) 0
set Total(Teams) 0
set Total(Individuals) 0
set rank(1) "pt"
set rank(2) "pte"
set rank(General) ""
set rank(Personal) ""
set rank(Time) ""
set team(Keys) ""
set MAX_LEN 414
# members' grades
# Junior
set grad(1) ""
# Fulger
set grad(2) [list "speed=record"]
# Senior
set grad(3) [list "scor=300" "joined=5 days" "last=2 days"]
# Geniu
set grad(4) [list "scor=600"]
# Lider
set grad(5) [list "rank=1" "scor=100"]
# Veteran
set grad(6) [list "scor=800" "joined=20 days" "last=3 days"]
### grades interpretation: the above: a Veteran requires at least 800 points, registered at least 20 days ago and last seen on channel at most 3 days ago
# colorizing
set color(0) "08"
set back(0) "04"
set color(1) "04"
set back(1) "08"
set color(misc) "02"
set color($::team(Team)) "03"
set color(nr1) "00,04"
set color(nr2) "15,05"
set color(nr3) "14,05"
# colorx: a color toggle index internally set (0,1)
set colorx 1
# Color sets
set colorset(gri,color,0) "00"
set colorset(gri,color,1) "01"
set colorset(gri,color,bg) "14"

source $team(dir)/Trivia.tcl
source $team(dir)/etapa.tcl
source $team(dir)/filetrace.tcl
source $team(dir)/updater.tcl
source $team(dir)/topic.tcl
source $team(dir)/tcd.tcl


#########################################################
##################### I, w:procs
#########################################################
proc w:Duration {seconds} {
	if {$seconds==0} { return "0 secunde" }
	set plural [list years ani weeks saptamani days zile hours ore minutes minute seconds secunde]
	set singular [list year an week saptamana day zi hour ora minute minut second secunda]
	return [lrange [string map [concat $plural $singular] [duration $seconds]] 0 3]
}
proc w:EpochDuration {seconds} {
	if {$seconds==0} { return "0 secunde" }
	return [lrange [w:Duration [expr [clock seconds]-$seconds]] 0 3]
}
proc w:Chattr {target flags} {
	Trace [info level 0]
	foreach hand [userlist] {
		if {[string match -nocase [strlwr $target] [strlwr $hand]]} {
			dump "w:Chattr $hand $flags"
			chattr $hand $flags
		}
	}
}
proc w:DateFormat {seconds {stripped "0"}} {
	if {$stripped} { return [clock format $seconds -format $::team(clockformat)]
	} else { return <|[clock format $seconds -format $::team(clockformat)]|> }
}
proc w:Trimer {what} { return [string trim [string map {"\[" "" "\]" "" "\{" "" "\}" "" "<" "" ">" ""} $what] " "] }
proc w:TeamTrimer {what} {
	set illegal [list " " "" "`" "" "~" "" "!" "" "@" "" "#" "" "$" "" "%" "" "^" "" "&" "" "*" "" "(" "" ")" "" "_" "" "+" "" "=" "" "-" "" "\]" "" "\[" "" "\}" "" "\{" "" "\\" "" "'" "" ";" "" "\"" "" ":" "" "/" "" "." "" "," "" "?" "" ">" "" "<" ""]
	set what [string map $illegal $what]
	if {[string length $what]>18} { set what [string range $what 0 17] }
	return $what
}
proc w:PathType {type {params ""}} {
	Trace [info level 0]
	if {$type==$::team(Team)} {
		set path $::team(path,dir_teams)/$::team(prefix)$params
	} elseif {$type==$::team(Teams)} {
		set path $::team(path,file_teams)
	} elseif {$type==$::team(Individual)} {
		set path $::team(path,file_individuals)
	} elseif {$type==$::team(Rank)} {
		set path $::team(path,file_ranks)
	} elseif {$type==$::team(Request)} {
		set path $::team(path,file_requests)
	} elseif {$type==$::team(Personal)} {
		set path $::team(path,file_ranksPersonal)
	} elseif {$type==$::team(Web)} {
		set path $::team(path,file_web)				
	} else { return "PathType: unknown type! ($type)" }
	return $path
}
proc w:Read {type {params ""}} {
	Trace [info level 0]
	set path [w:PathType $type $params]
	if {[string match -nocase "*unknown*" $path]} { dump "PathType couln't match the type: $type"; return }
	if {[file exists $path]==0} { team:touch $path }
	set _main [open $path r]
	set _data [read -nonewline $_main]
	close $_main
	return [split $_data "\n"]
}
proc w:Write {type data {params ""}} {
	Trace [info level 0]
	set path [w:PathType $type $params]
	set _main [open $path w]
	puts $_main [join $data "\n"]
	close $_main
}
proc w:Conv {x {type ""} {ToMode ""}} {
	Trace [info level 0]
	if {$type==""||$type==$::team(Member)||$type==$::team(Team)} {
		set arrCodes $::team(sets,Member,codes)
		set arrNames $::team(sets,Member,names)
	} elseif {$type=="f$::team(Member)"} {
		set x [w:Conv $x $::team(Member) code]
		set arrCodes $::team(sets,Member,codes)
		set arrNames $::team(sets,Member,friendly)
	} elseif {$type=="f$::team(Individual)"} {
		set x [w:Conv $x $::team(Individual) code]
		set arrCodes $::team(sets,Individual,codes)
		set arrNames $::team(sets,Individual,friendly)		
	} elseif {$type==$::team(Teams)} {
		set arrCodes $::team(sets,Team,codes)
		set arrNames $::team(sets,Team,names)
 	} elseif {$type==$::team(Individual)} {
		set arrCodes $::team(sets,Individual,codes)
		set arrNames $::team(sets,Individual,names)
	} elseif {$type==$::team(Grad)} {
		set arrCodes $::team(sets,Grad,codes)
		set arrNames $::team(sets,Grad,names)
	} else {
		dump "w:Conv: unknown conversion type ($type)" error; return
	}
	if {[string is alpha $x]} { set FromMode "name" } elseif {[string is digit $x]} { set FromMode "code" } else { dump "w:Conv: unknown conversion mode" error; return -1 }
	if {$ToMode==""} { if {$FromMode=="name"} { set ToMode "code" } elseif {$FromMode=="code"} { set ToMode "name" } }
	set ret $x
	if {$FromMode!=$ToMode} {
		if {$FromMode=="name"} {
			set cod [lsearch $arrNames $x]
			if {$cod>-1} { set ret [lindex $arrCodes $cod] } else { dump "w:Conv: undefined alphaset ($x)" error; return -1 }
		} elseif {$FromMode=="code"} {
			if {$x<=[llength $arrCodes]} { set ret [lindex $arrNames $x] } else { dump "w:Conv: undefined digitset ($x)" error; return -1 }
		} else { dump "w:Conv unknown conversoin mode ($ToMode)" error; return -1 }
	}
	return $ret
}
proc w:Extract {type line {col 1}} {
	Trace [info level 0]
	if {[string match "*;*" $line]} { set line [split $line ";"] }
	return [lindex $line [w:Conv $col $type code]] 
}
proc w:Insert {type line col {new ""}} {
	Trace [info level 0]
	if {[string match "*;*" $line]} { set line [split $line ";"] }
	set colCode [w:Conv $col $type code]
	set colName [w:Conv $col $type name]
	set old [w:Extract $type $line $col]
	if {[string is digit $old]&&$colName!="last"&&$colName!="joined"&&$colName!="rank"} {
		set new [expr $old + 1]
	}
	return [lreplace $line $colCode $colCode $new]
}
proc onAuth {nick uhost hand params} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	putlog "onAuth triggered by $nick"
	set pass  [string range [lindex $params 0] 0 29]
	if {[passwdok $hand $pass]} {
		w:onLogin $hand
	}
}
proc getTrigger {key {needsCharPrefix 0}} {
	set triggers [lindex [lindex [array get ::team *$key*] 1] 1]
	set triggers [split $triggers ";"]
	set ret [string trim [lindex $triggers 0] "*"]
	if {$needsCharPrefix} { set ret $::team(char)$ret }
	return $ret
}
proc onNewpass {nick uhost hand params} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	set newpass [string range [lindex $params 1] 0 29]
	set oldpass [lindex $params 0]
	if {![passwdok $hand $oldpass]} { msg $hand "Eroare: vechea parola specificata este incorecta!"; return }
	if {$newpass==""} { msg $hand "Nu ai specificat noua parola!"; return }
	if {$newpass==$oldpass} { return }
	setuser $hand PASS $newpass
	# dump "<|$hand|> si-a schimbat vechea parola (<|$oldpass|>) in <|$newpass|>"
	msg $hand "Parola a fost schimbata. De acum, te vei putea loga cu: <|/msg $::botnick [getTrigger auth] $newpass|>"
}
proc w:onLogin {hand} {
	Trace [info level 0]
	dump "$hand Logged in!"
	say $::team(chan) [team:FormatWelcome $hand "S-a logat"]
	msg [hand2nick $hand] "[fcolor 02]Te-ai logat cu succes sub numele de jucator <|$hand|>.[fcolor]"
	team:Request:CheckHand $hand
	w:Mod put $hand last
	w:Mod put $hand uptime
}


proc R:Scor {scor} {
	return [textparse <|$scor|>\ [expr $scor==1?"$::rank(1)":"$::rank(2)"]]
}
proc fcolor {{code "\003"}} { return "\003$code" }
proc color {{type ""}} {
	set y $::colorx
	set ::colorx [expr !$y]
	if {$type!=""} {
		if {[string match "nr*" $type]} { return [fcolor $::color($type)]
		} else { return [fcolor $::color($type),$::back($y)] }
	} else { return [fcolor $::color($y),$::back($y)] }
}
proc rcolor {colorset} {
	set y $::colorx
	set ::colorx [expr !$y]
	return [fcolor $::colorset($colorset,color,$y),$::colorset($colorset,color,bg)]
}
proc colorize {text {colorset "gri"} {separator ";"}} {
	set ret ""
	foreach block [split $text $separator] {
		append ret "[rcolor gri]$block"
	}
	return $ret[fcolor]
}

proc dump {what {type ""}} {
	set head ""
	if {$type=="error"} { set head "<|ERROR|>: " }
	if {$::team(verbose)} { putlog [textparse "$::logo $head$what"] } 
}
proc textparse {what} { return [string map -nocase {"<<" "\"" ">>" "\"" "<|" "\002" "|>" "\002" } $what] }
proc Trace {target} {
	if {$::team(Trace)==0} { return }
	set ProcName [lindex $target 0]
	set ProcArgs [lrange $target 1 end]
	dump "\[<|Trace|>\] [clock format [clock seconds] -format %T]: .tcl <|$ProcName |>$ProcArgs"
}
proc Paths {type} {
	Trace [info level 0]
	if {$type!="file"&&$type!="dir"} { set ret -1 } else { set ret ""; foreach {name value} [array get ::team path,$type*] { lappend ret $value } } 
	return $ret
}
proc say {chan what} { set output [split $what "\n"]; 	foreach msg $output { puthelp "privmsg $chan :$::logo [textparse $msg]" } }
proc msg {nick message} { puthelp "privmsg $nick :[textparse $message]" }
proc notice {nick message} { puthelp "notice $nick :[textparse $message]" }
proc explode {data} {
	set new ""
	foreach element $data { lappend new [split $element ";"] }
	return $new
}
proc implode {data} {
	set new ""
	foreach element $data { lappend new [join $element ";"] }
	return $new
}



#########################################################
##################### Grade g:procs
#########################################################
proc g:DoAll {team} {
	Trace [info level 0]
	set Members [team:GetAll nick $team]
	foreach Member $Members {
		g:Do $Member
	}
}
proc g:Do {hand} {
	Trace [info level 0]
	if {[matchattr $hand C|]==1} { return }
	set line [team:Mod get ? $hand *]
	set order [lsort -integer -decreasing [array names ::grad]]
	#dump "##################"
	#dump "###############"
	foreach cod $order {
		set reqs $::grad($cod)
		set codName [w:Conv $cod $::team(Grad) name]
		#dump "- - -"
		#dump "Checking requirements for $hand to be a `$codName`"
		set ok 1
		if {[llength $reqs]>0} {
			foreach req $reqs {
				set req [split $req "="]
				set minName [lindex $req 0]
				set msg " - $minName (C/M): "
				set minValue [lrange $req 1 end]
				set curValue [w:Extract $::team(Member) $line $minName]
				switch $minValue {
					record {
						set minValue [lindex [GetSet $minName] 1]
					}					
				}
				switch $minName {
					last - joined {
						set curDate [clock seconds]
						set minValue [clock scan [string trim $minValue "{}"]]
						set minValue [expr $minValue - $curDate]
						set curValue [expr $curDate - $curValue]
						if {$minName=="last"} { set operation "lower" }
						set minDuration [w:Duration $minValue]
						set curDuration [w:Duration $curValue]
						#dump " (( C/M DUrations: $curDuration $operation than $minDuration ? ))"
					}
					speed {
						set operation "lower"
						if {$curValue=="-"} { set curValue 2000 }
					}
					rank {
						set operation "lower"
					}
					default {
						set operation "bigger"
					}
				}
				append msg " OP: $operation: C/M $curValue $operation than $minValue ?= "
				if {$operation=="bigger"} {
					if {$curValue<$minValue} { append msg "ERR"; set ok 0 } else { append msg "OK" }
					if {$ok==0} {
						#dump $msg;
						break
					}
				} elseif {$operation=="lower"} {
					if {$curValue>$minValue} { append msg "ERR"; set ok 0 } else { append msg "OK" }
					
					if {$ok==0} { 
						#dump $msg
						break 
					}
				
				} else { return }
				#dump $msg
			}
		}
		if {$ok} {
			set msg " - Could be a $codName!"
			set oldGrad [team:GetInfo $hand grad]
			if {$oldGrad!=$codName} {
				set team [team:GetInfo $hand team]
				team:Mod put $team $hand grad $codName
				append msg " SET TO $codName!!!"
				#dump $msg
				return $codName
				break;
			} else {
				append msg " But already this, returning."
				#dump $msg
				return
			}
		} else {
			#dump "- Doesn't meet the requirements to be a $codName!" 
		}
	}
	return
}
proc g:Show {{grad "*"}} {
	Trace [info level 0]
	set order [lsort -integer -increasing [array names ::grad]]
	set msg "Exista <|[llength $order]|> grade disponibile membrilor. Denumirile si cerintele acestora sunt:\n"
	foreach cod $order {
		set reqs $::grad($cod)
		set codName [w:Conv $cod $::team(Grad) name]
		append msg "[color] $cod) <|$codName|> [color]"
		if {[llength $reqs]>0} {
			foreach req $reqs {
				set req [split $req "="]
				set minName [lindex $req 0]
				append msg " [strupr [w:Conv $minName f$::team(Member)]]"
				set minValue [lrange $req 1 end]
				switch $minValue {
					record {
						set minValue "RECORD ([lindex [GetSet $minName] 1])"
					}
				}
				switch $minName {
					last - joined {
						set curDate [clock seconds]
						set minValue [clock scan [string trim $minValue "{}"]]
						set minValue [expr $minValue - $curDate]
						if {$minName=="last"} { set operation "maxim" } else { set operation "minim" }
						set minValue [w:Duration $minValue]
					}
					speed - rank {
						set operation "exact"
					}
					default {
						set operation "de minim"
					}
				}
				append msg " $operation $minValue;"
			}
		} else { append msg " apartenenta la o echipa"}
	}
	return [textparse $msg]
}



#########################################################
##################### team:procs
#########################################################
proc team:bind:pubm {what} {
	set what [split $what " "]
	set _flags [split [lindex $what 0] ";"]
	set _triggers [split [lindex $what 1] ";"]
	set _handler team:[lindex $what 2]
	foreach chan [concat $::team(chan) $::team(otherchans)] {
		foreach _flag $_flags {
			foreach _trigger $_triggers {
				dump "BIND pubm ADDED: bind pubm $_flag \"$chan %$::team(char)$_trigger\" $_handler"
				bind pubm $_flag "$chan %$::team(char)$_trigger" $_handler			
			}
		}
	}
}
proc team:binder {trigger values} {
	set trigger [split $trigger ","]
	set _type [lindex $trigger 1]
	if {[strlwr $_type]=="pubm"} { 
		team:bind:pubm $values 
	} else { 
		set values [split $values " "]
		set _flags [split [lindex $values 0] ";"]
		set _triggers [split [lindex $values 1] ";"]
		set _handler [lindex $values 2]
		foreach _flag $_flags {
			foreach _trigger $_triggers {
				dump "BIND $_type ADDED: bind $_type $_flag $_trigger $_handler"
				bind $_type $_flag $_trigger $_handler			
			}
		}
	}
}
proc team:autobind {} {
	foreach {trigger values} [array get ::team trigger,*] {
		team:binder $trigger $values
	}
}
proc team:bindings {} {
	team:autobind
	bind join ITC|- "$::team(chan) *" onJoin
	bind kick ITC|- "$::team(chan) *" onKick
	bind part ITC|- "$::team(chan) *" onPart
	bind evnt - rehash team:init
	bind sign TIC|- *!*@* onSign
}
proc team:mkdir {cpath} { dump "    mkdir `$cpath`"; file mkdir $cpath }
proc team:touch {cpath} {
	dump "    touch `$cpath`";
	set _file [open $cpath w]
	close $_file
}
proc team:check {} {
	dump "Routine checking..."
	team:check:paths
}
proc team:check:paths {} {
	dump " - checking paths..."
	foreach path [Paths dir] { team:check:path:dir $path }
	foreach path [Paths file] { team:check:path:file $path }
}
proc team:check:path:dir {cpath} {
	set _msg "    checking directory path `$cpath`: "
	if {[file exists $cpath]} {
		if {![file readable $cpath]} { append _msg "UNREADABLE"
		} elseif {![file writable $cpath]} { append _msg "UNWRITABLE"
		} else { append _msg "OK" }
	} else {
		if {$cpath==$::team(path,dir_teams)} { w:Chattr * -TIC }
		append _msg "NOT FOUND"
		dump $_msg
		team:mkdir $cpath
		return
	}
	dump $_msg
}
proc team:check:path:file {cpath} {
        set _msg "    checking file `$cpath`: "
        if {[file exists $cpath]} {
			if {![file readable $cpath]} { append _msg "UNREADABLE"
			} elseif {![file writable $cpath]} { append _msg "UNWRITABLE"
			} else { append _msg "OK" }
        } else {
			if {$cpath==$::team(path,file_teams)} { w:Chattr "*" "-TC" }
			if {$cpath==$::team(path,file_individuals)} { w:Chattr "*" "-I" }
			append _msg "NOT FOUND"
			dump $_msg
			team:touch $cpath
			return
        }
        dump $_msg
}
proc team:erase {nick uhost hand chan params} {
	Trace [info level 0]
	if {[llength $params]<2||[string match "*[lindex $params 1]*" "users players everything"]==0} {
		say $chan "Eroare: Erase what? Options: <players>, <users> \[flags\] or <everything>"
		return
	} else {
		set params [lrange $params 1 end]
		set what [lindex $params 0]
		set flags [lindex $params 1]
		erase $what $flags
	}
}
proc erase {what {flags ""}} {
	Trace [info level 0]
	if {$what=="everything"} {
		set msg "Erasing EVERYTHING"
		erase users
		erase players
		#team:touch $::ofile
		DefSet
		rehash
	} elseif {$what=="users"} {
		set _flags "[expr \"$flags\"==""?\"\":\"($flags)\"]"
		set ulist [userlist $flags]
		set msg "Erasing users ([llength $ulist]): "
		foreach user $ulist {
			if {$::owner!=$user} {
				deluser $user
				append msg "$user, "
				dump "Erasing $what: $user $_flags"
			} else { append msg "$::owner untouched, "; dump "Erasing skipped, owner $::owner untouched..." }
			set msg [string trim $msg " ,"]
			append msg " $_flags"
		}
		userlist
	} elseif {$what=="players"} {
		set msg "Erasing players"
		dump "Erasing players from teams, individuals, ranks..."
		file delete -force $::team(path,dir_teams)
		team:check:paths
	}
	dump $msg
	say $::team(chan) $msg
	R:Update
}



#########################################################
##################### team:procs management
#########################################################
proc team:is {type cname} {
	Trace [info level 0]
	set _file [open $::team(path,file_teams) r]
	set data [read -nonewline $_file]
	close $_file
	set teams [split $data "\n"]
	foreach cteam $teams {
		set parts [split $cteam ";"]
		if {$type=="echipa"} { set comp [lindex $parts 0]
		} elseif {$type=="capitan"} { set comp [lindex $parts 1] }
		if {[strlwr $comp]==[strlwr $cname]} { return $cteam }
	}
	return 0
}
proc team:g:pubShow {nick uhost hand chan {text ""}} { Trace [info level 0]; say $chan [g:Show] }
proc team:multi_view {nick host hand chan params} {
	Trace [info level 0]
	set type [strlwr [string trim [lindex $params 0] " !"]]
	if {[string match "*$type*" $::team(sets,all)]} {
		team:view $nick $host $hand $chan "x toti"
	} elseif {$type==$::team(Teams)||$type=="teams"} {
		team:view $nick $host $hand $chan "x $::team(Teams)"
	} elseif {$type==$::team(Team)||$type=="team"} {
		if {[lindex $params 1]==""} {
			if {[is $hand]==$::team(Member)} {
				set team [team:GetInfo $hand team]
			} else { say $chan "Eroare: ai uitat sa specifici echipa!"; return }
		} else { set team [lindex $params 1] }
		team:view $nick $host $hand $chan "x $team"
	} elseif {$type==$::team(Individuals)||[string match "indiv*" $type]} {
		team:view $nick $host $hand $chan "x $::team(Individuals)"
	}
}
proc team:view {nick host hand chan params} {
	Trace [info level 0]
	set what [lindex [split $params " "] 1]
	set msg ""
	if {[lsearch -exact $::team(sets,all) [strlwr $what]]>-1} {
		set _teams [team:Count teams]
		set _individuals [team:Count individuals]
		set msg "Exista <|$_teams|> echip[expr $_teams==1?\"a\":\"e\"] si <|$_individuals|> [expr $_individuals==1?\"$::individuals(name1)\":\"$::individuals(name2)\"]."
	} elseif {$what==""} {
		if {$hand=="*"} { set hand $nick }
		set type [is $hand]
		if {$type==$::team(Member)} {
			set msg [team:Format [team:Mod get ? $hand *]]
		} elseif {$type==$::team(Individual)} {
			set msg [i:Format [i:Mod get $hand *]] 
		} else { set msg "Eroare: <|$hand|> este un membru/individ <|inexistent|>!"}
	} elseif {$what==$::team(Teams)} {
		set msg [team:FormatTeams]
	} elseif {$what==$::team(Individuals)} {
		set msg [team:FormatIndividuals]
	} else {
		set type [is $what]
		if {$type==$::team(Team)} {
			set msg [team:FormatTeam [team:Mod2 get $what team]]
		} elseif {$type==$::team(Member)} {
			set msg [team:Format [team:Mod get ? $what *]] 
		} elseif {$type==$::team(Individual)} {
			set msg [i:Format [i:Mod get $what *]] 
		} else { set msg "Eroare: <|$what|> este o persoana/echipa <|inexistenta|>!"}
	}
	say $chan $msg
}
proc team:FormatIndividuals {} {
	Trace [info level 0]
	set _total [team:Count individuals]
	set _all [i:Read]
	set _list ""
	set i 0
	set max [expr $::MAX_LEN - 50]	
	set overlen 0
	while {$i<$_total} {
		set line [lindex $_all $i]
		set nick [w:Extract $::team(Individual) $line nick]
		set scor [w:Extract $::team(Individual) $line scor]
		set new "[color] [R:Get $nick]) <|$nick|> [color]([R:Scor $scor])"
		set len1 [string length $_list]
		set len2 [expr $len1 + [string length $new]]
		if {$len2 > $max} { set overlen 1; break }
		append _list $new
		incr i
	}
	set _list [string trim $_list ", "]
	if {$overlen==1} { append _list " ...etc" }
	set Aname individual[expr $_total==1?"":"i"]
	return [textparse "Exista <|$_total|> $Aname:$_list"]
}
proc team:FormatTeams {} {
	Trace [info level 0]
	set _total [team:Count teams]
	set _teams [team:Read]
	set _list ""
	set i 0
	set max [expr $::MAX_LEN - 50]	
	set overlen 0
	while {$i<$_total} {
		set teamline [lindex $_teams $i]
		set team [w:Extract $::team(Teams) $teamline team]
		set total [w:Extract $::team(Teams) $teamline total]
		set scor [w:Extract $::team(Teams) $teamline scor]
		set capitan [w:Extract $::team(Teams) $teamline capitan]
		set Amembers "membr[expr $total==1?\"u\":\"ii\"]"
		set new "[color] [R:Get $team]) <|$team|> [color](Cpt. $capitan, $total $Amembers, [R:Scor $scor])"
		set len1 [string length $_list]
		set len2 [expr $len1 + [string length $new]]
		if {$len2 > $max} { set overlen 1; break }
		append _list $new
		incr i
	}
	set _list [string trim $_list ", "]
	if {$overlen==1} { append _list " ...etc" }
	set Ateams echip[expr $_total==1?\"a\":\"e\"]
	return [textparse "Exista <|$_total|> $Ateams:$_list"]
}
proc team:FormatTeam {team} {
	Trace [info level 0]
	set details [team:Mod2 get $team *]
	set _total [w:Extract $::team(Teams) $details total]
	set cpt [w:Extract $::team(Teams) $details capitan]
	set tScor [w:Extract $::team(Teams) $details scor]
	set created [w:Extract $::team(Teams) $details created]
	set _members [team:GetAll * $team]
	set _list ""
	set i 0
	set _tRank [R:Get $team]
	set Amembers "membr[expr $i==1?\"u\":\"ii\"]"
	set max [expr $::MAX_LEN - 50]
	set overlen 0
	while {$i<$_total} {
		set member [lindex $_members $i]
		set nick [w:Extract $::team(Member) $member nick]
		set grad [w:Extract $::team(Member) $member grad]
		set scor [w:Extract $::team(Member) $member scor]
		set new "[color] [expr $i+1]) <|$nick|> [color]($grad, [R:Scor $scor])"
		set len1 [string length $_list]
		set len2 [expr $len1 + [string length $new]]
		if {$len2 > $max} { set overlen 1; break }
		append _list $new
		incr i
	}
	set _list [string trim $_list ", "]
	if {$overlen==1} { append _list " ...etc" }
	return [textparse "Echipa <<<|$team|>>>, condusa de <|$cpt|>, este pe locul <|$_tRank|> cu [R:Scor $tScor] si are <|$_total|> $Amembers: $_list\nEchipa <<<|$team|>>> a fost creata in data de [w:DateFormat $created] (acum [w:EpochDuration $created])"]
}
proc team:GetAll {columns {team "*"}} {
	Trace [info level 0]
	if {$team!="*"} { set team [team:Mod2 get $team team] }
	set files [split [glob -nocomplain $::team(path,dir_teams)/$::team(prefix)$team] " "]
	set data ""
	set colCodes ""
	if {$columns!="*"} {
		set columns [split $columns ","]
		foreach col $columns { lappend colCodes [w:Conv $col $::team(Member) code] }
	}
	foreach fil $files {
		set fo [open $fil r]
		set _data [read -nonewline $fo]
		set _data [split $_data "\n"]
		foreach mem $_data {		
			set mem [split $mem ";"]
			set returnColumns ""
			if {$columns!="*"} {
				foreach colCode $colCodes { lappend returnColumns [lindex $mem $colCode] }
			} else { set returnColumns $mem }
			lappend data [join $returnColumns ";"]
		}
		close $fo
		unset _data
	}
	return $data
}
proc team:Count {what} {
	Trace [info level 0]
	switch $what {
		teams { set _file $::team(path,file_teams) }
		individuals { set _file $::team(path,file_individuals) }
		default { set _file $::team(path,dir_teams)/$::team(prefix)$what }	
	}
	set fo [open $_file r]
	set _data [read -nonewline $fo]
	set _data [split $_data "\n"]
	close $fo
	return [llength $_data]
}
proc team:GetInfo {nick {col ""}} {
	Trace [info level 0]
	if {$col==""} { set col "nick"}
    set Members [team:GetAll *]
	foreach Member $Members {
		set cols [split $Member ";"]
		if {[strlwr [lindex $cols 1]]==[strlwr $nick]} {
			return [lindex $cols [w:Conv $col $::team(Member) code]]
		}
	}
	return 0
}
proc team:IsMember {who} {
	Trace [info level 0]
	set Members [team:GetAll nick *]
	foreach Member $Members {
		if {[strlwr $Member]==[strlwr $who]} { return 1 }
	}
	return 0;
}
proc team:Read {{team "."}} {
	Trace [info level 0]
	if {$team=="."} { set team $::team(path,file_teams)
	} else { set team $::team(path,dir_teams)/$::team(prefix)$team }
	set _main [open $team r]
	set _data [read -nonewline $_main]
	close $_main
	return [split $_data "\n"]
}
proc team:Write {data {team "."}} {
	Trace [info level 0]
	if {$team=="."} {
		set team $::team(path,file_teams)
		set data [SortData scor $data $::team(Teams)]
	} else {
		set data [SortData scor $data $::team(Team)]
		set team $::team(path,dir_teams)/$::team(prefix)$team 
	}
	set _main [open $team w]
	puts $_main [join $data "\n"]
	close $_main
}
proc team:Mod {act targetteam targetnick col {mod 1}} {	
	Trace [info level 0]
	if {$targetteam=="?"} { set targetteam [team:GetInfo $targetnick team] }
	set data [team:Read $targetteam]
	set new ""
	if {$col!="*"} {
		set colCodes ""
		set col [split $col ","]
		foreach x $col { lappend colCodes [w:Conv $x $::team(Member) code] }
	} 	
	foreach line $data { set line [split $line ";"]
		set team	[lindex $line 0]
		set nick 	[lindex $line 1]
		set grad	[lindex $line 2]
		set scor 	[lindex $line 3]
		set correct [lindex $line 4]
		set joined 	[lindex $line 5]
		set last 	[lindex $line 6]
		set joins 	[lindex $line 7]
		set kicks 	[lindex $line 8]
		set speed 	[lindex $line 9]
		set consec	[lindex $line 10]
		set rank	[lindex $line 11]
		set time	[lindex $line 12]
		set uptime	[lindex $line 13]
		if {[strlwr $nick]==[strlwr $targetnick]} {
			switch $act {
				put {
					switch $col {
						0 - team { set team $mod }
						1 - nick { set nick $mod }
						2 - grad { set grad [w:Conv $mod grad name] }
						3 - scor { set scor [expr $scor + $mod] }
						4 - correct { set correct [expr $correct + $mod] } 
						5 - joined { set joined $mod }
						6 - last { set last [clock seconds]  }
						7 - joins { set joins [expr $joins + $mod] }
						8 - kicks { set kicks [expr $kicks + $mod] }
						9 - speed { set speed $mod }
						10 - consec { set consec $mod}
						11 - rank { set rank $rank }
						12 - time {
							if {$mod!=""} {
								set time $mod 
							} else {
								if {$uptime!=0} {
									set ad [expr [clock seconds] - $uptime]
									set uptime 0
									set time [expr $time + $ad] 
								}
							}
						}
						13 - uptime {
							if {$mod!=""} {
								set uptime $mod
							} else {
								set uptime [clock seconds]
							}
						}
						default { return -1 }
					}
				}
				get {
					if {$col=="*"} {
						return $line
					} else {
						set returnColumns ""
						foreach colCode $colCodes {
							lappend returnColumns [lindex $line $colCode]
						}
						return $returnColumns
					}					
				}
			}
		}
		if {$act=="put"} { lappend new "$team;$nick;$grad;$scor;$correct;$joined;$last;$joins;$kicks;$speed;$consec;$rank;$time;$uptime" }
	}
	if {$act=="put"} {
		team:Write $new $targetteam 
		if {$col=="scor"} {
			team:Compute $targetteam
		}
	}
}
proc team:IsCapitan {hand} {
	Trace [info level 0]
    set cpt [split [team:is capitan $hand] ";"]
	if {$cpt!=0} { return 1 } else { return 0 }
}
proc team:create {nick host hand chan params} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	if {[llength $params]!=2} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-echipa> (fara spatii; creatorul echipei este considerat si capitanul ei)"; return }
	set team [w:TeamTrimer [lindex $params 1]]
	if {$hand=="*"} { 
		team:Inregistrare $nick $host $hand $chan $params
		set hand [nick2hand $nick]
	}
	set capitan $hand
	if {[team:is echipa $team]!=0} { say $chan "Eroare: Numele de echipa <<<|$team|>>> este deja <|ocupat|>!"; return }
	if {![validuser $capitan]} { say $chan "Eroare: Numele capitanului, <<<|$capitan|>>>, este <|neinregistrat|>! $::team(help,0)"; return }
    set cpt [split [team:is capitan $capitan] ";"]
	if {$cpt!=0} { say $chan "Eroare: Capitanul <<<|$capitan|>>> detine deja echipa <|[lindex $cpt 0]|>!"; return }
	if {[is $hand]==$::team(Member)} { say $chan "Eroare: Pentru a-ti crea <|propria echipa|>, trebuie sa <|parasesti|> echipa la care esti deja membru, <|[team:GetInfo $hand team]|>. $::team(help,1)"; return }	
	set new ""
	set created [clock seconds]
	# new!!! DYNAMIC COLUMNS WRITE METHOD
	foreach col $::team(sets,Team,names) {
		set col "\$$col"
		set x [catch {info exists [expr $col]}]
		# x values: 0 for SUCCESS; 1 for FAIL
		if {$x==0} { set input [expr $col]
		} else { set input 0 }
		
		append new "$input "
	}
	set new [join [string trim $new] ";"]
	set _file [open $::team(path,file_teams) a+]
	puts $_file $new
    close $_file
	if {[i:is $hand]==0} {
		team:iAddMember $capitan $team 10 
	} else {
		w:Individual2Member $hand $team
		team:Mod put $team $capitan grad 10
	}
	chattr $hand +C
	say $chan "Echipa <<<|$team|>>> condusa de capitanul <<<|$capitan|>>> a fost <|creata|>."
	team:Compute $team
	R:Update
	set now [clock seconds]
	PutSet LastRegisteredTeam "$team;$capitan;[w:DateFormat $now 1]"
}
proc team:Compute {team} {
	Trace [info level 0]
	set Scores [w:GetAll membru scor $team]
	set Total 0
	foreach Score $Scores {
		set Total [expr $Total + $Score]
	}
	team:Mod2 put $team scor $Total
}
proc team:IsOwner {hand team} {
	Trace [info level 0]
	if {[strlwr [team:Mod2 get $team capitan]]==[strlwr $hand]} { return 1} else { return 0 }
}
proc team:delete {nick host hand chan params} {
	Trace [info level 0]
	if {[llength $params]!=2} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-echipa>"; return }
	set echipa [string trim [lindex $params 1]]
	if {[team:is echipa $echipa]==0} { say $chan "Eroare: Echipa <<<|$echipa|>>> nu exista ba!"; return }
	set echipa [team:Mod2 get $echipa team]
	if {![team:IsOwner $hand $echipa]&&![matchattr $hand o|-]} { say $chan "Eroare: Nu esti capitanul echipei <|$echipa|>"; return }
	say $chan [w:Individualizer $echipa]
    say $chan "Echipa <|$echipa|> a fost stearsa de <|$hand|>"
	chattr $hand -TC
	R:Update
}
proc team:iTeamDelete {team} {
	Trace [info level 0]
	set _tmp $::team(path,file_teams).tmp
	file copy -force $::team(path,file_teams) $_tmp
    set _main [open $::team(path,file_teams) w]
	set _tmpo [open $_tmp r]
	fconfigure $_tmpo -buffering line
	gets $_tmpo data
	while {$data != ""} {
		set temp [split [lindex $data 0] ";"]
		if {[strlwr [lindex $temp 0]]!=[strlwr $team]} { puts $_main $data }
		gets $_tmpo data	
	}
	close $_tmpo
	close $_main
	file delete -force $_tmp $::team(path,dir_teams)/$::team(prefix)$team
}
proc team:rename {nick host hand chan params} {
	Trace [info level 0]
	if {[llength $params]!=3} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <numele-de-echipa-initial> <numele-nou-de-echipa>"; return }
	set OldTeamName [string trim [lindex $params 1]]
	if {[team:is echipa $OldTeamName]==0} { say $chan "Eroare: Echipa <<<|$OldTeamName|>>> nu exista ba!"; return }
	set OldTeamName [team:Mod2 get $OldTeamName team]
	set NewTeamName [w:TeamTrimer [lindex $params 2]]
	if {![team:IsOwner $hand $OldTeamName]&&![matchattr $hand o|-]} { say $chan "Eroare: Nu esti capitanul echipei <|$OldTeamName|>!"; return }
	if {[team:is echipa $NewTeamName]!=0} { say $chan "Eroare: Numele de echipa <<<|$NewTeamName|>>> este deja ocupat!"; return }
	say $chan "Echipa <<<|$OldTeamName|>>> devine <<<|$NewTeamName|>>>."
	team:iRename $OldTeamName $NewTeamName
	#say $chan [w:Individualizer $echipa]
   # say $chan "Echipa <|$echipa|> a fost stearsa de <|$hand|>"
	#chattr $hand -TC
	#R:Update
}
proc team:iRename {old new} {
	Trace [info level 0]
	set Members [team:GetAll nick $old]
	foreach Member $Members {
		team:Mod put $old $Member team $new
	}
	team:Mod2 put $old team $new
	file rename -force $::team(path,dir_teams)/$::team(prefix)$old $::team(path,dir_teams)/$::team(prefix)$new
	R:Update
}
proc team:addmember {nick host hand chan params} {
	Trace [info level 0]
	if {[llength $params]>4||[llength $params]<2} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-membru> \[nume-echipa\]|> \[grad-membru\]"; return }
	set who [w:Trimer [lindex $params 1]]
	set hashandle [nick2hand $who]
	if {$hashandle!=""&&$hashandle!="*"} { set who $hashandle }
	if {![validuser $who]} { say $chan "Eroare: Numele membrului, <<<|$who|>>>, este <|neinregistrat|>! $::team(help,0)"; return }
	set stat [split [team:is capitan $hand] ";"]
	set echipa [string trim [lindex $params 2]]
	if {$echipa==""} {
		if {$stat==0} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-membru> \[nume-echipa\]|> \[grad-membru\] (Este obligatoriu sa specifici numele echipei deoarece nu esti [w:Conv 10 grad]"; return }
		set echipa [lindex $stat 0]
	} else  {
        	if {[team:is echipa $echipa]==0} { say $chan "Eroare: Numele de echipa <<<|$echipa|>>> nu <|exista|>!"; return }
	}
	if {[lsearch [team:GetAll nick] $who]>-1} { say $chan "Eroare: <<<|$who|>>> este deja <|[team:GetInfo $who grad]|> al echipei <|[team:GetInfo $who team]|>!"; return }
	set msg ""
	if {[is $who]==$::team(Individual)} {
		w:Individual2Member $who $echipa
		append msg "<<<|$who|>>>, fost $::individuals(name1), s-a alaturat echipei <|$echipa|>"
	} else {
		append msg "<<<|$who|>>> s-a alaturat echipei <|$echipa|>"
		team:iAddMember $who $echipa
	}
	set codName [g:Do $who]
	set xtra ""
	if {$codName!=""} { set xtra " ca si <|$codName|>" }
	g:DoAll $echipa
	say $chan "$msg."
	team:Compute $echipa
	R:Update
}
proc Write {where what} {
	Trace [info level 0]
	set _file $where
	set _stream [open $_file a]
	puts $_stream $what
	close $_stream
}
proc Sort {bycolumn type {params ""}} {
	Trace [info level 0]
	if {$params!=""} {
		set data [w:Read $type $params]
	} else { set data [w:Read $type] }
	w:Write $type [implode [lsort -dict -decreasing -index [w:Conv $bycolumn $type code] [explode $data]]] $params
}
proc SortData {bycolumn data type} {
	Trace [info level 0]
	set data [lsort -dict -decreasing -index [w:Conv $bycolumn $type code] [explode $data]]
	if {$type==$::team(Team)||$type==$::team(Teams)} {
		set i 1
		set new ""
		foreach element $data {
			lappend new [w:Insert $type $element rank $i]
			incr i
		}
		set data $new
	} elseif {$type==$::team(Individual)||$type==$::team(Individuals)} {
		foreach element $data {
			set nick [w:Extract $type $element nick]   
			lappend new [w:Insert $type $element rank [R:Get $nick]]
		}
		set data $new
	}
	return [implode $data]
}
proc team:iAddMember {nick team {grad "1"} {line ""}} {
	Trace [info level 0]
	set grad [w:Conv $grad grad name]
	set data [w:Read $::team(Team) $team]
	if {$line==""} {
		set line "$team;$nick;$grad;0;0;[clock seconds];0;0;0;-;0;0;0;0"
	} else {		
	}
	lappend data $line
	w:Write $::team(Team) [SortData scor $data $::team(Team)] $team
	chattr $nick -I
	chattr $nick +T
	team:Mod2 put $team total +1
	team:Mod put $team $nick last [clock seconds]
}
proc team:delmember {nick host hand chan params} {
	Trace [info level 0]
	if {[llength $params]!=2} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-membru>|>"; return }
	set who [string trim [lindex $params 1]]
	set stat [split [team:is capitan $hand] ";"]
	set echipa [lindex $stat 0]
	if {[team:is echipa $echipa]==0} { say $chan "Eroare: Numele de echipa <<<|$echipa|>>> nu <|exista|>!"; return }
	set membership [team:GetInfo $who team]
	if {$membership==0} { say $chan "Eroare: <<<|$who|>>> nu apartine niciunei echipe!"; return }
	if {$membership!=$echipa} { say $chan "Eroare: <<<|$who|>>> nu apartine echipei <|$echipa|>!"; return }
	if {[team:is capitan $who]!=0} { say $chan "Eroare: <<<|$who|>>> este <|[team:GetInfo $who grad]|> al echipei <|[team:GetInfo $who team]|>. Nu poti exclude un <|[team:GetInfo $who grad]|> din propria-i echipa!"; return }
	say $chan "<<<|$who|>>> a fost <|exclus|> din echipa <|$echipa|> de <|$hand|>."
	w:Individualizer $who
	team:Compute $echipa
	R:Update	
}
proc team:iDelMember {member {team ""}} {
	Trace [info level 0]
	if {$team==""} { set team [team:GetInfo $member team] }
	set _tmp $::team(path,dir_teams)/$::team(prefix)$team.tmp
	file copy -force $::team(path,dir_teams)/$::team(prefix)$team $_tmp
	set _main [open $::team(path,dir_teams)/$::team(prefix)$team w]
	set _tmpo [open $_tmp r]
	fconfigure $_tmpo -buffering line
	gets $_tmpo data
	while {$data != ""} {
		set temp [lindex [split $data ";"] 1]
		if {$temp!=$member} { puts $_main $data }
		gets $_tmpo data
	}
	close $_tmpo
	close $_main
	team:Mod2 put $team 2 -1
	file delete -force $_tmp $::team(path,dir_teams)/$::team(prefix)$team.tmp
}
proc team:Format {line} {
	Trace [info level 0]
	set team	[lindex $line 0]
	set nick 	[lindex $line 1]
	
	set grad	[lindex $line 2]
	set scor 	[lindex $line 3]
	set correct [lindex $line 4]
	set joined 	[lindex $line 5]
	set last 	[lindex $line 6]
	set joins 	[lindex $line 7]
	set kicks 	[lindex $line 8]
	set speed 	[lindex $line 9]
	set consec	[lindex $line 10]
	set rank	[lindex $line 11]
	set time	[lindex $line 12]
	set tRank [R:Get $team]
	set JoinedDuration [w:EpochDuration $joined]
	set LastDuration [w:EpochDuration $last]
	set TimeDuration [w:Duration $time]
	set line "Echipa: <|$team|>; Rank: <|$tRank|>; Nick: <|$nick|>; Grad: <|$grad|>; Scor: <|$scor|>; SubRank: <|$rank|>; Raspunsuri corecte: <|$correct|>; Record consecutive: <|$consec|>; Record viteza: <|$speed|>; Inregistrat: [w:DateFormat $joined] (acum $JoinedDuration); Ultima prezenta: [w:DateFormat $last] (acum $LastDuration); Vizite: <|$joins|>; Kickuri: <|$kicks|>; Timp total petrecut: <|$TimeDuration|>"
	return [textparse [colorize $line]]
	#return [textparse "Echipa: <|$team|> Rank: <|$tRank|> Nick: <|$nick|> Grad: <|$grad|> Scor: <|$scor|> SubRank: <|$rank|> Raspunsuri corecte: <|$correct|> Record consecutive: <|$consec|> Record viteza: <|$speed|> Inregistrat: [w:DateFormat $joined] (acum $JoinedDuration) Ultima prezenta: [w:DateFormat $last] (acum $LastDuration) Vizite: <|$joins|> Kickuri: <|$kicks|>"]
}
proc team:FormatWelcome {hand {msg "A intrat"}} {
	Trace [info level 0]
	set type [is $hand]
	if {$type!=0} {
		if {$type==$::team(Member)} {
			set line [team:Mod get ? $hand *]
			set team [w:Extract $type $line team]
			set nick [w:Extract $type $line nick]
			set grad [w:Extract $type $line grad]
			set scor [w:Extract $type $line scor]
			set last [w:Extract $type $line last]
			set lastDuration [w:EpochDuration $last]
			set rank [R:Get $nick $::team(Personal)]
			append msg " <|$nick|>, <|$grad|> al echipei <|$team|>, cu [R:Scor $scor] pe locul <|$rank|> in clasamentul $::team(Personal). Ultima vizita: acum $lastDuration."
		} elseif {$type==$::team(Individual)} {
			set line [i:Mod get $hand *]
			set nick [w:Extract $type $line nick]
			set scor [w:Extract $type $line scor]
			set last [w:Extract $type $line last]
			set lastDuration [w:EpochDuration $last]
			set rank [w:Extract $type $line rank]
			append msg " <|$nick|>, $::individuals(name1), cu [R:Scor $scor] pe locul <|$rank|> in clasamentul General. Ultima vizita: acum $lastDuration."
		} else { return "team:FormatWelcome: unsupported type $type for line $line!" }
		return [textparse $msg]
	}
	
}
proc team:selfexclude {nick uhost hand chan params} {
	Trace [info level 0]
	set team [team:GetInfo $hand team]
	if {[matchattr $hand C|]} { say $chan "Eroare: Esti capitanul echipei <|$team|>! Nu poti pleca pur si simplu din echipa! Prima data trebuie sa o <|desfiintezi|>! $::team(help,2)"; return }
	w:Individualizer $hand
	say $chan "<|$hand|> a renuntat la echipa <|$team|>, devenind un <|$::individuals(name1)|>"
	team:Compute $team
	R:Update
}
proc team:GetKey {hand {col 1}} {
	set res [lsearch $::team(Keys) "*$hand*"]
	if {$res!=-1} { return [lindex [lindex $::team(Keys) $res] $col] } else { return 0 }
}
proc team:HasKey {hand} {
	if {[lsearch $::team(Keys) "*$hand*"]==-1} { return 0 } else { return 1 }
}
proc team:AddKey {hand} {
	if {[team:HasKey $hand]==0} {
		set key [rand 10000]
		lappend ::team(Keys) "$hand $key"
		return $key
	} else { return [team:GetKey $hand] }
}
proc team:DelKey {hand} {
	if {[team:HasKey $hand]} {
		set pos [lsearch $::team(Keys) "*$hand*"]
		set ::team(Keys) [lreplace $::team(Keys) $pos $pos]
	}
}
proc team:Inregistrare {nick uhost hand chan params} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	# both = same conditions?
	if {$hand!="*"||[validuser $nick]} {
		set type [is $hand]
		if {$type!=0} {
			say $chan "Eroare: Numele de jucator <|$nick|> ($hand) este deja inregistrat!"
			return
		}
	}
	msg $nick "<|Confirma inregistrarea|> numelui de jucator <|$nick|> cu: <|/msg $::botnick confirma [team:AddKey $nick]|>"
}
proc team:selfadd {nick uhost hand chan params} {
	# useless?
	Trace [info level 0]
	set nick [w:Trimer $nick]
	if {[llength $params]>2 || [llength $params]<2} { say $chan "Eroare: Sintaxa corecta este: <|[lindex $params 0] <nume-echipa>|> (Pentru o lista cu echipele tasteaza $::team(char)$::team(Teams))"; return }
	set team [w:Trimer [lindex $params 1]]
	if {$hand=="*"} { set hand [getuser $nick handle] }
	if {[team:is $::team(Team) $team]==0} { say $chan "Eroare: Numele de echipa <<<|$team|>>> nu <|exista|>!"; return }
	w:Individual2Member $hand $team
	say $chan "<<<|$hand|>>>, $::individuals(name1), s-a alaturat echipei <|$team|>"
}
proc team:Top {nick uhost hand chan {params ""}} {
	Trace [info level 0]
	set top [lrange $params 1 end]
	set table "General"
	if {![string is digit $top]||$top==""||$top<1} {
		switch $top {
			timp - time { set table "Time" }
		}
		set top 10
	}
	say $chan [R:FormatAll $top $table]
}
proc team:PersonalTop {nick uhost hand chan {params ""}} {
	Trace [info level 0]
	set top [lrange $params 1 end]
	if {![string is digit $top]||$top==""||$top<1} {
		set top 10
	}	
	say $chan [R:FormatAll $top $::team(Personal)]
}

proc team:TopTimeFormat {} {
	Trace [info level 0]
	set rank 1
	set i 0
	set ::Total($ctable) [llength $::rank($ctable)]
	if {$top==""||$top=="*"} { set top ::Total($ctable) }
	set table ""
	set overlen 0
	set max [expr $::MAX_LEN - 50]
	if {$::Total($ctable)>0} {
		while {$rank<=$top&&$i<$::Total($ctable)} {
			set new [R:Format $rank $ctable]
			set len1 [string length $table]
			set len2 [expr $len1 + [string length $new]]
			if {$len2 > $max} { set overlen 1; break }
			append table $new
			incr i
			incr rank
		}
		append table [fcolor]
		if {$overlen==1} { append table " ...etc [fcolor $::color(misc)](tabela completa pe <|$::settings(homepage))|>" }
		set table "Top $i ($ctable): $table (din $::Total($ctable))"
	} else { append table "Tabela $ctable este goala." }
	set colorx 1
	return $table
}
proc team:Mod2 {action team col {mod 1}} {
	####
	# team:Mod2 - Gets/sets a certain column in the teams indexing file; "get" can also retrieve all columns
	Trace [info level 0]
	set data [team:Read]
	set new ""
	if {$col!="*"} {
		set colName [w:Conv $col $::team(Teams) name]
		set colCode [w:Conv $col $::team(Teams) code]
	} 
	foreach line $data {
		set line [split $line ";"]
		set cteam [lindex $line 0]
		if {[strlwr $team]==[strlwr $cteam]} {
			switch $action {
				put {
					set bak [lindex $line $colCode]
					if {$colCode==2||$colCode==4} {
						set mod [expr [lindex $line $colCode] + $mod]
					}
					set line [lreplace $line $colCode $colCode $mod]
				}
				get {				
					if {$col!="*"} { return [lindex $line $colCode] } else { return $line }
				}
			}
		}
		lappend new [join $line ";"]
	}
	if {$action=="put"} {
		team:Write $new
	}
}



#########################################################
##################### i:procs
#########################################################
proc i:is {nick} {
	Trace [info level 0]
	set _file [open $::team(path,file_individuals) r]
	set data [read -nonewline $_file]
	close $_file
	set persons [split $data "\n"]
	foreach person $persons {
		set parts [split $person ";"]
		set comp [lindex $parts 0]
		if {[strlwr $comp]==[strlwr $nick]} { return $person }
	}
	return 0	
}
proc i:Add {nick {line ""}} {
	Trace [info level 0]
	if {$line==""} {
		set nick [w:Trimer $nick]
		if {[validuser $nick]} {
			set now [clock seconds]
			Write $::team(path,file_individuals) "$nick;0;0;$now;0;0;0;-;0;0;0;0"
			PutSet LastRegistered "$nick;[w:DateFormat $now 1]"
		}
	} else {
		Write $::team(path,file_individuals) [join $line ";"]
	}
	w:Mod put $nick last
	chattr $nick +I-TC
	
}
proc i:Del {hand} {
	Trace [info level 0]
	if {[team:Count individuals]<2} { team:touch $::team(path,file_individuals); return }
	set new ""
	foreach line [i:Read] {
		set line [split $line ";"]
		if {[strlwr [lindex $line 0]]!=[strlwr $hand]} {
			lappend new [join $line ";"]
		}
	}
	i:Write $new
	chattr $hand -I
}
proc i:Read {} {
	Trace [info level 0]
	set _main [open $::team(path,file_individuals) r]
	set _data [read -nonewline $_main]
	close $_main
	return [split $_data "\n"]
}
proc i:Write {data} {
	Trace [info level 0]
	set _main [open $::team(path,file_individuals) w]
	puts $_main [join [SortData scor $data $::team(Individual)] "\n"]
	close $_main
}
proc i:Mod {act target col {mod 1}} {
	Trace [info level 0]
	set data [i:Read]
	set new ""
	if {$col!="*"} {
		set colCodes ""
		set col [split $col ","]
		foreach x $col { lappend colCodes [w:Conv $x $::team(Individual) code] }
	} 
	set _return ""
	set scorChanged 0
	foreach line $data {
		set line [split $line ";"]
		set nick 	[lindex $line 0]
		set scor 	[lindex $line 1]
		set correct [lindex $line 2]
		set joined 	[lindex $line 3]
		set last 	[lindex $line 4]
		set joins 	[lindex $line 5]
		set kicks 	[lindex $line 6]
		set speed 	[lindex $line 7]
		set consec	[lindex $line 8]
		set rank	[lindex $line 9]
		set time	[lindex $line 10]
		set uptime	[lindex $line 11]
		if {[strlwr $nick]==[strlwr $target]} {
			switch $act {
				put {
					switch $col {
						0 { set nick $mod }
						1 - scor { set scor [expr $scor + $mod]; set scorChanged 1 }
						2 - correct { set correct [expr $correct + $mod] } 
						3 - joined { set joined $mod }
						4 - last { set last [clock seconds]  }
						5 - joins { set joins [expr $joins + $mod] }
						6 - kicks { set kicks [expr $kicks + $mod] }
						7 - speed { set speed $mod } 
						8 - consec { set consec $mod }
						9 - rank { set rank $mod }
						10 - time {
							if {$mod!=""} {
								set time $mod 
							} else {
								if {$uptime!=0} {
									set ad [expr [clock seconds] - $uptime]
									set uptime 0
									set time [expr $time + $ad] 
								}
							}
						}
						11 - uptime {
							if {$mod!=""} {
								set uptime $mod
							} else {
								set uptime [clock seconds]
							}
						}						
						default { return -1 }
					}
				}
				get {
					if {$col=="*"} {
						return $line
					} else {
						set returnColumns ""
						foreach colCode $colCodes {
							lappend returnColumns [lindex $line $colCode]
						}
						return $returnColumns
					}
				}
			}
		}
		lappend new "$nick;$scor;$correct;$joined;$last;$joins;$kicks;$speed;$consec;$rank;$time;$uptime"
	}
	if {$act=="put"} {
		i:Write $new
	}
}
proc i:GetAll {columns} {
	Trace [info level 0]
	set data [i:Read]
	if {$columns!="*"} {
		set colData ""
		set colCodes ""
		set columns [split $columns ","]
		foreach col $columns { lappend colCodes [w:Conv $col $::team(Individual) code] }
		foreach line $data {
			set line [split $line ";"]
			set newCol ""
			foreach colCode $colCodes {
				lappend newCol [lindex $line $colCode]
			}			
			lappend colData $newCol
		}
		return $colData
	} else { return $data }
}
proc i:Format {line} {
	Trace [info level 0]
#"$nick;$scor;$correct;$joined;$last;$joins;$kicks;$speed;$consec;$rank"
	set nick 	[lindex $line 0]
	set scor 	[lindex $line 1]
	set correct [lindex $line 2]
	set joined 	[lindex $line 3]
	set last 	[lindex $line 4]
	set joins 	[lindex $line 5]
	set kicks 	[lindex $line 6]
	set speed 	[lindex $line 7]
	set consec	[lindex $line 8]
	set rank	[lindex $line 9]
	set time	[lindex $line 10]
	set JoinedDuration [w:EpochDuration $joined]
	set LastDuration [w:EpochDuration $last]
	set TimeDuration [w:Duration $time]
	set line "Nick: <|$nick|>; Tip: <|$::individuals(name1)|>; Scor: <|$scor|>; Rank: <|$rank|>; Raspunsuri corecte: <|$correct|>; Raspunsuri consecutive: <|$consec|>; Viteza maxima: <|$speed|>; Inregistrat: [w:DateFormat $joined] (acum $JoinedDuration); Ultima prezenta: [w:DateFormat $last] (acum $LastDuration); Vizite: <|$joins|>; Kickuri: <|$kicks|>; Timp total petrecut: <|$TimeDuration|>"
	return [textparse [colorize $line]]
}



#########################################################
##################### II, w:procs
#########################################################
proc is {nick} {
	Trace [info level 0]
	if {[team:IsMember $nick]==1} { return $::team(Member)
	} else {
		if {[i:is $nick]!=0} { return $::team(Individual)
		} else {
			if {[team:is echipa $nick]!=0} { return $::team(Team) } else { return 0 }
		}
	}
}
proc w:Register {nick {type ""}} {
	Trace [info level 0]
	set key [team:AddKey $nick]
	if {[validuser $nick]==0} {
		adduser $nick "*![getchanhost $nick]"
		setuser $nick pass $key
	}
	chattr $nick +R
	if {$type=="autoadded"}  { say $::team(chan) "Numele de jucator <|$nick|> a fost <|inregistrat|> si declarat din oficiu <|$::individuals(name1)|>." }
	i:Add $nick
	msg $nick "Parola ta actuala pentru numele de jucator <|$nick|> este: <<<|$key|>>>. In continuare: 1) Trebuie sa te loghezi, cu: <|/msg $::botnick auth $key|> apoi, 2) Sa iti schimbi parola (daca vrei): <|/msg $::botnick newpass $key 'PAROLA NOUA'|> (fara ghilimele!) \002\00304 Tine minte: parola este utila pentru a te recunoste ca si jucator! Daca adresa ta de internet (IP) ti se schimba regulat si nu iti setezi parola, BOTUL de trivia NU TE VA RECUNOASTE PE VIITOR!\002\00304"
}
proc w:Get {target col} {
	Trace [info level 0]
	set type [is $target]
	if {$type==$::team(Team)} {
		return [team:GetAll $col $target]
	} elseif {$type==$::team(Member)} {
		return [team:Mod get ? $target $col]
	} elseif {$type==$::team(Individual)} {
		return [i:Mod get $target $col]
	} else { dump "w:Get: $target type is unknown ($type)" error; return -1 }
}
proc w:Set {target col val} {
	Trace [info level 0]
	set type [is $target]
	if {$type==$::team(Team)} {
		team:Mod2 put $target $col $val
	} elseif {$type==$::team(Member)} {	
		team:Mod put ? $target $col $val
	} elseif {$type==$::team(Individual)} {
		i:Mod put $target $col $val
	} else { dump "w:Get: $target type is unknown ($type)" error; return -1 }
}
proc w:Individualizer {target} {
	Trace [info level 0]
	set msg "w:Individualizer ERROR"
	if {[llength $target]==1} {
		if {[team:is $::team(Team) $target]!=0} {
			set exMembers [team:GetAll nick $target]
			w:Member2Individual $exMembers
			team:iTeamDelete $target
			set msg "Ex-membrii echipei <|$target|> <|(|>[join $exMembers ", "]<|)|> au fost declarati <|$::individuals(name2)|>."
		} else {
			w:Member2Individual $target
			team:iDelMember $target
			set msg "$target"
		}
	} else {
		w:Member2Individual $target
		team:iDelMember $target
		set msg $target
	}
	return $msg
}
proc w:Member2Individual {hands} {
	Trace [info level 0]
	set n [llength $hands]
	foreach hand $hands {
		set line [team:Mod get ? $hand *]
		set line "[lindex $line 1] [lrange $line 3 end]"
		i:Add $hand $line
	}
	return 1
}
proc w:Individual2Member {hand team {grad 1}} {
	Trace [info level 0]
	set line [i:Mod get $hand *]
	set line "$team [lindex $line 0] [w:Conv $grad grad name] [lrange $line 1 end]"
	team:iAddMember $hand $team $grad [join $line ";"]
	i:Del $hand
	return 1
}
proc w:Mod {action target col {mod ""}} {
	Trace [info level 0]
	set type [is $target]
	set data ""
	if {$type==$::team(Member)} {
		set data [team:Mod $action ? $target $col $mod]
	} elseif {$type==$::team(Individual)} {
		set data [i:Mod $action $target $col $mod]
	}	
	if {$action=="get"} { return $data }
}
proc w:GetAll {type columns {team ""}} {
	Trace [info level 0]
	if {$type==$::team(Teams)} {
		set data [team:Read]
	} elseif {$type==$::team(Member)} {
		set data [team:Read $team]
		#return "w:GetAll / members / NOT IMPLEMENTED YET!"
	} elseif {$type==$::team(Individual)} {
		set data [i:Read]
	} else { return "w:GetAll: You're retarded?! ERROR!" }		
	if {$columns!="*"} {
		set colData ""
		set colCodes ""
		set columns [split $columns ","]
		foreach col $columns { lappend colCodes [w:Conv $col $type code] }
		foreach line $data {
			set line [split $line ";"]
			set newCol ""
			foreach colCode $colCodes {
				lappend newCol [lindex $line $colCode]
			}			
			lappend colData $newCol
		}
		return $colData
	} else { return $data }
}
proc w:CorrectAnswer {nick hand chan scor} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	if {[validuser $hand]==0} {
		if {[validuser $nick]} {
			# say $chan "Utilizatorul $nick nu s-a logat!"
			set hand $nick
		} elseif {[validuser $nick]==0} {
			w:Register $nick autoadded
			set hand $nick
		}
	}
	set type [is $hand]
	if {$type==0} { i:Add $hand; set type $::team(Individual) }
	set _oldrank ""
	set _name ""
	set _who ""
	if {$type==$::team(Member)} {
		set team [team:GetInfo $hand team]
		set _oldrank [R:Get $team]
		set _who $team
		team:Mod put $team $hand scor $scor
		team:Compute $team
		set _name "Echipa <<<|$team|>>>"
	} elseif {$type==$::team(Individual)} {
		set _oldrank [R:Get $hand]
		set _who $hand
		i:Mod put $hand scor $scor
		set _name "<|$hand|>"
	} elseif {$type==0} {
		dump "Correct answer by: unknown" 
	}
	R:Update
	w:Mod put $hand correct 1
	set _newrank [R:Get $_who]
	set _avans ""
	if {$_newrank<$_oldrank} {
		if {$_newrank==1} {
			append _avans " [fcolor 04]$_name a ajuns pe primul loc![fcolor]"
		} else {
			set rankage [expr $_oldrank - $_newrank]
			append _avans " [fcolor 04]$_name avanseaza $rankage loc[expr $rankage==1?"":"uri"][fcolor]."
		}
	}
	set _record "[fcolor 04]<|RECORD NOU|>[fcolor])"
	set _speed ""
	if {$::tgtimeanswer==1} {
		set _timetoanswer [expr [expr [clock clicks -milliseconds]-$::tgtimestart]/1000.00]
		set hv ""
		set _timetoanswer_old [w:Mod get $hand speed]
		if {$_timetoanswer<$_timetoanswer_old} { w:Mod put $hand speed $_timetoanswer }		
		if {$_timetoanswer<[lindex [GetSet speed] 1]} {
			PutSet speed "$hand $_timetoanswer"
			append hv "($_record [lindex [GetSet speed] 1]"
			w:Mod put $hand speed $_timetoanswer
		} else { append hv "$_timetoanswer" }
		set _speed " [expr $::tgtimeanswer==1?"Viteza: ${hv}s.":""]"
	}
	if {$nick!=$hand} { set _nick "$nick ($hand)" } else { set _nick $hand }
	set _head "[RandS tgcongrats] <|$_nick|>! [RandS corect] <|$::tgcurrentanswer|>."
	set _cumul " Acumulari: [R:Scor $scor]."
	set _consec ""
	if {$::tgstreak!=0} {
		if {[lindex [split $::tgstreak ,] 0]==[strlwr $nick]} {
			set ::tgstreak [strlwr $nick],[expr [lindex [split $::tgstreak ,] 1]+1]
			if {$::tgstreakmin>0&&[lindex [split $::tgstreak ,] 1]>=$::tgstreakmin} {
				set crasp [lindex [split $::tgstreak ,] 1]
				set crasp_old [w:Mod get $hand consec]
				if {$crasp_old<$crasp} { w:Mod put $hand consec $crasp }
				set hc ""
				if {$crasp>[lindex [GetSet consec] 1]} {
					PutSet consec "$nick $crasp"
					append hc "$_record "
				}
				append hc "$crasp"
				set _consec " Consecutive: $hc."
			}
		} else {
			if {$::tgstreakmin>0&&[lindex [split $::tgstreak ,] 1]>=$::tgstreakmin} { ::tgstreakend }
			set ::tgstreak [strlwr $nick],1
		}
	} else {
		set ::tgstreak [strlwr $nick],1
	}	
	set _xtra ""
	set _scor ""
	if {$type==$::team(Member)} {
		if {[matchattr $hand C|]==0} {
			set codName [g:Do $hand]
			if {$codName!=""} { set _xtra " [fcolor 04]<|$hand|> devine <|$codName|> al echipei <|$team|>![fcolor]" }
			g:DoAll $team
		}
		set sTeam [R:Scor [R:GetInfo $team 1]]
		set sMember [R:Scor [team:Mod get $team $hand scor]]
		append _scor " Echipa <|$team|> este pe locul <|$_newrank|> si are acum $sTeam, iar <|$hand|> are $sMember."
	} elseif {$type==$::team(Individual)} {
		append _scor " <|$hand|>, $::individuals(name1), este pe locul <|$_newrank|> si are acum [R:Scor [R:GetInfo $hand 1]]."
	}
	set msg "$_head$_consec$_speed$_avans$_xtra$_cumul$_scor"
	say $chan "$msg"
}



#########################################################
##################### Rank R:procs
#########################################################
proc R:Update {} {
	Trace [info level 0]
	dump "Updating tables..."
	set General [concat [w:GetAll $::team(Teams) team,scor,capitan] [w:GetAll $::team(Individual) nick,scor]]
	set Personal [concat [explode [team:GetAll nick,scor,team]] [w:GetAll $::team(Individual) nick,scor]]
	set ::Total(General) [llength $General] 
	set ::Total(Personal) [llength $Personal]
	set ::rank(Time) [lsort -dict -decreasing -index end [concat [i:GetAll nick,time] [explode [team:GetAll nick,time *]]]]
	if {$::Total(General)>0} {
		set ::rank(General) [lsort -dict -decreasing -index 1 $General]
		w:Write rank $::rank(General)
	}
	if {$::Total(Personal)>0} {
		set ::rank(Personal) [lsort -dict -decreasing -index 1 $Personal]
		w:Write $::team(Personal) $::rank(Personal)
	}
	set ::Total(Teams) [team:Count teams]
	set ::Total(Individuals) [team:Count individuals]
	return $::Total(General)
}
proc R:Init {type} {
	R:Update
}
proc R:Get {who {table "General"}} {
	Trace [info level 0]
	set ret ""
	if {[string is digit $who]} {
		append ret [lindex $::rank($table) [incr who -1]]
	} else {
		append ret [expr [lsearch $::rank($table) "*$who*"] + 1]
	}
	return $ret
}
proc R:GetInfo {who {col} {table "General"}} {
	Trace [info level 0]
	### 
	# retrieves information by COLUMN CODE about a certain ranked player given by #RANK or PLAYER NAME
	set ret ""
	if {[string is digit $who]} {
		append ret [lindex [lindex $::rank($table) [incr who -1]] $col]
	} else {
		append ret [R:GetInfo [expr [lsearch $::rank($table) "*$who*"] + 1] $col]
	}
	return $ret
}
proc R:Format {rank {table "General"}} {
	Trace [info level 0]
	set ranked [split [R:Get $rank $table] " "]
	set name [lindex $ranked 0]
	set scor [lindex $ranked 1]			
	if {[llength $ranked]==3} { set ccolor [color $::team(Team)] } else { set ccolor [color] }
	if {$rank==1} {
		set ccolor "[color nr1]<|"
	} elseif {$rank==2} {
		set ccolor [color nr2]
	} elseif {$rank==3} {
		set ccolor [color nr3]
	}
	if {$table=="Time"} { set scor [w:Duration $scor] }
	set ret "$ccolor $rank\) $name $scor "
	if {$rank==1} { append ret "|>" }
	return [textparse $ret]
}
proc R:FormatAll {{top ""} {ctable "General"}} {
	Trace [info level 0]
	set rank 1
	set i 0
	set ::Total($ctable) [llength $::rank($ctable)]
	if {$top==""||$top=="*"} { set top ::Total($ctable) }
	set table ""
	set overlen 0
	set max [expr $::MAX_LEN - 50]
	if {$::Total($ctable)>0} {
		while {$rank<=$top&&$i<$::Total($ctable)} {
			set new [R:Format $rank $ctable]
			set len1 [string length $table]
			set len2 [expr $len1 + [string length $new]]
			if {$len2 > $max} { set overlen 1; break }
			append table $new
			incr i
			incr rank
		}
		append table [fcolor]
		if {$overlen==1} { append table " ...etc [fcolor $::color(misc)](tabela completa pe <|$::settings(homepage))|>" }
		set table "Top $i ($ctable): $table (din $::Total($ctable))"
	} else { append table "Tabela $ctable este goala." }
	set colorx 1
	return $table
}


#########################################################
##################### team:Request:procs
#########################################################
proc team:syntax {inviter} { return "[fcolor 04]Pentru a refuza invitatia lui <|$inviter|> scrie: <|/msg $::botnick [getTrigger RequestAnswer] $::requests2(1) $inviter|> iar pentru a accepta: <|/msg $::botnick [getTrigger RequestAnswer] $::requests2(2) $inviter|>[fcolor]" }

proc team:Request:Expiration {date} {
	set now [clock seconds]
	set expSeconds [expr [clock scan [string trim $::requests(expiration) "{}"]] - $now]
	set expAfter [w:Duration $expSeconds]
	set remSeconds [expr $now - $date]
	if {$remSeconds<=$expSeconds} {
		if {$remSeconds==0} { set remDuration $expAfter } else { set remDuration [w:Duration $remSeconds] }
		set status "expira in <|$remDuration|>."
	} else { set msg "a expirat!" }
	
	set madeOn [clock format $date -format $::team(clockformat)]
	return "[fcolor 14]Invitatia a fost facuta in data de $madeOn si $status[fcolor]"
}
proc team:Request:Add {inviter invited} {
	Trace [info level 0]
	set agreement $::requests(0)
	set data [w:Read request]
	set date [clock seconds]
	lappend data "$inviter;$invited;$agreement;$date"
	w:Write request $data
	team:Request:Announce $invited [textparse "<|$inviter|> te-a invitat sa te alaturi echipei <<<|[team:GetInfo $inviter team]|>>>. [team:Request:Expiration $date] [team:syntax $inviter]"]
}
proc CurrentHand {nick} {
	Trace [info level 0]
	set hand [nick2hand $nick]
	if {$hand!=""&&$hand!="*"} {
		if {$hand!=$nick} {
			return $hand
		} else {
			return $nick
		}
	} else { return $nick }
}
proc team:Request:OneCheck {data inviter invited} {
	# returning values:
	#	- 0: neinregistrat
	#	- 1: already added/existent (in asteptare)
	#	- 2: OK TO GO
	#	- 3: capitan
	#	- 4: already member
	#	- 5: team name
	Trace [info level 0]
	set invited [CurrentHand $invited]
	if {[matchattr $invited T|]} {
		if {[team:GetInfo $invited team]==[team:GetInfo $inviter team]} { return 4 }
	}
	set ret 2
	set type [is $invited]
	putlog "$invited: $type"
	if {$type==0} {
		set ret 0
	} elseif {$type==$::team(Team)} {
		set ret 5
	} else {
		if {[matchattr $invited C|]} { set ret 3
		} else {
			foreach line $data {
				set line [split $line ";"]
				set _inviter [lindex $line 0]
				set _invited [lindex $line 1]
				set _agreement [lindex $line 2]			
				if {[strlwr $inviter]==[strlwr $_inviter]&&[strlwr $invited]==[strlwr $_invited]} {
					if {$_agreement==$::requests(0)} {
						set ret 1
					}
					break;
				}
			}
		}
	}
	return $ret
}
proc team:Request:MultiCheck {inviter players} {
	Trace [info level 0]
	set data [w:Read request]
	set listUnregs ""
	set listExists ""
	set listCpt ""
	set listOK ""
	set listAlreadyMems ""
	set listTeams ""
	set players [lsort -unique $players]
	foreach player $players {
		set state [team:Request:OneCheck $data $inviter $player]
		switch $state {
			0 { append listUnregs "$player, " }
			1 { append listExists "$player, " }
			2 { append listOK "$player, "; team:Request:Add $inviter $player }
			3 { append listCpt "$player, " }
			4 { append listAlreadyMems "$player, " }
			5 { append listTeams "$player, " }
		}
	}
	set listUnregs [string trim $listUnregs ", "]
	set listExists [string trim $listExists ", "]
	set listCpt [string trim $listCpt ", "]
	set listOK [string trim $listOK ", "]
	set listAlreadyMems [string trim $listAlreadyMems ", "]
	set listTeams [string trim $listTeams ", "]
	set team [team:GetInfo $inviter team]
	set final "Invitatii pentru echipa <|$team|> -"
	
	set now [clock seconds]
	set expSeconds [expr [clock scan [string trim $::requests(expiration) "{}"]] - $now]
	set expAfter [w:Duration $expSeconds]

	if {$listOK!=""} { append final " <|ADAUGATE|>: $listOK. (expira dupa $expAfter)" }
	if {$listExists!=""||$listUnregs!=""||$listCpt!=""||$listAlreadyMems!=""||$listTeams!=""} {
		append final " <|NEADAUGATE|>:"
		if {$listExists!=""} { append final " <|In asteptare|>: $listExists." } 
		if {$listUnregs!=""} { append final " <|Neinregistrati|>: $listUnregs." }
		if {$listCpt!=""} { append final " <|Capitani|>: $listCpt (nu poti adauga capitani ai altor echipe)." }
		if {$listAlreadyMems!=""} { append final " <|Deja membri|>: $listAlreadyMems." }
		if {$listTeams!=""} { append final " <|Echipe|>: $listTeams (nu poti invita o echipa intreaga)." }
	}
	return [textparse $final]
}
proc team:Request:Setup {nick uhost hand chan params} {
	if {[lindex $params 1]=="clean"} {
		say $chan [team:Request:Clean]
	}
}
proc team:Request:Clean {} {
	Trace [info level 0]
	set data [w:Read request]
	set invitations ""
	set new ""
	set ok 0
	set no 0
	foreach invitation $data {
		set invitation [split $invitation ";"]
		set inviter [lindex $invitation 0]
		set invited [lindex $invitation 1]
		set agreement [lindex $invitation 2]
		set date [lindex $invitation 3]
		if {[team:Request:IsValid $date]} {
			incr ok 
			lappend new [join $invitation ";"]
		} else {
			incr no
		}
	}
	w:Write request $new
	return "Am sters <|$no|> invitatii expirate si au mai ramas <|$ok|> invitatii."
}
proc team:Request:IsValid {date} {
	if {$date==0||$date==""} { return 0 }
	set now [clock seconds]
	set expSeconds [expr [clock scan [string trim $::requests(expiration) "{}"]] - $now]
	set remSeconds [expr $now - $date]
	if {$remSeconds<=$expSeconds} {
		set ret 1
	} else { set ret 0 }
	return $ret
}

proc team:Request:Announce {hand message} {
	Trace [info level 0]
	set isonline [hand2nick $hand $::team(chan)]
	if {$isonline!=""} {
		msg $isonline $message
	}
}
proc team:Request:AnnounceAll {} {
	Trace [info level 0]
	set data [w:Read request]
	if {$data==""} { return }
	foreach invitation $data {
		set invitation [split $invitation ";"]
		set _inviter [lindex $invitation 0]
		set _invited [lindex $invitation 1]
		set _agreement [lindex $invitation 2]
		set _date [lindex $invitation 3]
		if {$_agreement==$::requests(0)} {
			set isonline [hand2nick $_invited $::team(chan)]
			if {$isonline!=""} {
				set team [team:GetInfo $_inviter team]
				msg $isonline "<|$_inviter|> te-a invitat sa te alaturi echipei <<<|$team|>>>. [team:Request:Expiration $_date] [team:syntax $_inviter]"
				dump "\[team:Request:AnounceAll\] Announced $isonline to join $team ($_inviter)"
			}
		}
	}
}
proc team:Request:Mod {inviter invited {toagreement ""}} {
	Trace [info level 0]
	set data [w:Read request]
	if {$toagreement==""} { set toagreement 2 }
	set toagreement $::requests($toagreement)
	set new ""
	set msg ""
	foreach line $data {
		set skip 0
		set line [split $line ";"]
		set inviter2 [lindex $line 0]
		set invited2 [lindex $line 1]
		set agreement2 [lindex $line 2]
		if {$inviter==$inviter2&&[strlwr $invited]==[strlwr $invited2]} {
			if {$agreement2==$toagreement} {
				append msg "Statusul invitatiei lui $inviter2 catre $invited2 este deja $agreement2"
			} else {
				append msg "Statusul invitatiei lui $inviter2 catre $invited2 modificat in: $toagreement"
				set line "$inviter2 $invited2 $toagreement"
				set skip 1
			}
			if {$toagreement==$::requests(2)} {
				set inviter_type [is $inviter]
				set invited_type [is $invited]
				if {$inviter_type!=0&&$invited_type!=0&&$inviter_type==$::team(Member)} {				
					if {$invited_type==$::team(Member)} {
						set oldteam [team:GetInfo $invited team]
						w:Individualizer $invited
						set team [team:GetInfo $inviter team]
						w:Individual2Member $invited $team
						set pubmsg "<<<|$invited|>>> <|RENUNTA|> la echipa <<$oldteam>> si se <|ALATURA|> echipei <|$team|> la invitatia lui <|$inviter|>"
					} elseif {$invited_type==$::team(Individual)} {
						set team [team:GetInfo $inviter team]
						w:Individual2Member $invited $team
						
						set pubmsg "<<<|$invited|>>> <|ACCEPTA|> invitatia lui <|$inviter|> si se <|ALATURA|> echipei <|$team|>"
					}
					set codName [g:Do $invited]
					set xtra ""
					if {$codName!=""} { set xtra ", ca si <|$codName|>" }											
					say $::team(chan) "$pubmsg$xtra."
					g:DoAll $team
					team:Compute $team
				}
			} elseif {$toagreement==$::requests(1)} {
				set team [team:GetInfo $inviter team]
				say $::team(chan) "<<<|$invited|>>> <|REFUZA|> invitatia lui <|$inviter|> de a se alatura echipei <|$team|>."
			}
		}
		if {$skip==0} { lappend new [join $line ";"] }
	}
	w:Write request $new
	R:Update
	return $msg
}
proc team:Request:IsInvited {invited} {
	Trace [info level 0]
	set data [w:Read request]
	set invitations ""
	foreach invitation $data {
		set invitation [split $invitation ";"]
		set _inviter [lindex $invitation 0]
		set _invited [lindex $invitation 1]
		set _agreement [lindex $invitation 2]
		if {[strlwr $invited]==[strlwr $_invited]&&$_agreement==$::requests(0)} {
			lappend invitations $invitation
		}
	}
	if {[llength $invitations]>0} {
		return $invitations
	} else { return 0 }
}	
proc team:Request:CheckHand {hand} {
	Trace [info level 0]
	set invitations [team:Request:IsInvited $hand]
	if {$invitations!=0} {
		foreach invitation $invitations {
			set inviter [lindex $invitation 0]
			msg [hand2nick $hand] "<|$inviter|> te-a invitat sa te alaturi echipei <<<|[team:GetInfo $inviter team]|>>>. [team:syntax $inviter]"
		}
	}
}
proc team:request {nick uhost hand chan params} {
	Trace [info level 0]
	set com [lindex $params 0]
	set linvited [lrange $params 1 end]
	if {[llength $linvited]<1} {
		say $chan "Eroare: Sintaxa corecta este: $com <jucator> <jucator2> <jucator3> ..."
		return
	}
	say $chan [team:Request:MultiCheck $hand $linvited]
}



#########################################################
##################### onEvent:procs
#########################################################
# all these pre-handlers could be replace by lastbind's functionality
proc TimeAdd {hand} {
	Trace [info level 0]
	set us [w:Mod get $hand uptime]
	if {$us!=0} { 
		set usd [w:Duration [expr [clock seconds] - $us]]
		#putlog "Added to $hand time: $usd"
		w:Mod put $hand time		
	}
}


proc team:time {nick uhost hand chan params} {
	set uptime [w:Mod get $hand uptime]
	if {$uptime==0} { set upDuration "0 secunde" } else { set upDuration [w:Duration [expr [clock seconds] - $uptime]] }
	set who $nick
	putlog "$uptime $upDuration"
	set time [w:Mod get $hand time]
	set TimeDuration [w:Duration $time]
	if {$nick!=$hand} { append who " ($hand)" }
	say $chan "<|$who|>, timpul curent petrecut pe canal este de: <|$upDuration|>. Timpul total petrecut: <|$TimeDuration|> [fcolor 14](acesta timp actual va fi adaugat la timpul total petrecut la joc doar DUPA iesirea ta (quit/part) - comenzi ajutatoare: !scor !timp sau !top timp)"
}

proc onJoin {nick uhost hand chan} { onEvent $nick $uhost $hand $chan "join" }
proc onPart {nick uhost hand chan {msg ""}} { onEvent $nick $uhost $hand $chan "part" }
proc onKick {nick uhost hand chan target {msg ""}} { onEvent $nick $uhost $hand $chan "kick" "$target" }
proc onSign {nick uhost hand chan {reason ""}} {
	Trace [info level 0]
	putlog "onSign triggered: $nick"
	onEvent $nick $uhost $hand $chan "sign"
}
proc onEvent {nick uhost hand chan event {params ""}} {
	Trace [info level 0]
	set ok 1
	set type 0
	if {[matchattr $hand T|]} {
		set type $::team(Team)
	} elseif {[matchattr $hand I|]} {
		set type $::team(Individual)	
	} else { set ok 0 }
	putlog "event: $event"
	if {$ok==1} { 
		if {$event=="join"} {
			team:Welcome $hand $chan
			w:Mod put $hand uptime
			w:Mod put $hand last
			w:Mod put $hand joins +1
			team:Request:CheckHand $hand
		} elseif {$event=="part"||$event=="sign"} {
			w:Mod put $hand last
			TimeAdd $hand
			w:Mod put $hand uptime 0
		} elseif {$event=="kick"} {
			w:Mod put $params kicks +1
		}
	} 
	#else { Unknow user or someone that's not a trivia player }
}
proc team:Welcome {hand chan} {
	Trace [info level 0]
	say $chan [team:FormatWelcome $hand]
}

proc onConfirmation {nick uhost hand params} {
	Trace [info level 0]
	set nick [w:Trimer $nick]
	if {[team:HasKey $nick]} {
		if {[llength $params]>2} { msg $nick "Eroare: Sintaxa corecta este: <|/msg $::botnick confirma COD|> (unde COD este codul primit)"; return }
		set key [lindex $params 0]
		set _hand [team:GetKey $nick 0]
		set _key [team:GetKey $nick]
		if {$nick==$_hand} {
			if {$key==$_key} {
				w:Register $nick
				say $::team(chan) "Numele de jucator <|$nick|> ($_hand) a fost <|inregistrat|> cu succes!" 
			} else {
				msg $nick "Codul introdus este <|gresit|>. Incearca din nou..."
			}
		}
	}
}
proc onRequestAnswer {nick uhost hand text} {
	Trace [info level 0]
	set invitations [team:Request:IsInvited $hand]
	set text [stripcodes bcruag $text]
	if {$invitations!=0} {
		foreach invitation $invitations {
			set inviter [lindex $invitation 0]
			set invited [lindex $invitation 1]
			if {[llength $text]!=2} {
				msg $nick "Eroare: [team:syntax $inviter]"
			} else {
				set decision [strupr [lindex $text 0]]
				set _inviter [lindex $text 1]
				if {$inviter!=$_inviter} {
					msg $nick "[team:syntax $inviter]"		
				} else {
					if {$decision==$::requests2(2)} {
						dump "$hand accepta invitatia ($invitation)"
						team:Request:Mod $inviter $hand
						msg $nick "Raspunsul tau la invitatia lui $inviter a fost primit!"
					} elseif {$decision==$::requests2(1)} {
						dump "$hand refuza invitatia ($invitation)"
						team:Request:Mod $inviter $hand 1
						msg $nick "Raspunsul tau la invitatia lui $inviter a fost primit!"
					} else {
						msg $nick "Eroare: [team:syntax $inviter]"
					}
				}
			}
		}
	}
}








proc Stats:Gen:FormatOne {rank {table "General"}} {
	Trace [info level 0]
	set ranked [split [R:Get $rank $table] " "]
	set name [lindex $ranked 0]
	set scor [lindex $ranked 1]	
	if {[llength $ranked]==3} {
		if {$table==$::team(Personal)} {
			append name " (Echipa [lindex $ranked 2])"
		} elseif {$table==$::team(General)} {
			append name " (Cpt. [lindex $ranked 2])"
		}
	}
	if {$table=="Time"} {
		if {$scor=="{}"||$scor==0} {
			return 0
		}
		set scor [w:Duration $scor] 
	}
	set color "rank"
	if {$rank<4} {
		set color "rank$rank"
	}
	set ret "<tr class=\"$color\"><td class=\"center\">$rank</td> <td nowrap=\"nowrap\">$name</td> <td class=\"center\">$scor</td>"
	return $ret
}
proc Stats:Gen:FormatAll {{ctable "General"}} {
	Trace [info level 0]
	set rank 1
	set i 0
	set ::Total($ctable) [llength $::rank($ctable)]
	set table "<table border=\"1\" cellpadding=\"3\" cellspacing=\"3\" width=\"300\">"
	append table "<tr class=\"rankingType\"><td colspan=\"10\">Clasamentul $ctable ($::Total($ctable))</td></tr>"
	append table "<tr class=\"header\">"
	set overlen 0
	if {$::Total($ctable)>0} {
		if {$ctable=="Time"} { set criteria "TIMP" } else { set criteria "SCOR" }
		append table "<th>RANK</th><th>NUME</th><th>$criteria</th></tr>"
		while {$i<$::Total($ctable)} {
			set new [Stats:Gen:FormatOne $rank $ctable]
			if {$new==0&&$ctable=="Time"} { break }
			append table $new
			incr i
			incr rank
		}
		append table "</table><br />"
	} else { append table "Tabela $ctable este goala." }
	return $table
}
proc Stats:Gen:Info {} {
	Trace [info level 0]
	set uptime [w:EpochDuration ${::server-online}]
	set html ""
	set dot "&bull;"
	lappend html "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>Informatii:</b>"
	lappend html "<b>$dot Numele meu</b>: $::botnick"
	lappend html "<b>$dot Uptime</b>: $uptime"
	lappend html "<b>$dot Server</b>: <a href=\"irc://$::server/$::team(chan)\">$::server</a>"
	lappend html "<b>$dot Canal joc</b>: $::team(chan)"
	lappend html "<b>$dot Canal chat</b>: $::team(otherchans)"
	lappend html "<b>$dot Total echipe</b>: $::Total(Teams)"
	lappend html "<b>$dot Total jucatori individuali</b>: $::Total(Individuals)"
	lappend html "<b>$dot Total jucatori</b>: $::Total(General) (membri si individuali)"
	lappend html "<b>$dot Total intrebari</b>: $::qtotal"
	set record [GetSet speed]
	lappend html "<b>$dot Record viteza</b>: [lindex $record 0] cu [lindex $record 1]s"
	set record [GetSet consec]
	lappend html "<b>$dot Record consecutive</b>: [lindex $record 0] cu [lindex $record 1] raspunsuri"	
	set LastRegistered [GetSet LastRegistered]
	if {$LastRegistered==0} { set LastRegistered "n/a" } else {
		set LastRegistered [split $LastRegistered ";"]
		set LastRegistered "[lindex $LastRegistered 0] ([lindex $LastRegistered 1])"
	}
	set LastRegisteredTeam [GetSet LastRegisteredTeam]
	if {$LastRegisteredTeam==0} { set LastRegisteredTeam "n/a" } else {
		set LastRegisteredTeam [split $LastRegisteredTeam ";"]
		set LastRegisteredTeam "[lindex $LastRegisteredTeam 0] de [lindex $LastRegisteredTeam 1] ([lindex $LastRegisteredTeam 2])"
	}	
	
	lappend html "<b>$dot Ultimul jucator inregistrat</b>: $LastRegistered"	
	lappend html "<b>$dot Ultima echipa inregistrata</b>: $LastRegisteredTeam"	
	lappend html "$dot Statistici generate in data de [w:DateFormat [clock seconds] 1]"
	return [join $html "<br />"]
}
proc Stats:Gen:Logo {} {
	Trace [info level 0]
	set html ""
	lappend html "<span class=\"BigText\">Ophmisu @ $::team(chan)</span>"
	lappend html "Versiunea $::team(Version) by WSergio"
	return [join $html "<br />"]
}

proc team:Stats:Gen {nick uhost hand chan {params ""}} {
	Trace [info level 0]
	Stats:Gen
	say $chan "Generated Web Stats..."
}
proc Stats:Gen {} {
	Trace [info level 0]
	set html ""
	lappend html "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
	lappend html "<html xmlns=\"http://www.w3.org/1999/xhtml\">"
	lappend html "<head>"
	lappend html "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"
	lappend html "<title>Ophmisu versiunea $::team(Version)</title>"
	lappend html "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">"
	lappend html "<meta http-equiv=\"refresh\" content=\"300\">"
	lappend html "<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />"
	lappend html "<style type=\"text/css\"><!-- body { background-image: url(homicide.jpg); background-repeat: repeat; } --> </style>"
	#lappend html "<script type=\"text/javascript\" src=\"collapse.js\"></script>"
	
	lappend html "<script type=\"text/javascript\">"
	lappend html "function togOn(obj) {"
	lappend html "	var el = document.getElementById(obj);"
	lappend html "	el.style.display = '';"
	lappend html "}"
	lappend html "function togOff(obj) {"
	lappend html "	var el = document.getElementById(obj);"
	lappend html "	el.style.display = 'none';"
	lappend html "}"
	lappend html "function tog(obj) {"
	lappend html "	var el = document.getElementById(obj);"
	lappend html "	if (obj=='div1') {"
	lappend html "		togOff('div2');"
	lappend html "		togOff('div3');"
	lappend html "	}"
	lappend html "	if (obj=='div2') {"
	lappend html "		togOff('div1');"
	lappend html "		togOff('div3');"
	lappend html "	}"
	lappend html "	if (obj=='div3') {"
	lappend html "		togOff('div1');"
	lappend html "		togOff('div2');"
	lappend html "	}"
	lappend html "	togOn(obj);"
	lappend html "}"
	lappend html "function togOffAll() {"
	#lappend html "	togOff('div1'); "
	lappend html "	togOff('div2'); "
	lappend html "	togOff('div3');"
	lappend html "}"
	lappend html "</script>"
	
	
	lappend html "</head>"
	lappend html "<body>"
	lappend html "<div id=\"divLogo\">[Stats:Gen:Logo]</div>"
	lappend html "<div id=\"divInfo\">[Stats:Gen:Info]<hr width=\"300\"/></div>"
	
	set dot "&bull;"
	lappend html "<div id=\"divMenu\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<b>Clasamente:</b><br />"
	lappend html "$dot <a href=\"#div1\" onclick=\"tog('div1');\" title=\"General\">General</a><br />"
	lappend html "$dot <a href=\"#div2\" onclick=\"tog('div2');\" title=\"Personal\">Personal</a><br />"
	lappend html "$dot <a href=\"#div3\" onclick=\"tog('div3');\" title=\"Timp\">Timp</a><br />"
	lappend html "</div>"
	
	lappend html "<div id=\"div1\">[Stats:Gen:FormatAll]</div>"
	lappend html "<div id=\"div2\">[Stats:Gen:FormatAll $::team(Personal)]</div>"
	lappend html "<div id=\"div3\">[Stats:Gen:FormatAll Time]</div>"

	lappend html "<script type=\"text/javascript\">"
	lappend html "<!--"
	lappend html "togOffAll();"
	lappend html "//-->"
	lappend html "</script>"
	
	lappend html "</body>"
	lappend html "</html>"
	w:Write $::team(Web) $html
}
proc w:SaveAndReset {} {
	Trace [info level 0]
	
}
proc callbackdump {input} {
	foreach line [split $input "\n"] {
	  dump $line
	}
}
proc Backup:Do {} {
	# tar czf 
	bgexec "$::team(dir)/tools/backup" callbackdump 1
}








set EtapaCurenta ""

proc Etapa:SetCurenta {{val ""}} {
	Trace [info level 0]
	# if no value specified, just update the internal variable; else set new value
	if {$val==""} {	
	set qw [IsSet EtapaCurenta]
	if {$qw==1} {
			set ::EtapaCurenta [GetSet EtapaCurenta]
		} else {
			set ::EtapaCurenta [string trimleft [clock format [clock seconds] -format "%m"] " 0"]
		}
	} else {
		set ::EtapaCurenta $val
	}
	PutSet EtapaCurenta $::EtapaCurenta
	return $::EtapaCurenta
}

proc Etapa:Check {} {
	Trace [info level 0]
	set EtapaActuala [string trimleft [clock format [clock seconds] -format "%m"] " 0"]
	if {$EtapaActuala!=$::EtapaCurenta}  {
		set msg "Etapa a $::EtapaCurenta-a s-a terminat. A inceputa etapa a [Etapa:SetCurenta $EtapaActuala]-a!"
		Etapa:SetCurenta $EtapaActuala
	} else { set msg "Etapa a $::EtapaCurenta-a." }
	return $msg
}
proc team:Etapa {nick uhost hand chan params} {
	Trace [info level 0]
	global tgchan etluna tcdannounceevent2
	if {[matchattr $hand o|]==1} {
		if {[llength $params]<2} {
			utimer 10 [say $chan "[tcdannounceevent2]"]
		}		
		set action [lindex $params 1]
		switch $action {
			check { say $chan [Etapa:Check] }
			set { say $chan [Etapa:SetCurenta [lrange $params 2 2]] }
		
		}
	} else { utimer 10 [say $chan "[tcdannounceevent2]"] }
}







bind time - "00 * * * *" team:timed:01:hours
proc team:timed:01:hours {min hour day month year} {
	Trace [info level 0]
	Stats:Gen
	Etapa:Check
	team:Request:Clean
}


proc team:ModAll {nick uhost hand chan params} {
	Trace [info level 0]
	set params [split $params " "]
	
	if {[llength $params]!=3} {
		set what "Sintaxa corecta: !ModAll <column> <modification>"
	} else {
		set what [w:ModAll put [lindex $params 1] [lindex $params 2]]
	}
	say $chan $what
}

proc w:ModAll {action col {mod ""}} {
	Trace [info level 0]
	set allowed "time uptime"
	if {[string match -nocase "*$col*" $allowed]==0} { set msg "w:ModAll restricted to `$allowed` columns mass changing only. $col unallowed!"
	} else {
		set all $::rank($::team(Personal))
		set msg "Modifying [llength $all] players' column $col with $mod..."
		foreach {player} $all {
			set player [split $player " "]
			set nick [lindex $player 0]
			putlog "moding $nick - col $col to $mod"
			if {[llength $player]==3} {
				set team [lindex $player 2] 
				team:Mod put $team $nick $col $mod
			} else {
				i:Mod put $nick $col $mod
			}
		}
		append msg " done!"
	}
	return $msg
}

bind pubm - "$tgchan *" checkbeat
proc checkbeat {nick uhost hand chan text} {
	global tgchan tgplaying botnick
	if {$nick!=$botnick&&$tgplaying==0&&[matchattr $hand b]==0&&$nick!=$::stopper} {
		utimer 5 [list tgastart $tgchan $nick]
	} else { return 0 }
}
proc team:init {{type "rehash"}} {
	Trace [info level 0]
	team:check
	team:bindings
	Etapa:SetCurenta
	R:Update
	tgreadqdb
}
team:init

# getTimer {by_criteria search_what}: checks if a timer exists or not, by "id" or (command's) "pattern"/"name" - by WSergio
proc getTimer {by what} {
	if {$by!="id"&&$by!="pattern"&&$by!="name"} { dump "getTimer: invalid BY parameter! (id or pattern/name)"; return 0; }
	foreach timer [timers] {
		if {![string match *{*}* $timer]} { set timer [split $timer " "] } 
		set ti [lindex $timer 0]
		set cm [lindex $timer 1]
		set id [lindex $timer 2]
		if {$by=="id"} {
			set ok 0
			if {[string match -nocase timer* $what]&&$id==$what} { set ok 1
			} else { if {$id=="timer$what"} { set ok 1 } }
			if {$ok} { return 1; }
		}
		if {$by=="pattern"||$by=="name"} { if {[string match -nocase *$what* $cm]} { return $id; } }
	}
	return 0;
}
# getTimer {by_criteria search_what}: checks if a utimer exists or not, by "id" or (command's) "pattern"/"name" - by WSergio
proc getuTimer {by what} {
	if {$by!="id"&&$by!="pattern"&&$by!="name"} { dump "getTimer: invalid BY parameter! (id or pattern/name)"; return 0; }
	foreach timer [utimers] {
		if {![string match *{*}* $timer]} { set timer [split $timer " "] } 
		set ti [lindex $timer 0]
		set cm [lindex $timer 1]
		set id [lindex $timer 2]
		if {$by=="id"} {
			set ok 0
			if {[string match -nocase timer* $what]&&$id==$what} { set ok 1
			} else { if {$id=="timer$what"} { set ok 1 } }
			if {$ok} { return 1; }
		}
		if {$by=="pattern"||$by=="name"} { if {[string match -nocase *$what* $cm]} { return $id; } }
	}
	return 0;
}




proc team:Test {nick uhost hand chan params} {
	set msg "CurrentQuestion: $::CurrentQuestion CurrentQuestionAnswer: $::CurrentQuestionAnswer CurrentQuestionNumber: $::CurrentQuestionNumber CurrentQuestionDB: $::CurrentQuestionDB LastQuestion: $::LastQuestion LastQuestionAnswer: $::LastQuestionAnswer LastQuestionNumber: $::LastQuestionNumber LastQuestionDB: $::LastQuestionDB"
	say $chan $msg
}
