Register forum user name Search FAQ

Gammon Forum

Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to verify your details, confirm your email, resolve issues, making threats, or asking for money, are spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the password reset link.

Due to spam on this forum, all posts now need moderator approval.

 Entire forum ➜ MUSHclient ➜ General ➜ Working with tables and regexp

Working with tables and regexp

It is now over 60 days since the last post. This thread is closed.     Refresh page


Posted by Mccane   (28 posts)  Bio
Date Tue 27 Nov 2007 07:50 AM (UTC)

Amended on Fri 30 Nov 2007 09:16 AM (UTC) by Mccane

Message
Okay, on this game there are different trading centers. When you go into a trading center, you type MENU and see something like:


             --- Place; Trading Post ---             

Item                          Demand         Buying For     
----------------------------------------------------------
Product1                     201500.0       145.93         
Product2                     19780.0        275.0          
Product3                     526700.0       48.87                


Item                          Supply         Selling For    
----------------------------------------------------------
Produ1a                      971390.0       50.07          
Produ1b                      463284.0       35.0           
Produ1c                      133500.0       88.57    


At every trading center, they sell different items and buy different items. Every center has different prices.

Here is what I'm trying to do. I figured I would have a trigger that's regexp that fires on <String>spaces <Floating Point Number>spaces <Floating Point Number>

