Today's shaping up to be pretty good. I give today a 10/10.
#Region "Structs"
Private Structure WeatherTable
Public nodTimeLayout As XmlNode
Public nodData As XmlNode
End Structure
Private Structure WeatherData
Public wtHighTemp As WeatherTable
Public wtLowTemp As WeatherTable
Public wtPointTemp As WeatherTable
Public wtLiquidPrecip As WeatherTable
Public wtSnowPrecip As WeatherTable
Public wtPrecipProb As WeatherTable
Public wtWindSpeed As WeatherTable
Public wtWindDirection As WeatherTable
Public wtCloudCover As WeatherTable
End Structure
Private Structure TemperatureData
Public F As Integer
Public ReadOnly Property C() As Integer
Get
Return Integer.Parse(Math.Round(((Double.Parse(F) - 32) / 9) * 5))
End Get
End Property
Public dt As Date
End Structure
Private Structure PrecipitationData
Public Inches As Double
Public ReadOnly Property MM() As Double
Get
Return Inches * 25.4
End Get
End Property
Public dt As Date
End Structure
Private Structure PercentData
Public Pct As Integer
Public dt As Date
End Structure
Private Structure WindData
Public Knots As Integer
Public ReadOnly Property MPH() As Integer
Get
Return Integer.Parse(Math.Round((Double.Parse(Knots) * 6076.12) / 5280))
End Get
End Property
Public Degrees As Integer
Public ReadOnly Property Dir() As String
Get
Select Case Degrees
Case 0 To 11.25, 348.75 To 360
Return "N"
Case 11.25 To 33.75
Return "NNE"
Case 33.75 To 56.25
Return "NE"
Case 56.25 To 78.75
Return "ENE"
Case 78.75 To 101.25
Return "E"
Case 101.25 To 123.75
Return "ESE"
Case 123.75 To 146.25
Return "SE"
Case 146.25 To 168.75
Return "SSE"
Case 168.75 To 191.25
Return "S"
Case 191.25 To 213.75
Return "SSW"
Case 213.75 To 236.25
Return "SW"
Case 236.25 To 258.75
Return "WSW"
Case 258.75 To 281.25
Return "W"
Case 281.25 To 303.75
Return "WNW"
Case 303.75 To 326.25
Return "NW"
Case 326.25 To 348.75
Return "NNW"
End Select
End Get
End Property
Public dt As Date
End Structure
Private Structure FormattedWeatherData
Public HighTemp() As TemperatureData
Public LowTemp() As TemperatureData
Public PointTemp() As TemperatureData
Public LiquidPrecip() As PrecipitationData
Public SnowPrecip() As PrecipitationData
Public PrecipProb() As PercentData
Public Wind() As WindData
Public CloudCover() As PercentData
End Structure
#End Region
#Region "NWS XML Reader http://www.nws.noaa.gov/forecasts/xml"
Private Function FindLayoutTable(ByVal xmlDoc As XmlDocument, ByVal nodData As XmlNode)
Dim nlTimeLayouts As XmlNodeList = xmlDoc.SelectNodes("/dwml/data/time-layout")
Dim strTimeLayout As String = nodData.Attributes("time-layout").Value
Dim node As XmlNode
For Each node In nlTimeLayouts
If strTimeLayout = node.SelectSingleNode("layout-key").InnerText Then
Return node
End If
Next
Return Nothing
End Function
Private Function ParseDateTime(ByVal str As String) As Date
Return Date.Parse(str.Replace("T", " ").Substring(0, str.LastIndexOf("-")))
End Function
Private Sub FillTemperatureData(ByVal wt As WeatherTable, ByRef temp() As TemperatureData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(temp) - 1
temp(intCount) = New TemperatureData()
temp(intCount).F = Integer.Parse(nlData(intCount).InnerText)
temp(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillPrecipitationData(ByVal wt As WeatherTable, ByRef precip() As PrecipitationData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(precip) - 1
precip(intCount) = New PrecipitationData()
If Len(nlData(intCount).InnerText) = 0 Then
precip(intCount).Inches = 0
Else
precip(intCount).Inches = Double.Parse(nlData(intCount).InnerText)
End If
precip(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillPercentData(ByVal wt As WeatherTable, ByRef pct() As PercentData)
Dim intCount As Integer
Dim nlData As XmlNodeList = wt.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(pct) - 1
pct(intCount) = New PercentData()
pct(intCount).Pct = Integer.Parse(nlData(intCount).InnerText)
pct(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Sub FillWindData(ByVal wtSpeed As WeatherTable, ByVal wtDir As WeatherTable, ByRef wind() As WindData)
Dim intCount As Integer
Dim nlSpeed As XmlNodeList = wtSpeed.nodData.SelectNodes("value")
Dim nlDir As XmlNodeList = wtDir.nodData.SelectNodes("value")
Dim nlDate As XmlNodeList = wtSpeed.nodTimeLayout.SelectNodes("start-valid-time")
For intCount = 0 To UBound(wind) - 1
wind(intCount) = New WindData()
wind(intCount).Knots = Integer.Parse(nlSpeed(intCount).InnerText)
wind(intCount).Degrees = Integer.Parse(nlDir(intCount).InnerText)
wind(intCount).dt = ParseDateTime(nlDate(intCount).InnerText)
Next
End Sub
Private Function ParseForecastXML(ByVal strXMLWeather) As FormattedWeatherData
Try
'Setup variables
Dim xmlDoc As New XmlDocument()
Dim wdData As New WeatherData()
Dim fwdData As New FormattedWeatherData()
wdData.wtHighTemp = New WeatherTable()
wdData.wtLowTemp = New WeatherTable()
wdData.wtPointTemp = New WeatherTable()
wdData.wtLiquidPrecip = New WeatherTable()
wdData.wtSnowPrecip = New WeatherTable()
wdData.wtPrecipProb = New WeatherTable()
wdData.wtWindSpeed = New WeatherTable()
wdData.wtWindDirection = New WeatherTable()
wdData.wtCloudCover = New WeatherTable()
'Load XML data
xmlDoc.LoadXml(strXMLWeather)
'Load data and their corresponding time nodes
wdData.wtHighTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='maximum']")
wdData.wtLowTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='minimum']")
wdData.wtPointTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='hourly']")
wdData.wtLiquidPrecip.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/precipitation[@type='liquid']")
wdData.wtSnowPrecip.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/precipitation[@type='snow']")
wdData.wtPrecipProb.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/probability-of-precipitation[@type='12 hour']")
wdData.wtWindSpeed.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/wind-speed[@type='sustained']")
wdData.wtWindDirection.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/direction[@type='wind']")
wdData.wtCloudCover.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/cloud-amount[@type='total']")
wdData.wtHighTemp.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtHighTemp.nodData)
wdData.wtLowTemp.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtLowTemp.nodData)
wdData.wtPointTemp.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtPointTemp.nodData)
wdData.wtLiquidPrecip.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtLiquidPrecip.nodData)
wdData.wtSnowPrecip.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtSnowPrecip.nodData)
wdData.wtPrecipProb.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtPrecipProb.nodData)
wdData.wtWindSpeed.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtWindSpeed.nodData)
wdData.wtWindDirection.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtWindDirection.nodData)
wdData.wtCloudCover.nodTimeLayout = FindLayoutTable(xmlDoc, wdData.wtCloudCover.nodData)
'Setup formatted data variables
ReDim fwdData.HighTemp(wdData.wtHighTemp.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.LowTemp(wdData.wtLowTemp.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.PointTemp(wdData.wtPointTemp.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.LiquidPrecip(wdData.wtLiquidPrecip.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.SnowPrecip(wdData.wtSnowPrecip.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.PrecipProb(wdData.wtPrecipProb.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.Wind(wdData.wtWindSpeed.nodTimeLayout.SelectNodes("start-valid-time").Count)
ReDim fwdData.CloudCover(wdData.wtCloudCover.nodTimeLayout.SelectNodes("start-valid-time").Count)
'Fill in data
FillTemperatureData(wdData.wtHighTemp, fwdData.HighTemp)
FillTemperatureData(wdData.wtLowTemp, fwdData.LowTemp)
FillTemperatureData(wdData.wtPointTemp, fwdData.PointTemp)
FillPrecipitationData(wdData.wtLiquidPrecip, fwdData.LiquidPrecip)
FillPrecipitationData(wdData.wtSnowPrecip, fwdData.SnowPrecip)
FillPercentData(wdData.wtPrecipProb, fwdData.PrecipProb)
FillWindData(wdData.wtWindSpeed, wdData.wtWindDirection, fwdData.Wind)
FillPercentData(wdData.wtCloudCover, fwdData.CloudCover)
Return fwdData
Catch ex As Exception
Return Nothing
End Try
End Function
#End Region Dim weather As New gov.weather.ndfdXML()
Dim params As New gov.weather.weatherParametersType()
params.maxt = True
params.mint = True
params.temp = True
params.qpf = True
params.snow = True
params.pop12 = True
params.wspd = True
params.wdir = True
params.sky = True
Dim fwdWeather as FormattedWeatherData = ParseForecastXML(weather.NDFDgen(sngLatitude, sngLongitude, "time-series", Now, Now.AddDays(30), params))
weather = Nothing
params = Nothing

Today's shaping up to be pretty good. I give today a 10/10.

In California, truck license plates are 7 characters, all numbers except for one letter in either the second or the sixth position. Whenever that letter is an X, I get nerd snipped into treating it as a multiplication problem and solving it in my head.

Crap, we pulled an extra pack of gargoyles and wiped! Damn DPS.

Okay I've been warned to watch out for the lizard people... And the final boss is some horse named Blucifer...

Just landed in Denver and I can't get it out of my mind that this was a FFXIV cutscene for
THE ILLUMINATI HEADQUARTERS
DENVER, COLORADO
Yikes. I hope the tank's good.

we should have paid more attention to the cats who, for decades, put their bodies on the line to walk on keyboards and sit on laptops and prevent us from programming

The Eagles took it to the limit WAY more than one more time.

Is that... T-Pain?
Take a good hard look at the mother fucking float.

Did you know that Pavlov's hair was famously soft and silky?
It's because he conditioned it. :ablobcatlurk:

And when the groundhog saw its shadow, the people declared:
"FOUR MORE YEARS OF STRESS EATING!"

Boss: "We need to come up with a number of hours it will take to do this super big project."
Me: "Do you want that number written out, or can I use exponential form?"
🙃

I guess you CAN'T do it with True Value. https://www.cnn.com/2024/10/14/business/true-value-bankruptcy

Former 2 time world champion DogPlayingTetris becomes the first player to ever rollover the level counter in NES Tetris, performing what's known in the community as "Rebirth". Final score: 29,486,164, 4216 lines, level 347 (256 + 91)... all huge world records. #tetris

Back row... Mother with screaming infant, 300 lb linebacker, and me. Or what's left of me. #airporthell

I'd also love a 6 hour layover overnight instead of taking the red eye I was going to take and be 7 hours later getting into Cleveland than I wanted, why do you ask? #airporthell

Why yes, I'd love to leave at 4:40 to get to the airport at 6:20 for an 8:20 flight that got delayed to 9:05 which is too late for my connection so now I'm on a 10:20 flight instead. Why do you ask? #airporthell

I've never had as much fun on comms for a Tetris match as I did tonight with NinjaOfNinjas for the silver bracket semis and finals. What a show!

I'm not done! I'll be casting the later rounds of the silver bracket today at 6:30 PM Pacific at https://twitch.tv/classictetris3. Cya there!

I'll be live casting qualifiers today for CTWC at https://twitch.tv/classictetris2 at 1 PM Pacific and https://twitch.tv/classictetris3 at 3:30 PM Pacific. This year's CTWC is the craziest yet so don't miss it!

Just a note to everyone out there who still believes 2020 hasn't ended that today is Unquinquaginember 21st, 2020.

@shanselman Who at Microsoft do I have to bribe to fix ADO so that those of us on dark mode who copy/paste text from one task to another can do so without our friends on light mode seeing dark text on a dark background?

I updated the blog post with a statement from Revival. While I'm not particularly happy with Revival's decision, I understand their motives. It's just a shame that it was someone from Interplay that had to go and do this. "By games for gamers" my ass.

Damn, got another Tetris world record! This time in the arcade variant developed by Atari. 6,008,005 points, 5,386 lines, round 363. Be warned, it's nearly FIVE HOURS. https://www.twitch.tv/videos/2131759212

I certainly didn't have "Overload but with web3 features" on my 2024 bingo card. WTF did Revival Productions just do?
https://roncli.com/blogger/3949527510668683306/wtf-did-revival-productions-just-do

@solitha New rule: cat tax. For every pun you post or repost, you're now required to pay the tax of posting one cute cat video.

Today was a special day. I scored 1,016,221 points in classic NES Tetris, the first time I broke the 999,999 maxout barrier.
With that maxout, I became the oldest person to get their first ever maxout at 46 years 319 days.
After I scored that, I learned that today would have been 7-time Tetris world champion Jonas Neubauer's 43rd birthday.
I am FILLED with incredible emotion tonight.
https://clips.twitch.tv/AverageImportantGoldfishHassaanChop-bRfUxo4q5SxEgJvI

"I'm Sorry, What?!" The biggest bailout in the history of Descent II! https://www.youtube.com/watch?v=GLlTk7wa59A

“BART anime merch" are three words that I would not have expected to go together, but here we are. https://www.railgoods.com/bart/anime/

Does anyone else sing the chorus to "Cherish" by Kool & The Gang to themselves whenever they play or watch streams of Balatro? Or is that just me?

I'm fact that's what Lingo needs: a "phone" block. The clue is an incorrect autocorrected form of the answer. 🙃

It's like my phone knows I've been playing Lingo. I typed in "exited" and my phone was all:
⬜️ EXCITED ------
▪️
▪️