StDoodle's Libray - Another function library

StDoodle

Minion
StDoodle's Function Library v1.3
Requires KoLmafia r9020

Notes on v1.3

No more "unreachable code" warnings (functionally unchanged).

Notes on v1.2

More centralization of clan-management related stuff has taken place. I swear I'll get around to documentation... someday.

Old Intro

Yes folks, it's another function library. Yay! Like Zarqon, I noticed I was re-using a few functions, and thought "hey, whatcha putting the same functions in your scripts over and over for?" (I also talk to myself.)

For this development version, I have only a couple of the functions included. I need to go clear out all of the stuff from other scripts and place them in here if they need to be re-used. It'll happen eventually.

Note: This library script requires zlib.ash. If you're the type of person to want another library script, you probably have it already! ;)

What's inside so far:

string get_csv_property(string property, string setting, [boolean zlib])
void set_csv_property(string property, string setting, string value, [boolean zlib])

Have you ever wanted to avoid using 50 gazillion properties for your script? Ever thought, "hey, it'd be nice to be able to easily save all of these setting / value pairs in a single property?" Well I did anyway...

Using these two functions, you can set and get values corresponding to specific settings to and from a KoLmafia property or a zlib setting. Note that both versions can ommit the zlib boolean and default to using KoLmafia properties. Note that in terms of the parameters above, property is what we usually refer to as "setting" when discussing zlib.

Examples:
Let's say I want to save several values inside of a single zlib "setting" called "std_stupid_stuff".
If I want to set "thing" to "rock" I would use set_csv_property("std_stupid_stuff", "thing", "rock", true);
If I wanted to get the specific value of a setting called "bob" that was saved in a KoLmafia property called "std_misc_stuff" I would use get_csv_property("std_misc_stuff", "bob");

As with the normal get_property() in mafia, attempting to retrieve info that doesn't exist returns a blank string (in this case, if either the property or setting does not exist). Note that additional (private) functions transparently handle url encoding & decoding, so your setting and value can contain the delimiters used in saving to properties without any problems. They also handle checking to see if a value exists when using set_csv_property(), so no worries about having multiple values with the same setting saved in a property.

Important! zlib settings are intended to be controlled by the user only! The use of set_csv_property() with zlib set to true is only intended to be used on the initial run of a script, and as such you should check for the existence of said settings first. If you plan to overwrite existing zlib settings in your script, you must document this clearly to avoid causing a great deal of confusion for script users.

While I personally find the ability to easily access zlib settings with multiple values to be valuable, I won't hesitate to remove this functionality if it becomes a problem for users that could reflect poorly on either this script or on zlib.

void zbatch_open()
boolean zbatch_close()

If you plan to use set_csv_property() with zlib true more than once, call zbatch_open() before hand, and zbatch_close() afterwards, and zlib's updatevars() will only run once, at the end. These functions do absolutely nothing beyond setting a booleanflag called "_batch_zlib_save", so you could easily make use of them if you had another script that changed zlib settings. See notes above regarding best practices for zlib settings.

string compare_versions( string verA, string verA )

This function returns the highest of two version strings, or "" if they're equal, or "error" if one or both cannot be parsed into a version.

Here's a quick summary of how it operates:

1) Looks for the first numerical sequence in each string. These are defined as any series of digits, with any number / type / combinations of separator characters in between them. These are: dot[.] space[ ] dash[-] colon[:] and underscore[_]. ie. in the string "bob 12.4-0x5" it would find "12.4-0"

2) Compares each "section" of numbers as integers. Ie 12 & 4 & 0 would be the integers compared, in order, from the above. At any time, if they aren't equal in the two strings, the string containing the largest is returned. If one string has a longer list of numerical parts than the other, any "missing" segments (trailing) are set to 0. Ie comparing "1.2.3" to "1.2" would compare the latter as if it were "1.2.0"

3) If all of the above are equal, next look for the given keywords (parts in parentheses are optional, either abbreviation or full words accepted): d(ev) or development < a(lpha) < b(eta) < rc or release candidate < f(inal). If a string doesn't contain any of those keywords, it defaults to "final." Return the highest level if not equal.

4) If all keywords are also equal, look for any other section of numbers in the string. Note: it only bothers doing this once, taking the first set of continuous numbers integers (separators ignored this time). Ie in "11.2 alpha 1", this level of comparison would look at "1"

5) Compare the above numbers (again, if only one of the two strings has such a number, assume "0" for the other). Again, return the string corresponding to the largest number found here.

6) If everything is still considered equal at this point, return a blank string. Any extraneous text is simply ignored.

Advantages of using this function:

1) Script authors have the freedom to use a wide variety of formats. You can use a date/time stamp, as longs as the date is in iso format and precedes the time. You can use a major.minor.bug-keyword[keyword build number] format. You can use simple integers. You can prefix your version number with "v".

2) You can change your mind back-and-forth among formats each format, so longs as it evaluates "properly" with the above rules.

3) You can get wacky and call your version "pimped-out 13.69 biotch" if you want, and this will be recognized as being "greater" than "lameass v1.2"

4) Theoretically, a new check_version() could be written to obey a preference that only warns on updates when a certain "level" is given (ie don't warn on dev / alpha / beta / rc) (Sorry zarqon) It's possible to go even further with major / minor / etc, but since a) the script doesn't limit those levels and b) that sounds like more trouble for scripters than it would ever save for users, I wouldn't count on it (but I can see supporting the keyword part)

