It is currently April 28th, 2024, 6:01 pm

MSIAfterburner.dll

Get help with creating, editing & fixing problems with skins
User avatar
arcanosa84
Posts: 173
Joined: May 21st, 2023, 1:47 am

Re: MSIAfterburner.dll

Post by arcanosa84 »

[...]
On the menu skin and the configuration skin:

You did everything well, except it should be IfFalseAction instead of fFalseAction like you have it in your code - just a typo. I think you can remove updating the meters and redrawing the skin from the conditions as well, since this is already done by the Folder measure when it finishes opening the current folder. :thumbup:

That being said, you should make sure that you understand WHAT the code does, and WHY it does it this way (I already explained this in my initial reply about this), because it's the last time I repeat such things, next time I'll just let you figure out things on your own. :sly:
If I already fixed it, apparently when copying and pasting it deleted the first letter, that's it and it's done. :D :D
Both your ideas (the conditional and the disabling) are good, but there is a problem: none of the things you use in either of your attempts are RELEVANT NUMERICAL values, but either strings or numbers without relevance to what you'd like to achieve (both conditionals and IfConditions work with numbers only, I already told you that, by the way). Even so, you omitted the name of the measure where you wanted to set the Disabled option in your 2nd idea code, and that is not valid.
Even so, you omitted the name of the measure where you wanted to set the Disabled option in your 2nd idea code, and that is not valid.
From here I know what you tell me but I don't know how to assemble it correctly, help me here. I think it's a silly mistake but I'm not sure how to do it, and I don't want to do things wrong by saying I did.
- add a String measure as the 1st measure in your code
- set its String option to your #Select# variable, which is also a string
- use a Substitute option to replace its "Internet" and "Ping" values with "0" and "1", basically turning it into a number
- add a Disabled option to both the InternetStatus and the commented MeasurePing2 measures, and set those options to the proper formulas or conditional, based on the now numerical value of your newly created String measure above
- add a DynamicVariables=1 line to the InternetStatus measure, so that Rainmeter can see the dynamic value of the things in its Disabled option you just added
- add the contents of the IfTrue and IfFalse actions from your uncommented MeasurePing2 measure to the same actions in the InternetStatus measure, then remove the uncommented MeasurePing2 (makes no sense to have two measures for this when you can have just one)
- finally, uncomment your commented MeasurePing2 measure

Code: Select all

