egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Timers (Searching, killing, using time binds)

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ
View previous topic :: View next topic  
Author Message
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Wed Jun 22, 2005 7:54 pm    Post subject: Timers (Searching, killing, using time binds) Reply with quote

Catching if a certain timer is running, then kill it.

There're several ways to do so, for example suppose we have a timer that should execute the proc check:voices.
Code:
timerexists check:voices

this code returns the timer id of the timer which should execute check:voices. So to catch it and kill it, we can use:
Code:
if {[set thetimer [timerexists check:voices]]!=""} {
 # if it's == "" then it doesn't exist, otherwise it returns the timerID
 killtimer $thetimer
 # timer is killed
}

another way would be to use lsearch with the glob switch.
Code:
if {[set timerindex [lsearch -glob [timers] *check:voices*]] != -1} {
 # if it's == -1 then it doesn't exist, otherwise it returns the index of this timer.
 killtimer [lindex [lindex [timers] $timerindex] 2]
 # the 3rd element of this list is the timerID which is now killed.
}

Now the previous 2 methods will not match if there's a difference in case (i.e. Upper or Lower letters.)
So this way will match whatever case is used.
Code:
foreach thetimer [timers] {
 if {[string equal -nocase check:voices [lindex $thetimer 1]]} {
  # got a match
  killtimer [lindex $thetimer 2]
  # killed the timerID which is the 3rd element of $thetimer.
  break
  # stopped since no need for further checks.
 }
}


Same methods can be applied to utimers, just change timer(s) to utimer(s).
_________________
Follow me on GitHub

- Opposing

Public Tcl scripts


Last edited by Sir_Fz on Mon Jul 30, 2007 4:00 pm; edited 2 times in total
Back to top
View user's profile Send private message Visit poster's website
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Sat Jul 02, 2005 6:33 pm    Post subject: Reply with quote

You can also search for a timer independant from any cases (capital or lower letters) using lsearch.
Code:
lsearch -glob [string tolower [timers]] "* {check:voices} *"

but note that check:voices should be in lowercase as well. so if you want to make sure that a variable is in lowercase use
Code:
string tolower $variable


PS: After a test of which method is faster (lsearch or foreach and matching) I found out that using the foreach method is faster.
_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
sKy
Op


Joined: 14 Apr 2005
Posts: 194
Location: Germany

PostPosted: Tue Jul 12, 2005 4:17 pm    Post subject: Reply with quote

i might add:
Code:
timer time command

Quote:
returns timerID

example: set timer [timer 1 [list putserv "..."]]
same for utimer.

this timer-id can you put in a variable (perhaps a global variable) and use later.

some less important procs:
Code:
proc isutimer { id } {
   foreach utimer [utimers] {
      set isid [lindex $utimer 2]
      if { $id == $isid } {
         return 1
      }
   }
   return 0
}

proc istimer { id } {
   foreach timer [timers] {
      set isid [lindex $timer 2]
      if { $id == $isid } {
         return 1
      }
   }
   return 0
}

Ex:
Quote:

if { [istimer $timerid] } { killtimer $timerid }
Back to top
View user's profile Send private message
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Mon Aug 08, 2005 6:43 pm    Post subject: Reply with quote

