It is currently April 23rd, 2024, 9:56 pm

Strategy Request: indicate values are LOWER or HIGHER

Get help with creating, editing & fixing problems with skins
ms310
Posts: 225
Joined: April 1st, 2015, 7:16 am

Strategy Request: indicate values are LOWER or HIGHER

Post by ms310 »

Hi

I am reading values from a website that change on an hourly basis. I would like my skin to indicate, with each read, if the current values are lower, higher or the same as the previously read value. I am looking for good logic for this (maybe a best practice). My thinking is this:

1. Prior to the WebParser ready store the current value into a variable, overwriting whatever that value is currently
2. Read the new value via WebParser
3. Do the math between the two values and display up, down, same icon, text, or whatever

Does this seem reasonable? Are there some pitfalls with this logic?

Thanks!
mak_kawa
Posts: 908
Joined: December 30th, 2015, 9:47 am

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by mak_kawa »

Hi ms310

I think your strategy is OK. But one thing, when the skin is loaded (refreshed), all variables are empty (or as decsribed in the [Variables] section), so at the first data-get cycle, you can't evaluate "the difference between previous and current data". This could be the problem if the update cycle of the measure is long. And also you can't know the difference from, for example, the "last night/yesterday" value.

My workaround for this is to store variable value to the include file such as Variables.inc by !WriteKeyValue bang at every data update (see the footnote below), so that you can get previous data when the skin is loaded (refreshed) and know the data difference since last unloading.

*) If you don't want to store value when the value is unchanged, OnchangeAction option in the measure can be used.

As always, maybe I am misunderstanding your point. If so, sorry.
User avatar
balala
Rainmeter Sage
Posts: 16164
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by balala »

Besides mak_kawa's explanation, I'd add an example code for you, to show you how did I achieved something similar. Not knowing your source, I used a Calc measure, but probably similarly could be done even for WebParser measures. The Calc measure is updated regularly (precisely here on each second update cycle, but this can be changes easily) and on each update the skin shows if the new value has increased, decreased or didn't change.
Not sure if you need a sample code or you already have a workaround, but here is my code, if you are interested:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1

[Variables]
Change=0

