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.

Greeting on join with countdown days

Help for those learning Tcl or writing their own scripts.
Post Reply
j
juanamores
Master
Posts: 317
Joined: Sun Mar 15, 2015 9:59 am

Greeting on join with countdown days

Post by juanamores »

I want to create a script that greets the nicks when join a channel and indicates how many days rest for the last day of the month.

The last day of the month will be known who was the winner.

I have problem with the variables nick and chan, since I can not put them in the process because it gives error.

Code: Select all

bind join v|v * greet:awards
set mychan "#chann1"

proc greet:awards  {min hour day month weekday nick uhost hand chan text} {
global chann1
if {$chan == "$chann1"} {
#set number of days of the month
if {$month == "January"}  {set mo 31} 
if {$month == "February"} {set mo 29} 
if {$month == "March"} {set mo 31} 
if {$month == "April"} {set mo 30} 
if {$month == "May"} {set mo 31} 
if {$month == "June"} {set mo 30} 
if {$month == "July"} {set mo 31} 
if {$month == "August"} {set mo 31} 
if {$month == "September"} {set mo 30} 
if {$month == "October"} {set mo 31} 
if {$month == "November"} {set mo 30} 
if {$month == "December"} {set mo 31} 

#rest the number of days of the month with today
set rest [expr $mo - $day]

putquick "PRIVMSG $chan :$nick rest  $rest days for de awards"
return 
} else { return }
}  


How can it be fixed?
If you do not understand my ideas is because I can not think in English, I help me with Google Translate. I only speak Spanish. Bear with me. Thanks :)
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

You have way too many arguments for the join process, hence the error. Give this a try:

Code: Select all

set mychan "#chann1"
bind join v|v * greet:awards

proc greet:awards {nick uhost hand chan} {
	global mychan

	# skip if it's bot that is joining
	if {[isbotnick $nick]} return
	
	# skip if it's not the channel you defined above
	if {![string equal -nocase $chan $mychan]} return

	# set system time
	set systemTime [clock seconds]

	# set current day
	set today [clock format $systemTime -format %e]

	# set month
	set month [clock format $systemTime -format %m]
	
	# set year
	set year [clock format $systemTime -format "%Y"]

	# compute the number of days in the current month
	set days [clock format [clock scan "$month/1/$year + 1 month - 1 day"] -format %d]

	# set the number of days remaining in the month starting with today
	set rest [expr $days - $today]

	# output the result
	puthelp "PRIVMSG $chan :$nick rest $rest days for de awards"
}
Since your system language is in Spanish and having the months names in English it would fail, so did a little workaround this and should work on all systems no matter the language it has set.

Edit: Here is a little tip. Instead of having:

Code: Select all

if {$month == "January"}  {set mo 31}
if {$month == "February"} {set mo 29}
if {$month == "March"} {set mo 31}
if {$month == "April"} {set mo 30}
if {$month == "May"} {set mo 31}
if {$month == "June"} {set mo 30}
if {$month == "July"} {set mo 31}
if {$month == "August"} {set mo 31}
if {$month == "September"} {set mo 30}
if {$month == "October"} {set mo 31}
if {$month == "November"} {set mo 30}
if {$month == "December"} {set mo 31}
that is a mistake because all if statements are checked you have 3 options:

Option #1 would be to use if ... elseif

Code: Select all

if {$month == "January"} {
	set mo 31
} elseif {$month == "February"} {
	set mo 29
} elseif { ... }
and so on. In this case the first if statement that is true will stop the remaining ones. Still not a very good choice because if $month is equal with December then it will still check all statements until reaches last.

Moving on to option #2: switch

Code: Select all

switch -- $month {
	"January" {
		set mo 31
	}
	"February" {
		set mo 29
	}
	
	... and so on...
	
	default {
		set mo 0
	}
}
Switch is a better option than a bunch of if or if ... elseif since it will jump at the exactly match, or to default (if you added it) in case there's no match inside the switch.

But we can do better and here we got option #3 the string map.. the champion! :)

Code: Select all

set days [string map [list "January" 31 "February" 29 "March" 31 "April" 30 "May" 31 "June" 30 "July" 31 "August" 31 "September" 30 "October" 31 "November" 30 "December" 31] $month]
and that's all in a single line. :)

Depending on the $month name it will return the element behind it from the list. For example For "February" it will return 29, for "October" it will return 31 and so on.

Edit: Fixed typo.
Edit #2: There's no 'text' argument inside the bind join.. how did I miss that? :roll:
Last edited by caesar on Thu Apr 20, 2017 12:29 pm, edited 2 times in total.
Once the game is over, the king and the pawn go back in the same box.
j
juanamores
Master
Posts: 317
Joined: Sun Mar 15, 2015 9:59 am

Post by juanamores »

Hi Caesar, I worked perfect your script from above. :)
Could you explain to me, to learn, how does this line work?

Code: Select all

# compute the number of days in the current month
set days [clock format [clock scan "$month/1/$year + 1 month - 1 day"] -format %d]
Thank you very much! :)
If you do not understand my ideas is because I can not think in English, I help me with Google Translate. I only speak Spanish. Bear with me. Thanks :)
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

Sure. If we put in the values for the variables inside

Code: Select all

 
clock scan "$month/1/$year + 1 month - 1 day"
then the result will be:

Code: Select all

clock scan "04/1/2017 + 1 month - 1 day"
I chose the 04/1/2017 format from the acceptable formats for clock scan to work that is in TCL version 8.4 upwards. Could have used 1 April 2017, or just 1 April without year and results would have been the same, but decided to stick with a standard accepted format so won't get in any problems.

Without the + 1 month - 1 day part:

Code: Select all

clock scan "04/1/2017"
basically we define the current day to be 1st April 2017 and the result will be 1490994000, meaning 1st April 2017 exactly as we wanted.

Now, in order to get the last day of current month we use the + 1 month - 1 day part:
1) Add one month to 1st April 2017:

Code: Select all

%clock scan "04/1/2017 +1 month"
1493586000
meaning 1st May 2017
2) subtract one day from the above result

Code: Select all

% clock scan "04/1/2017 +1 month -1 day"
1493499600
meaning 30th April 2017.

Next with the help of the first command:

Code: Select all

clock format unixtime -format %d
where unixtime now is 1493499600 meaning 30th April 2017, we get the day of the month from this unixtime time stamp, thus the result will be 30. :)
Once the game is over, the king and the pawn go back in the same box.
j
juanamores
Master
Posts: 317
Joined: Sun Mar 15, 2015 9:59 am

Post by juanamores »

Excellent solution and excellent explanation. :mrgreen:
You are a genious :)
If you do not understand my ideas is because I can not think in English, I help me with Google Translate. I only speak Spanish. Bear with me. Thanks :)
Post Reply