Skip to content

Instantly share code, notes, and snippets.

@jmbeach
Created April 5, 2020 20:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jmbeach/f3a83b6a79e688d43c9ab6c252f9d088 to your computer and use it in GitHub Desktop.
Save jmbeach/f3a83b6a79e688d43c9ab6c252f9d088 to your computer and use it in GitHub Desktop.
DINJ (Do I Need a Jacket) Updated for openweathermap.org
[Rainmeter]
Update=1000
MiddleMouseUpAction=!Refresh #CURRENTCONFIG#
DynamicWindowSize=1
; spaces prefix formulas in WriteKeyValue so that WKV doesn't try to parse the formula and log a syntax error
; http://rainmeter.net/forum/viewtopic.php?f=5&t=9806&p=57507
ContextTitle="Align left"
ContextAction=[!WriteKeyValue mainString StringAlign LeftTop][!WriteKeyValue mainString X 0][!WriteKeyValue subString X " (Floor(#*size*# * 0.2))"][!Refresh #CURRENTCONFIG#]
ContextTitle2="Align center"
ContextAction2=[!WriteKeyValue mainString StringAlign CenterTop][!WriteKeyValue mainString X " (Floor(#*size*# * 7.5))"][!WriteKeyValue subString X " (Floor(#*size*# * 7.5))"][!Refresh #CURRENTCONFIG#]
ContextTitle3="Align right"
ContextAction3=[!WriteKeyValue mainString StringAlign RightTop][!WriteKeyValue mainString X " (Floor(#*size*# * 15))"][!WriteKeyValue subString X " (Floor((#*size*# * 15) - (#*size*# * 0.2)))"][!Refresh #CURRENTCONFIG#]
[Metadata]
Name=Do I Need a Jacket?
Author=Flying Hyrax | flyinghyrax.deviantart.com
Information=Weather, simplified - do you need a jacket? This skin checks the current temperature and lets you know. | - Options are all in the [Variables] section of the skin file; just edit dinaj.ini, save, and refresh. | - Change the size of the skin by mouse-wheel scrolling on it. | - Change text alignment using the skin context menu
Version=2.1
License=Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
[Variables]
; Weather.com location code
; Go to weather.com and search for your location.
; The location code is in the URL on the page for your location.
; e.g. for Chicago:
; https://weather.com/weather/today/l/USIL0225:1:US
; ^^^^^^^^
location=c005bbc4fbd44a680fe4a942a9d7872f3f4c701984bd67564363d0c32f24b34b
; 'f' for English, 'm' for Metric
unit=f
tempUnit=F
windUnit=mi/hr
substringLength=1
substringX=0
; temperature thresholds; if you are using Celsius make sure you adjust these
jacket_temp=65
coat_temp=40
; appearance
font=Segoe UI Light
text_color=255,255,255,200
; this can be changed manually, or just scroll the mouse over the skin
size=12
;;====================================================
;; Measures
;;====================================================
[mWeatherData]
Measure=Plugin
Plugin=WebParser
Url="https://api.openweathermap.org/data/2.5/weather?units=Imperial&id=4623560&appid=<your-api-key>"
RegExp="(?siU)^(.*)$"
UpdateRate=900
ErrorString="DINAJ2: WebParser fail"
ForceReload=1
FinishAction=[!EnableMeasureGroup Weather][!UpdateMeter *][!Redraw]
[MeasureDegree]
Measure=Plugin
Plugin=Plugins\WebParser.dll
UpdateRate=3600
Url="file:///C:/Users/jared/Documents/Rainmeter/Skins/Minimalist%202/Weather/degree.txt"
RegExp=(.*)
StringIndex=1
[mTemperature]
Measure=Plugin
Plugin=WebParser
Group=Weather
Disabled=1
Url=[mWeatherData]
StringIndex2=1
RegExp=(?siU)\"temp\":.*([0-9]+)[.][0-9]+,
[mFeelsLike]
Measure=Plugin
Plugin=WebParser
Group=Weather
Disabled=1
Url=[mWeatherData]
StringIndex2=1
RegExp=(?siU)\"feels_like\":.*([0-9]+)[.][0-9]+,
[mCondition]
Measure=Plugin
Plugin=WebParser
Group=Weather
Disabled=1
Url=[mWeatherData]
StringIndex2=1
RegExp=(?siU)\"description\":.*\"(.*)\",
[mWindSpeed]
Measure=Plugin
Plugin=WebParser
Group=Weather
Disabled=1
Url=[mWeatherData]
StringIndex2=1
RegExp=(?siU)\"speed\":.*([0-9]+)[.][0-9]+,
[mStringScript]
Measure=Script
ScriptFile=dinaj.lua
Group=Weather
TempMeasureName=mFeelsLike
WindMeasureName=mWindSpeed
FirstString=mainString
SecondString=subString
Unit=#unit#
JacketThreshold=#jacket_temp#
CoatThreshold=#coat_temp#
Disabled=1
;;====================================================
;; Meters
;;====================================================
[bg]
Meter=Image
SolidColor=0,0,0,1
X=0
Y=0
W=(#size# * 15)
H=(#size# * 3)
DynamicVariables=1
MouseScrollUpAction=[!SetVariable size (#size#-1)][!UpdateMeter *][!Redraw][!WriteKeyValue Variables size #size#]
MouseScrollDownAction=[!SetVariable size (#size#+1)][!UpdateMeter *][!Redraw][!WriteKeyValue Variables size #size#]
[mainString]
Meter=String
MeasureName=mCondition
MeasureName2=mTemperature
MeasureName3=MeasureDegree
MeasureName4=mFeelsLike
FontFace=#font#
FontColor=#text_color#
SolidColor=00000001
FontSize=#size#
AntiAlias=1
X=0
Y=0
Text="..."
ToolTipText="%1, %2%3 (Feels like %4%3)"
DynamicVariables=1
StringAlign=LeftTop
[subString]
Meter=String
MeasureName=mPlaceName
MeasureName2=mTimestamp
MeterStyle=mainString
FontSize=(Floor(#size# * 0.8))
X= #substringX#
Y=(Floor(#size# * -0.2))R
Text="loading..."
ToolTipText="%1, %2"
LeftMouseUpAction="https://weather.com/weather/today/l/#location#"
--[[
Lua script to use with dinaj.ini Rainmeter skin
FlyingHyrax
2014-11-15
--]]
--[[ LOCAL VARIABLES =========================================================]]
-- lists the options the script measure can take
local Settings_Meta = {
String_Options = {
"TempMeasureName",
"WindMeasureName",
"FirstString",
"SecondString",
"Unit"
},
Number_Options = {
"JacketThreshold",
"CoatThreshold"
},
Defaults = {
JacketThreshold = 60,
CoatThreshold = 30,
Unit = "f"
}
}
-- things which should not change
local Constants = {
ADVERBS = {
"damn cold",
"darn cold",
"bone chilling",
"glacial",
"frigid",
"freezing",
"frosty",
"pretty cold",
"chilly",
"brisk",
"cool",
"quite temperate",
"rather mild",
"pretty nice",
"positively balmy",
"extra warm",
"kinda hot",
"roasting",
"scorching",
"oven-like",
"your hair is on FIRE",
},
RANGE_MIN = -10,
RANGE_MAX = 120,
}
-- measure and meter references
local Handles = {}
Handles.init = function(props)
Handles.Temperature_Measure = SKIN:GetMeasure(props.TempMeasureName)
Handles.Wind_Measure = SKIN:GetMeasure(props.WindMeasureName)
Handles.Main_Meter = SKIN:GetMeter(props.FirstString)
Handles.Sub_Meter = SKIN:GetMeter(props.SecondString)
end
-- script measure settings
local Settings = {}
Settings.init = function(props)
Settings.Jacket_Limit = SELF:GetNumberOption(props.JacketThreshold, 60)
Settings.Coat_Limit = SELF:GetNumberOption(props.CoatThreshold, 35)
local metric = { m = true, c = true }
local unit = string.lower(string.sub(props.Unit, 1, 1))
Settings.Unit = metric[unit] and 'c' or 'f'
end
--[[ LOCAL FUNCTIONS =========================================================]]
--[[ printf shortcut ]]
local function printf(format, ...)
print(string.format(format, ...))
end
local function print_table( t )
local str = "[ "
for k, v in pairs(t) do
str = str .. string.format("'%s' = %s, ", tostring(k), tostring(v))
end
str = str .. "]"
print(str)
end
--[[ Given a measure handle an metadata about the measures options,
return a table of Option=Value pairs. ]]
local function getMeasureOptions( measure, meta )
local options = {}
local function grabOptions( list, getter )
for _, v in pairs(list) do
options[v] = getter(measure, v, meta.Defaults[v])
end
end
grabOptions( meta.String_Options, measure.GetOption)
grabOptions( meta.Number_Options, measure.GetNumberOption)
return options
end
--[[ Keeps a value inside the given range ]]
local function clamp( value, min, max )
local clamped = value
if value < min then
clamped = min
elseif value > max then
clamped = max
end
return clamped
end
--[[ Adjusts a value and its defined range if the value is negative ]]
local function normalize( value, min, max )
local excess = min < 0 and 0 - min or 0
return value + excess, min + excess, max + excess
end
--[[ Return a value as a percentage of its range ]]
local function percentOfRange( value, min, max )
-- normalize
local value, min, max = normalize( value, min, max)
-- maths
local percent = (value / max - min)
-- clamping
return clamp( percent, 0.0, 1.0)
end
--[[ Convert a number from fahrenheit to celsius ]]
local function f2c( fahrenheit )
return (((fahrenheit - 32) * 5) / 9)
end
--[[ Convert a number from celsius to fahrenheit (unused) ]]
local function c2f( celsius )
return (((celsius * 9) / 5) + 32)
end
--[[ Given the current temperature and its scale,
return a descriptor for that temperature ]]
local function getTempWord( temp, unit )
-- convert our range bounds to celsius if necessary
local unit = unit or 'f'
local tmin = unit == 'f' and Constants.RANGE_MIN or f2c(Constants.RANGE_MIN)
local tmax = unit == 'f' and Constants.RANGE_MAX or f2c(Constants.RANGE_MAX)
-- percentage of our temperature range
local tempPer = percentOfRange( temp, tmin, tmax )
-- index in array of descriptors, based on that percentage
local index = math.ceil( #Constants.ADVERBS * tempPer )
-- if temp is 0% of our range, index will be off by one
if index < 1 then index = 1 end
-- return that word
return Constants.ADVERBS[index]
end
--[[ Given the current temperature, return the appropriate
string for the main string meter ]]
local function getMainString( temp )
local negation = (temp > Settings.Jacket_Limit) and " don't" or ""
local outerwear = (temp < Settings.Coat_Limit) and "coat" or "jacket"
return string.format("You%s need a %s", negation, outerwear)
end
--[[ Given the current temperature and its unit, return the appropriate string
for the secondary string meter ]]
local function getSubString( temp, unit )
return string.format("It's %s outside", getTempWord(temp, unit))
end
--[[ Sets the Text value of the specified meter with a SetOption bang ]]
local function setMeterText( meter, text )
SKIN:Bang('!SetOption', meter:GetName(), 'Text', text)
end
--[[ Log the descriptor which is returned for various temperatures ]]
local function test()
for i = -20, 100, 5 do
printf("t=%d, s=%s", i, getTempWord(i))
end
end
--[[ GLOBAL SKIN FUNCTIONS ===================================================]]
--[[ Run on Refresh (or on update if DynamicVariables is set on the script measure)
Retrieves user specified values from variables and handles to measures and meters ]]
function Initialize()
-- grab script measure options
local opts = getMeasureOptions( SELF, Settings_Meta )
-- read settings
Settings.init(opts)
-- get measure/meter refs
Handles.init(opts)
-- run some tests
-- test()
end
--[[ Run on Update - We need to update two different string meters on every tick,
So we use a bang for both and do not return a value. ]]
function Update()
-- get current temp
local temp = tonumber(Handles.Temperature_Measure:GetStringValue())
-- WebParser will not have returned values for the first few update ticks
if temp ~= nil then
local subString = getSubString(temp, Settings.Unit)
local size = tonumber(SKIN:GetVariable('size', 1))
local substringLength = string.len(subString)
setMeterText(Handles.Main_Meter, getMainString(temp))
setMeterText(Handles.Sub_Meter, subString)
SKIN:Bang('!SetVariable', 'substringLength', substringLength)
SKIN:Bang('!SetVariable', 'substringX', substringLength * (size * 0.17))
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment