Help needed introducing delays in loop for help index system

Post Reply
User avatar
ulysses
Posts: 43
Joined: Fri Jan 05, 2018 7:43 pm

Help needed introducing delays in loop for help index system

Post by ulysses »

Hi,

I posted this on discord and got some ideas, but still haven't quite cracked it. This is the basic idea:

1. Read a help index file - this is a list of all help topics available.
2. Loop over the items
3. For each one send("help " .. item)
4. Capture contents
5. When the prompt arrives stop capturing.
6. Resume loop.

The problem is between 5 and 6. The following is the best experiment that I've made so far which ALMOST works. It works perfectly for the first couple of hundred items, but then the global name helpitemname gets out of sync with the one which is actually sent using the send("help" .. helpitem) command. I think this is because the accumulated lag on the server over several hundred commands exceeds the 5 second slot allotted to one help/capture cycle. What I really need to do is for the capture trigger to signal back to the loop that it has finished so the next help/capture cycle can start. I tried that by means of setting a global variable to control a queue, but the main loop checking the queue locked the GUI. Not quite experienced enough with lua/mudlet to work out what to do here. Ideas welcome!

Alias: buildhelpdb:

Code: Select all


_base = getMudletHomeDir() .. "/help"
_indexfile = _base .. "/aproposdb"

items = {}
for line in io.lines(_indexfile) do 
  items[#items + 1] = line
end

-- test array
items = {}
items[1] = 'LOOK'
items[2] = 'GATE'

helpitemname = ''
helpitemtext = {}

delay = 5.0
for i, helpitem in ipairs(items) do
	tempTimer(delay, function()
		helpitemname = helpitem
		helpitemtext = {}
		send("help " .. helpitem)
		enableTrigger("CaptureHelpText")
	end)
	delay = delay + 5.0
end
And the CaptureHelpText trigger looks like this:

Code: Select all

function isMyPrompt(line)
	return string.match(line, "^%(%d%d:%d%d%)")
end

local myline = line

if not isMyPrompt(myline) then
	--echo("Adding line to helptext")
	table.insert(helpitemtext, myline)
else

	_base = getMudletHomeDir() .. "/help"
  _file = _base .. "/" .. helpitemname
	echo("saving helpfile to " .. _file)  
  recordFile = io.open( _file, "w" )
  io.output( recordFile )
	for _,v in ipairs(helpitemtext) do
		io.write(v .. '\n')
	end
  io.flush()
  io.close()
	disableTrigger("CaptureHelpText")
end
Thanks!
Wod
Wod :mrgreen:
CthulhuMUD
www.cthulhumud.com
A hugely entertaining MUD based on the horror writings of HP Lovecraft.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Help needed introducing delays in loop for help index system

Post by Jor'Mox »

Instead of using a time based system, I would recommend just making a function that does what your tempTimers are doing, and once each help file is collected, call that function again, iterating through the table of help topics.

User avatar
ulysses
Posts: 43
Joined: Fri Jan 05, 2018 7:43 pm

Re: Help needed introducing delays in loop for help index system

Post by ulysses »

Jor'Mox wrote:
Fri May 11, 2018 7:27 pm
Instead of using a time based system, I would recommend just making a function that does what your tempTimers are doing, and once each help file is collected, call that function again, iterating through the table of help topics.
Hey Jor'Mox!

Right, I thought about doing it like that, but the called function needs to read in multiple lines, and the only way I know how to do that is to use a gate trigger. The loop can call a function which:

Code: Select all

send("help " .. X)
enables the gate which:
   captures output
   close the gate on prompt
   disables the gate
The problem is I don't know how to make this function block in the loop. What happens without any timing control, is that all the send("help " .. X) commands are fired off at once. How to I effectively make a blocking call to the gate open/close? Or perhaps there is another way to capture multiple lines?

Thanks!
Wod
Wod :mrgreen:
CthulhuMUD
www.cthulhumud.com
A hugely entertaining MUD based on the horror writings of HP Lovecraft.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Help needed introducing delays in loop for help index system

Post by Jor'Mox »

Well, you already seem to have a trigger to do the necessary text capture, and it clearly has something that caps things off once the help file is finished (when it encounters a prompt). That seems like the perfect place to call a function that sends the next command and such, or, given that it seems to be a fairly simple set of things that need to happen, it could just do those things on its own without a function call. Here is some pseudocode for the trigger showing what I'm talking about:

Code: Select all

local function isMyPrompt(str)
   return string.match(str,"prompt")
end

if not isMyPrompt(line) then
   table.insert(helpitemtext,line)
else
   saveHelpFile() -- just all the stuff you currently have performing this task
   helpitemindex = helpitemindex + 1
   if items[helpitemindex] then
      helpitemname = items[helpitemindex]
      helpitemtext = {}
      send("help " .. helpitemname
   else
      disableTrigger("CaptureHelpText")
   end
end
With something like that, your alias just needs to kick things off, and your trigger will keep running until it is finished. Pointedly though, you could just make a HUGE table out of all the help files, and save the whole thing as a table (with table.save), rather than saving each individual bit of help text as its own file, but that is neither here nor there.

User avatar
ulysses
Posts: 43
Joined: Fri Jan 05, 2018 7:43 pm

Re: Help needed introducing delays in loop for help index system

Post by ulysses »

Jor'Mox wrote:
Fri May 11, 2018 8:29 pm
Well, you already seem to have a trigger to do the necessary text capture, and it clearly has something that caps things off once the help file is finished (when it encounters a prompt). That seems like the perfect place to call a function that sends the next command and such, or, given that it seems to be a fairly simple set of things that need to happen, it could just do those things on its own without a function call. Here is some pseudocode for the trigger showing what I'm talking about:

Code: Select all

local function isMyPrompt(str)
   return string.match(str,"prompt")
end

if not isMyPrompt(line) then
   table.insert(helpitemtext,line)
else
   saveHelpFile() -- just all the stuff you currently have performing this task
   helpitemindex = helpitemindex + 1
   if items[helpitemindex] then
      helpitemname = items[helpitemindex]
      helpitemtext = {}
      send("help " .. helpitemname
   else
      disableTrigger("CaptureHelpText")
   end
end
With something like that, your alias just needs to kick things off, and your trigger will keep running until it is finished. Pointedly though, you could just make a HUGE table out of all the help files, and save the whole thing as a table (with table.save), rather than saving each individual bit of help text as its own file, but that is neither here nor there.
Interesting idea, thanks! I will try it and let you know.
Wod :mrgreen:
CthulhuMUD
www.cthulhumud.com
A hugely entertaining MUD based on the horror writings of HP Lovecraft.

User avatar
ulysses
Posts: 43
Joined: Fri Jan 05, 2018 7:43 pm

Re: Help needed introducing delays in loop for help index system

Post by ulysses »

ulysses wrote:
Fri May 11, 2018 9:19 pm
Interesting idea, thanks! I will try it and let you know.
It worked! There are two issues remaining for perfection. Firstly, the reason I started putting the timers in, was to slow the process down a little. I'm concerned that this could be a bit of a drain on the server. A second or two pause between each help/capture cycle would be good. Perhaps in that case a blocking wait such as this one would be OK, or would an alternative method be more desirable I wonder:

https://stackoverflow.com/questions/103 ... ew-seconds

The other issue is that events on the mud cause the prompt to be issued. I switched off as many of those as I could but it still took a couple of goes at it to generate all 964 help files correctly. To fix I just found the smallest file (that was the one with the interrupting event), worked out the index at that point and reran, setting the index to number-1. To fix this it might be necessary to put an extra condition on the isMyPrompt line to detect that we have indeed seen some help text (I noticed that all help files have ---BLAH--- at the top so can use that to detect).

I wanted to store all the help files separately since it helps for indexing. In game one will type something like helpsearch STRING and the output will be HELPFILE, #of occurences of STRING, first occurance of STRING for all matches, ordered by #of occurences. It's a little bit like the apropos (man -k) command on linux. This could of course be done by looking through one large file, but the logic would have to be a little more complex (to my mind anyway).

Once I've got that bit working I'll post it to the scripts section so people can adapt it for their MUDs. Reminds me I need to work out how to create a package!

Thanks again Jor'Mox. You really are a legend!
-Wod
Wod :mrgreen:
CthulhuMUD
www.cthulhumud.com
A hugely entertaining MUD based on the horror writings of HP Lovecraft.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Help needed introducing delays in loop for help index system

Post by Jor'Mox »

You can just wrap the bit that is doing the sending in the trigger into a temptimer. So, the trigger captures the help file, and when it is done, it makes a timer that fires off after however long, and the timer turns the trigger back on and calls up the next help file.

Given what you want to do, it might be worth looking into using the actual database system in place within Mudlet, as that will give you a much nicer way to search within all the files you are collecting.

User avatar
ulysses
Posts: 43
Joined: Fri Jan 05, 2018 7:43 pm

Re: Help needed introducing delays in loop for help index system

Post by ulysses »

Jor'Mox wrote:
Fri May 11, 2018 11:18 pm
You can just wrap the bit that is doing the sending in the trigger into a temptimer. So, the trigger captures the help file, and when it is done, it makes a timer that fires off after however long, and the timer turns the trigger back on and calls up the next help file.
Not sure I follow that 100%. Can you please post a pseudo-code snippet?
Given what you want to do, it might be worth looking into using the actual database system in place within Mudlet, as that will give you a much nicer way to search within all the files you are collecting.
Right, I hadn't thought about that actually. I'll take a look!

Thanks again!
Wod
Wod :mrgreen:
CthulhuMUD
www.cthulhumud.com
A hugely entertaining MUD based on the horror writings of HP Lovecraft.

Jor'Mox
Posts: 1142
Joined: Wed Apr 03, 2013 2:19 am

Re: Help needed introducing delays in loop for help index system

Post by Jor'Mox »

So basically, when your trigger recognizes the end of a help file, and it is pulling up the next one, you have some code that I'll say looks like this:

Code: Select all

updateVariables()
sendCommand()
I'm suggesting changing it to look like this:

Code: Select all

disableTrigger('name')
tempTimer(time, function () enableTrigger('name') updateVariables() sendCommand() end)

Post Reply