Incase you have a timer which has more than 1 element in it and some of these elements always vary (i.e. $nick $uhost...etc) then you can use string match instead of string equal to be able to use wildcards. Suppose we have:
Quote:
{12 {check:voices #bla} timer1}

We can use this code to find and kill this timer:
Code:
foreach thetimer [timers] {
 if {[string match -nocase "check:voices *" [lindex $thetimer 1]]} {
  # got a match
  killtimer [lindex $thetimer 2]
  # killed the timerID which is the 3rd element of $thetimer.
  break
  # stopped since no need for further checks.
 }
}

And ofcourse you can also use "lsearch -glob"
Code:
if {[set timerindex [lsearch -glob [timers] "* {check:voices *} *"]] != -1} {
 # if it's == -1 then it doesn't exist, otherwise it returns the index of this timer.
 killtimer [lindex [lindex [timers] $timerindex] 2]
 # the 3rd element of this list is the timerID which is now killed.
}

but the first method is faster.
_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Thu Sep 08, 2005 10:26 am    Post subject: Reply with quote

Btw, [timerexists] and [utimerexists] are alltools.tcl commands. Incase you're not loading it:
Code:
proc timerexists {command} {
  foreach i [timers] {
    if {![string compare $command [lindex $i 1]]} then {
      return [lindex $i 2]
    }
  }
  return
}

proc utimerexists {command} {
  foreach i [utimers] {
    if {![string compare $command [lindex $i 1]]} then {
      return [lindex $i 2]
    }
  }
  return
}

_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
awyeah
Revered One


Joined: 26 Apr 2004
Posts: 1580
Location: Switzerland

PostPosted: Tue May 08, 2007 9:49 pm    Post subject: Reply with quote

Since we are dealing with timers here, some info regarding the minute, hour, day, month, year masks for bind time and how they are used for specific intervals would be appreciated.
_________________
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================
Back to top
View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger MSN Messenger
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Thu May 10, 2007 4:51 pm    Post subject: Reply with quote

Quote:
TIME (stackable)
bind time <flags> <mask> <proc>
proc-name <minute> <hour> <day> <month> <year>

Description: allows you to schedule procedure calls at certain
times. mask matches 5 space separated integers of the form:
"minute hour day month year". minute, hour, day, month have a
zero padding so they are exactly two characters long; year is
four characters. Flags are ignored.

What's also worth mentioning about the time bind is that the first day is 01 and the first month is 00 (this is not documented).

If you want to trigger an operation every x minutes without using the (u)timer command, then bind time is what you need. Example:
Code:
bind time - * operation

# This proc (operation) is called every minute (00, 01, 02, 03,...59)
proc operation {min hour day mon year} {
 # We want to trigger our command every 3 minutes for example
 if {[scan $min %d] % 3 == 0} {
  # Perform the needed operation here
 }
}

[scan %d] is applied over $min in order to convert it from an octal to a decimal number (since 08 & 09 are invalid octals) to be divided over the number of minutes (the interval of your choice which is 3 in our example). If the remainder is not 0 (greater than 0) then $min is not divisible by 3 and thus 3 minutes did not pass. This means that the "needed operation" is triggered at minutes 00, 03, 06, 09, ..., 57 (all divisible by 3).
_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Sun May 13, 2007 5:24 pm    Post subject: Reply with quote

In case you are worried about minute intervals which are not divisible by 60, there is a solution. What I mean by "not divisible by 60" are intervals like 7 for example: 00, 07, 14, 21, 28, 35, 42, 49, 56 - now the operation should be performed at minute 03 but instead it triggers at minute 00 which is not after 7 minutes. To solve this, you can use:
Code:
bind time - * operation

# This proc (operation) is called every minute (00, 01, 02, 03,...59)
proc operation {min hour day mon year} {
 # We want to trigger our command every 7 minutes
 if {([scan $min %d]+([scan $hour %d]*60)) % 7 == 0} {
  # Perform the needed operation here
 }
}

What's happening here is that the hour is being converted into its minutes equivalent, added to the minute, and then divided by the interval to check if the remainder is 0. This way the difference between every call of the needed operation is always 7 minutes.

This, of course, can be applied on all intervals (divisible or not divisible by 60) so I recommend using it as default.
_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
awyeah
Revered One


Joined: 26 Apr 2004
Posts: 1580
Location: Switzerland

PostPosted: Tue Jul 24, 2007 1:27 am    Post subject: Reply with quote

The mask is "MM HH dd mm yyyy" and can have wildcards (MM=minute, HH=hour, dd=day, mm=month(-1), yyyy=year)

The month comes with -1. So, january is 00 and december is 11.

Examples:

Code:

bind time - * procname ; # is called every minute
bind time - "?5 *" procname ; # is called every 10 minutes, 05,15,25,35,45,55
bind time - "30 *" procname ; # is called every hour, 30 mins after full
bind time - "30 1? * 200?" procname ; # work from 10:30 - 19:30 every hour, but only in the year 2000-2009


Code:

proc procname {minute hour day month year} { .. } ; # full var support
proc procname {min hour args} { .. } ; # args is special var for a list
proc procname args { .. } ; # you dont need the time, only proc called


Hint:

To trim the minutes (or other vars) it is best to use:

Code:

set minutes [string trimleft $minutes 0]; if {$minutes==""} {set minutes 0}

_________________
·­awyeah·

==================================
Facebook: jawad@idsia.ch (Jay Dee)
PS: Guys, I don't accept script helps or requests personally anymore.
==================================


Last edited by awyeah on Tue Jul 24, 2007 10:56 am; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail Visit poster's website Yahoo Messenger MSN Messenger
Sir_Fz
Revered One


Joined: 27 Apr 2003
Posts: 3793
Location: Lebanon

PostPosted: Tue Jul 24, 2007 6:32 am    Post subject: Reply with quote

awyeah wrote:
Hint:

To trim the minutes (or other vars) best use:

Code:

set minutes [string trimleft $minutes 0]; if {$minutes==""} {set minutes 0}

Or simply convert it to decimal as done in my code above:
Code:
set minutes [scan $minutes %d]

_________________
Follow me on GitHub

- Opposing

Public Tcl scripts
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Tcl FAQ All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber