How to send a random line of text to a user followed by permanent ignore in mIRC - scripting

Below is an example of my mirc script that triggers on channel JOIN...
on 1:JOIN:#:/timer 1 10 /msg $nick Welcome | /timer 1 20 If you like the game please vote on the main page | /timer 1 30 Thanks for visiting and enjoy your stay ignore $nick
I want to randomise the replies from a text file stored locally, how exactly do I do this? I am quite new to mIRC and am just learning and have been testing used $rand but failed miserably.
I'd like to have say 10 options for EACH sequential reply. So first message to the user has 10 variations, so does the second and so forth. For the sake of efficiency I would then like to ignore the user permanently once they have had all messages. So any time they next come online and join the channel they will not receive the messages ever again. I guess maybe this would require an .ini to store the users id?

Not entirely sure why you want to have everything on one line, even as that may be from lack of knowledge on the subject. For readability, you can replace the event execution line with brackets:
on 1:JOIN:#: {
timer 1 10 msg $nick Welcome
timer 1 20 If you like the game please vote on the main page
timer 1 30 Thanks for visiting and enjoy your stay
ignore $nick
}
Of course, there are still some problems with the above example. /msg isn't used, thus the next timers won't do anything, and /ignore won't prevent the event from triggering. I'll address that in a bit.
On top of that, you don't ignore the nick because your last line(shown here: /timer 1 30 Thanks for visiting and enjoy your stay ignore $nick) doesn't separate out ignore $nick from the rest of the execution line, thus it simply treats it as part of the sentence. To do that, you'd need to give it another pipe character(shown here: /timer 1 10 /msg $nick Welcome | /timer 1 20 If you like the game please vote on the main page | /timer 1 30 Thanks for visiting and enjoy your stay | ignore $nick, or like the above with my bracket example).
Now, onto the main question itself; a call to the $read identifier, with just the file name and no extra parameters will cause it to read a random line from that file. So, with that in mind you could do the following:
on 1:JOIN:#: {
timer 1 10 msg $nick $read(welcome.txt)
timer 1 20 msg $nick $read(vote.txt)
timer 1 30 msg $nick $read(closing.txt)
ignore $nick
}
Note that calls to read any file is local to the mIRC app data folder. Meaning that welcome.txt is expected to exist at $mircdir. If you want to load it from elsewhere, either specify the absolute path, or use $scriptdir $+ filename.extension, and be sure have the script itself exists in a specific directory, such as scripts\script_name\script.mrc.
To make sure the user never receives the message again, you will need to keep track of users. To do this, we can just use $read again, as when used with certain parameters, if $read doesn't find what we're looking for, it will return $null. Ignoring the user will not prevent the user from triggering the join event.
$read's s parameter, supplied as the second parameter, searches for a line beginning with the third parameter; if that line exists, it returns the line. Otherwise, it returns $null.
After that, we simply /write to the file. /write can take a variety of options, but none are relevant as we only need to append a line to the file(the first parameter), which is in this case is $nick(the second parameter).
on 1:JOIN:#: {
if ($read(ignored_nicks.txt, s, $nick) == $null) {
timer 1 10 msg $nick $read(welcome.txt)
timer 1 20 msg $nick $read(vote.txt)
timer 1 30 msg $nick $read(closing.txt)
write ignored_nicks.txt $nick
}
}
Of note, when an event uses the bracket format, we don't need to supply the forward slash(/) for each command. Only when executing a command from mirc's input box do you need the first slash. The pipe(|) doesn't need a slash, though I add it myself out of good practice, to make it obvious its a command(example: /somecommand blah | /someothercommand blah).
Lastly, if you are going to add more replies, that changes my answer a slight, but as there are only 3, there is no need to complicate it further for the moment.

Related

What is the race condition for Redis INCR Rate Limiter 2?

I have read the INCR documentation here but I could not understand why the Rate limiter 2 has a race condition.
In addition, what does it mean by the key will be leaked until we'll see the same IP address again in the documentation?
Can anyone help explain? Thank you very much!
You are talking about the following code, which has two problems in multiple-threaded environment.
1. FUNCTION LIMIT_API_CALL(ip):
2. current = GET(ip)
3. IF current != NULL AND current > 10 THEN
4. ERROR "too many requests per second"
5. ELSE
6. value = INCR(ip)
7. IF value == 1 THEN
8. EXPIRE(ip,1)
9. END
10. PERFORM_API_CALL()
11.END
the key will be leaked until we'll see the same IP address again
If the client dies, e.g. client is killed or machine is down, before executing LINE 8. Then the key ip won't be set an expiration. If we'll never see this ip again, this key will always persist in Redis database, and is leaked.
Rate limiter 2 has a race condition
Suppose key ip doesn't exist in the database. If there are more than 10 clients, say, 20 clients, execute LINE 2 simultaneously. All of them will get a NULL current, and they all will go into the ELSE clause. Finally all these clients will execute LINE 10, and the API will be called more than 10 times.
This solution fails, because these's a time window between LINE 2 and LINE 3.
A Correct Solution
value = INCR(ip)
IF value == 1 THEN
EXPIRE(ip, 1)
END
IF value <= 10 THEN
return true
ELSE
return false
END
Wrap the above code into a Lua script to ensure it runs atomically. If this script returns true, perform the API call. Otherwise, do nothing.

GML Alarm event not working second time

I have my game setup so that it starts and goes back to a loading screen room for 45 steps after which the next room is randomized. So at alarm[0] the following code activates:
randomize();
chosenRoom = choose(rm_roomOne, rm_roomTwo, rm_roomThree, rm_roomFour);
room_goto(chosenRoom);
The code here works fine the first time, but when it goes back from the randomly chosen room to the loading screen room it stays there and doesn't execute the code again.
Any help would be very much appreciated.
This may sound stupid but did you remember to set the alarm again after it's gone off? I know I've done this several times without thinking. Without seeing your code, I assume that after the alarm goes off it's not being set again, so it won't go off again.
I'm guessing the control object is "persistant", thus the Control Object only exists once and will remain forever (also after swithcing rooms) - thus thie create event only gets fired once - thus the alarm only gets set once.
Try to move your code to the event "Room Start" in your controller and it will work.
you can use event_perform(ev_alarm,0);.
The code here performs alarm[0] after 45 steps. after 45 steps again it triggers alarm[0]. Note that you have to put it in step event. And you have to initialize wait variable and times to zero in create event.
times is the repeat and wait is distance between events.
if(wait == 45 && times !=2){
event_perform(ev_alarm,0);
times++;
wait = 0;
}
else{
wait++;
}

cocoa-applescript: running handler or command every few seconds

In normal applescript, the script is executed down the page, and so any code in loops for every 5 seconds will only run while the loop is running - there is no way to have a single function run every few second regardless of what the script is currently doing or where it is in the script (that I know of). In cocoa-applescript, however, is there a way to run a handler every 5 seconds, at all times, no matter what it is currently doing? Here is what it should be doing in my cocoa-applescript app:
on checkInternetStrength()
do shell script "/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I | grep 'agrCtlRSSI:'" -- this being the script which returns the line containing the signal strength
set SignalStrength to result
set RSSIcount to (count of characters in SignalStrength)
set SignalStrength to ((characters 18 thru RSSIcount of SignalStrength) as string) as integer -- this to turn SignalStrength into just the number and not the whole output line
set SignalStrength to (100 + SignalStrength) as integer
set SignalBar's setIntValue_(SignalStrength) -- SignalBar being the Level Indicator described below
end checkInternetStrength
Summed up, it runs the airport command to check internet connection, turns this into a number from 1 to 100 and uses this on an NSLevelIndicator (100 maximum) to show current signal strength graphically. Now, there is no point having this run once or when you hit a button - that is an option, but it would be nice if it updated itself every, say, 5 seconds with the realtime value. So is there any way to have a process which runs every 5 seconds to do this, while still enabling full functionality of the rest of the script and interface - i.e. as a background process? Comment if you need more extracts from the script.
Example
In Unity-C# scripting, the 'void Update() {code}' will run the code within it every frame while doing everything else simultaneously, so a cocoa-applescript version of this might be an answer, if anyone knows.
I Dont believe this is possible but what I had a similar problem before, what i do, I have an external applescript applicaion that is hidden the repeats the commands, the only problem is, it wont send it back to the app, you'll have to make the external applescript app do it, like
display notification, etc..., in the applescript apps "Info.plist" you can add this:
<key>LSUIElement</key>
<string>1</string>
To make the app run invisibly, but sorry i dont think you can run a handler in the app its self

ring server messages not traversing ring

