Visit_url()

The following piece of code is actually just a snippet I wrote up real quick for an example. It logs the amount of 2 specific items in my store to a file.

Code:
 mmbquant = shop_amount($item[meat maid body]);
 gaquant = shop_amount($item[Gnollish autoplunger]);
 cli_execute("mirror " + filename);
 print("Gnollish autoplunger=" + gaquant);
 print("meat maid body=" + mmbquant);
 cli_execute("mirror");

Now each time this script would be run = 2 server hits. If it were that simple, I'd go with it, however I want to log several items instead of just 2. Fact is I don't care to log thos items, they were just a copy/paste. I do however want to log maybe a hundred or more other items, and that to me is way too many server hits.

I would like to use visit_url() to obtain all the information in just 1 server hit, but the only information so far I can find that would relate is the following:

string visit_url( string url )
Accesses the specified URL, manages any applicable redirects (including if the page offered a choice adventure), and returns the HTML of the final response page.

boolean contains_text( string source, string query )
Reveals if the query string is a substring of the source string.

Are there more functions for manipulating strings returned by visit_url()? If so, could someone point me towards information about them, and how to use them?
 

Nightmist

Member
We also have a
Code:
string substring( string Text, int StartFrom)
string substring( string Text, int StartFrom, int EndAt)

You could just store the HTML returned by hitting your store manager in a string var and then reuse that to check for each item... (With the substring command it allows it quite well)

Edit: Fixed some typo's...
 

Veracity

Developer
Staff member
I'd suggest you also look at index_of(), which came in when substring() did.

Code:
int index_of( string source, string search ) 
int index_of( string source, string search, int start ) 
string substring( string source, int end ) 
string substring( string source, int begin, int end )

index_of() lets you find where your desired text starts in the string returned by visit_url() and substring() lets you trim down the string to focus in on that area of the text.
 

holatuwol

Developer
In addition to the functions Veracity mentioned, v8.9 adds the following functions to your list of abilities to locate strings (I'll add them to the wiki in the middle next week, if nobody else adds them):

int last_index_of( string source, string search )
int last_index_of( string source, string search, int stop )
string replace_string( string source, string search, string replace )

Also included are some regular expression type functions that I use a lot in developing KoLmafia's internal functions.  The first splits a string, using the given regular expression as a delimiter.  It uses Java's built in regular expression handler, not PERLs, so be careful when you're writing scripts.

FS: string [int] split_string( string source, string regex )
EX: string [int] test = split_string( "Hello4world", "\\d" );

The above function call will split the string into two strings, "Hello" and "World" which will be returned in a mapping that closely resembles an array (actually, it is an array, which only exists as an internal data type, and may throw array-index-out-of-bounds exceptions, so be careful.

Another useful one is grouping things by regular expressions.  The function signature is as follows (oh, right, "FS" means "function signature" and "EX" means "example"):

FS: string [int,int] group_string( string source, string regex )
EX: string [int,int] test = group_string( "This is a test", "([a-z]+) " );

If you understand regular expressions, then you'll be able to use this feature really easily. If not, then it'll be a little complicated because you need to learn regular expressions first.  After understanding regular expressions, the above function generates a map with the following key-value pairs:

test[0][0] => "his "
test[0][1] => "his"
test[1][0] => "is "
test[1][1] => "is"
test[2][0] => "a "
test[2][1] => "a"

That's more or less it as far as string parsing goes.  There's a few other functions that were added along the way, including:

float square_root( float value )
monster [int] get_monsters( location l )
 
Hey thanks everyone! Now I got some work to do!

Hmm, this is the first sign I have seen of overloaded functions in kolmafia. Do I have the ability to write overloaded functions into a script also?

Edit: In my studying and preparing to write, I came up with another small question. Is there a function available which returms the length of a string?
 

Nightmist

Member
[quote author=efilnikufecin link=topic=451.msg2236#msg2236 date=1158929920]
Edit: In my studying and preparing to write, I came up with another small question. Is there a function available which returns the length of a string?
[/quote]
I don't think there is. I was about to request it before but I found a workaround for what I was doing, (Searching for a item, save the index_of and then use another index_of for the HTML thats after the number by making it only start searching from the starting index_of, this gives you a "start" and "end" which you can substring and then usually further cut down to whatever you want, although this is from my KMail parsing so I'm not entirely sure if the same tactic would work for what your trying to do)

But all of that aside, a len( string) (Heh yeah... the excel name for it) would be nice though if your passing it to search a item and you want for it to set the index to the end of the name, unless "last_index_of()" does that since I haven't actually messed around with that but I always just assumed it returned the last instance of a string rather then the first. (since the item name would have variating length you cant just use a simple +number after it.)
 

holatuwol

Developer
I think it's because of some code centralization that I did in order to make sure that KoLmafia never double-parsed things, which resulted in store management being on the list of restricted URLs.


KoLmafiaASH.java

Code:
		public ScriptValue visit_url( ScriptVariable string )
		{
			String location = string.toStringValue().toString();
			if ( KoLRequest.shouldIgnore( location ) )
				return STRING_INIT;

			boolean wasChoice = location.indexOf( "choice.php" ) != -1;

			KoLRequest request = new KoLRequest( getClient(), location, true );
			request.run();

			if ( !wasChoice && request.getURLString().indexOf( "choice.php" ) != -1 && getBooleanProperty( "makeBrowserDecisions" ) )
				request.handleChoiceResponse( request );

			StaticEntity.externalUpdate( location, request.responseText );
			return new ScriptValue( request.fullResponse == null ? "" : request.fullResponse );
		}



KoLRequest.java

Code:
	private boolean shouldIgnoreResults()
	{	return shouldIgnore( formURLString ) || formURLString.startsWith( "messages.php" );
	}

	public static boolean shouldIgnore( String formURLString )
	{
		return formURLString.startsWith( "mall.php" ) || formURLString.startsWith( "searchmall.php" ) ||
			formURLString.startsWith( "clan" ) || formURLString.startsWith( "manage" ) || formURLString.indexOf( "chat" ) != -1;
	}
 
I see now after some confusion that this has been changed.
The following:

Code:
cli_execute("mirror test.txt");
print(visit_url("managestore.php"));
cli_execute("mirror");

Makes quite a mess out of things in the cli, carriage returns seem to be inserted all over the place in the output file and so on, but over all I can manage to work it out with time...time to get busy!!! :)
 

Nightmist

Member
It would probably be alot easier if you just opened up a "view source" window of "managestore.php" and work from there.
PS. If you want any help feel free to ask, my K-Mail parser is pretty much been put on "hold" until I find a use for it and so a store manager price finder might be a interesting little project. Your just trying to find the prices of the items you already have in store right?
 
actually I am after the quantity of the item. I'm writing to a file in csv format so I can open with a spreadsheet program for later parsing. It's hard to explain in full detail what I am going for, but I will be saving a data map, and then later comparing the saved data to the current. and building another data map showing the difference, then parsing that one into csv format...I think I explained that right.
 

Nightmist

Member
Uhhh so... *brain implodes* Uhhh could you just give me the layout of the data map?
Code:
Name=Qty
Name=Qty
Name=Qty
Name=Qty
 
Code:
record store_data_type {
 int stock_amount;
 int Limit;
 int Price;
};

store_data_type [item] store_data;

but I'm not sure that I have the exact format right. In the past hour I've managed to spend all of about 30 seconds on it because I keep doing other things.

It's an array of records.

Some of the work I had previously done on it was:

Code:
string[int] tables;

void ParseTables(string source)
{
int count = 1;
string temp = source;
while(contains_text(temp, "<table>"))
 {
 tables[count] = substring(temp, index_of(temp, "<table>"), index_of(temp, "</table>") + 7);
 replace_string(temp, tables[count], "");
 count = count + 1;
 }
}
which is supposed to take the tables out of the http response, then I was going to go from there. If I remember right, it was the second table I would be looking at, and there are 3 tables total.

I was also planning for re-usable functions wherever possible "ParseTables" was just such a function.

looking at the second table by default doesn't quite fill the bill for me though. Instead I planned on a function determining which table was the correct one. When I start writing it generally winds up being rather complex.
 

Nightmist

Member
*Continues to be lost*
Ummm... I'm really bad at understanding you, (Self taught at computer stuff so knowledge = limited). >> Uhh well I edited my script to just print out
Code:
ItemName=ItemQty
And it shouldn't be too hard to change it around and add other things to print out such as the ItemLimit and ItemPrice. I'm really just looking for the order to print them out in and in what way (Such as use a "=" sign to separate or a ","?)
 
oh you mean the output file? Well the format would be:
Code:
itemname,int1,int2,int3
itemname,int1,int2,int3
csv=comma seperated values

itemname is the name of the item, int1=quantity, int2=price, int3=limit


When you asked for the layout of the data map I thought you meant inside the script. Note no spaces where the comma seperates the values. This is key because when excel converts the csv file to xls format if there is a space it will interpret it as a string. If there is not, Excel will interpret it as an integer.

OK let me put together what my plan is...
first re-load the previous datamap, then build a second datamap from the stores current inventory, then compare the 2, and write the difference to a file in .csv format, then save the datamap which was built from the current inventory to a file (the same file we loaded before) so as to be able to run the same comparison again later.
 

Nightmist

Member
Messy and it lacks any comments but you should be able to follow it pretty easily.
 

Attachments

  • Store.ash
    1.3 KB · Views: 74
print( "No items in store.");

I so wish that would happen!!! At the price I have set for them there are 287,200,000 meat worth of tortoise's blessings in my store alone!

anyway, I can follow it well, and it will be easy to modify so as to push the data into an array first, and do the comparison. I was modifying my last message while you were posting your last message.

Thanks! You saw a way to handle it which was far simpler than what I was seeing.
 

macman104

Member
Your array of records is formatted correctly. One thing, you are starting count at 1? The index starts at Tables0] not Tables[1].

So you'll access your records as like: store_data[item].stock_amount, store_data[item].limit, and so on.

What does replace_string do, is that a function of your own?

Other than that, it looks fine.
 
I've made the introduction of replace_string bold in the following quote. It was introduced here in this thread.

[quote author=holatuwol link=topic=451.msg2235#msg2235 date=1158914637]
In addition to the functions Veracity mentioned, v8.9 adds the following functions to your list of abilities to locate strings (I'll add them to the wiki in the middle next week, if nobody else adds them):

int last_index_of( string source, string search )
int last_index_of( string source, string search, int stop )
string replace_string( string source, string search, string replace )
[/quote]

As for indexing, I start at 1 for no good reason at all other than just habit. If you count 4 items starting at 0 you will come up with 3. If you count them starting at 1 you will come up with 4. The way shown is totally the wrong way, but I would have caught it later when things didn't work as planned.
 

Nightmist

Member
Looking back through this thread I noticed the request for a "Length of string" function.
Code:
int Len( string TheString)
{
 int Counter;
 while( substring( TheString, Counter) != "")
 {
  Counter = Counter + 1;
 }
 return( Counter);
}
Hahah, yeah it might lag when you have huge++ strings but it works for most people.
 
Top