Bug - Fixed Buy() function incorrectly claims successful purchase on buying from store that raised limit today

katyarn

Member
If a store raises a limit (or you previously bought less than the limit), for example 1/day to 2/day, and you have already purchased 1, buy(k, item, priceLimit); where k >= 2 will state that it purchased 2 items from the store. In reality, KoL returns an error that you have already bought 1 and you will receive 0 of the item. KoLMafia should retry, using that returned value and instead buy up to limit - value.

The KoL response is:
You may only buy 2 of this item per day from this store. You have already purchased 1 in the last 24 hours.
 
Last edited:

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
Looked briefly into the code, it is at least trying to handle this. This sounds expensive to test :p
 

heeheehee

Developer
Staff member
gausie -- this line?

Bash:
$ rg 'may only buy'
src/net/sourceforge/kolmafia/request/MallPurchaseRequest.java
28:          "You may only buy ([\\d,]+) of this item per day from this store\\.You have already purchased ([\\d,]+)");

feels like there's a missing space after the period
 

gausie

D̰͕̝͚̤̥̙̐̇̑͗̒e͍͔͎͈͔ͥ̉̔̅́̈l̠̪̜͓̲ͧ̍̈́͛v̻̾ͤe͗̃ͥ̐̊ͬp̔͒ͪ
Staff member
well! that's a good spot
 

Veracity

Developer
Staff member
Yeah. I got a log and, sure enough, KoL has a space in there.

I added the space and looked at the mall stores with disassembled clovers.

12,338 limit 2 @ 200
649 limit 1 @201

I bought one from the shop and logged out and exited KoLmafia. (clearing cached mall prices)

Session log:

Code:
mall.php?category=allitems&consumable_byme=0&weaponattribute=3&wearable_byme=0&nolimits=0&max_price=0&sortresultsby=price&justitems=0&x_cheapest=5&pudnuggler=%22disassembled+clover%22
mall.php?category=allitems&consumable_byme=0&weaponattribute=3&wearable_byme=0&nolimits=0&max_price=0&sortresultsby=price&justitems=0&x_cheapest=0&pudnuggler=%22disassembled+clover%22

buy 1 disassembled clover for 200 each from shop #1799392 on 20211219
I logged in and tried this:

Code:
> ash buy(2, $item[disassembled clover], 200)

Searching for "disassembled clover"...
Search complete.
Purchasing disassembled clover (2 @ 200)...
Purchasing disassembled clover (1 @ 200)...
Desired purchase quantity not reached (wanted 2, got 1)
Returned: 1

Session log:

Code:
mall.php?category=allitems&consumable_byme=0&weaponattribute=3&wearable_byme=0&nolimits=0&max_price=0&sortresultsby=price&justitems=0&x_cheapest=5&pudnuggler=%22disassembled+clover%22
mall.php?category=allitems&consumable_byme=0&weaponattribute=3&wearable_byme=0&nolimits=0&max_price=0&sortresultsby=price&justitems=0&x_cheapest=0&pudnuggler=%22disassembled+clover%22

buy 2 disassembled clover for 200 each from shop #1799392 on 20211219

buy 1 disassembled clover for 200 each from shop #1799392 on 20211219

I'll submit a PR that adds the missing space to the message.
 

Veracity

Developer
Staff member
Regarding a store that raises its limit:

KoLmafia caches the results of a mall search. So, if you buy an item and later (in the same session) buy another of the same item, KoLmafia will not do another search. As of recently, KoLmafia will also update cached results to account for your purchase vs. store limits. These cached results are cleared when you log out, so if you log in again with a new session, we'll be able to notice that a (limited) store is still available to purchase from, and this fix (the missing space) will kick in and you'll be able to buy another item from the store.

Caching allows multiple purchases without having to do a mall search for each one - at cost of not noticing changed prices or changing inventories. We do timestamp each mall search and internal methods allow you specify how new a mall price must be before we do a new search. "acquire" generally insists on less than 7 days old.

I'm experimenting with adding ASH function int mall_price( item, float maxAge ), where maxAge is the (fraction) of a day that is allowed. 0 will force a new mall search to update the cached search results.
 

Veracity

Developer
Staff member
Code:
> ash mall_price( $item[ disassembled clover ] )

Searching for "disassembled clover"...
Search complete.
Returned: 2995

> ash mall_price( $item[ disassembled clover ] )

Returned: 2995

> ash mall_price( $item[ disassembled clover ], 0 )

Searching for "disassembled clover"...
Search complete.
Returned: 2995

> ash mall_price( $item[ disassembled clover ], 0 )

Searching for "disassembled clover"...
Search complete.
Returned: 2995

> ash mall_price( $item[ disassembled clover ] )

Returned: 2995
The new ASH function works fine. But I changed an existing core function which is called in a handful of other places. I need to make sure that those places are still hunky dory.
 

ereinion

Member
I'm experimenting with adding ASH function int mall_price( item, float maxAge ), where maxAge is the (fraction) of a day that is allowed. 0 will force a new mall search to update the cached search results.
Heh, I was going to ask if historical_price wasn't already doing this, but it turns out what I was doing in my scripts was

Code:
int get_price(item item_to_check, float acceptable_age) {
	return ((historical_age(item_to_check) <= acceptable_age)? historical_price(item_to_check) : mall_price(item_to_check));
}

Soooo.... Just posting for posting's sake, I guess >_>
 

Veracity

Developer
Staff member
Revision 26057 adds that ASH function: int mall_price( item it, float maxAge )
I think that's all we can do for this bug report.
 
Top