[MeasurePingIP]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping02#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha2 ([MeasurePingIP]<1300?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
IfCondition=(#Select# = Ping)
IfTrueAction=[!SetOption Disabled 0][!UpdateMeter *][!Redraw]
IfFalseAction=[!SetOption Disabled 1][!UpdateMeter *][!Redraw]
Disabled=1
DynamicVariables=1

[MeasurePingIE]
Group=Pings
Measure=SysInfo
SysInfoType=INTERNET_CONNECTIVITY
IfCondition=(InternetStatus=1)
UpdateRate=3
;UpdateDivider=5
IfTrueAction=[!SetVariable Alpha2 #AlphaOn#][!UpdateMeter *][!Redraw]
IfFalseAction=[!SetVariable Alpha2 #AlphaOff#][!UpdateMeter *][!Redraw]
IfCondition2=(#Select# = Internet)
IfTrueAction2=[!SetOption Disabled 0][!UpdateMeter *][!Redraw]
IfFalseAction2=[!SetOption Disabled 1][!UpdateMeter *][!Redraw]
Disabled=1
DynamicVariables=1

[MeasureSub]
Measure=String
String=#Select#
Substitute="Internet:1","Ping:0"
DynamicVariables=1

[MeasurePing2]
Formula=([MeasureSub] = 1?[MeasurePingIE]:[MeasurePingIP])
Until then I would need:
- add the contents of the IfTrue and IfFalse actions from your uncommented MeasurePing2 measure to the same actions in the InternetStatus measure, then remove the uncommented MeasurePing2 (makes no sense to have two measures for this when you can have just one)
- finally, uncomment your commented MeasurePing2 measure

But see me saying how I'm going, I know I need to put (Even so, you omitted the name of the measure where you wanted to set the Disabled option in your 2nd idea code, and that is not valid.) that I was asking you how to do it correctly. and then continue with everything else

I await your review. thank you :welcome: :welcome: :welcome:
:Whistle :Whistle Learning is the most complete art of life. Just enjoy it. :bow: :bow:
User avatar
Yincognito
Rainmeter Sage
Posts: 7179
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: MSIAfterburner.dll

Post by Yincognito »

My bad here, let me clarify:

- when talking about your omission, I was only referring to your 2nd code earlier, just to indicate where you were wrong, that's all
- when talking about what you need to do, I referred to your 1st code earlier, so don't bother with the two measures from your 2nd code at all

In other words, do what I advised, but in the complete code you posted first.

‐----‐------------------------------------

As for explaining again what I already wrote, I told you I won't do it again. The descriptions are as clear and precise as possible, the rest is on you. I'll only say this though: the only point (hyphen) you did well was the 2nd one. Just follow precisely all those points, in the order they are written, check the exact syntax for options in the manual when in doubt, and you'll figure it out. It's about time you do so from start to finish, considering I still describe every line of code you need to have, something I should have ceased to do for a while now. Baby birds need help to learn how to fly, but at some point they need to launch themselves into the unknown on their own. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
arcanosa84
Posts: 173
Joined: May 21st, 2023, 1:47 am

Re: MSIAfterburner.dll

Post by arcanosa84 »

[...]
I'm on my phone now so I can't test, but you can make a combination of your ideas and:
- add a String measure as the 1st measure in your code
- set its String option to your #Select# variable, which is also a string
- use a Substitute option to replace its "Internet" and "Ping" values with "0" and "1", basically turning it into a number
- add a Disabled option to both the InternetStatus and the commented MeasurePing2 measures, and set those options to the proper formulas or conditional, based on the now numerical value of your newly created String measure above
- add a DynamicVariables=1 line to the InternetStatus measure, so that Rainmeter can see the dynamic value of the things in its Disabled option you just added
- add the contents of the IfTrue and IfFalse actions from your uncommented MeasurePing2 measure to the same actions in the InternetStatus measure, then remove the uncommented MeasurePing2 (makes no sense to have two measures for this when you can have just one)
- finally, uncomment your commented MeasurePing2 measure
These were the steps to follow, and I'm already on the original code.
Now this is what I developed. According to the manual, locate the value of the string. Tell me where I have the error since it doesn't work. I know what the error is but I didn't detect it :-( :-( :-(
I fully agree with you, I already think I should be able to create something myself, but I come across these polemics and I get lost. I'm requesting a course in PHP here to see if it's better for everyone in this world. At the moment I keep learning here.

Code: Select all

[MeasureStatus]
Measure=Calc
Formula=#Select#
Substitute="Internet":"0","Ping":"1"

[InternetStatus]
Measure=SysInfo
SysInfoType=INTERNET_CONNECTIVITY
UpdateDivider=5
IfCondition=(InternetStatus=1)
IfTrueAction=[!SetOptionGroup Pings UpdateRate 0][!UpdateMeasureGroup Pings][!SetOptionGroup Pings UpdateRate 10][!SetVariable Alpha2 #AlphaOn#][!UpdateMeter *][!Redraw]
IfFalseAction=[!SetOptionGroup Pings UpdateRate 0][!UpdateMeasureGroup Pings][!SetOptionGroup Pings UpdateRate 5][!SetVariable Alpha2 #AlphaOff#][!UpdateMeter *][!Redraw]
IfCondition2=MeasureStatus = 0
IfTrueAction2=[!SetOption Disabled 0]
IfFalseAction2=[!SetOption Disabled 1]
DynamicVariables=1
Disabled=1

[MeasurePing1]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping01#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha1 ([MeasurePing1]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing2]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping02#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha2 ([MeasurePing2]<1300?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
IfCondition=MeasureStatus = 1
IfTrueAction=[!SetOption Disabled 0]
IfFalseAction=[!SetOption Disabled 1]
DynamicVariables=1
Disabled=1
In this part of the code, it shows the Internet text on the screen but based on the measure [MeasurePing2] now when the error I have in the above is rectified, this measure will only work when it is through the ping, not through the internet, the image is It would show why the image is manipulated transparency and it is through #Alpha2# am I correct??

Code: Select all

[ComputerLabel2]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha2#
FontEffectColor=0,0,0,#Alpha2#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing2
Text=Internet
DynamicVariables=1
:Whistle :Whistle Learning is the most complete art of life. Just enjoy it. :bow: :bow:
User avatar
Yincognito
Rainmeter Sage
Posts: 7179
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: MSIAfterburner.dll

Post by Yincognito »

Alright, now it's MUCH better, although you insisted working with your 2nd code instead of the 1st, but anyway.

Maybe the 4th step needs a clarification, now that you deal with your 2nd code: get rid of the last IfCondition in each of the two measures (they didn't exist in your 1st code, which is why I didn't mention this additional step earlier).

Next, complete the 4th step and "set those (aka the Disabled) options to the proper formulas or conditional, based on the now numerical value of your newly created String measure above". So basically, set the Disabled option based on the value of MeasureStatus accordingly in each of the two measures.

If done correctly, this would be all, you should already see the results, based on what you set from your configuration skin. Let me know how it goes.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
arcanosa84
Posts: 173
Joined: May 21st, 2023, 1:47 am

Re: MSIAfterburner.dll

Post by arcanosa84 »

Alright, now it's MUCH better, although you insisted working with your 2nd code instead of the 1st, but anyway.
I need to see why we are crossed, that is the original code, the other one that I published is the one that I was testing and doing tests. That I'm working on is the one we had officially working on.
Maybe the 4th step needs a clarification, now that you deal with your 2nd code: get rid of the last IfCondition in each of the two measures (they didn't exist in your 1st code, which is why I didn't mention this additional step earlier).
Here I already eliminated what you told me.
Next, complete the 4th step and "set those (aka the Disabled) options to the proper formulas or conditional, based on the now numerical value of your newly created String measure above". So basically, set the Disabled option based on the value of MeasureStatus accordingly in each of the two measures.

Code: Select all

IfCondition2=[MeasureStatus] = 0
IfTrueAction2=[!SetOption Disabled 0]
Is this not the condition you ask for, or do I have to add something else?

This was what I had put in my tests to enforce the measureping2 function for the rest of the code.

Code: Select all

[MeasurePing2]
Group=Pings
Measure=Calc
Formula=(MeasureStatus = 0?[MeasurePingIE]:(MeasureStatus = 1?[MeasurePingIP]:[MeasurePingIE]))
If done correctly, this would be all, you should already see the results, based on what you set from your configuration skin. Let me know how it goes.
It doesn't work for me, I know I'm missing something but I have doubts, please help me clarify.
Install Visual Studio Core to better guide me into the code.
Sorry this time for not achieving the goal, I need help. :-( :-(

This is the complete code.

Code: Select all

[Rainmeter]
Author=AlexSoft
Update=100
AccurateText=1
DynamicWindowSize=1
BackgroundMode=2
SolidColor=0,0,0,1

[Variables]
@Include=#ROOTCONFIGPATH#\@Resources\Config\Variables.inc
@Include2=#ROOTCONFIGPATH#\@Resources\Config\Styles.inc
@Include3=#ROOTCONFIGPATH#\@Resources\Config\Links.inc

Milliseconds=#MilisegPing#
Font=#Font5#
FontColor=#Color6#
AlphaOn=255
AlphaOff=#Transparent#
Alpha1=#AlphaOff#
Alpha2=#AlphaOff#
Alpha3=#AlphaOff#
Alpha4=#AlphaOff#
Alpha5=#AlphaOff#
Alpha6=#AlphaOff#
Ping01=#Ping1#
Ping02=#Ping2#
Ping03=#Ping3#
Ping04=#Ping4#
Ping05=#Ping5#
Ping06=#Ping6#
Ping07=#Ping7#
Ping08=#Ping8#
Ping09=#Ping9#
UpdateRate=20

---Measures---

[MeasureStatus]
Measure=Calc
Formula=#Select#
Substitute="Internet":"0","Ping":"1"

[MeasurePingIE]
Measure=SysInfo
SysInfoType=INTERNET_CONNECTIVITY
UpdateDivider=5
IfCondition=(InternetStatus=1)
IfTrueAction=[!SetOptionGroup Pings UpdateRate 0][!UpdateMeasureGroup Pings][!SetOptionGroup Pings UpdateRate 10][!SetVariable Alpha2 #AlphaOn#][!UpdateMeter *][!Redraw]
IfFalseAction=[!SetOptionGroup Pings UpdateRate 0][!UpdateMeasureGroup Pings][!SetOptionGroup Pings UpdateRate 5][!SetVariable Alpha2 #AlphaOff#][!UpdateMeter *][!Redraw]
IfCondition2=[MeasureStatus] = 0
IfTrueAction2=[!SetOption Disabled 0]
DynamicVariables=1
Disabled=1

[MeasurePing1]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping01#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha1 ([MeasurePing1]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePingIP]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping02#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha2 ([MeasurePingIP]<1300?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
IfCondition=[MeasureStatus] = 1
IfTrueAction=[!SetOption Disabled 0]
DynamicVariables=1
Disabled=1

[MeasurePing2]
Group=Pings
Measure=Calc
Formula=(MeasureStatus = 0?[MeasurePingIE]:(MeasureStatus = 1?[MeasurePingIP]:[MeasurePingIE]))

[MeasurePing3]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping03#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha3 ([MeasurePing3]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing4]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping04#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha4 ([MeasurePing4]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing5]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping05#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha6 ([MeasurePing5]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing6]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping06#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha6 ([MeasurePing6]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing7]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping07#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha5 ([MeasurePing7]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing8]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping08#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha5 ([MeasurePing8]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

[MeasurePing9]
Group=Pings
Measure=Plugin
Plugin=PingPlugin
DestAddress=#Ping09#
UpdateRate=#UpdateRate#
OnChangeAction=[!SetVariable Alpha5 ([MeasurePing9]<#Milliseconds#?#AlphaOn#:#AlphaOff#)][!UpdateMeter *][!Redraw]
DynamicVariables=1

---Meters---

[ComputerImage1]
Meter=Image
X=0
Y=0
W=64
H=64
ImageAlpha=#Alpha1#
ImageName=#@#\Images\Ping\Ap.ico
DynamicVariables=1

[ComputerImage2]
Meter=Image
X=10R
Y=0r
W=64
H=64
ImageAlpha=#Alpha2#
ImageName=#@#\Images\Ping\Internet.png
DynamicVariables=1

[ComputerImage3]
Meter=Image
X=10R
Y=0r
W=64
H=64
ImageAlpha=#Alpha3#
ImageName=#@#\Images\Ping\LG Alex.ico
DynamicVariables=1

[ComputerImage4]
Meter=Image
X=10R
Y=0r
W=64
H=64
ImageAlpha=#Alpha4#
ImageName=#@#\Images\Ping\LG Lena.ico
DynamicVariables=1

[ComputerImage5]
Meter=Image
X=10R
Y=0r
W=64
H=64
ImageAlpha=#Alpha5#
ImageName=#@#/Images/Ping/Inv.ico
DynamicVariables=1

[ComputerImage6]
Meter=Image
X=10R
Y=0r
W=64
H=64
ImageAlpha=#Alpha6#
ImageName=#@#\Images\Ping\Laptop.ico
DynamicVariables=1

---Label---

[ComputerLabel1]
Meter=String
X=32
Y=10R
W=64
FontColor=#FontColor#,#Alpha1#
FontEffectColor=0,0,0,#Alpha1#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing1
Text=AP
DynamicVariables=1

[ComputerLabel2]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha2#
FontEffectColor=0,0,0,#Alpha2#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing2
Text=Internet
DynamicVariables=1

[ComputerLabel3]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha3#
FontEffectColor=0,0,0,#Alpha3#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing3
Text=Alex
DynamicVariables=1

[ComputerLabel4]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha4#
FontEffectColor=0,0,0,#Alpha4#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing4
Text=Lena
DynamicVariables=1

[ComputerLabel5]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha5#
FontEffectColor=0,0,0,#Alpha5#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing7
MeasureName=MeasurePing8
MeasureName=MeasurePing9
Text=Invitado
DynamicVariables=1

[ComputerLabel6]
Meter=String
X=74r
Y=0r
W=64
FontColor=#FontColor#,#Alpha6#
FontEffectColor=0,0,0,#Alpha6#
FontFace=#Font#
FontSize=12
AntiAlias=1
StringEffect=Shadow
StringAlign=Center
MeasureName=MeasurePing5
MeasureName=MeasurePing6
Text=Laptop
DynamicVariables=1
:Whistle :Whistle Learning is the most complete art of life. Just enjoy it. :bow: :bow:
User avatar
Yincognito
Rainmeter Sage
Posts: 7179
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: MSIAfterburner.dll

Post by Yincognito »

I'll let someone else continue to advise or write the entire code for you, if they want to (this is what basically happens here, after all), cause it seems I just can't get away with explaining things as simple as possible a single time. Can't continue if instructions are not followed unless repeated a million times, to the point of writing someone else's code myself, sorry (e.g. not getting rid of the conditions I mentioned, the first measure being a calc and not a string which I only noticed now, not setting the Disabled option in its own line after the equal sign, and so on - and this only when it comes to the last part we talked about). :confused:

Good luck in your future endeavors, because bar the code aspects, it's been a pleasure to talk to you, being such a nice person willing to learn. Maybe you'll have better success afterwards, so don't give up. ;-)
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth
User avatar
arcanosa84
Posts: 173
Joined: May 21st, 2023, 1:47 am

Re: MSIAfterburner.dll

Post by arcanosa84 »

Yincognito wrote: September 3rd, 2023, 11:46 am I'll let someone else continue to advise or write the entire code for you, if they want to (this is what basically happens here, after all), cause it seems I just can't get away with explaining things as simple as possible a single time. Can't continue if instructions are not followed unless repeated a million times, to the point of writing someone else's code myself, sorry (e.g. not getting rid of the conditions I mentioned, the first measure being a calc and not a string which I only noticed now, not setting the Disabled option in its own line after the equal sign, and so on - and this only when it comes to the last part we talked about). :confused:

Good luck in your future endeavors, because bar the code aspects, it's been a pleasure to talk to you, being such a nice person willing to learn. Maybe you'll have better success afterwards, so don't give up. ;-)
It's a shame that you think like that, it's impossible that I could ask for more, since the skins in which he has helped me are working perfectly, and his method of teaching is not that it doesn't work, it's just that I started from scratch doing advanced things, and there are things in which I get lost, even if I don't want to, I asked him several questions to find out what he means by what he is asking me because if I don't understand it, it is impossible for him to perform the steps correctly. I have not asked him to write the code for me, only to guide me, the path is a bit complicated to follow, yes, he is teaching someone who does not know and that is not easy, perhaps the others who can help me will just do the I work and that's it, I won't learn anything from that, that's the difference. But as I already told you, I can't force you. Thank you very much for all your help and precious time spent. :thumbup:
:Whistle :Whistle Learning is the most complete art of life. Just enjoy it. :bow: :bow:
User avatar
Yincognito
Rainmeter Sage
Posts: 7179
Joined: February 27th, 2015, 2:38 pm
Location: Terra Yincognita

Re: MSIAfterburner.dll

Post by Yincognito »

arcanosa84 wrote: September 3rd, 2023, 2:13 pmThank you very much for all your help and precious time spent. :thumbup:
You're welcome. ;-)
I know you didn't directly ask me to write the code for you, but having to basically spell everything that you need to do in each line is indirectly the same. To make matters worse, this has to be repeated again and again. To make matters even worse, this has to be repeated the same way even if a couple of replies ago a similar issue has been dealt with successfully and the approach should presumably be understood already.
Profiles: Rainmeter ProfileDeviantArt ProfileSuites: MYiniMeterSkins: Earth