Searching map_to_file

fronobulax

Developer
Staff member
Is it possible to search for a specific word, or set of words inside a map?

You are going to have to be more specific than that. You can use "contains" to find out whether they map has a particular key but you probably have to iterate over the map and search each value otherwise.
 

Pazleysox

Member
The search wasn't as difficult as I first thought it would be.

I've been scouring the forums for over an hour, and I can't find, nor can I figure out how to add info to an existing map.

IE:

Current map says:
0 Mr. Accessory
1 Mrs. Accessory
2 Time Sword


I would like to keep all current information IN the map, and just be able to add to it.
 

AlbinoRhino

Active member
If the map is items -- to add an additional entry:

item[int] mapname;

mapname[count(mapname)] = NEW $item ENTRY;

(Assuming the map is 0-indexed, so the count() of the map will be the (highest index +1).)

===============

If you are talking about adding additional information to an existing entry (probably a map of strings or ints, as (all?) other data types aren't additive):

Code:
string[int] mapname;

foreach i in mapname {
  if (mapname[i] == "Mr. Accessory" ) {
    mapname[i] [COLOR=#ff0000][B]+=[/B][/COLOR] " the text to add";
  }
}
 
Last edited:

Pazleysox

Member
Ok. Here's the code I'm working on.
PHP:
	string [int] my_list;
	file_to_map( "pazsox.txt" , my_list);
	for i from 0 to (count(my_list) - 1) 
	{
		if (contains_text(my_list[i], sender))
		{	print ("true");	 return; }
		if(!contains_text(my_list[i], sender))
		{	print("false");	record note
			{
			string message;
			}
		[int] test;
        	int NE= count(test);
	        test[NE].message= sender;
	        Map_to_File(test, "pazsox.txt");
		}
	}
Regardless of if a users name is in the file or not, it adds the name again. I obviously only want a persons name on the list once, and never again.

I have a feeling the answer is in AlbinoRhino's response above, I just need to figure it out.
 

fronobulax

Developer
Staff member
If you are just making a list of things - what matters is whether the item in your example is in the list, or not, and you don't care abut the order, you could also flip things.

int[item] things

things[Mr. Accessory] = 0; would add Mr. A to the list if it is not already there.

You could use contains to find out whether something was in the list, or not.
 

AlbinoRhino

Active member
Ok. Here's the code I'm working on.
Code:
    string [int] my_list;
    file_to_map( "pazsox.txt" , my_list);
    for i from 0 to (count(my_list) - 1) 
    {
        if (contains_text(my_list[i], sender))
        {    print ("true");     return; }
         [B]If the 'sender' you are testing for happens to be the first name in the map, then this will print true and return.
[/B]         
         [B]If any other name is  first in the map, then this will print false and add the name WHETHER it appears later in the map or not.[/B]
        if(!contains_text(my_list[i], sender))
        {    print("false");
            
           [B]'test' can just be a string[int] map.  There is no need to make a record[int] map here (that I can see).[/B]
            [COLOR=#ff0000]record note
            {
            string message;
            } [int] test;   [/COLOR][B]--> string[int] test;
[/B]
            int NE= count(test);
            test[NE][COLOR=#ff0000].message[/COLOR]= sender;  --> just [B]test[NE] = sender;[/B]
            Map_to_File(test, "pazsox.txt");
        }
    }
Regardless of if a users name is in the file or not, it adds the name again. I obviously only want a persons name on the list once, and never again.

I have a feeling the answer is in AlbinoRhino's response above, I just need to figure it out.

To do what you are trying to do...(I think)...maybe something like this:

Code:
string [int] my_list;
file_to_map( "pazsox.txt" , my_list);
[B]string storage_string = "";[/B]
foreach i in my_list {
 storage_string += my_list[i] + " ";
}

[B]All the names in the list are now in a single string....[/B]

if ( !contains_text(storage_string, sender) ) {
 my_list[count(my_list)] = sender;
 map_to_file(my_list, "pazsox.txt");
}
 
Last edited:

Pazleysox

Member
I'm trying to write a clan stash checker script. I have a matcher written already that can look at the stash list, and return anything I'm looking for. I don't understand maps enough to be able to to anything with the information though.

Here's my idea:
Pasox added talisman of baio
Set a flag that item was returned

Pazsox took talisman of baio
Check "map" for returned flag, if it exists, remove it, and move on.

Right now the script can look at any number of line items. It creates a setting that an item was returned, looks at the next line from the log, if the next line says item was taken, it removes the setting. If there's no added, it prints out the necessary information. This only works if the item was returned on the next line from which it was taken. This doesn't work if someone takes multiple items, then returns them together.

I'm not looking for someone to write this for me. I'm just looking for some help, because I don't understand maps enough to do this.
 

fronobulax

Developer
Staff member
I don't understand what you are trying to do.

Do you have a predefined list of items you want to track so that you look for each item in the list and do something if the log shows it was taken or returned?

Do you look at the log and only track things that were taken and returned?

Are you assuming that there will be zero or one of an item of interest in the stash or could there be more than one?

The map I would suggest (and walk you through if necessary) depends upon what you are trying to do.
 

Pazleysox

Member
I don't understand what you are trying to do.

Do you have a predefined list of items you want to track so that you look for each item in the list and do something if the log shows it was taken or returned?

Do you look at the log and only track things that were taken and returned?

Are you assuming that there will be zero or one of an item of interest in the stash or could there be more than one?

The map I would suggest (and walk you through if necessary) depends upon what you are trying to do.

I'm trying to keep track of what's already in the stash, and has been taken/returned.

The clan has a large number of (expensive) items that are used by multiple players.

Code:
void main() 
{
string ClanLog= visit_url( "clan_log.php" );
int start=index_of( ClanLog , "Stash") +55;
ClanLog=substring(ClanLog, start);
matcher m_stash_put = create_matcher( ">(\\d{2})/(\\d{2})/(\\d{2}), (\\d{2}):(\\d{2})(AM:|PM:) <(.+?)>(.+?) \\(#(\\d+)\\)</a> (added|took|contributed) (\\d+) (.+?)\\.<" , ClanLog );
int I=0;
while( I<6 )//test # iterations
	{
	m_stash_put.find();
	I=I+1;
	string group1= m_stash_put.group( 1 );
	string group2= m_stash_put.group( 2 );
	string group3= m_stash_put.group( 3 );
	string group4= m_stash_put.group( 4 );
	string group5= m_stash_put.group( 5 );
	string group6= m_stash_put.group( 6 );
	string group7= m_stash_put.group( 7 );
	string group8= m_stash_put.group( 8 );
	string group9= m_stash_put.group( 9 );
	string group10= m_stash_put.group( 10 );
	string group11= m_stash_put.group( 11 );
	string group12= m_stash_put.group( 12 );

	string [int] mymap;
	if ((group10) == "took")
		{
		print(group8 + " " + group10 + " " + group11 + " " + group12);
		mymap[count(mymap)] = (group8) + (group10) + (group12);
		}
	map_to_file(mymap,"myfile.txt");
	}
}
This is what I have right now. This will hopefully help with what I'm trying to do.

Group8 is playername, Group9 is playernumber, Group10 is (took/added/contributed), Group11 is how many of an item, and group12 is the actual item itself.

Right now, I've got it saving only one line. I've been messing around with this today, trying to figure out how to add multiple lines to a map, multiple times.
 

Pazleysox

Member
Here's the script I came up with. It writes to a file everything that's been taken from the stash. It then checks to see if that item has been returned. If it hasn't been returned, it spits out a username, how many, and what was taken. I'm going to make my copy only look at yesterday stash results, because that's what I need it for.

Code:
void main() 
{
string [int] mymap;
map_to_file(mymap,"myfile.txt");
string ClanLog= visit_url( "clan_log.php" );
int start=index_of( ClanLog , "Stash") +55;
ClanLog=substring(ClanLog, start);
matcher m_stash_put = create_matcher( ">(\\d{2})/(\\d{2})/(\\d{2}), (\\d{2}):(\\d{2})(AM:|PM:) <(.+?)>(.+?) \\(#(\\d+)\\)</a> (added|took|contributed) (\\d+) (.+?)\\.<" , ClanLog );
int I=0;
while( I<50 )//test # iterations
	{
	m_stash_put.find();
	I=I+1;
	string group8= m_stash_put.group( 8 ); // user name
	string group9= m_stash_put.group( 9 ); // user's number
	string group10= m_stash_put.group( 10 ); // took/added/contributed
	string group11= m_stash_put.group( 11 ); // how many
	string group12= m_stash_put.group( 12 ); // what was taken

	string [int] mymap;
	string filename = "myfile.txt";
	file_to_map(filename, mymap);
	if ((group10) == "added")
		{
//		print(group8 + " " + group10 + " " + group11 + " " + group12);
		mymap[count(mymap)] = (group8) + (group10) + (group12);
		}

	map_to_file(mymap,filename);

	file_to_map(filename, mymap);
	string storage_string = "";
	foreach i in mymap {
	storage_string += mymap[i] + " ";
			}
	if (!contains_text(storage_string, group8+"added"+group12))
		print(group8 + " " + group10 + " " + group11 + " "+ group12);
	}
}
 
Last edited:

heeheehee

Developer
Staff member
nit: instead of calling your variables groupN and explaining what they are, why not use descriptive variable names?

Also, you're serializing and deserializing your map with every single loop iteration to work around the fact that your map variable is scoped inside the loop, so it won't persist across iterations.

If I were to do something like this, I'd keep track of a map that's essentially playerid -> (item -> delta). Roughly:
Code:
int [int, item] stash_deltas;
file_to_map("stash.txt", stash_deltas);

matcher m = create_matcher("...", visit_url("clan_log.php"));
while (m.find()) {
  int time = parseTimestamp(m.group(1));
  if (time < get_property("lastClanStashRefresh")) {
    continue;
  }
  if (m.group(3) == "contributed") {
    // Player donated Meat.
    continue;
  }

  int pid = m.group(2).to_int();
  int sign = m.group(3) == "took" ? -1 : 1;
  int qty = m.group(4).to_int();
  item it = m.group(5).to_item();
  stash_deltas[pid, it] += sign * qty;
}
map_to_file(stash_deltas, "stash.txt");

foreach pid, it, delta in stash_deltas {
  if (historical_price(it) > THRESHOLD && delta > 0) {
    // player ${pid} owes ${delta} of ${it}; use get_player_name(pid) to yield something human-readable
  }
}

If I wanted to make this even more robust, I'd consider also indexing by clan ID.
 

heeheehee

Developer
Staff member
That particular map has potential for bloat over time, since I never remove any elements from it. You'd probably also want to add an "if (stash_deltas[pid, it] == 0) remove stash_deltas[pid, it];"
 
Top