[MeasureRandom]
Measure=Calc
Formula=Random
LowBound=0
HighBound=100
UpdateRandom=1
IfCondition=(#CURRENTSECTION#>#Change#)
IfTrueAction=[!SetVariable Direction "[\x2197]"]
IfCondition2=(#CURRENTSECTION#<#Change#)
IfTrueAction2=[!SetVariable Direction "[\x2198]"]
IfCondition3=(#CURRENTSECTION#=#Change#)
IfTrueAction3=[!SetVariable Direction "-"]
OnChangeAction=[!Delay "1000"][!SetVariable Change "[MeasureRandom]"][!UpdateMeter "MeterShow"][!Redraw]
DynamicVariables=1
UpdateDivider=2

[MeterShow]
Meter=STRING
MeasureName=MeasureRandom
X=0
Y=0
Padding=15,5,15,5
FontColor=220,220,220
FontEffectColor=0,0,0
StringEffect=Shadow
SolidColor=0,0,0,150
FontSize=8
FontFace=Segoe UI
StringStyle=BOLD
StringAlign=LEFT
AntiAlias=1
Text=%1 / #Direction#
DynamicVariables=1
Please let me know if you have any related question.
ms310
Posts: 225
Joined: April 1st, 2015, 7:16 am

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by ms310 »

balala wrote: March 27th, 2020, 7:58 am Besides mak_kawa's explanation, I'd add an example code for you, to show you how did I achieved something similar. Not knowing your source, I used a Calc measure, but probably similarly could be done even for WebParser measures. The Calc measure is updated regularly (precisely here on each second update cycle, but this can be changes easily) and on each update the skin shows if the new value has increased, decreased or didn't change.
Not sure if you need a sample code or you already have a workaround, but here is my code, if you are interested:

Code: Select all

[Rainmeter]
Update=1000
DynamicWindowSize=1

[Variables]
Change=0

[MeasureRandom]
Measure=Calc
Formula=Random
LowBound=0
HighBound=100
UpdateRandom=1
IfCondition=(#CURRENTSECTION#>#Change#)
IfTrueAction=[!SetVariable Direction "[\x2197]"]
IfCondition2=(#CURRENTSECTION#<#Change#)
IfTrueAction2=[!SetVariable Direction "[\x2198]"]
IfCondition3=(#CURRENTSECTION#=#Change#)
IfTrueAction3=[!SetVariable Direction "-"]
OnChangeAction=[!Delay "1000"][!SetVariable Change "[MeasureRandom]"][!UpdateMeter "MeterShow"][!Redraw]
DynamicVariables=1
UpdateDivider=2

[MeterShow]
Meter=STRING
MeasureName=MeasureRandom
X=0
Y=0
Padding=15,5,15,5
FontColor=220,220,220
FontEffectColor=0,0,0
StringEffect=Shadow
SolidColor=0,0,0,150
FontSize=8
FontFace=Segoe UI
StringStyle=BOLD
StringAlign=LEFT
AntiAlias=1
Text=%1 / #Direction#
DynamicVariables=1
Please let me know if you have any related question.
Thanks Balala - so even though you set Change=0 in the variables section this variable will hold the values from [!SetVariable Change "[MeasureRandom]" through skin refreshes in memory? Right now I am seeing the value also "up" which could be true, but I don't know if its comparing 0 to the current value or the #currentsection# value to the new value. Thanks as always for your help!
User avatar
balala
Rainmeter Sage
Posts: 16164
Joined: October 11th, 2010, 6:27 pm
Location: Gheorgheni, Romania

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by balala »

ms310 wrote: March 29th, 2020, 4:39 am so even though you set Change=0 in the variables section this variable will hold the values from [!SetVariable Change "[MeasureRandom]" through skin refreshes in memory? Right now I am seeing the value also "up" which could be true, but I don't know if its comparing 0 to the current value or the #currentsection# value to the new value.
The [!SetVariable Change "[MeasureRandom]"] bang of the OnChangeAction option of the [MeasureRandom] measure sets the Change variable to the value of the measure, with one second after the new value is got by the measure (the delay is caused by the [!Delay "1000"] bang of the same option). I set the initial value of the Change variable to 0 because the first value of a Calc measure is anyway 0, when the skin is refreshed / loaded.
The above !SetVariable bang sets the appropriate value for the variable when needed (one second later), which for sure is higher then 0. The first change is always an increase (at least if the measure doesn't achieve negative values).
On skin refresh no dynamically set values are kept. Every value set through a !SetVariable bang, as well as every dynamic option set through a !SetOption bang, are lost. On every update of the [MeasureRandom] measure, the IfCondition options establish the direction of change, by comparing the current value of the measure (done by the #CURRENTSECTION# variable) with the previous value of the same measure, which is kept by the #Change# variable (set, as described, by the !SetVariable bang). The value of the #Direction# variable is set accordingly and used into the String meter.
ms310
Posts: 225
Joined: April 1st, 2015, 7:16 am

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by ms310 »

balala wrote: March 29th, 2020, 12:58 pm The [!SetVariable Change "[MeasureRandom]"] bang of the OnChangeAction option of the [MeasureRandom] measure sets the Change variable to the value of the measure, with one second after the new value is got by the measure (the delay is caused by the [!Delay "1000"] bang of the same option). I set the initial value of the Change variable to 0 because the first value of a Calc measure is anyway 0, when the skin is refreshed / loaded.
The above !SetVariable bang sets the appropriate value for the variable when needed (one second later), which for sure is higher then 0. The first change is always an increase (at least if the measure doesn't achieve negative values).
On skin refresh no dynamically set values are kept. Every value set through a !SetVariable bang, as well as every dynamic option set through a !SetOption bang, are lost. On every update of the [MeasureRandom] measure, the IfCondition options establish the direction of change, by comparing the current value of the measure (done by the #CURRENTSECTION# variable) with the previous value of the same measure, which is kept by the #Change# variable (set, as described, by the !SetVariable bang). The value of the #Direction# variable is set accordingly and used into the String meter.
Thanks Balala. I am seeing the values now as always "down". I had a small error where I was checking the non decimal version - but now it looks like there are no syntax errors but the skin is always indicating "down".

I have uploaded a copy of the skin here: https://forum.rainmeter.net/viewtopic.php?f=27&t=34873&p=173438#p173438 if you have a chance to take a look.

Thanks!
User avatar
eclectic-tech
Rainmeter Sage
Posts: 5406
Joined: April 12th, 2012, 9:40 pm
Location: Cedar Point, Ohio, USA

Re: Strategy Request: indicate values are LOWER or HIGHER

Post by eclectic-tech »

I must admit I have avoided looking at your skin simply because there is an overload of related info...

You seem to be asking if the values are retained through skin refreshes... and balala explained that the current version does NOT save the values, it waits a second before it updates them but never saves them when the skin is reloaded or refreshed.

If this is something you would like, then you need to make a few changes to the Variables and the IfCondition test and actions.

First move the [Variables] section from '@Resources\CovidMeasures.inc' to your main skin and create 3 new variables: LastTotal=0, LastDeaths=0, and LastRecovered=0.

Code: Select all

[Variables]
@Include=#@#CovidMeasures.inc
@Include2=#@#Style.ini
FontS=18
LabelColor=
MainTextColor=
ChangeTotal=0
ChangeDeaths=0
ChangeRecovered=0
LastTotal=0
LastDeaths=0
LastRecovered=0
This gives you 3 variables to store the last values received from the webparser measure, so the values are retained even if the skin refreshed or reloaded.

You need to change '@Resources\CovidMeasures.inc' to write those variables before updating the with the latest webparser info.
Change each of the IfCondition(s) and OnChangeAction for each piece of info (total, deaths, recovered). Here is the rewritten 'CovidMeasures.inc':

Code: Select all

[MeasureOverall]
Measure=WebParser
URL=https://www.worldometers.info/coronavirus/
RegExp=(?siU).*Last updated: (.*)</div>.*<tbody>.*<td>.*</td>.*<td>(.*)</td>.*<td>(.*)</td>.*<td>(.*)</td>.*
UpdateRate=3600
FinishAction=[!EnableMeasure "percentDeaths" "#CURRENTCONFIG#"][!EnableMeasure "percentRecovered" "#CURRENTCONFIG#"]

[MeasureUpdated]
Measure=WebParser
URL=[MeasureOverall]
StringIndex=1
Substitute="":"Updating..."

[MeasureTotal]
Measure=WebParser
URL=[MeasureOverall]
StringIndex=2
Substitute="":"...",",":""
DynamicVariables=1

[MeasureDeaths]
Measure=WebParser
URL=[MeasureOverall]
StringIndex=3
Substitute="":"...",",":""

[MeasureRecovered]
Measure=WebParser
URL=[MeasureOverall]
StringIndex=4
Substitute="":"...",",":""

[decOverall]
Measure=String
String=[MeasureTotal]
IfCondition=(#CURRENTSECTION#>#LastTotal#)
IfTrueAction=[!SetVariable DirectionTotal "[\x2191]"]
IfCondition2=(#CURRENTSECTION#<#LastTotal#)
IfTrueAction2=[!SetVariable DirectionTotal "[\x2193]"]
IfCondition3=(#CURRENTSECTION#=#LastTotal#)
IfTrueAction3=[!SetVariable DirectionTotal "[\x2194]"]
OnChangeAction=[!WriteKeyValue Variables LastTotal #ChangeTotal#][!Delay "1000"][!WriteKeyValue Variables ChangeTotal "[decOverall]"][!SetVariable ChangeTotal "[decOverall]"][!UpdateMeter "mTotal"][!Redraw]
DynamicVariables=1

[decDeaths]
Measure=String
String=[MeasureDeaths]
IfCondition=(#CURRENTSECTION#>#LastDeaths#)
IfTrueAction=[!SetVariable DirectionDeaths "[\x2191]"]
IfCondition2=(#CURRENTSECTION#<#LastDeaths#)
IfTrueAction2=[!SetVariable DirectionDeaths "[\x2193]"]
IfCondition3=(#CURRENTSECTION#=#LastDeaths#)
IfTrueAction3=[!SetVariable DirectionDeaths "[\x2194]"]
OnChangeAction=[!WriteKeyValue Variables LastDeaths #ChangeDeaths#][!Delay "1000"][!WriteKeyValue Variables ChangeDeaths "[decDeaths]"][!SetVariable ChangeDeaths "[decDeaths]"][!UpdateMeter "mDeaths"][!Redraw]
DynamicVariables=1

[decRecovered]
Measure=String
String=[MeasureRecovered]
IfCondition=(#CURRENTSECTION#>#LastRecovered#)
IfTrueAction=[!SetVariable DirectionRecovered "[\x2191]"]
IfCondition2=(#CURRENTSECTION#<#LastRecovered#)
IfTrueAction2=[!SetVariable DirectionRecovered "[\x2193]"]
IfCondition3=(#CURRENTSECTION#=#LastRecovered#)
IfTrueAction3=[!SetVariable DirectionRecovered "[\x2194]"]
OnChangeAction=[!WriteKeyValue Variables LastRecovered #ChangeRecovered#][!Delay "1000"][!WriteKeyValue Variables ChangeRecovered "[decRecovered]"][!SetVariable ChangeRecovered "[decRecovered]"][!UpdateMeter "mRecovered"][!Redraw]
DynamicVariables=1

[percentDeaths]
Measure=Calc
Formula=[decDeaths]/[decOverall]
DynamicVariables=1
Disabled=1

[percentRecovered]
Measure=Calc
Formula=[decRecovered]/[decOverall]
DynamicVariables=1
Disabled=1

[pDeaths]
Measure=Calc
Formula=[percentDeaths]*100
DynamicVariables=1

[pRecovered]
Measure=Calc
Formula=[percentRecovered]*100
DynamicVariables=1
The IfCondition(s) will now test the webparser values against the "Last" saved value, which is zero the first time the skin is loaded, but is "Written" in OnChangeAction before the new value is "Set".

Using !WriteKeyValue will save the webparser info for comparison the next time the webparser updates, the skin refreshed, or reloaded. You use !SetVariable to update the active skin variables, and !WriteKeyValue to save the last values for comparison if the skin is unloaded, refreshed, or updated.

The first time you run the skin all the arrows will be "Up" because all the initial values are zero; once the skin updated or is refreshed/reloaded, the values will give the actual difference between the latest webparser info and what was saved earlier.

Regards, stay safe!