4-a) (See what I did there...) I suppose it could be possible to have a check_version() that looked for more than one script version in the thread, even, and only reported the "final" version, or a "dev/etc" version if the user was ok with it.

Disadvantages:

1) In order to accept a large number of versioning schemes, I had to draw a line somewhere. Recognizing "1.41" as greater than "1.5" is one of those things that kind of had to give (or ignore lots of other stuff). I know a few scripts on here use such a system, but the up side is that you can simply add another separator; I did similar versioning at times, so that I could use float comparison, but since there's now a more robust way, why not turn those into "1.4-1" or whatever?

2) Lots of regex. While extensive debugging has been done, it is difficult for me to say with absolute certainty that this will work for all situations.

See script comments for additional details as to what it does and doesn't recognize.

string check_version_extended( string software_name, string property, string this_version, int thread )
void check_version_extended( string software_name, string property, string this_version, int thread, boolean in_relay )

This function operates very similar to Zarqon's version, and accepts the same parameters (with the same meaning). However, I've found that I 1) Really dislike the forced wait(), especially in a fight.php override and 2) Wanted the ability to compare version strings, so that my scripts would stop bugging me to upgrade when I'm using a development version. If neither of those bother you, I'd suggest sticking with Zarqon's version; more people have zlib.ash, so why make them get yet another library script?

Note that this script checks for script version and KoLmafia revision in the same format as zlib.ash, plus it checks for an additional format of "<font size=\"1\">Requires KoLmafia r(\\d+?)</font>" for KoLmafia revision. (Added backwards-compatability in v1.0a2)

Also note, there is a slight difference between the text returned under some circumstances between my version and the zlib.ash version. Notably, the classes permit a small amount of greater flexibility and code reuse in styling; however, it is doubtful this will be of interest to most people, and should remain backwards compatible for most cases.

The second version is the same as the first, except it will pass the string either to write() if in_relay is true, or vprint_html() (with a verbosity threshold of 1) if false.

boolean boolean_modifier( string name, boolean use_spec )
float numeric_modifier( string name, boolean use_spec )
string string_modifier( string name, boolean use_spec )

Overloaded versions of the modifier functions that can meaningfully use "_spec" to allow for functions in my fight scripts that can have the same logic whether they're being called from a current fight, or from a "let's see" script (haven't got that far yet, but will eventually be useful).

float std_eval( string expression, float [string] values )

Identical to zlib's eval(), save for using expression_eval() in place of modifier_eval(). I ran into a case where the former supported something the latter didn't... if I could just recall what that case was, I'd list it here!

string iso_date( string raw )

Takes a string in a format such as "Dec 12, 2012" and returns an ISO-style string, such as "2012-12-12"; for doing comparisons on dates as found in KoL text. Will probably extend to a full date pseudo-class eventually.

void relay_abort( [string msg] )

For sending the abort message to a relay browser screen. First uses write() to print the message to the relay browser with a class of "abort," then abort()'s. Can omit the string parameter to use the standard "KoLmafia declares world peace." message, though I don't recommend doing so.

record clan { string name; int id; }
string get_clan_name()
int get_clan_id()

Bale isn't the only one who's used this; I have it in quite a few scripts myself, and figured it was about time to put it in a library. Note: These functions hit the server every single time they are called; so if you're going to use the info more than once in a script, please call them at a high level and assign to globals.

void library_script_main()

Simply aborts the script with the message "This is a library script! It does nothing on its own and is intended to be imported in other scripts." I got tired or remembering what exact message I'd used in several imported scripts.
 

Attachments

  • std_lib.ash
    31.3 KB · Views: 324
Last edited:

Veracity

Developer
Staff member
I love it. "std_lib". Where, we assume, "std" is "StDoodle", although it COULD be "standard" or "sexually transmitted disease". :)
 

StDoodle

Minion
Heh, I'm a drafter, so in my field, it usually means "standard." However, in Hardcore Nation, it's usually taken to mean the other definition. ;)

But yeah, I started abbreviating a few script-related settings and names as "std" a while ago, because of that triple-meaning.
 

zarqon

Well-known member
Wow, you're giving this away for free? Much cheaper than this one!

What does expression_eval() support that modifier_eval() doesn't? That function didn't exist when I added eval() to ZLib, and I'd prefer to keep it as widely functional as possible.
 

StDoodle

Minion
I really wasn't kidding in the original post... I ran into a case where expression_eval() worked and modifier_eval() didn't, but can't for the life of me remember what it was...

Of course, it was something I was using in a test script, which I no longer have. But I remember thinking "hmm, this could be an issue in the fight script..."
 

gncc

New member
utc_offset does not work for me. most likely it is my fault somehow, but it was reproduced elsewhere.
so either way, here's what i am experiencing:

the regexp in line 681 ("\\b(\\+|\\-)?(\\d{1,2})\:(\\d\\d)\\b") does not give the expected result.
group 1 is always an empty string -- if i am right, this is because the dash is not a word character, that is neither + nor - are word borders. changing \\b to a caret ("^(\\+|-)?(\\d{1,2})\:(\\d\\d)\\b") fixes the problem for me.

also, i think the "-" does not have to be escaped outside of sets. as far as i can see it does not change anything here, threw me off the scent though.
 
Last edited:
Top