Mini Macro Challenges (Interest)

Discuss macro implementations, ask for macro help (to share your creations, see User Creations, probably either Campaign Frameworks or Drop-in Resources).

Moderators: Azhrei, dorpond, trevor, giliath, jay, Mr.Ice

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Mini Macro Challenges (Interest)

Post by aliasmask »

I'm just wondering about interest if I were to present some macro coding challenges if there would be anyone (other than me) who would do them?

I just got an interesting question and I thought it would be a good learning experience for those new to MT coding.

Question
Take a comma separated list of names and convert to a plain English version, for example:

[H: list = "Alice, Bob, Charlie"]

converts to output as:

Alice, Bob and Charlie


There are several ways to do this, but as an exercise, how would you do this? I recommend wrapping your answer in a spoiler for those who would try the challenge for themselves.

If you like this I can do more.

digiacom
Cave Troll
Posts: 31
Joined: Thu Sep 27, 2018 3:00 am

Re: Mini Macro Challenges (Interest)

Post by digiacom »

Like this? I like the idea - I love small coding challenges :)
Spoiler

Code: Select all

/self
[h: list = "Alice, Bob, Charlie"]
[h: assert(listCount(list), "Nobody here!", 0)]
[r, if(listCount(list) > 1): 
	listDelete(list, listCount(list) - 1) + " and " + listGet(list, listCount(list) - 1); 
	list]
a.k.a. Melek on Discord.
Check out my Simple 5e Framework!

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

Yep, good example. I could think of at least 3 conceptional ways to do the challenge and this is one of them. Although, your example is a bit of a hybrid of method 1 and 2.

digiacom
Cave Troll
Posts: 31
Joined: Thu Sep 27, 2018 3:00 am

Re: Mini Macro Challenges (Interest)

Post by digiacom »

This is also a fun solution, though I admit my understanding of the regex is shaky:
Spoiler

Code: Select all

[h: list = "Alice, Bob, Charlie"]
[replace(list, "(,)(?!.*,)", " and")]
a.k.a. Melek on Discord.
Check out my Simple 5e Framework!

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

Yep, using regex is method 3 and is probably the most efficient method.

So, to recap method 1 is to use list functions to remove the last item, insert "and" and add the last item back.
Method 3 is to replace the last comma with " and" using regex.

Method 2 is use string functions like lastIndexOf and substring to get the stuff before the , add the "and" and then add the stuff after.

Can you guys think of any other methods? Maybe strfind, but replace() is essentially the same thing.

User avatar
wolph42
Deity
Posts: 9708
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Mini Macro Challenges (Interest)

Post by wolph42 »

ah so here came the solution to my question from :D smart letting other do the work...o wait, that's what I did!

Note that the regex solution was used in the latest dev of this: viewtopic.php?p=276106#p276106

bubblobill
Cave Troll
Posts: 97
Joined: Sun Jan 24, 2010 3:07 pm

New Mini Macro Challenge

Post by bubblobill »

Coding challenge:

Given

Code: Select all

[h: '<!-- get current MapTool version -->']
[h: versionRaw=lower(json.get(getInfo('client'), 'version'))]
<!-- missing bit -->
[r: macro.return=version]
Complete the missing bit.
Allow for "a", "b", "Alpha", "Beta", "rc" and who knows what else can be in there;
Return a valid decimal that will rank any and all releases in order.

Use Case:

Code: Select all

[h: dVer=getVersion()]
[h, if(dVer<1.6), code:{};{}]
Ideal answer should cope with every MapTool release.

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

If version 1.6 is 1.6, then what is 1.6 alpha 1.. The only value that comes before 1.6 is 1.5... which wouldn't be a good check. I would say any dev version rc, alpha, beta wouldn't/shouldn't even be checked for. So, having any post script of rc, alpha, beta would default to the previous stable version, so version -0.1?.

Also, given that 1.5.13 was a thing, but not a valid number I would suggest removing the 2nd decimal and anything after a 2nd decimal would be forced to 2 digits, so 1.5.1 would be before 1.5.10.

There's not an easily accessible dynamic way to track version releases with either, so there's no telling what the actual last stable version of 1.6 alpha 1 was other than using the base 1.5 value. You wouldn't want to skip over versions by something like changing the alpha version to 1.599 (last pre 1.6 alpha possible). And making it 1.5 wouldn't actually be accurate seeing how features may change which is probably the whole reason for this exercise.

One way to handle it is to just have a list of all the released versions at the time of creating the code. Anything not in the list is a future version and would assumingly be compatible. So, instead of a numeric value, just test version like versionCheck("1.6") and it'll return 0 (current version before 1.6) or 1 (1.6 or later).

Gathering an accurate list of the versions would be the real challenge.
Spoiler
But converting to a number I would probably convert 1.#b# to 1.##, so 1.3b69 would be 1.369 and then ignore anything after other than to note to subtract 1 version given "rc","alpha" or "beta" being present. Regex may look something like this:

[H: regex = "(\d[.]\d+)(b|[.])(\d*)(.*)"]

Group 1 holds the main version 1.3 and beyond. We ignore group 2 and then add group 3 as a 2 digit number where "" is 00. The last group would be checked for one of the key words. Then a table would be reference against the current version to get your result and adjusted accordingly.

Again, the only reason to have a table to check against is because of the rc, alpha... releases because they represent the version before their release. If you ignore that, then using just a number would work just fine.

bubblobill
Cave Troll
Posts: 97
Joined: Sun Jan 24, 2010 3:07 pm

Re: Mini Macro Challenges (Interest)

Post by bubblobill »

Since my use case is to workaround bugs in various releases including alpha, beta, & release candidates, your assumptions do not work for me.

My thoughts were to;
pad the versioning to two digits
1.5.1d beta-rc -> 01.05.01d beta-rc
replace
"alpha" with 00, "beta" with 01 "rc" with 02
01.05.01d beta-rc -> 01.05.01d 01-02
non-word "a"-"z" with 01-26
01.05.01d 01-02 -> 01.05.0104 01-02
strip all irrelevant characters
01.0501040102

Which is why I would like to see someone achieve it in a clever and less painful fashion.

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

Having a release list, imo, would be the simplest method. Instead of a made up number, you use the actual release string and it checks the list.

On another subject, I was thinking about what would be the easiest way to update a lib token for someone not really familiar with the ins and outs of MT. One scenario I often see is they drop a new token on them map, it gets renamed, they delete the original token and things don't work because of name change. Users can also put tokens on wrong layer, lose saved data on original token, so the plan is when the token is dropped it would update the original token, be able to check for custom modifications and save to a .bak version or not change if not one of the macros being updated, then delete itself.

bubblobill
Cave Troll
Posts: 97
Joined: Sun Jan 24, 2010 3:07 pm

Re: Mini Macro Challenges (Interest)

Post by bubblobill »

So how does one get the up-to-date release list programmatically?

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

My thought is to have a list somewhere like github and when a new build is made it updates that list. I'm not sure of the build process and how it gets uploaded to github, but it would be ideal if the list is updated at this point. Then maybe use the REST api to get that list? Or maybe have it built in to MT at that point?

But outside of that ideal way, someone will have to install each version since 1.3b69(?) and load a campaign with a lib token that spits outs the version string to be manually put in to a file or automatically added to a property (lib tokens will need to use a defer to do this without duplicating token) and build your list that way.

User avatar
wolph42
Deity
Posts: 9708
Joined: Fri Mar 20, 2009 5:40 am
Location: Netherlands
Contact:

Re: Mini Macro Challenges (Interest)

Post by wolph42 »

new one!

I have some ideas about this but Im curious how others would approach this and its generally a useful function.

Given a certain area, you have a configuration of token (images) on all layers and you want to move this entire configuration somewhere else.

You could use copy paste, but given the fact that it on multiple layers, that would be an annoying hassle. So how would you do this?

User avatar
aliasmask
Deity
Posts: 8579
Joined: Tue Nov 10, 2009 6:11 pm
Location: Bay Area

Re: Mini Macro Challenges (Interest)

Post by aliasmask »

I think the main challenge is how you select your area. You can use vbl or manually put in the dimensions based on a source token. Rather than using the area option for getTokens I would stick with distance (radius) and just change the metric to 1:1 so it forms a square. For non-square areas you can then loop through to check if token is still in bounds. Then again, maybe the area option is better than it was (so slow before), but I haven't really messed with it in a long time and not since some optimization updates.

One issue I can see is if a large image falls within the area you want but it's footprint is outside. I know there are some functions that use the stamp to determine if it's in a square (not the footprint), but I would need to look in to that. Then there are those instances where you don't want to include that larger image, say if it has a large transparent area that's in your area, but doesn't effect your capture area. I guess you could always just delete those after the fact.

I think my preferred method would be to drop a token in to the viewable area, after changing the zoom to 1:1, which is much easier now with some of the newer functions. This token will have the macros needed to mark the upper left and lower right corners of your area and "copy" your area. Then you can cut/copy paste that token to the new area/map, then paste it. The token image will be an arrow pointing to a corner. When done, click "done" macro and it will delete that token.

bubblobill
Cave Troll
Posts: 97
Joined: Sun Jan 24, 2010 3:07 pm

Re: Mini Macro Challenges (Interest)

Post by bubblobill »

Faster to get either all tokens or all tokens in range and cull the results than to generate an area for use in getTokens().

Of course if this is Innteresting, you could cull all ids that have a space in their name.

Depending on if moveTokenFrom() & moveTokenToMap() preserve the original layer, this could be a very short loop indeed.
Barring that, good old copyToken() can be run on the target map once you have your ids.

Post Reply

Return to “Macros”