|
|
Thursday, March 31, 2005 |
Updated NWS Code
Posted: 10:17:00 PM
|
Now playing: Atomship - Pencil Fight (3:38)
Mikhail's code was enough to get me started on combining all of the various parameters I wanted (just the relative ones, none of this dewpoint crap) together to come up with one single variable that has all of the forecast possible for one location.
#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
A little more complicated in some ways, a bit simpler in others, but the data is complete. To call the web service and retrieve the data:
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
fwdWeather now has all the forecasting data you need. It also has easy functions to convert F to C, Knots to MPH, and Inches to Millimeters.
Not bad for a day of research and coding! Now if only they'd make web services for current conditions and severe weather statements, I'd be all set.Labels: Coding, NWS, VB.NET
|
Damn Hackers
Posted: 5:51:00 PM
|
Now playing: Atomship - Pencil Fight (3:38)
I've been using w.bloggar as my method to post since I started this thing... It's very useful and puts a little "b" in the systray, which I leave visible all the time as a reminder for me to not ignore my blog. It's worked rather well so far, until I've had to edit a post.
Apparantly, w.bloggar is getting some sort of "invalid property value" whenever I try to load up an old post. It loads the text fine, but when I go to update the post, it actually creates a NEW post.
No problem, I figure, I'll just go to the website, wbloggar.com, check for a new version, or report a bug. Well, I guess they have an invalid property value thing going on too, no site comes up. A quick run at the source reveals the reason.
<!--r00t by Team g0dmode, greets to BasS-Z & Para Sh4rk!-->
PWNED!!!!!1111one11!!1onetwo11six11shiftone!!!111½½¼¼¼ Bastard hackers.Labels: Hackers, Life, w.bloggar
|
NWS XML web service for VB.Net
Posted: 5:35:00 PM
|
Now playing: Atomship - Pencil Fight (3:38)
In my quest for consuming the NWS XML Web Service, I came across this blog post by Mikhail Arkhipov over at Microsoft. He has available for download a bit of code that allows you to consume said web service. Problem is, it's in C#.Net.
After reading the code and finally understanding NWS's NDFD format, I went ahead and converted the C#.Net code to VB.Net. Now, this isn't the first time I've done something with C# code, so it was fairly easy to go through the code and come up with a VB.Net equivalent. In fact, it was dead easy.
Anyway, I figured I'd post my conversion. The code is practically identical, except I chagned the variable names to suit the standards I'm used to.
First, create a new project and add a web reference to http://weather.gov/forecasts/xml/SOAP_server/ndfdXMLserver.php?wsdl. This will hook you into NWS's free service.
Second, add this bit of code to your project.
#Region "Structs"
Private Structure DayWeatherData
Public dtDate As Date
Public strLowTempF As String
Public strHighTempF As String
Public strLowTempC As String
Public strHighTempC As String
Public strCloudIconURL As String
End Structure
Private Structure WeatherTable
Public nodTimeLayout As XmlNode
Public nodData As XmlNode
End Structure
#End Region
#Region "NWS XML Reader http://www.nws.noaa.gov/forecasts/xml"
'Converted to VB.Net by Ronald M. Clifford
'Original C#.Net by Mikhail Arkhipov
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 Sub FillLowTemperatures(ByVal nodXML As XmlNode, ByRef dwdData() As DayWeatherData)
Dim nlNodes As XmlNodeList = nodXML.SelectNodes("value")
Dim intCount As Integer
For intCount = 0 To UBound(dwdData) - 1
dwdData(intCount).strLowTempF = nlNodes(intCount).InnerText
dwdData(intCount).strLowTempC = Math.Round(5 * (Double.Parse(dwdData(intCount).strLowTempF) - 32) / 9).ToString
Next
End Sub
Private Sub FillHighTemperatures(ByVal nodXML As XmlNode, ByRef dwdData() As DayWeatherData)
Dim nlNodes As XmlNodeList = nodXML.SelectNodes("value")
Dim intCount As Integer
For intCount = 0 To UBound(dwdData) - 1
dwdData(intCount).strHighTempF = nlNodes(intCount).InnerText
dwdData(intCount).strHighTempC = Math.Round(5 * (Double.Parse(dwdData(intCount).strHighTempF) - 32) / 9).ToString
Next
End Sub
Private Function ParseDateTime(ByVal str As String) As Date
Return Date.Parse(str.Replace("T", " ").Substring(0, str.LastIndexOf("-")))
End Function
Private Sub FillDayNameAndTime(ByVal nodLows As XmlNodeList, ByVal nodHighs As XmlNodeList, ByRef dwdData() As DayWeatherData)
' Choose first elemnt from low or high list depending on what is close to the current time.
' Typically weather report is about 'today' or 'tonight' on the current day or about
' day temperatures for the coming days. Therefoce remaining elements always come from
' the high temperatures list.
Dim dtFirstLow As Date = ParseDateTime(nodLows(0).InnerText)
Dim dtFirstHigh As Date = ParseDateTime(nodHighs(0).InnerText)
Dim dtNow As Date = Now
Dim nlNodes As XmlNodeList
If dtFirstLow.Day = dtNow.Day And dtFirstHigh.Day = dtNow.Day Then
' choose nearest
Dim intDiffFromLow = Math.Abs(dtFirstLow.Hour - dtNow.Hour)
Dim intDiffFromHigh = Math.Abs(dtFirstHigh.Hour - dtNow.Hour)
If intDiffFromHigh < intDiffFromLow Then
nlNodes = nodHighs
Else
nlNodes = nodLows
End If
ElseIf dtFirstHigh.Day = dtNow.Day Then
' choose highs
nlNodes = nodHighs
Else
' choose lows
nlNodes = nodLows
End If
Dim intCount As Integer
For intCount = 0 To UBound(dwdData) - 1
Dim dt As Date = ParseDateTime(nlNodes(intCount).InnerText)
If intCount = 0 Then
dwdData(intCount).dtDate = dt
Else
dwdData(intCount).dtDate = New Date(dt.Year, dt.Month, dt.Day, 12, 0, 0)
End If
Next
End Sub
Private Sub FillCloudData(ByVal wt As WeatherTable, ByRef dwdData() As DayWeatherData)
' Cloud data is typically much longer than day high/low data
' We need to find times that match ones in high and low temp tables.
Dim nlTimes As XmlNodeList = wt.nodTimeLayout.SelectNodes("start-valid-time")
Dim nlIcons As XmlNodeList = wt.nodData.SelectNodes("icon-link")
Dim intWeatherData As Integer = 0
Dim intNodes As Integer = 0
Dim intHourDiff As Integer = Integer.MaxValue
Dim nodXML As XmlNode
For Each nodXML In nlTimes
Dim dt As Date = ParseDateTime(nodXML.InnerText)
If dt.Date > dwdData(intWeatherData).dtDate.Date Then
intWeatherData += 1
If intWeatherData > UBound(dwdData) Then Exit For
intHourDiff = Integer.MaxValue
End If
If dt.Date = dwdData(intWeatherData).dtDate.Date Then
Dim intDiff As Integer = Math.Abs(dt.Hour - dwdData(intWeatherData).dtDate.Hour)
If intDiff < intHourDiff Then
intHourDiff = intDiff
dwdData(intWeatherData).strCloudIconURL = nlIcons(intNodes).InnerText
End If
End If
intNodes += 1
Next
End Sub
Private Function ParseWeatherXML(ByVal strXMLWeather) As DayWeatherData()
Try
Dim dwd() As DayWeatherData
Dim xmlDoc As New XmlDocument()
' load XML data into a tree
xmlDoc.LoadXml(strXMLWeather)
' locate dwml/data/time-layout nodes. There should be three of them:
' - next week nighttime temperatures (lows)
' - next week daytime temperatures (highs)
' - next week cloud data
' Find roots nodes for temperature and cloud data
Dim wtLowTemp As New WeatherTable()
Dim wtHighTemp As New WeatherTable()
Dim wtClouds As New WeatherTable()
wtLowTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='minimum']")
wtHighTemp.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/temperature[@type='maximum']")
wtClouds.nodData = xmlDoc.SelectSingleNode("/dwml/data/parameters/conditions-icon")
' Find out corresponding time layout table for each top data node
wtLowTemp.nodTimeLayout = FindLayoutTable(xmlDoc, wtLowTemp.nodData)
wtHighTemp.nodTimeLayout = FindLayoutTable(xmlDoc, wtHighTemp.nodData)
wtClouds.nodTimeLayout = FindLayoutTable(xmlDoc, wtClouds.nodData)
' Number of day data is min of low and high temperatures
Dim nlLowTimes As XmlNodeList = wtLowTemp.nodTimeLayout.SelectNodes("start-valid-time")
Dim nlHighTimes As XmlNodeList = wtHighTemp.nodTimeLayout.SelectNodes("start-valid-time")
Dim intTimes As Integer = Math.Min(nlLowTimes.Count, nlHighTimes.Count)
Dim dwdData(intTimes) As DayWeatherData
Dim intCount As Integer
For intCount = 0 To intTimes - 1
dwdData(intCount) = New DayWeatherData()
Next
' Fill highs and lows
FillLowTemperatures(wtLowTemp.nodData, dwdData)
FillHighTemperatures(wtHighTemp.nodData, dwdData)
FillDayNameAndTime(nlLowTimes, nlHighTimes, dwdData)
FillCloudData(wtClouds, dwdData)
Return dwdData
Catch ex As Exception
Return Nothing
End Try
End Function
#End Region
Finally, simply make a call to their web service.
Dim weather As New gov.weather.ndfdXML()
Dim params As New gov.weather.weatherParametersType()
params.maxt = True
params.mint = True
params.icons = True
Dim strWeatherXML As String = weather.NDFDgen(39, -77, "time-series", Now, Now.AddDays(5), params)
weather = Nothing
params = Nothing
Dim dwdWeather() As DayWeatherData = ParseWeatherXML(strWeatherXML)
You now have a DayWeatherData object, dwdWeather, that contains the highs and lows for the day, along with a URL to an icon that displays the type of weather to expect for the day. This is ultra basic. If you check out the NWS site, you'll find there are many other options you can add in, including cloud cover, percipitation chance and amount, and a couple other things. You'll have to code the XML reader to parse these things, but it's pretty easily done. And best of all, it's free!
The only down side to this is that you need to come up with the latitude and longitude (negative for the western hemisphere) for the location you want to use, which means you'll need to grab a Zip Code to latitude & longitude database.Labels: Coding, NWS, VB.NET
|
Web Junkie
Posted: 5:16:00 PM
|
Now playing: Atomship - Pencil Fight (3:38)
Here it is about 5:15 in the afternoon. I've been up since about 8 in the morning, mostly trying to figure out the NWS XML web service. I eventually got it (more on that in my next post) thanks to a website that had downloadable code available that consumes the service.
So, I wanted to make a post here in my blog about it. I open up Crazy Browser, got to the history, and click on "today". How many freaking websites did I visit today?! The list is absolutely ENORMOUS, showing over 100 sites.
Am I a junkie or what?Labels: Coding, Crazy Browser, Life, NWS
|
Monday, March 28, 2005 |
Lose That Buger Belly!
Posted: 7:21:00 PM
|
Found this inside our regular Chic-Fil-A in Meyerland.
Labels: Chick-Fil-A, Life, Silliness
|
Sleep is Needed?
Posted: 3:43:00 PM
|
Now playing: dfast - rauhaisa (3:05)
I can code VB in my sleep. C++ is a different story.
After pulling a 30 hour marathon Saturday/Sunday for no reason other than I wasn't tired, I woke up this morning (I think it was around 1:30 AM) and did stuff throughout the day. About 12 hours into being awake, I started playing with the textboxes again. I fixed some annoying bugs I was having with them, and then decided that I would start adding features. One of which is the ability to use the tab key to go between textboxes.
Well, it wasn't working, and I couldn't for the life of me figure out what was wrong. I went into the debugger to see what the key code was. It was coming back as a "9" as expected. Alright, that meant that it was likely the "9" didn't equal CSKEY_TAB. Right? I go and look, and CSKEY_TAB is defined to '\t'.
This is where the lack of sleep comes in. I thought, "Oh wait, \t is 20! It should be \i instead!!"
So I spent an hour trying to figure out 1) Why CSKEY_TAB wasn't '\i', and 2) Why tab worked in OTHER Crystal Space applications. After looking around for some documentation on keyboard events in Crystal Space and finding nothing, I decided to work up the nerve to ask on #crystalspace on IRC. The conversation went something like this.
roncli: Hmm. CSKEY_TAB is defined as '\t' (20), but when I hit tab, it's coming back with '\i' (9)... Is that normal?
res2k: roncli: \t should be 9
res2k: looks to me like you believe '\X' would resolve to the index of X in the alphabet, which is totally wrong
That's when the error in what I was doing sunk in, and when I decided to crawl into a little hole for a while I went back and studied what I apparantly didn't learn reading my C++ materials.Labels: Coding, Crystal Space, Life, Sleep
|
Sunday, March 27, 2005 |
More on Textboxes
Posted: 11:25:00 AM
|
I went ahead and played some more with Textboxes, and they really weren't too hard to figure out. About the toughest time I had is what to do with Backspace & Delete. But it handles most things right now, with the rest of the required features soon on its way. Once I get through making textboxes working right, the rest of the settings page is going to seem like a breeze. Labels: Cent, Coding, Crystal Space, Gaming
|
Saturday, March 26, 2005 |
Making Textboxes Ain't Easy
Posted: 7:52:00 PM
|
Now playing: Peter Enroth - Tarmdansen (3:00)
In Cent there is going to be several places where you can type in text. Naturally, I want to have a decent GUI and give the user a textbox within which they may place their text. In VB, or anything else that's got a form designer for that matter, this is a snap. Just drag and drop a textbox onto your form and you've got yourself a nice textbox.
However, I'm not using a form designer. Instead, I'm coding every aspect of the display, which means I can't just drag and drop things. For images, buttons, and text this isn't too bad. However, the fun began when I wanted a textbox a user can edit.
Now, Crystal Space has some sort of Windowing System. I didn't look too much into it, but from what I gather it's quite complicated. So I figured I'd do my own controls. How hard can it be anyway?
Textboxes hurt. Think of all the things you take for granted. When you click inside a textbox, what actually happens? You've gotta figure out where in the textbox the user clicked. But that's not enough! You have to calculate what character is at the point the user clicked, find out if it's closer that character's left side or right side, and move the cursor there. To do this, you must know how wide each character is and exactly where on the screen it is positioned.
And what if the text is too wide for the field? AARGH!!! As you can see, this gets really ugly really quick. Thank goodness for reusable code.
In any case, so far I've got my text box properly clickable so that the cursor appears in the right place. I just have to add in the eye candy (I-beam mouse when you're over the textbox, and a flashing cursor), and the ability to actually... you know... type characters into the box.
Moving? Yes. Slowly? Definitely.Labels: Cent, Coding, Crystal Space, Gaming
|
Liquid War
Posted: 4:02:00 PM
|
Perhaps the craziest and most addictive game I've played in a long time, check out Liquid Wars. It has many different maps along with skill settings you can tweak. And it's visually mesmerizing, too. Labels: Gaming, Liquid Wars
|
Sunday, March 20, 2005 |
Poker
Posted: 4:59:00 AM
|
Texas Hold'em, all in, with a pair of 5's in the hole, and a 5 and two 8's showing... losing to a straight flush... ugh! It's tough losing with a full house, but still a heck of a lot of fun. I'll definitely have to go poker playing again in the near future. Labels: Life, Poker
|
Friday, March 18, 2005 |
Slow Going
Posted: 2:16:00 AM
|
Now playing: troupe - rfc1459 (3:19)
I've been working on the routines to load, save, and manipulate the pilot and controller profiles in preparation of getting the settings section of Cent fully functional. So far it's been like most programming tasks - long, drawn out, and quite repetative.
So needless to say, it's been slow going, but the good news is that it's at least been going. It's still going to be a while before I have a nice 3D shot up here, but my mantra of "functionality before beauty" and the knowledge that I'm doing things the right way the first time (hopefully!) keeps me motivated.
I've actually thought about taking a break to start designing some maps for the game, but my mild unfamiliarity with Blender combined with the fact that there is no good Crystal Space exporter from within Blender (at least not using the latest buggy Python version anyway, that's another story in and of itself) kinda makes me wanna pass for now and focus on the programming aspect.
Plus there's still OSMusic stuff to work on, which I haven't touched in quite some time. So many projects, so little time. Who's bright idea was it to only put 24 hours in a day anyway? It needs at least 40.Labels: Blender, Cent, Coding, Crystal Space, Gaming, OSMusic.Net
|
Tuesday, March 15, 2005 |
Troupe
Posted: 8:14:00 PM
|
Now playing: roncli, The Nightstalker - Cent Credits (2:40)
Met up with Troupe today, who's in town with his family. Didn't do much more than talk shop about Reason/ModPlug/Renoise/Outpost/CTG/TiS, but it was still fun. I'm hoping we can get together and whip out some totally kickass tune at some point before he leaves, he's a very talented musician, worth checking out!Labels: Life, Troupe
|
Music Clean Up
Posted: 8:11:00 PM
|
Now playing: roncli, The Nightstalker - Cent Main Theme (2:28)
I cleaned up the Cent Music a bit. centMain.ogg is of higher quality, and has a new guitar solo to boot. I am still not entirely pleased with it yet, especially the fake-sounding guitar, but it's getting there. centCredits.ogg is also new, I replaced the piano with a better sounding one. Horray for Reason 3.0!Labels: Cent Credits, Cent Main Theme, Music
|
Sunday, March 13, 2005 |
Cent Settings Screenshot
Posted: 11:47:00 PM
|
Now playing: AmBeam - Heartland (9:34)
Just posting a screenshot of the settings page for Cent.
Labels: Cent, Coding, Gaming, Screenshot
|
Saturday, March 12, 2005 |
Comparing Cherries to Pears
Posted: 5:35:00 PM
|
Now playing: roncli, The Nightstalker - Cent Credits (2:37)
Read a blog post today about the product CherryOS, which is essentially a Mac OS X emulator for Windows. It turns out that CherryOS stole most of their code from PearPC, and are categorically denying it.
How stupid do you have to be to rip off someone else's software? I mean really, in this day and age when people will sue at the drop of the hat for ridiculously stupid things, this company's really gotta have its head in the ground if they believe that just because it's open source means that they're not going to get sued. Sure, the people running PearPC may not have the time or resources to start a lawsuit, but it's just a matter of time before someone does on their behalf.
Incredible the idiocy of some people.Labels: CherryOS, Editorials, PearPC
|
Thursday, March 10, 2005 |
Cent Main Theme
Posted: 10:48:00 PM
|
More Cent music, this time the Main Theme.
Cent's just about all I've been working on in my spare time, hence the lack of updates. When I get some more exciting screenshots, I'll start posting. In the meantime, enjoy the soundtrack.Labels: Cent Main Theme, Music
|
Tuesday, March 08, 2005 |
Cent Credits
Posted: 7:47:00 PM
|
Now playing: roncli, The Nightstalker - Cent Credits (2:37)
I finished up the credits tune today, had a bit of fun on my keyboard making it too. It took me back about 12 years when I used to write tunes solely for the piano all the time. Anyway, check out Cent Credits. If you've listened to the intro tune I posted earlier, the beginning and end of this one follow the same theme.Labels: Cent Credits, Music
|
New Music
Posted: 11:09:00 AM
|
Now playing: roncli, The Nightstalker - roncli Productions Intro (0:13)
Just a note that I have a new piece up, roncli Productions Intro. It's a 13s OGG file that will serve as the intro for Cent.
I'm working on the credits version, which is basically just a piano version of this combined with the main theme. The upside is that I will be recording it all into reason with my MIDI keyboard, so it should sound pretty sweet.Labels: Music, roncli Productions Intro
|
Monday, March 07, 2005 |
Google Desktop Search
Posted: 1:04:00 PM
|
Now playing: Karmann - Number 27 (5:30)
Google continues to impress me with the quality of the products that they put out. Today I downloaded the Google Desktop Search. Easy install, and great integration with your desktop. Get this, it'll even put search results from your desktop into your google.com search results, all without sending anything to Google. It's absolutely brilliant, and makes all my other file finding utilities I've downloaded over the years irrelevant.
Google rocks.Labels: Google Desktop, Software
|
Saturday, March 05, 2005 |
Crystal Space
Posted: 10:47:00 AM
|
What have I been working on?
This is my pet project lately, working with Crystal Space to make an application. What sort of application? Well, it's not very far along yet, so giving out any details would be unfair.
But the interesting thing about this is that I understand the engine, and even with my limited knowledge of C++, I can do some pretty neat things. How far will this go? Only time will tell.Labels: Cent, Coding, Crystal Space, Gaming, Screenshot
|
Thursday, March 03, 2005 |
Crystal Space
Posted: 8:44:00 PM
|
Now playing: Karmann - Number 27 (5:30)
I've spent the last couple of days - in between tweaking video settings - playing with the Crystal Space engine. For the first time, I am beginning to really understand C++ classes, and the result is the language getting easier for me to learn. I still get occasional oddities that I'm not immediately sure how to resolve, but they are becoming more and more trivial.
That said, the Crystal Space engine is really nice. Not only does it have a full 3D renderer, but it takes care of a lot of common problems associated with coding a 3D app. If this takes off, I'll be able to do some seriously cool things with it.Labels: Coding, Crystal Space
|
Pushing the Limits
Posted: 6:48:00 AM
|
Now playing: RedHeat Sonic Soundscapes - Outer Circle (Vocal, Dance) (4:50)
A followup on the screen resolution.
I did end up finding a good application called PowerStrip that allows you to totally tweak out your monitor and customize it's resolutions.
Not only can I experience the computing bliss of 2048 by 1536 at a eye-pleasing 64 Hz, I can also play Descent 3 at a screen resolution of 800 by 600 at a mind-blowing 158 Hz! The game is so fluid at that refresh rate, very enjoyable experience.
The only thing that bothers me about my ungodly large resolution is patches of bright white. I've actually tweaked the contrast down about a bit, and may go more should I get bothered by it. But for now, I'm content stretching my monitor's capabilities to the limit!Labels: Monitor Resolution, PowerStrip, Software
|
Wednesday, March 02, 2005 |
Side Effects
Posted: 1:01:00 PM
|
Now playing: Sagal - National Geographic Mix (11:37)
I don't know where or why, but at some point I lost Open GL capability on my Raedon 8500. I ended up going to ati.com for the latest drivers just to be safe.
It didn't fix my OpenGL problem, but the next time I showed up in the Display Properties, I had a surprise waiting for me - more video options! For the past several years I've been running at a 1600 by 1200 resolution, largely because my 19" Mag Innovision monitor supposedly can't do more.
Well, these new drivers certainly put this monitor in it's place. It can go as high as 1920 by 1440! Unfortunately for me, that is only available in a 60 Hz refresh rate which kills my eyes, I have found through testing I need at least 66 Hz.
However, I was able to squeeze another 384,000 pixels out of my desktop, expanding the right edge of my screen by a full 320 pixels to a new resolution of 1920 by 1200, running at 75 Hz! It's going to take a while to get used to the horizontal compression I'm sure, but hey, I'll take all the pixels I can get. The more, the merrier.
I've heard of some programs that allow you to tweak the refresh rate of your video. I may try that later and see if I can't fake out my monitor to run the 1920 by 1440 at 66 Hz or more, which is approximately the lower limit of comfort for my eyes. But for now, viva la desktop real estate!
Oh yeah, if you know how to fix my OpenGL, let me know...Labels: Life, Monitor Resolution
|
Attention BitTorrent Client Writers
Posted: 10:53:00 AM
|
Have you ever heard of MULTITHREADING for Pete's sake?!
I've now downloaded four different BitTorrent clients, all of which choke on the MAME complete ROM set, because there's thousands of files to download and whoever coded these lame BitTorrent clients didn't realize that it would be used for that purpose. Come on, people, have a little decency and be nice to your users, make your GUI not lock up when it's got a lot to do...Labels: BitTorrent, Editorials, Life
|
Tuesday, March 01, 2005 |
Clearing Up Space
Posted: 10:17:00 AM
|
Well, after about a week or so of struggling with my quickly evaporating hard drive space, I decided to do something about it. I went through all my Program Files and uninstalled everything I didn't use anymore, and deleted all of the shell folders that were left behind from previous installations. Everything went crisp and clean, and to my knowledge I didn't delete anything I needed.
The problem started when I compared the output from Disk Size Manager to my actual free space. Approximately 76,000 MB of hard drive space, approximately 6,000 MB free. DSM reported I had used 62,700 MB of disk space.
76,000 - 6,000 > 62,700. Where were the other 7 or so GB?
My first instinct was permissions. I quickly logged out and logged on as Administrator. Of course, my user account has Administrator access, so the 62,700 persisted.
Now, 6 GB is a lot of space to be honest. The problem is with NASCAR SimRacing wanting 4 GB for some ridiculous reason, and I still have about 5 GB left of CHDs to download for my full MAME collection. So I probably wouldn't have even dealt with it if I didn't have a need for the space.
Anyway, I did some searching around on Google and found a couple of possibilities. The one that worked for me was the System Restore option. Sure enough, I go in, and there it is taking up 10% - A full seven and a half gigs - of disk space. I move that down to 1%, reboot, and for the first time in months, I have double digit free space!
What annoys me the most about is is that, although Windows is reporting free space correctly, it's not reporting used space correctly. Where does Windows put the System Restore data if not on the C: drive? It's stupid.
Oh well, that's one problem licked. That's what matters.Labels: Gaming, Hard Drives, MAME, NASCAR SimRacing, Servers
|
Phone Features Poll
Posted: 6:49:00 AM
|
Now playing: Sagal - The Tragidy of Love (7:02)
Found a poll on neowin.net that asked what features would you use most on a phone. Answers ranged from MP3 Player, to Radio, to Internet, even Chat and Text Messaging.
The number one response, of course, was "Phoning!", proving that not all hope is lost in the realm of common sense.Labels: Life, Silliness
|
|