I could also make a trigger that toggles between selling and buy based on (when it sees Item Supply Selling For
it sets a Selling variable to 1, which the previous trigger checks and stores accordingly by or it sets it to 0, on which the previous trigger assumes you're buying and not selling).

I was hoping someone could help me figure out or point me to documentation in regular expressions so I could make it match on <String>spaces <Floating Point Number>spaces <Floating Point Number>

I'd also like some help with or a point towards documentation that would help me in figuring out how to store A) The trading center name B) Item name C) Selling/Buy price. The item and price would be associated to that center (the center could be set as a variable when it matches the line

--- Place; Trading Post ---

What I'm eventually trying to do is take all the values for Product1 and print me the lowest value and where it's being sold out, then take the highest buying value for Product1 and spit out the price and place so I can make the most efficient trades. Any help would be much appreciated!
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #1 on Tue 27 Nov 2007 07:52 PM (UTC)

Amended on Tue 27 Nov 2007 07:53 PM (UTC) by Nick Gammon

Message
If you are logged into the forum you can edit and delete posts you know, you don't have to repost the same thing with corrections.

As for the regexp, something like this will match on the product lines:


<triggers>
  <trigger
   enabled="y"
   match="^(?P&lt;name&gt;[A-Za-z0-9]+)\s+(?P&lt;demand&gt;[0-9.]+)\s+(?P&lt;buying&gt;[0-9.]+)\s+$"
   regexp="y"
   send_to="2"
   sequence="100"
  >
  <send>Name = %&lt;name&gt;
Demand = %&lt;demand&gt;
Buying = %&lt;buying&gt;
</send>
  </trigger>
</triggers>


I used named wildcards to make subsequent scripting a bit easier, so you can refer to the names rather than just %1, %2 etc.

The match line looks a bit strange in XML, if you look at it in the trigger edit dialog it looks like this:


^(?P<name>[A-Za-z0-9]+)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+$


Using your test data I got this, the echoed lines are in bold:


Item                          Demand         Buying For     
----------------------------------------------------------
Product1                     201500.0       145.93         
Name = Product1
Demand = 201500.0
Buying = 145.93
Product2                     19780.0        275.0          
Name = Product2
Demand = 19780.0
Buying = 275.0
Product3                     526700.0       48.87                
Name = Product3
Demand = 526700.0
Buying = 48.87


Item                          Supply         Selling For    
----------------------------------------------------------
Produ1a                      971390.0       50.07          
Name = Produ1a
Demand = 971390.0
Buying = 50.07
Produ1b                      463284.0       35.0           
Name = Produ1b
Demand = 463284.0
Buying = 35.0
Produ1c                      133500.0       88.57    
Name = Produ1c
Demand = 133500.0
Buying = 88.57


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Mccane   (28 posts)  Bio
Date Reply #2 on Wed 28 Nov 2007 07:42 AM (UTC)
Message
Gracias, Nick.

I've gotten the regex down, I think. It turned out some of the items in the game have more than one word in the name, for example there's a product called 'Carbon' and a product called 'carbon dioxide', so

^(?P<name>[A-Za-z0-9]+)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+$


would not match to the carbon dioxide line. I changed it to
^(?P<name>.+)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+

and it seems to match to every line right.

The trouble for me comes in with Lua tables. I thought the easiest way to do it would to be make a table such as

trade.Item.Selling/Buying = {Location, Demand/Supply, Price}

The problem comes in with the multiple names. I can't seem to figure out how to turn 'Carbon Dioxide' into just 'CarbonDioxide' (I tried doing an if Name == "Carbon Dioxide" then Name = "CarbonDioxide" but I couldn't get it to work. I also can't seem to figure out how to add tables to within tables in the format I'm using (right now it just rewriting a new location over the last location every time I test it).

I thought about doing trade.Item.Selling/Buying.@Location = {}, where Location is stored in a variable and expand variables is checked, but I didn't see any feasability on running searches through all the data (my goal is to run through trade.Item1.Selling and find the LOWEST number and then trade.Item2.Buying and find the HIGHEST number. I figured it might help to show a realistic look at what the game actually shows:


             --- Miriani; Trading Post ---             

Item                          Demand         Buying For     
----------------------------------------------------------
Aluminum                      201500.0       145.93         
Bardenium                     19780.0        275.0          
Grain                         526700.0       48.87          
Carbon                        602970.0       53.88          
Oxygen                        950000.0       75.0           
Argon                         285000.0       156.81         


Item                          Supply         Selling For    
----------------------------------------------------------
Xenon                         971395.0       50.07          
Bread                         463284.0       35.0           
Carbon Dioxide                133500.0       88.57          
Water                         51432426.0     5.0            
Zyprexasil                    12456.0        900.0          
Aluminum Wires                108476.0       119.75


Every trading center has different stuff, so it doesn't overlap consistently to every center. There's about twenty trading centers or so. The supply/demand changes everytime you sell or buy (if you buy a lot, supply will go down, et cetera), so I was hoping to just continuously reupdate the tables every time I made a trade at a different center by rechecking the menu when I finish a trade.

Thanks for your help.
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #3 on Wed 28 Nov 2007 06:42 PM (UTC)
Message
Quote:

The problem comes in with the multiple names. I can't seem to figure out how to turn 'Carbon Dioxide' into just 'CarbonDioxide'


So you are saying that something like:


trade.Carbon Dioxide.Selling = { something }


... won't work?

You can use a different syntax and keep the original names, like this:


trade ["Carbon Dioxide"].Selling = { something }


Quote:

I also can't seem to figure out how to add tables to within tables in the format I'm using ...


You can create the tables, where needed. Something like this:


trade = trade or {}   -- create trade table if it doesn't exist

item = "Carbon Dioxide"  -- test

-- make table for this item and its subtables, if this is the first time for this item

trade [item] = trade [item] or { Selling = {}, Buying = {} }

-- now fill in the fields

trade [item] . Selling . Location = "John's General Store"
trade [item] . Selling . Demand = 602970.0
trade [item] . Selling . Price = 156.81


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Mccane   (28 posts)  Bio
Date Reply #4 on Thu 29 Nov 2007 08:44 AM (UTC)
Message
Thanks Nick, here is the code I have:

Selling = tonumber(GetVariable("Selling"))
item = "%<name>"
if Selling == 0 then
trade [item] = trade [item] or { Buying = {}, Selling = {} }
trade [item] . Buying . Location = "@LocName"
trade [item] . Buying . Demand = %<demand>
trade [item] . Buying . Price = %<buying>
else
trade [item] = trade [item] or { Buying = {}, Selling = {} }
trade [item] . Selling . Location = "@LocName"
trade [item] . Selling . Demand = %<demand>
trade [item] . Selling . Price = %<buying>
end


When I try to enter
/table.foreach (trade, print)
, it returns this:

table: 0244B8F0
Bardenium                     table: 0232F728
Xenon                         table: 024A8380
Oxygen                        table: 0232E398
Bread                         table: 0232D030
Aluminum Wires                table: 00D84128
Zyprexasil                    table: 0244DBB0
Water                         table: 0241E480
Carbon Dioxide                table: 0241E3E0
Carbon                        table: 024A5800
Aluminum                      table: 024A4190
Argon                         table: 0232DD20
Grain                         table: 0232F088


But when I try to go further, such as trade.Bardenium or anything like that, it returns this error:

Error number: 0
Event:        Run-time error
Description:  [string "Command line"]:1: bad argument #1 to 'foreach' (table expected, got nil)

stack traceback:

	[C]: in function 'foreach'

	[string "Command line"]:1: in main chunk
Called by:    Immediate execution


It seems as though the data is not being entered into a subtable as I thought the code would do. Where is the data going, and now do I retrieve it?
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #5 on Thu 29 Nov 2007 06:45 PM (UTC)
Message
Well that doesn't make a heap of sense, because you have already established they are tables. Perhaps, because of your triggers, the keys have a space in them. Table keys "Bardenium", "Bardenium " and " Bardenium" are all different.

I suggest to print your table you use "tprint" which comes with MUSHclient. That recursively prints tables for you. For example, with my test data from before I see this:


require "tprint"
tprint (trade)


Output:

"Carbon Dioxide":
  "Selling":
    "Location"="John's General Store"
    "Demand"=602970
    "Price"=156.81
  "Buying":


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Mccane   (28 posts)  Bio
Date Reply #6 on Fri 30 Nov 2007 05:31 AM (UTC)

Amended on Fri 30 Nov 2007 08:33 AM (UTC) by Mccane

Message
Thanks, Nick. Got it working almost. Turned out the regex I was using to match on was storing the space after the item name and before the first number in the subtable name. The only problem is that if I change it so it doesn't match whitespace, it'll cutoff after the first names (will match Carbon but not Carbon Dioxide). Here is what I mean:

^(?P<name>[A-Za-z0-9]+)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+$

will match Carbon but not Carbon Dioxide because of whitespace in between the two.

^(?P<name>.+)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+

will match everything, but the matching ends up like this:

"Carbon Dioxide               ":
  "Buying":
  "Selling":
    "Location"="Miriani"
    "Demand"=133500
    "Price"=88.57
"Carbon                       ":
  "Buying":
    "Location"="Miriani"
    "Demand"=602970
    "Price"=53.88
  "Selling":


A lot of whitespace following the item name. How can I cut out the additional whitespace after the name from being stored in the %<name> variable?
Top

Posted by Nick Gammon   Australia  (23,133 posts)  Bio   Forum Administrator
Date Reply #7 on Fri 30 Nov 2007 07:47 AM (UTC)
Message
It's an interesting problem. ;)

This worked for me, adding in an assertion that the name has to end on a word boundary:


^(?P<name>[A-Za-z0-9 ]+\b)\s+(?P<demand>[0-9.]+)\s+(?P<buying>[0-9.]+)\s+$


- Nick Gammon

www.gammon.com.au, www.mushclient.com
Top

Posted by Mccane   (28 posts)  Bio
Date Reply #8 on Fri 30 Nov 2007 08:37 AM (UTC)
Message
You know, it's not often you use someone's software and then you post questions to their forums and they help you every time personally. In most instances you'd be told to figure it out for yourself. 10,000+ posts? In other words, thanks, you're awesome. :)
Top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


20,632 views.

It is now over 60 days since the last post. This thread is closed.     Refresh page

Go to topic:           Search the forum


[Go to top] top

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.