It is currently April 27th, 2024, 12:34 pm

Splitting measure string

Get help with creating, editing & fixing problems with skins
User avatar
Cerberus9
Posts: 2
Joined: February 27th, 2024, 9:32 pm

Splitting measure string

Post by Cerberus9 »

Hello!

I have now google'd out my eyes already, but I'm still not able to find a solution...

I have a json, which I parsed:

Code: Select all

[MeasureWinning]
Measure=WebParser
URL=file://#CURRENTPATH#data.json
RegExp=(?siU)Winnings":"(.*)".*WinningNumbers":"(.*)"

[WinningNumbers]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=2
In the WinningNumbers I have 7 numbers which I want to display separately.
This is how the output looks now:

Code: Select all

9, 10, 33, 54, 75, 84, 98
I have already made a template and I want to display the numbers at certain places (without the commas).
I tried substituting and using some regexp too, but I just couldn't get out values, can I get some hint on this one?

At the moment I just output the whole string:

Code: Select all

[WinningNumbersOut]
Meter=STRING
String=WinningNumbers
FontFace=#FontName#
FontColor=#FontColor#
FontSize=#FontSize#
AntiAlias=1
StringAlign=right
X=365
Y=35
RicardoTM
Posts: 268
Joined: December 28th, 2022, 9:30 pm
Location: México

Re: Splitting measure string

Post by RicardoTM »

Can you share the skin package (including the json file) so I can take a look?
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5407
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Splitting measure string

Post by eclectic-tech »

Yes, an accurate copy of the json file would be helpful...

If the return is exactly as you posted, then you should be able modify the RegExp and capture each number in a separate stringindex and then use in any meter.
Note: The RegExp was made NOT greedy (the "G" was removed) and each number is captured in a separate index; the data must have 7 numbers, each be separated by a comma and a space, or the expression will fail.
The finish action updates the meter after the data is captured.

Code: Select all

[MeasureWinning]
Measure=WebParser
URL=file://#CURRENTPATH#data.json
RegExp=(?si)Winnings":"(.*)".*WinningNumbers":"(\d+),\s(\d+),\s(\d+),\s(\d+),\s(\d+),\s(\d+),\s(\d+)"
FinishAction=[!UpdateMeter *][!Redraw]

[WinningNumber1]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=2

[WinningNumber2]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=3

[WinningNumber3]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=4

[WinningNumber4]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=5

[WinningNumber5]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=6

[WinningNumber6]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=7

[WinningNumber7]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=8

[Meter]
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber1
MeasureName2=WinningNumber2
MeasureName3=WinningNumber3
MeasureName4=WinningNumber4
MeasureName5=WinningNumber5
MeasureName6=WinningNumber6
MeasureName7=WinningNumber7
Text=Num1: %1#CRLF#Num2: %2#CRLF##CRLF#Num3: %3#CRLF#Num4: %4#CRLF##CRLF#Num5: %5#CRLF#Num6: %6#CRLF##CRLF#Num7: %7
7numbers.jpg
If this does not work, please post a complete package. :)
You do not have the required permissions to view the files attached to this post.
User avatar
Yincognito
Rainmeter Sage
Posts: 7175
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Splitting measure string

Post by Yincognito »

Eclectic-tech already described how to do this right from the WebParser regex pattern, but you can do it afterwards as well, using your original code, via substitutes, e.g.:

Code: Select all

[MeasureWinning]
Measure=WebParser
URL=file://#CURRENTPATH#data.json
RegExp=(?siU)Winnings":"(.*)".*WinningNumbers":"(.*)"
FinishAction=[!UpdateMeasure *][!UpdateMeter *][!Redraw]

[WinningNumbers]
Measure=WebParser
URL=[MeasureWinning]
StringIndex=2

[WinningNumber1]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\1"
DynamicVariables=1

[WinningNumber2]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\2"
DynamicVariables=1

[WinningNumber3]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\3"
DynamicVariables=1

[WinningNumber4]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\4"
DynamicVariables=1

[WinningNumber5]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\5"
DynamicVariables=1

[WinningNumber6]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\6"
DynamicVariables=1

[WinningNumber7]
Measure=String
String=[WinningNumbers]
RegExpSubstitute=1
Substitute="(?U)^(.+),(.+),(.+),(.+),(.+),(.+),(.+)$":"\7"
DynamicVariables=1