I've almost implemented the well-known ring server, however the messages do not seem to be traversing the ring - here's my code:
module(ring).
-import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]).
-export([start/3,server/0]).
start(M,N,Msg)->
start(M,N,[],Msg).
start(0,0,_,_)->
ok;
start(M,0,PList,Msg)->
nth(1,PList)!nthtail(1,reverse(zip(append(duplicate(M,PList)),duplicate(M*length(PList),Msg))));
start(M,N,PList,Msg)->
start(M,N-1,[spawn(ring, server, [])|PList],Msg).
server()->
receive
[]->
ok;
[{Pid,Msg}|T]->
io:format("~p,~p~n",[self(),Msg]),
Pid!T;
terminate->
true
end.
it returns the following when executed:
2> ring:start(3,3,"hello").
<0.42.0>,"hello"
<0.41.0>,"hello"
[{<0.41.0>,"hello"},
{<0.42.0>,"hello"},
{<0.40.0>,"hello"},
{<0.41.0>,"hello"},
{<0.42.0>,"hello"},
{<0.40.0>,"hello"},
{<0.41.0>,"hello"},
{<0.42.0>,"hello"}]
May I ask where I am going wrong here? I've checked the zipped process list, and it seems as if it should work. Thanks in advance.
There are 2 mistakes here, the main one is that you do not recursively recall server after printing the message.
The second one is that you should not remove the head of your list when you build the first message, otherwise you will have only m*n - 1 messages passed.
this code works, but it leaves all the processes active, you should enhance it to kill all processes at the end of the "ring":
-module(ring).
-import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]).
-export([start/3,server/0]).
start(M,N,Msg)->
start(M,N,[],Msg).
start(0,0,_,_)->
ok;
start(M,0,PList,Msg)->
nth(1,PList)!reverse(zip(append(duplicate(M,PList)),duplicate(M*length(PList),Msg)));
start(M,N,PList,Msg)->
start(M,N-1,[spawn(ring, server, [])|PList],Msg).
server()->
receive
[]->
ok;
[{Pid,Msg}|T]->
io:format("In Server ~p,~p~n",[self(),Msg]),
Pid!T,
server();
terminate->
true
end.
On my side, I don't use import, I find it more explicit when I have lists:reverse..., You can use hd/1 to get the first element of a list, and you could use list comprehension to generate your list of {Pid,Msg}
Your processes are terminating, not looping (and there is never a condition under which they will receive 'terminate'). To solve the termination issue, have them spawn_link instead of just spawn so that when the first one dies, they all die.
It is good to kick things off by messaging yourself, to make sure you're not stripping the first message entirely.
-module(ring).
-import(lists,[duplicate/2,append/1,zip/2,nthtail/2,nth/2,reverse/1]).
-export([start/3,server/0]).
start(M, N, Msg)->
Scroll = start(M, N, [], Msg),
self() ! Scroll.
start(0, 0, _, _)->
ok;
start(M, 0, PList, Msg)->
nth(1, PList) ! nthtail(1, reverse(zip(append(duplicate(M, PList)),
duplicate(M * length(PList), Msg))));
start(M, N, PList, Msg)->
start(M, N - 1, [spawn_link(ring, server, []) | PList], Msg).
server()->
receive
[]->
ok;
[{Pid, Msg} | T]->
io:format("~p,~p~n", [self(), Msg]),
Pid ! T,
server()
end.
This produces:
1> c(ring).
{ok,ring}
2> ring:start(3,3,"raar!").
<0.42.0>,"raar!"
<0.41.0>,"raar!"
[{<0.41.0>,"raar!"},
{<0.42.0>,"raar!"},
{<0.40.0>,"raar!"},
{<0.41.0>,"raar!"},
{<0.42.0>,"raar!"},
{<0.40.0>,"raar!"},
{<0.41.0>,"raar!"},
{<0.42.0>,"raar!"}]
<0.42.0>,"raar!"
<0.40.0>,"raar!"
<0.41.0>,"raar!"
<0.42.0>,"raar!"
<0.40.0>,"raar!"
<0.41.0>,"raar!"
As expected. Note that I'm calling server() again on receipt of a message. When the empty list is received they all die because they are linked. No mess.
Some spacing for readability would have been a little more polite. Erlangers usually aren't so leet that we want to plow through a solid mass of characters -- and this actually causes errors with a few operators in some edge cases (like in map syntax). Also, using imported functions is a little less clear. I know is gums up the code with all that namespace business, but its a lifesaver when you start writing larger programs (there are a lot of list operations in the erlang module -- so some of this importing is unnecessary anyway http://www.erlang.org/doc/man/erlang.html#hd-1).

jmeter stop current iteration

I am facing the following problem:
I have multiple HTTP Requests in my testplan.
I want every request to be repeated 4 times if they fail.
I realized that with a BeanShell Assertion, and its already working fine.
My problem is, that I don't want requests to be executed if a previous Request failed 5 times,
BUT I also dont want the thread to end.
I just want the current thread iteration to end,
so that the next iteration of the thread can start again with the 1st request (if the thread is meant to be repeated).
How do I realize that within the BeanShell Assertion?
Here is just a short extract of my code where i want the solution to have
badResponseCounter is being increased for every failed try of the request, this seems to work so far. Afterwards, the variable gets resetted.
if (badResponseCounter = 5) {
badResponseCounter = 0;
// Stop current iteration
}
I already checked the API, methods like setStopTest() or setStopThread() are given, but nothing for quitting the current iteration. I also need the preference "continue" in the thread group, as otherwise the entire test will stop after 1 single request failed.
Any ideas of how to do this?
In my opinion the easiest way is using following combination:
If Controller to check ${JMeterThread.last_sample_ok} and badResponseCounter variables
Test Action Sampler as a child of If Controller configured to "Go to next loop iteration"
Try this.
ctx.setRestartNextLoop(true);
if the thread number is 2, i tried to skip. I get the below result as i expected (it does not call b-2). It does not kill the thread either.