Please criticize my search script

philmasterplus

Active member
Update: I've officially released the item search script here.

So I've been working on my inventory killer cleanup script and the IOTM catalog script, and decided that I needed a universal item search script. So after a full week of tinkering, here is my first attempt at ASH scripting.

Now that I've got most of the basics working fine, could you please look at my script for helpful criticism? In particular, could anyone help me with parsing text queries? I can't figure out how to parse and process A-OR-B queries, such as brimstone accessory, stainless accessory, plexiglass accessory

Edit: To clarify, my script tries to do what most item-related CLI commands do--match a query to a specific item. However, instead of trying to find a single exact match, it tries to find multiple matches of an item, so you can specify a class of items--IOTMs, untradeable equipment, etc. This would help scripts like OCD Inventory Control that require a large list of item management rules (right now you have to manually enter each item). Also, it would help accept arbitrary input from the user to evaluate multiple items at once. Of course, to prevent accidental mismatches, the user should be allowed to test the query before actually using it.

At the moment, I want to use this script in my inventory clean-up script and the IOTM catalogue script. Seeing as many scripts handle one or more list of items , I thought it would be neat to allow searching items based on categories and/or flags.
 

Attachments

  • search.ash
    8.2 KB · Views: 21
  • PUtils.ash
    6.1 KB · Views: 28
  • searchsystem_keywords.txt
    681 bytes · Views: 32
Last edited:

fronobulax

Developer
Staff member
Late to the party as usual, but a one or two sentence description of what the script is trying to accomplish might be helpful.
 

heeheehee

Developer
Staff member
You could try...
PHP:
string[int] keys = split_string("brimstone accessory, stainless accessory, plexiglass accessory", ", ")
foreach i in keys {
    // Do whatever you want with the keys here.
}
Also, I'd probably provide a handy alias or have the main function prompt a string for testing purposes. As it is, I'm not entirely sure how to use the script.
 

philmasterplus

Active member
Okay, I edited the first post to explain my purpose in creating this script. If you haven't read it, please do.

Also, to explain in brief what I'm doing: I first defined a record search_system containing the information necessary to evaluate a search.

PHP:
record search_system
{
	boolean [item] items;			//A full list of items handled by a particular instance of search_system
	int [item] prices;			//Where you can store mall prices of the items so as to allow predefined prices
	boolean [item, string] keywords;	//A map of keywords for each item. Takes a large segment of memory, but better than generating it for every search.
	matcher [item] initials_regex;		//Searching for item initials is a bit complex, I only allow exact searches.
	boolean [item] current_selection;	//A list of items that matched the latest search. Better than managing a boolean flag for every item.
};

Then I made several functions that create and interact with an instance of the search_system. Most of these functions accept a search_system as the first parameter and also returns that parameter, so as to allow for chained calls.

PHP:
search_system create_search_system( boolean [item] list );
search_system search( search_system ss , string query );
search_system search_autosell_price( search_system ss , int min , int max );	//Uses autosell_price()
search_system search_mall_price( search_system ss , int min , int max );	//Assumes that the mall prices are correct
search_system update_prices( search_system ss , float price_age );		//Uses historical_price() and mall_price().
search_system reset( search_system ss )						//copies the contents of the items array to the current_selection array.

The basic idea is that, every time a search() or similar function is called, the function checks the query/condition only for the items that exist in current_selection, weeding out any that do not match the criteria. This allows chained searches can be used to "narrow down" a query.
Normally you would create a single search_system using $items[] to register all items, but depending on the script it could start with a specific list of items, so as to improve performance.

PHP:
search_system my_ss = create_search_system( $items[] );

my_ss.search( "gift item" ).search( "off-hand" ).search_autosell_price( 0 , 20 ); //Search for Klaw stuffies
foreach it in my_ss.current_selection
	print( it + " " + it.autosell_price() );

The problem here, as I said above, is that I don't know how to properly incorporate OR-clauses and AND-clauses within the search() function. Right now I do it like this:

PHP:
search_system search( search_system ss , string query )
{
	string [int] query_fragments = query.to_lower_case().split_string( " " );
	foreach index, query_frag in query_fragments
		foreach it in ss.current_selection
			if ( !(
				query_frag.contains_text( it.to_string() )
				|| it.to_string().contains_text( query_frag )
				|| ss.initials_regex[ it ].reset( query_frag ).find()
				|| ss.keywords[ it ].match_keywords( query_frag )
			) )
			remove ss.current_selection[ it ];
	return ss;
}

What a textwall. Thanks for reading, and I'd appreciate any comments.

P. S. Putils.ash is just a collection of various functions that I intend to use in multiple scripts, just like zlib. If you have time, I'd be grateful to have you look at get_shop() and its friends as well.
 
Last edited:

heeheehee

Developer
Staff member
By the way, zarqon and I came up with a little something for take_shop(int i). Okay, fine, I came up with it, and then zarqon improved it like ten-fold. It's similar to what you've got going, except it can take any quantity (also regex-free, so zarqon would actually touch it in the first place). Also, since zarqon's looked over it, it's guaranteed to be fewer server hits than expected. (Minor typo in that post, I think, but it's easily fixed)

Also, a minor tip -- batches should help to cut down on server hits, especially in a function like take_shop_all() (no parameters).
PHP:
        batch_open();
	foreach it in get_shop()
		if ( !take_shop_all( it ) )
			return false;
        batch_close();
 

philmasterplus

Active member
By the way, zarqon and I came up with a little something for take_shop(int i). Okay, fine, I came up with it, and then zarqon improved it like ten-fold. It's similar to what you've got going, except it can take any quantity (also regex-free, so zarqon would actually touch it in the first place). Also, since zarqon's looked over it, it's guaranteed to be fewer server hits than expected. (Minor typo in that post, I think, but it's easily fixed)

Also, a minor tip -- batches should help to cut down on server hits, especially in a function like take_shop_all() (no parameters).

I did look at that thread before, but didn't really like its implementation. I like regular expressions, for one thing, and what I had been intending to make was take_shop_all(). Besides, both mine and zarqon's function makes exactly one request for the shop inventory, and my implementation of get_shop() also interprets purchase limits and prices.

Also, I thought batch_open() and batch_close() only worked when there was a "take multiple" interface available, such as the display case and the closet.

Also also, are regular expressions slow in ASH? I thought they were superior for complex text parsing in general.
 

Veracity

Developer
Staff member
Regular expressions in ASH call straight through to the Java runtime library. They are unambiguously the superior solution for complex text processing.
 

heeheehee

Developer
Staff member
Fair enough, it's only regular-expression free so zarqon would be willing to work with it. Just thought that if you already have functions for taking a certain amount from your shop, you might as well have one for taking a non-preset amount.

Also, regarding batches: forgot that was the case here.
 

zarqon

Well-known member
Regexes are unabashedly superior. This is why they make me nervous. I feel as though at any moment they will match ME and then perform some operation on me.
 

philmasterplus

Active member
An example of "safe regexp usage" for zarqon, as well as blatant explanation and advertisement of item_search.ash:
PHP:
void donate_bats( string forum_post_url )
{
	item_search bats = create_item_search( $items[] ).search( "bat" );
	int zarqons = count( visit_url( forum_post_url ).group_string( "\\bzarqon\\b" ) );
	int [item] send_list;
	
	for x from 1 upto zarqons
	{
		foreach it in bats.current_selection
		{
			if ( item_amount( it ) > 0 )
			{
				print( "Gonna send a " + it );
				send_list[ it ] += 1;
				break;
			}
		}
	}
	
	if ( count( send_list ) > 0 )
		kmail( "zarqon" , "The 847 k1n9 is dead! Long live the 847 k1n9!" , 847 , send_list );	
}
Obviously not tested :)
 
Top