This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

good voting script?

Old posts that have not been replied to for several years.
p
ppslim
Revered One
Posts: 3914
Joined: Sun Sep 23, 2001 8:00 pm
Location: Liverpool, England

Post by ppslim »

I hate to say it, but this sort of script, is not the simplest thing you can be starting off on, in the learning process.

Instead of coding such a script right off, you should be thinking of the design, including detailed ifnormation like the storage system.

This process incldues stuff like "Is this storage method possible with the commands I have available".

With Tcl, you have three memory storage system available to you.

1: Plain Tcl variables, storing strings of text, numbers and anything else.

2: Arrays. These are realy hash lists, but look and operate slightly like arrays.

3: Lists. These are strings of text, formatted in such a way, that multi-word arguments can be stored in one jar, and easily seperated.

One of the other things you need to remember, you want it so that multiple quoestions can be running at the same time.

This requires some form of multi-dimentional storage.
Multi-dimentional sotrage.

The ability to have an array of key, value pairs, where the value can be another array.
This are of discusion could go on forever, due to the fact, it's not easy to explain some of the topics to new users.

You can usualy touch on the basics with ease, but some of the tpoics are more advanced, are require an in depth knowledge, or how certain area operate.
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

well, nothing about you, but i'm not completely new to programming. just new to tcl, so i guess it should be possible to write such a script. especially, because i've got an example (loki's channelvoter). and don't worry, i gave up multi questions at the same time for now :D always keep something for a version "2.0" *gg* :D
and perhaps this script isn't one of the easier ones, but i'll write it part after part and so i think it should be not too hard. well, my opinion. i'll just keep trying, and thanks for your help :D
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

me again :-?

how can i increase one object in a list? can't get it to work :cry: tried everything i could think of...
p
ppslim
Revered One
Posts: 3914
Joined: Sun Sep 23, 2001 8:00 pm
Location: Liverpool, England

Post by ppslim »

You need to disasemble the list each time, increase the value, and reassemble it.

Code: Select all

set list [list [list item1 1] [list item2 1] [list item3 4]]

set ToIncrease "item2"

set IncreaseBy "4"

if {[set idx [lsearch $list "$ToIncrease *"]] != "-1"} {
  set value [lindex [lindex $list $idx] 1]
  incr value $IncreaseBy
  set list [lreplace $list $idx $idx [list $ToIncrease $value]]
}
You should see how that operates/.
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

thx... hm... looks not so different from my version *feelsproud* :D
i tested again yesterday and it seemed that one of my versions worked (i also tried an array), but i couldn't talk to my bot. i'll see today :D
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

heres my version: didnt know the search command, but shouldn't matter :D

Code: Select all

for {set number 0} {$number < [llength $vanswers]} {incr number} {
   if {[string tolower $arg] == [string tolower [lindex $vanswers $number]]} {
    puthelp "NOTICE $nick :Deine Stimme wurde gezählt ([string tolower $arg])."

    set vtemp [lindex $vcount $number]
    set vtemp [incr vtemp]
    set vcount [lreplace $vcount $number $number $vtemp]
    
    set vpeople($mask) 1
    return 0
   }
  }
btw: just finished version 1.0. if someone feels like to go through it and tell my what i could do better :D (see next post). its german, but i could make an english version on demand.

todo would be: limit voting to user groups (ops, voice...). but i didn't know how to solve this. how can i get the channel flags of a user? (not the flags on the bot). matchattr? or... guess it was because of the admin-status (! +a). should test it with normal ops (@ +o)...
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

Code: Select all

####################################################
#		aVote 1.0 by arcane
#		(#k13 @euIRC)	
#
# Umfrageskript
#
#
# Für Hilfe:
#	/msg <botnick> vhelp
#
#
# Features:
#
# - beliebige Antwortmöglichkeiten
# - Nachricht an alle, die noch nicht gewählt haben, beim Betreten des Channels
# - Hostmasken für Wähler (keine Mehrfach-Wahl)
# - keine Wahl über Bots
# - Abbruch der Umfrage durch den Starter
#
# ToDo:
#
# - mehrere Umfragen gleichzeitig
# - Erinnerung derjenigen, die noch nicht gewählt haben und away sind
# - Beschränkung auf bestimmte Gruppen (Ops, Voice...)
#
#
# Dank an:
#
# - Loki` für sein Channel Voter Script
# - ppslim @forum.egghelp.org für seine unermüdliche Hilfe  
####################################################

##################### Params #######################
set aversion "aVote 1.0"
set vvotes "0"

##################### Bindings #####################
bind pub - !vote any_vote
bind msg - vhelp vote_help
bind msg - vote vote_vote
bind pub - !endvote vote_end
bind join - * vote_reminder

##################### Remove old timers ############
if {![info exists vtopic]} {
	catch {
		killutimer $vtimer
	}
}

##################### AnyVote ######################
proc any_vote {nick mask hand chan arg} {
global botnick vchan vnick vpeople vvotes vtopic vanswers vcount vtime aversion vtimestart vtimer vhand
	
	if {$arg == ""} {
		if {$vvotes == "0"} {
			puthelp "NOTICE $nick :Zur Zeit läuft keine Umfrage."
			if {[info exists vtopic]} {
				puthelp "NOTICE $nick :Letzte Umfrage von $vnick:"
				puthelp "NOTICE $nick :\"$vtopic\""
				puthelp "NOTICE $nick :Endergebnis:"
				for {set number 0} {$number < [llength $vanswers]} {incr number} {
					puthelp "NOTICE $nick :\"[lindex $vanswers $number]\": [lindex $vcount $number]"
				}
			} else {
				puthelp "NOTICE $nick :Noch keine Umfragen gestartet."
			}
			return 0
		} else {
			puthelp "NOTICE $nick :Aktuelle Umfrage von $vnick:"
			puthelp "NOTICE $nick :\"$vtopic\""
			puthelp "NOTICE $nick :Mögliche Antworten: [join $vanswers " : "]"
			puthelp "NOTICE $nick :Verbleibende Zeit: [duration [expr (([unixtime] - $vtimestart) - $vtime) * -1]]"
			puthelp "NOTICE $nick :Abstimmen mit \"/msg $botnick vote <antwort>\""
			return 0
		}
	} else {
		if {$vvotes != 0} {	
			puthelp "NOTICE $nick :Es läuft bereits eine Umfrage."
			return 0
		}

		set time [lindex $arg 0]
		set topic [lindex $arg 1]
		set answers [split [lindex $arg 2] :]

		if {$time == "" || $topic == "" || [lindex $answers 0] == ""} {
			puthelp "NOTICE $nick :Der Syntax ist !vote <zeit> \"<thema>\" \"<antworten>\"."
			puthelp "NOTICE $nick :Die möglichen Antworten werden dabei durch \":\" getrennt. Thema und Antworten müssen in Anführungszeichen stehen."
			return 0
		}
		if {[lindex $answers 1] == ""} {
			puthelp "NOTICE $nick :Es müssen mindestens zwei Antwortmöglichkeiten gegeben werden."
			return 0
		}

		set vtimeleft [lindex $arg 0]
		if [string match "*m" [string tolower [lindex $arg 0]]] {
			set vtime [expr [string trimright $vtimeleft m] * 60]
			set vtimestart [unixtime]
		} elseif [string match "*h" [string tolower [lindex $arg 0]]] {
			set vtime [expr [string trimright $vtimeleft h] * 3600]
			set vtimestart [unixtime]
		} else {
			puthelp "NOTICE $nick :[lindex $arg 0]: Dies ist keine gültige Zeit (m: Minuten, h: Stunden)."
			return 0
		}

		set vchan $chan
		set vtopic $topic
		set vanswers $answers
		set vvotes "1"
		set vnick $nick
		set vhand $hand

		set vcount "0"
		for {set number 1} {$number < [llength $vanswers]} {incr number} {
			append vcount " 0"
		}

		set vcount [split $vcount]

		puthelp "PRIVMSG $vchan :Umfrage von $nick:"
		puthelp "PRIVMSG $vchan :\"$vtopic\""
		puthelp "PRIVMSG $vchan :Mögliche Antworten: [join $vanswers " : "]"
		puthelp "PRIVMSG $vchan :Dauer: $time"
		puthelp "PRIVMSG $vchan :Abstimmen mit \"/msg $botnick vote <antwort>\""

		if {[info exists vpeople]} { unset vpeople }

		set vtimer [utimer $vtime "vote_end endoftime 2 3 4 5"]
	}
}

##################### Vote #########################
proc vote_vote {nick mask hand arg} {
global botnick vchan vpeople vvotes vanswers vcount

	if {$vvotes == 0} {
		puthelp "NOTICE $nick :Es läuft keine Umfrage."
		return 0
	}

	set mask [maskhost $mask]
	if {[matchattr $hand b]} {
		puthelp "NOTICE $nick :Keine Bots."
		puthelp "PRIVMSG $vchan :Jemand versucht über $nick abzustimmen!"
		return 0
	} elseif {[info exists vpeople($mask)]} {
		puthelp "NOTICE $nick :Du hast bereits abgestimmt."
		return 0
	} else {
		for {set number 0} {$number < [llength $vanswers]} {incr number} {
			if {[string tolower $arg] == [string tolower [lindex $vanswers $number]]} {
				puthelp "NOTICE $nick :Deine Stimme wurde gezählt ([string tolower $arg])."

				set vtemp [lindex $vcount $number]
				set vtemp [incr vtemp]
				set vcount [lreplace $vcount $number $number $vtemp]
				
				set vpeople($mask) 1
				return 0
			}
		}
		puthelp "NOTICE $nick :$arg: keine gültige Antwort."
		puthelp "NOTICE $nick :Mögliche Antwort sind: [join $vanswers " : "]"
	}
}

##################### Help #########################
proc vote_vote {nick mask hand arg} { 
global botnick aversion 

	puthelp "NOTICE $nick :$aversion by arcane - Hilfe"
	puthelp "NOTICE $nick :Der Syntax ist !vote <zeit> \"<thema>\" \"<antworten>\"."
	puthelp "NOTICE $nick :Die möglichen Antworten werden dabei durch \":\" getrennt. Thema und Antworten müssen in Anführungszeichen stehen."
	puthelp "NOTICE $nick :Die Zeit wird in der folgenden Form angegeben:"
	puthelp "NOTICE $nick :xxm: xx Minuten; xxh: xx Stunden. Mischangaben mit m und h sind nicht möglich."
	puthelp "NOTICE $nick :Weitere Befehle:"
	puthelp "NOTICE $nick :/msg $botnick vhelp: Zeigt diese Hilfe"
	puthelp "NOTICE $nick :!vote (ohne Argumente): Zeigt Informationen über die aktuelle / letzte Umfrage"
	puthelp "NOTICE $nick :Abgestimmt wird mit /msg $botnick vote <antwort>"	
	puthelp "NOTICE $nick :Der Umfragestarter kann die Umfrage mit !endvote vorzeitig beenden."
}

##################### Endvote ######################
proc vote_end {nick mask hand chan arg} {
global botnick vchan vnick vpeople vvotes vtopic vanswers vcount vtime vtimer vhand vtimestart
	
	if {$vvotes == 0} {
		puthelp "NOTICE $nick :Es läuft keine Umfrage."
		return 0
	}	

	if {$chan == $vchan || $nick == "endoftime"} {
		if {$hand != $vhand && $nick != "endoftime"} {
			puthelp "NOTICE $nick :Nur der Umfragestarter kann die Umfrage vorzeitig beenden."
			return 0
		}
	
		if {$nick == "endoftime"} {
			puthelp "PRIVMSG $vchan :Umfrage von $vnick zum Thema $vtopic beendet (Zeit abgelaufen)."
		} else {
			puthelp "PRIVMSG $vchan :Umfrage von $vnick zum Thema $vtopic beendet von $nick."
		}
		puthelp "PRIVMSG $vchan :Ergebnis:"
		for {set number 0} {$number < [llength $vanswers]} {incr number} {
			puthelp "PRIVMSG $vchan :\"[lindex $vanswers $number]\": [lindex $vcount $number]"
		}

		set vvotes "0"
		
		catch {
			killutimer $vtimer
		}
		if {[info exists vpeople]} { unset vpeople }
	}
}

##################### OnJoin Reminder ##############
proc vote_reminder {nick mask hand chan} {
global botnick vchan vnick vpeople vvotes vtopic vanswers vtime vtimestart

	set mask [maskhost $mask]
	if {$chan == $vchan && [info exists vpeople($mask)] == 0 && vvotes != 0} {
		puthelp "NOTICE $nick :Es läuft eine Umfrage von $vnick"
		puthelp "NOTICE $nick :\"$vtopic\""
		puthelp "NOTICE $nick :Mögliche Antworten: [join $vanswers " : "]"
		puthelp "NOTICE $nick :Verbleibende Zeit: [duration [expr (([unixtime] - $vtimestart) - $vtime) * -1]]"
		puthelp "NOTICE $nick :Abstimmen mit \"/msg $botnick vote <antwort>\""
	}
}

##################### Log Message ##################
putlog "\0033$aversion loaded"
Last edited by arcane on Tue Feb 11, 2003 6:05 am, edited 1 time in total.
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

set time [lindex $arg 0]
set topic [lindex $arg 1]
set answers [split [lindex $arg 2] :]

Maybe I didn't understand the syntax correctly, but it appears you're using !vote <time> <topic> <options>. First error is, lindex takes a list as an argument, but $arg is actually a string. So special characters in the string may cause a tcl error. Also, even if the string is ok, you will only get the first word of the topic. It may be helpful to make the syntax something like:

!vote time|some topic|option 1|option 2|option 3

Then in your proc, do something like:
set parts [split $arg "|"]
set time [lindex $parts 0]
set topic [lindex $parts 1]
set answers [lrange $parts 2 end]

Ok the other thing isn't really an error, but in
set vtemp [incr vtemp]
incr will already modify vtemp, so the 'set' isn't necessary.

set vcount "0"
for {set number 1} {$number < [llength $vanswers]} {incr number} {
append vcount " 0"
}

set vcount [split $vcount]

That part makes vcount into a list. You might as well do it from the beginning:

set vcount
  • foreach answer $vanswers {
    lappend vcount 0
    }

    I see you're using utimer $vtime "vote_end endoftime 2 3 4 5" as your timer. I would be careful, because anybody could take the nick "endoftime" and end your votes. Maybe instead you could make the nick "end of time" (spaces) because that is an otherwise invalid nick.

    Only a few minor issues, good job on your first script!
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

stdragon wrote:set time [lindex $arg 0]
set topic [lindex $arg 1]
set answers [split [lindex $arg 2] :]

Maybe I didn't understand the syntax correctly, but it appears you're using !vote <time> <topic> <options>. First error is, lindex takes a list as an argument, but $arg is actually a string. So special characters in the string may cause a tcl error. Also, even if the string is ok, you will only get the first word of the topic. It may be helpful to make the syntax something like:

!vote time|some topic|option 1|option 2|option 3

Then in your proc, do something like:
set parts [split $arg "|"]
set time [lindex $parts 0]
set topic [lindex $parts 1]
set answers [lrange $parts 2 end]
you understood the syntax correctly. and, yes, special characters would be a problem. normally, topic and answers should be put in ""s, so i get the complete topic/answers with this commands. but i should change this.
stdragon wrote: Ok the other thing isn't really an error, but in
set vtemp [incr vtemp]
incr will already modify vtemp, so the 'set' isn't necessary.
alright :D
stdragon wrote: set vcount "0"
for {set number 1} {$number < [llength $vanswers]} {incr number} {
append vcount " 0"
}

set vcount [split $vcount]

That part makes vcount into a list. You might as well do it from the beginning:

set vcount
  • foreach answer $vanswers {
    lappend vcount 0
    }
didnt know all list commands, so i made my own solution, but your version looks better :D
stdragon wrote: I see you're using utimer $vtime "vote_end endoftime 2 3 4 5" as your timer. I would be careful, because anybody could take the nick "endoftime" and end your votes. Maybe instead you could make the nick "end of time" (spaces) because that is an otherwise invalid nick.
right.
stdragon wrote: Only a few minor issues, good job on your first script!
thanks :D

o yes, and:

Code: Select all

proc vote_help {nick} { 
global botnick 
should be

Code: Select all

proc vote_vote {nick mask hand arg} { 
global botnick aversion
User avatar
Papillon
Owner
Posts: 724
Joined: Fri Feb 15, 2002 8:00 pm
Location: *.no

Post by Papillon »

another small but vital error ;)

Code: Select all

##################### Vote ######################### 
proc vote_vote {nick mask hand arg} {

Code: Select all

##################### Help ######################### 
proc vote_vote {nick mask hand arg} {
perhapse you should change the proc-name on the help-proc ;)
Elen sila lúmenn' omentielvo
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

*gg* damn copy&paste :D theres also somewhere missing a "$", but dont want to search it now. i corrected it in my script.

but one more thing:
i made it as stdragon suggested, the syntax is now "!vote <time>|<topic>|<answers> but answers should be separated by ":"s.
but now, if the answer hast more than one word, i get for the first answer "{ answer" and for the last "answer }". how can i solve this? my code is this:

Code: Select all

set parts [split $arg "|"] 
set time [lindex $parts 0] 
set topic [lindex $parts 1] 
set answers [split [lrange $parts 2 end] :]
i know, im splitting $parts again, but i dont know how to solve this :-?
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

set answers [split [lindex $parts 2] :]

Lindex returns an element from the list, in this case a string. Lrange returns a subset from the list, which is another list (that's why the { } appears).
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

but how could i solve it?
User avatar
stdragon
Owner
Posts: 959
Joined: Sun Sep 23, 2001 8:00 pm
Contact:

Post by stdragon »

Take the part of your code, set answers [split [lrange $parts 2 end] :]

and change it to, set answers [split [lindex $parts 2] :]

That should fix it :)
User avatar
arcane
Master
Posts: 280
Joined: Thu Jan 30, 2003 9:18 am
Location: Germany
Contact:

Post by arcane »

:lol: i came to the same conclusion after thinking 5 minutes about it... (sometimes im too stupid...)
Locked