[Meter1]
Y=0
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber1
Text=%1

[Meter2]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber2
Text=%1

[Meter3]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber3
Text=%1

[Meter4]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber4
Text=%1

[Meter5]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber5
Text=%1

[Meter6]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber6
Text=%1

[Meter7]
Y=0R
SolidColor=0,0,0,1
Meter=String
MeasureName=WinningNumber7
Text=%1
The (?U) stands for ungreedy matching, aka match as few chars as possible. I used + instead of * in the substitutes to avoid Rainmeter giving back the literal \N when that capture is empty. Didn't account for spaces since by default, String meters trim leading and trailing spaces in the Text option, but you can easily account for them in the substitutes, if desired.

Notice that, for this to work, you have to update the relevant String measures / meters and redraw the skin in the FinishAction from the main WebParser (I used * aka all of the same kind, for simplicity), so that data retrieval triggers the extraction of such numbers from the aggregate string.

P.S. Neither the variant from eclectic-tech nor mine account for the (unlikely, but still) possibility that the winning numbers part from the site is something else, e.g. less than 7 numbers, empty, or containing some other message if data is not available, so typically you'll have to use (?(?=<patterntofind>)<patterntomatch>) lookahead assertions if that's the case.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
RicardoTM
Posts: 268
Joined: December 28th, 2022, 9:30 pm
Location: México

Re: Splitting measure string

Post by RicardoTM »

I'm just a beginner when it comes to regex, so, what if you don't know how many numbers are there? Is it possible to do something like what the fileview plugin does? Like, capture any amount of numbers and just change the index directly on the meter to scroll through them? Like, you just want to display 5 at a time so you only have 5 child measures, and scroll through any index number at will.
User avatar
Yincognito
Rainmeter Sage
Posts: 7175
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Splitting measure string

Post by Yincognito »

RicardoTM wrote: February 28th, 2024, 6:21 pm I'm just a beginner when it comes to regex, so, what if you don't know how many numbers are there? Is it possible to do something like what the fileview plugin does? Like, capture any amount of numbers and just change the index directly on the meter to scroll through them? Like, you just want to display 5 at a time so you only have 5 child measures, and scroll through any index number at will.
Yes, this is possible for any string. For example (in the comment you have the simplest form, without other adjustments, for clarity):

Code: Select all

[Variables]
Table=9, 10, 33, 54, 75, 84, 98
Start=0
Count=3
Piece=(?:.+,)

[Rainmeter]
Update=1000
AccurateText=1
DynamicWindowSize=1
BackgroundMode=2
SolidColor=0,0,0,255

---Measures---

[Group]
Measure=String
String=#Table#,
RegExpSubstitute=1
;Substitute="(?siU)^#Piece#{#Start#}(#Piece#{#Count#}).*$":"\1"
Substitute="(?siU)^(?:#Piece#{#Start#}(#Piece#{0,#Count#}+).*|.*+)$":"\1","^\\1$":""
DynamicVariables=1

---Meters---

