Welcome, Sit down, and make yourself comfortable.
Creating a new Sports Strip Gadget
Published on December 16, 2005 By RomanDA In OS Customization

The Birth of a Gadget
Birth does have its pains


SportStrip started out as an idea from jrthor2 on Desktop Gadgets asking: "How about a gadget that displays sports scores from say ESPN?? that would be very cool!! The following is some of the joys and pains of the birth of this gadget.

Step 1: (finding the feeds)

The first step in making a sports score gadget was to be able to pull an rss feed that has updated info.  Again, thanks to jrthor2 for finding the rss feeds that foxsports uses for their web site.

Step 2: (trying to read the rss feeds)

Ok, so now i have the feeds but since they were not really an rss feed that matched any "normal" format I had to write some custom code to be able to decode the feed into something that could be useful.

The first code is designed to pull the rss feed from the web site.
CerebroJD helped me make sure that I am always pulling the latest code by adding the "?x=" & (Second(Now) * Minute(Now) * Hour(Now)) to the url. This keeps the program from pulling a cached version of feed.

If System.InternetConnected Then
	Set http = CreateObject("Microsoft.XmlHttp")
	Uaddress = url & "?x=" & (Second(Now) * Minute(Now) * Hour(Now))
	http.Open "GET", Uaddress, False
	http.send ""
	FullText = http.responseText
	GameL = instr(x,FullText,"I made a function to pull the info from the "Fulltext" 
  so that it would be a LOT easier to get each item from the feed.
Function GetItemText(FullLine,LF_Start,LStart)
	LF_Start = LF_Start + Chr(34)
	ItemL = instr(LStart,FullLine,LF_Start)
	ItemLen = len(LF_Start)
	Start2 = ItemL+ItemLen
	If ItemL > 1 Then
		LEnd = Chr(34)
		ItemR = instr(Start2,FullLine,LEnd)
		ItemLength = ItemR - ItemL - ItemLen
		GetItemText = Mid(FullLine, ItemL+ItemLen, ItemLength)
		If len(GetItemText) < 1 Then GetItemText = ""
		GetItemText = replace(GetItemText, "&" , "&")
	Else
		GetItemText = ""
	End If
End Function

Step 3: (creating a sports "Tile")

The sport "tile" went thru about 100 different versions.  Since I had never used the CLONE feature in DX, I didn't know how to make that work.
My original idea was to use HTML since I'm used to dealing with web pages.  It actually was a web page on my server at one point.  But I realized there was no way to make it work right.  So I started to look at other widgets and things that used clones to do things.  This was a REALLY long process.  I finally got it working, it created the clones, had the right info in the tile and seemed to be working.  YEAH!!

THE CRASH

If you frequent these forums then you probably saw and read the thread "DX SUCKS!!!!" you know that DX decided to EAT my work, my code, even my backup.  This was a MAJOR setback.  To loose (at this point) 30 days of work was a major blow.   I was so upset I put everything on hold and decided to just forget it.  But after a week of venting on-line, on IRC, on IM, etc. as well as being pushed by jrthor2 to start over.  I did.

RE-CREATING THE CODE - AKA - BACKUP BACKUP BACKUP!

I had a backup in NOTEPAD of a previous version of the code that was working.  The problem was it was about 2 weeks old.  I did what I swore I would not do, I started all over.  The code actually was a lot worse then i thought.  One thing i did learn from this was to do "incremental" backups of several things.

  • Incremental Save Desktop - do this when you make any changes, but don't overwrite the same desktop over and over.
    When you make some changes, save it off as v1, V2, V3 etc.  As of this posting the last SportStrip Desktop file is V32.
  • Save as a WIDGET - This may sound like something that is the norm, but since this was going to be a GADGET not a WIDGET I just didn't want it out there in WIDGET form. But by saving things as a WIDGET you actually save EVERYTHING about you project.
    This is also done the same way, make a NEW widget for each VERSION of your code.  This way if you realize something has happened you can pull code back from an older version.
  • Save to multiple places - yeah I know this makes sense too but if you only work on things in one place (IE: my laptop) it may not be an easy thing to do.  I purchased as 200gb USB drive and have been using it as a backup drive.  Also, i have a CLONE of my laptop's hard drive that is created with TRUE IMAGE every week, so there are at least 3 version of this out there.

Step 1/2/3 ALL OVER Again:

Basically the process started all over again.  But this time I had a LOT of knowledge that I didn't have before. The process actually went a LOT faster and the code is a LOT better then it was when I started.  The cloning worked better this time, i was able to make the states change easier, and the creation of the logo's for most of the sports was made a lot easier because of  Chris Creamers SportsLogos.net.   I still needed to edit EVERY logo re-size them, make them PNG files, etc.  The Logo now contains somewhere around 100 png files. 

The new clone creation code:

Function MakeClone()
Dim i, strname
i=0
Do
i = i+1
strname = "SportTile_base" & i
Loop until DesktopX.IsObject(strname)=False
If (i > 3) And (i < Max_Tiles) Then
object.Width = 240 + (i * Tile_X_Space)
DesktopX.Object("Scroller-Cover").width = (i * Tile_X_Space) + 104
End If
DesktopX.Object("Scroller-Back").width = (i * Tile_X_Space) + 103
Desktopx.Object("UpdateScores").top = DesktopX.object("SportStrip").height - 25
Tile_Left = Tile_Left + Tile_X_Space
DesktopX.object("SportTile_base0").Clone strname, Tile_Left, Tile_Top
For x = 1 To CloneItemTotal
DesktopX.object(CloneNames(x)& "0").Clone CloneNames(x) & i, DesktopX.object(CloneNames(x)& "0").left, DesktopX.object(CloneNames(x)& "0").top
DesktopX.Object(CloneNames(x) & i).Parent = DesktopX.Object("SportTile_base" & i)
Next
Desktopx.Object("HomeTeam-Ball" & i).Visible = False
Desktopx.Object("AwayTeam-Ball" & i).Visible = False
Desktopx.Object("SportTile_HomeStandings" & i).Visible = False
Desktopx.Object("SportTile_AwayStandings" & i).Visible = False
End Function
The above uses a list of items to clone (defined at the top of the script)
CloneNames(1) = "SportTile_HomeName"
CloneNames(2) = "SportTile_HomeScore"
CloneNames(3) = "SportTile_AwayName"
CloneNames(4) = "SportTile_AwayScore"
CloneNames(5) = "SportTile_Stat"
CloneNames(6) = "HomeTeam-Logo"
CloneNames(7) = "AwayTeam-Logo"
CloneNames(8) = "HomeTeam-Ball" 
CloneNames(9) = "AwayTeam-Ball" 
CloneNames(10) = "SportTile_HomeStandings"
CloneNames(11) = "SportTile_AwayStandings"

Yeah i know some of these names are not 100% matching, but I have not had time to go in and clean everything up.

Step 4: (testing and more testing)

I had 4 or 5 people helping me test this out.  The main problem was that the only real time to check to see if it was 100% working was when the sports scores were being updated.  IE: During a game and not just one game, but all of them.  The feeds are for NHL/NFL/NBA/MLB/NCAA FB & BB and so the feeds themselves are not the same for each sport.  Each sport had to have some things different.  The main ones were in the NCAA tiles.  The school's names are so long that i had to remove the logos in order to get them to fit.  Then after the normal NCAA FB season Fox changed the feed for the Bowl games, so there was even more updates.

Step 5: (Updates?)

I realized pretty quickly that there would be a LOT of updates for this as time goes on.  The feeds change, I wanted to add scrolling of the tiles (which now work!), and a lot of other updates.  But the problem was how to let people know there was an update available.  Actually it was pretty simple, yeah you guessed it, an RSS feed from my server with the update info.  The feed has the latest version #, and a link to the new version.

Function CheckForUpdate()
     If System.InternetConnected Then
          Set http = CreateObject("Microsoft.XmlHttp")
          Uaddress = "http://(url not shown ###).xml" & "?x=" & (Second(Now) * Minute(Now) * Hour(Now))
          http.Open "GET", Uaddress, False
          http.send ""
          szCoreXML = http.responseText
          szCoreXML = Replace(szCoreXML, "'", "'")
          ' check to see if the site isn't available
          If InStr(LCase(szCoreXML), "page cannot be displayed") <> 0 Or InStr(LCase(szCoreXML), "") = 0 Then
               MsgBox "No Feed Avail at this time!"
          Exit Function
          End If
          Gadget_Title = xmlstripper("title", szCoreXML)
          Gadget_Link = xmlstripper("link", szCoreXML)
          Gadget_Ver = xmlstripper("gadgetversion", szCoreXML)
          Gadget_description = xmlstripper("description", szCoreXML)
          If len(Gadget_Ver) >1 Then
               If CDbl(Gadget_Ver) > CDbl(GadgetVersion) Then 
                    Gadget_description = Gadget_description & vbnewline & "Your Ver: " & GadgetVersion & " Updated Ver: " & Gadget_Ver
                    DesktopX.Object("SportStrip-UpdateAvail").left=(system.WorkareaRight-DesktopX.Object("SportStrip-UpdateAvail").width)/2
                    DesktopX.Object("SportStrip-UpdateAvail").top=(system.WorkareaBottom-DesktopX.Object("SportStrip-UpdateAvail").height)/2
                    desktopx.Object("SportStrip-UpdateAvail-URL").command = Gadget_Link
                    desktopx.Object("SportStrip-UpdateAvail-Desc").text = Gadget_description
                    desktopx.Object("SportStrip-UpdateAvail").visible = True
               End If
          End If
     End If
End Function

This works GREAT it allows me to make updates and give people the ability to be notified via a popup screen with a URL link.  So far the system has worked really well.

Step 6: (Demo/Trial version)

I wanted people to be able to test out my gadget before they purchase it.  My first thought was to make one that expired on a certain date, but then I would have to upload a new version all the time, and if someone wanted to keep using the FREE version then they would only need to download the latest TRAIL version.  Of course that was not going to work, so the next idea is to figure out a way to store a date in the registry and then make the trial version expire 15 days after that date.  Yep the problem there is people finding the date, and just changing it.  So what to do?
I really cant divulge the final solution (so that no one can break it) but it involved hiding the date in a format that is not easily discernable as a date. and putting it somewhere that no one would find (i hope).  This is not 100% full or HACK proof but it should eliminate most people from hacking things.  One problem with the demo version is that it doesn't show the Update notification so when i make enough changes to the gadget ill just upload the new one once a month or so.

The Working Gadget:

After almost 2 1/2 -3 months of (almost daily) updates and changes, the final version is up and working on DesktopGadgets.com.
It now has 3 different colors, has the ability to scroll the tiles left and right, show when updates are available, shows NFL/NBA/NHL/MLB/NCAA FB and BB scores LIVE as the games are on and changing.  I love to have this up and running at night when there are a lot of Basketball or NHL games going on, the tiles change colors when a team scores. When you watch a football game you can see who has the ball (a little football shows next to the teams score), it shows when a team is in the "RED ZONE" and LOTS more.  I think it turned out really well.  I have had a lot of great comments on this.  Please check out the demo (or better yet BUY THE FULL Version) here: http://www.desktopgadgets.com/ViewGadget.aspx?GadgetID=53


Above is a screen shot of the (finished) gadget.
Can anything EVER be Finished? - click HERE to download

Please please let me know what you think, It is VERY important to get feedback on things.  My plan is to make a tutorial in the early part of next year on how to do the clones and even the scrolling.

Thanks for your time,
David A. Roman
Gadgets@RomanDA.org


Comments
on Dec 16, 2005
Awesome read! Great article Roman. Than you VERY much for writing it!

Oh yeah, some better code for the non-cached url: (Second(Now)+1)*(Minute(Now)+1)*(Hour(Now)+1)*Int(Rnd()*1000)

on Dec 16, 2005
Right on, RomanDA. Even being somewhat familiar with the story, it was a great read. Too often skins or widgets are looked at only as the completed package--the process of their design and reasoning behind decidions made can be very interesting.

I guess the feed doesn't allow POST method? I'll have to remember to try that random-time trick.

Anyone else, I had the privelege of testing this gadget in some of its earlier forms. It is very cool, and works like nothing you've seen. I wholeheartedly recommend you get over to DesktopGadgets http://desktopgadgets.com/ViewGadget.aspx?GadgetID=53 and try it out.