| View previous topic :: View next topic |
| Author |
Message |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Fri Apr 22, 2011 9:36 am Post subject: [SOLVED] Set Variable to Line in File / Write Variable |
|
|
I am pretty sure I know how to write a variable to a line in a file. My goal here is to use an outside file to "record" the state of a variable, so that if the bot resets it doesn't forget what the variable was set to the last time it accessed the script.
Let me explain.
I need to increment the value of a variable, in order for the bot to know what change to make on which day, in the course of eleven days. I just realized that by initializing the variable the way I do in the script, that if the bot dies or resets the CONF, it will start the variable from scratch.
So, every time I increment the variable, I want to write the value to a file. Then, pull that value from that file, each time the bot needs it for the script. Thus, avoiding repeating the same action two or more days in a row.
What I need:
I can't quite figure out the code to set a variable to a line in a file, then after the variable is increased an increment, overwrite that file line with the new value.
I'd really appreciated some help with this!
Thank you.
Last edited by Seka on Tue Apr 26, 2011 1:49 pm; edited 1 time in total |
|
| Back to top |
|
 |
willyw Revered One
Joined: 15 Jan 2009 Posts: 1175
|
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Fri Apr 22, 2011 11:01 am Post subject: |
|
|
There are a few ways of doing this..
However, I'd probably settle with restoring the value when your eggdrop is restarted, rather than everytime the variable is read.
One of the simplest ways of doing this, is actually to have your code write a script that sets the value.. then all you need to do is add a "source restore.tcl" to your config-file
| Code: | ...
#assuming variable is named "state"
set fd [open "restore.tcl" "WRONLY CREAT TRUNC"]
puts $fd [list set state $state]
close $fd
... |
The above code writes a single line to the file restore.tcl, containing a (safe) set command to restore the value of "state". It should be fairly trivial to embed in your current code.
Other ways would be to just write the value to the file, and restore it by opening the file with read-access, reading the line, and restoring the value of the variable using the read value..
| Code: | ...
#assuming variable is named "state"
set fd [open "restore" "WRONLY CREAT TRUNC"]
puts $fd $state
close $fd
...
if {[catch {open "restore" "RDONLY"} fd]} {
#unable to open file, does not exist?
putlog "Error restoring state: $fd"
return
} else {
set ::state [gets $fd]
close $fd
}
... |
_________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Fri Apr 22, 2011 11:38 am Post subject: |
|
|
Thank you both for the quick responses. I was able to rig something together, using the documentation.
nml375,
It looks like what you're suggesting could significantly lower the amount of code in my primary script.
My question is this, though. If I need to increment the value of the variable and store it in several different scenarios, would I need to repeat that code snippet throughout the script?
Example:
| Code: | pub example{nick host channel text} {
if {$state == 1} {
putserv "TOPIC $channel :It is day 1!"
incr $state
} elseif {$state == 2} {
putserv "TOPIC $channel :It is day 2!"
set $state 1
}
} |
Would your snippet be repeated after the "incr $state" in each expression?
Edit:
The proc is actually a time bind, but I just used the above code as an example. |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Fri Apr 22, 2011 6:50 pm Post subject: |
|
|
The first problem with the code you posted, is that state is a local variable. The script-solution I mentioned "only" works with global variables (it could be made to work with local variables as well, but the hazzle really isn't worth it.. just use a global variable instead..)
Assuming we use a globalspace variable ::state instead; the posted code would only need one instance of the "save-code", provided that we add it at the end of the "example" proc, that we place the code at the end of the proc, and that we do not exit the proc prematurely (no return statements, etc).
| Code: | pub example {nick host handle channel text} {
if {$::state == 1} {
putserv "TOPIC $channel :It is day 1!"
incr ::state
} elseif {$::state == 2} {
putserv "TOPIC $channel :It is day 2!"
set ::state 1
}
set fd [open "restore.tcl" "WRONLY CREAT TRUNC"]
puts $fd [list set state $::state]
close $fd
} |
Btw, I fixed the issues where you use variable substitutions unintentinally: set $state 1 =>set state 1; incr $state => incr state _________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Sun Apr 24, 2011 11:46 am Post subject: |
|
|
Ok. So, here's what I've got. It is untested, so far.
Let me know if I need to change anything, please:
| Code: | set channel "#Bot_Test"
# Open the TCL with the variable?
set fd [open "restore" "WRONLY CREAT TRUNC"]
puts $fd $rpday
close $fd
# Execute every day at midnight?
bind time - "00 00 * * *" tchange
# Execute the proc.
proc tchange {min hour day month year} {
global channel
if {$::rpday == 1} {
putquick "TOPIC $channel :It is Day 1!"
incr ::rpday
} elseif {$::rpday == 2} {
putquick "TOPIC $channel :It is Day 2!"
incr ::rpday
} elseif {$::rpday == 3} {
putquick "TOPIC $channel :It is Day 3!"
incr ::rpday
} elseif {$::rpday == 4} {
putquick "TOPIC $channel :It is Day 4!"
incr ::rpday
} elseif {$::rpday == 5} {
putquick "TOPIC $channel :It is Day 5!"
incr ::rpday
} elseif {$::rpday == 6} {
putquick "TOPIC $channel :It is Day 6!"
incr ::rpday
} elseif {$::rpday == 7} {
putquick "TOPIC $channel :It is Day 7!"
incr ::rpday
} elseif {$::rpday == 8} {
putquick "TOPIC $channel :It is Day 8!"
incr ::rpday
} elseif {$::rpday == 9} {
putquick "TOPIC $channel :It is Day 9!"
incr ::rpday
} elseif {$::rpday == 10} {
putquick "TOPIC $channel :It is Day 10!"
incr ::rpday
} elseif {$::rpday == 11} {
putquick "TOPIC $channel :It is Day 11!"
set ::rpday 1
}
set fd [open "rpday.tcl" "WRONLY CREAT TRUNC"]
puts $fd [list set state $::rpday]
close $fd
}
} |
Also, do I need to create the "rpday.tcl" script in advance, or just enter the "source/rpday.tcl" entry in the bots conf?
what should the contents of that script look like, so that the variable can be read properly? |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Sun Apr 24, 2011 12:28 pm Post subject: |
|
|
Please indent your code properly when posting, it makes spotting issues such as the extra } in your code that much easier to spot... not to mention reading the code.
First, since you named your variable rpday, not state, you'll have to change that in the save-code as well..
Also, if you go with the script-solution, you don't need to write the value to "restore"; I'd suggest you only use one or the other to avoid confusion, not both..
Also a hint, since you're building such many states on a single expression (variable), I'd considder using switch instead of those stacked if/elseif/else's...
Finally, as for reading the generated rpday.tcl upon startup; I'd use a catch-statement - just so I wouldn't have to bother making sure the file is always created (yes, I'm lazy). I'll even add a default value in case there was an error loading the file...
| Code: | if {[catch {source rpday.tcl} err]} {
set ::rpday 1
}
set ::rpchan "#Bot_Test"
bind time - "00 00 * * *" tchange
proc tchange {min hour day month year} {
global rpchan
switch -exact -- $::rpday {
1 {putquick "TOPIC $::rpchan :It is Day One!"}
2 {putquick "TOPIC $::rpchan :It is Day Two!"}
#... and so on...
#until the default case, which maches if none of the above does...
default {
putquick "TOPIC $::rpchan :It is Day Eleven!"
set ::rpday 0
}
}
incr ::rpday
set fd [open "rpday.tcl" "WRONLY CREAT TRUNC"]
puts $fd [list set ::rpday $::rpday]
close $fd
} |
Edit: Corrected missing "incr ::rpday"
Edit: Corrected missing edit note... _________________ NML_375, idling at #eggdrop@IrcNET
Last edited by nml375 on Fri Apr 29, 2011 10:00 am; edited 2 times in total |
|
| Back to top |
|
 |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Tue Apr 26, 2011 1:18 pm Post subject: |
|
|
Looks like that is going to do it. I just need to format my topic a little better. I can't figure out how to keep the script from thinking that the brackets in the topic are code.
Thanks for your help, NML! |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Tue Apr 26, 2011 1:35 pm Post subject: |
|
|
Escape them as \[ \] _________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Tue Apr 26, 2011 1:48 pm Post subject: |
|
|
Awesome.
Solved.
Thanks again! |
|
| Back to top |
|
 |
Seka Voice
Joined: 19 Apr 2011 Posts: 18
|
Posted: Fri Apr 29, 2011 9:43 am Post subject: |
|
|
| Quote: | | Code: | if {[catch {source rpday.tcl} err]} {
set ::rpday 1
}
set ::rpchan "#Bot_Test"
bind time - "00 00 * * *" tchange
proc tchange {min hour day month year} {
global rpchan
switch -exact -- $::rpday {
1 {putquick "TOPIC $::rpchan :It is Day One!"}
2 {putquick "TOPIC $::rpchan :It is Day Two!"}
#... and so on...
#until the default case, which maches if none of the above does...
default {
putquick "TOPIC $::rpchan :It is Day Eleven!"
set ::rpday 0
}
}
set fd [open "rpday.tcl" "WRONLY CREAT TRUNC"]
puts $fd [list set ::rpday $::rpday]
close $fd
} |
|
It looks like the above script is stuck on the first entry in the "switch" statement. As it stands, at midnight, the topic is always changed to "It is Day One!" and never anything else in the list. |
|
| Back to top |
|
 |
nml375 Revered One
Joined: 04 Aug 2006 Posts: 2857
|
Posted: Fri Apr 29, 2011 9:58 am Post subject: |
|
|
Sorry, seems I forgot to increase the value of rpday at the end of the proc.. I'll update my previous post to correct the issue in a sec.. _________________ NML_375, idling at #eggdrop@IrcNET |
|
| Back to top |
|
 |
|