[Result]
Meter=String
FontFace=Consolas
FontSize=16
FontColor=255,255,255,255
AntiAlias=1
MeasureName=Group
Text=Table = #Table##CRLF#Start = #Start##CRLF#Count = #Count##CRLF#Group = %1
MouseScrollUpAction=[!SetVariable Start (#Start#+1)][!UpdateMeasure *][!UpdateMeter *][!Redraw]
MouseScrollDownAction=[!SetVariable Start (#Start#-1)][!UpdateMeasure *][!UpdateMeter *][!Redraw]
DynamicVariables=1
The Substitute can, of course, be adapted as a RegExp option in a WebParser measure, in order to get the desired "group" of "count" "pieces" (i.e. list of a number of items) and then break that group into separate measures / meters like described in my previous reply. There are a couple of problems with directly implementing this in a WebParser though:
- StringIndex has a maximum of 99 (even though a workaround is to use StringIndex2 too, and increase the number of possible captures)
- if you really want to capture items separately, the regex pattern will become longer (albeit variables can be used to write the redundant parts)
- any dynamic change in a WebParser implies making another request to the site / address where you get the data from (excessive polling possible)

So, while technically possible to directly get a reasonable number of separate items in a WebParser, I would go for getting the entire list of items in a single request in the WebParser parent, then extract what I need and use dynamic variables freely and without any drawback in subsequent String measures.

As for dynamically using a different number of separate measures (e.g. one for each item), you only have 2 possibilities: write a sufficient number of such measures and use how many you need, or use Lua to rewrite and refresh the skin to have a specific number of such measures (the latter will need care to avoid requesting data again at refresh time in the WebParser). Obviously, the most convenient choice is to have a sufficient number.

EDIT: Actually, doing it directly in the WebParser can be achieved by using lookahead assertions (but they must be a sufficient number of them, unlike the theoretical unlimited number in the substitute above). However, scrolling to display a number of those captures should be done through referencing variable index measure names, rather than dynamically altering the WebParser options (which would lead to a new request, as already mentioned).
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
RicardoTM
Posts: 268
Joined: December 28th, 2022, 9:30 pm
Location: México

Re: Splitting measure string

Post by RicardoTM »

Yincognito wrote: February 28th, 2024, 7:34 pm Yes, this is possible for any string.
Thanks for the detailed explanation Yin. I'll have to experiment with this. I wish there was a CommandMeasure "IndexUp " and "IndexDown" tho lol. I was thinking about making a skin that would display the last 5 rows in an excel table (would be a local file so no problem about making many requests). But with the capability of scrolling up and down through all the rows without needing to display the whole table.

Pretty much like what you did here, but instead of displaying the whole table, display only 5 rows at a time, and using scroll wheel to scroll up and down.
User avatar
Yincognito
Rainmeter Sage
Posts: 7175
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Splitting measure string

Post by Yincognito »

RicardoTM wrote: February 29th, 2024, 3:37 am Thanks for the detailed explanation Yin. I'll have to experiment with this. I wish there was a CommandMeasure "IndexUp " and "IndexDown" tho lol. I was thinking about making a skin that would display the last 5 rows in an excel table (would be a local file so no problem about making many requests). But with the capability of scrolling up and down through all the rows without needing to display the whole table.

Pretty much like what you did here, but instead of displaying the whole table, display only 5 rows at a time, and using scroll wheel to scroll up and down.
That is definitely possible, either from a Rainmeter Substitute or from the VBA macro in Excel (it might be possible via StringIndex too, if using lookbehind instead of lookahead assertions).

If you're after a quick solution, I guess reversing the above Substitute to:

Code: Select all

Substitute="(?siU)^(?:.*#Piece#{#Start#}(#Piece#{0,#Count#}+)|.*+)$":"\1","^\\1$":""
might be enough to get the last #Count# #Piece#-s instead of the first ones. If, on the other hand, you need a more detailed / specific overview on it using different methods, I suppose creating a new topic for it would be better, so as to not mix apples with oranges here. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
RicardoTM
Posts: 268
Joined: December 28th, 2022, 9:30 pm
Location: México

Re: Splitting measure string

Post by RicardoTM »

Yincognito wrote: February 29th, 2024, 12:49 pm That is definitely possible, either from a Rainmeter Substitute or from the VBA macro in Excel (it might be possible via StringIndex too, if using lookbehind instead of lookahead assertions).

If you're after a quick solution, I guess reversing the above Substitute to:

Code: Select all

Substitute="(?siU)^(?:.*#Piece#{#Start#}(#Piece#{0,#Count#}+)|.*+)$":"\1","^\\1$":""
might be enough to get the last #Count# #Piece#-s instead of the first ones. If, on the other hand, you need a more detailed / specific overview on it using different methods, I suppose creating a new topic for it would be better, so as to not mix apples with oranges here. ;-)
Thanks, yah I may start a new topic about it if I struggle when I actually start doing it. Is just that your answers here made me wonder about that. I'm still working on the Gauges :lol:
User avatar
Yincognito
Rainmeter Sage
Posts: 7175
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: Splitting measure string

Post by Yincognito »

RicardoTM wrote: February 29th, 2024, 5:59 pm Thanks, yah I may start a new topic about it if I struggle when I actually start doing it. Is just that your answers here made me wonder about that. I'm still working on the Gauges :lol:
Yep, I suspected that much. No worries, try your luck with it and if you have difficulties, a new topic on that should probably clarify any potential issue you may encounter with the implementation. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth