Silverlight 3 Countdown Counter


This post is part of my Crazy Cancer Tour developer series. It covers the site as it is today (countdown counter only). You can view the site at http://crazycancertour.com. I have some additional work going on behind the scenes, but the only visible portion right now is the counter, which is done in Silverlight 3. This is how the final site looks:

FinishedSite

Setting up a counter in Silverlight is actually quite easy, as you will see in this post.

Layout In Blend

I am a firm believer in saving time with tools, so I used Blend 3 to layout the site (free trial if you need a copy to play along). This is not completely necessary, however, as XAML is just an XML dialect, which means, for the designer/developer, you have to nest things properly to get them working. When you start a new Blend 3 project (Silverlight+ Web Application in this case), you end up with a blank XAML canvas. You can then attack with either code or drag and drop, with the same end result.

The main reason to choose drag and drop over coding XAML is the ability to visually layout your design. The designer then creates the XAML for you. Now to the steps I did.

When you open Blend 3, choose a new Project. I don’t really need a screenshot, as you cannot avoid this screen, but visual is good:

NewProject

From here you create a Silverlight + Web Application project and give it a location:

Create

What you have at this time is a solution folder with two projects in it: {Projectname} and {ProjectName}Site. The later holds the HTML and JavaScript necessary to run the Silverlight application. The Projects window shows the files:

ProjectWindow

Note that I have a few extra files in the screencap above, but this is due to my having already compiled the project and having added fonts to the project. When you first open the project, you will have App.xaml and MainPage.xaml and little else. When you look at MainPage.xaml, it looks like this. The XAML button is on the upper right side of the design window and looks like less than greater than <>.

<UserControl
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="CrazyCancerCountdown.MainPage"
    Width="640" Height="480">

    <Grid x:Name="LayoutRoot" Background="White"/>
</UserControl>

When you add items, the Grid becomes the container that holds them. In my case, I am going to start by adding a screencapture that is 879 pixels by 705 pixels (I really should resize, but it works for what I need right now). I hand altered the width and height of the UserControl element and then dragged the picture on the surface, making sure its margins are 0 in the layout panel (screen cap below):

LayoutPanel

To get the screen cap on the surface, I have two choices:

  1. Add as an asset and then pull from the Assets onto the design surface. This is too many steps for me.
  2. Drag an image from Windows Explorer directly on the surface. With two monitors, like I have here, it is very easy.

The XAML now looks like the following:

<UserControl
    xmlns="
http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="CrazyCancerTour.MainPage"
    Width="879" Height="705">

    <Grid x:Name="LayoutRoot" Background="White">
        <Image x:Name="BackgroudImage" Margin="0" Source="CrazyCancer.png"
           
Stretch="Fill" Opacity="0.5"/>
    </Grid>
</UserControl>

I then need a rectangle to place my elements, so I drag one from the toolbar:

Rectangle

If the toolbar is greyed out, it is due to having your design surface in XAML mode. Click on the design icon and you should be able to drag and drop a rectangle on the surface. The Grid in the XAML then looks like the following:

<Grid x:Name="LayoutRoot" Background="White">
    <Image x:Name="BackgroudImage" Margin="0" Source="CrazyCancer.png" Stretch="Fill" Opacity="0.5"/>
    <Rectangle Stroke="Black" Margin="335,231,282,347">
        <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Black" Offset="0"/>
                <GradientStop Color="#FF340435" Offset="1"/>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
</Grid>

Rather than hand hold through the rest in a very explicit step-by-step, I am simply going to show the XAML. To get to this XAML, I dragged a header textbox on the rectangle, 4 textboxes for my numbers (days, hours, minutes and seconds), and a footer textbox that states “ Days      Hours   Minutes  Seconds”. I then tweaked the look and feel, by changing graphics, etc. The Grid now looks like this, in XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Image x:Name="BackgroudImage" Margin="0" Source="CrazyCancer.png" Stretch="Fill" Opacity="0.5"/>
    <Rectangle Stroke="Black" Margin="335,231,282,347">
        <Rectangle.Fill>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Black" Offset="0"/>
                <GradientStop Color="#FF340435" Offset="1"/>
            </LinearGradientBrush>
        </Rectangle.Fill>
    </Rectangle>
    <TextBlock x:Name="TourBeginsTextBox" Height="35" Margin="345,237,298,0" VerticalAlignment="Top" Text="The Tour Begins In" TextWrapping="Wrap" FontSize="21.333" Foreground="#FFF587EB" TextAlignment="Center" FontFamily="Fonts/Fonts.zip#Planet Benson 2"/>
    <TextBlock x:Name="DayTextBox" Height="61" Margin="345,274,0,0" VerticalAlignment="Top" Foreground="#FFFCFCFC" TextAlignment="Center" TextWrapping="Wrap" HorizontalAlignment="Left" Width="51" FontSize="32" FontFamily="Fonts/Fonts.zip#Virginie"><Run Text="00"/><LineBreak/><Run Text=""/></TextBlock>
    <TextBlock Loaded="StartTimer" x:Name="LegendTextBox" Height="25" Margin="345,322,282,0" VerticalAlignment="Top" TextWrapping="Wrap" Foreground="#FFF587EB" FontSize="14.667" FontFamily="Arial" Text=" Days      Hours   Minutes  Seconds" FontWeight="Bold" FontStyle="Italic"/>
    <TextBlock x:Name="HourTextBox" Height="61" Margin="407,274,421,0" VerticalAlignment="Top" Foreground="#FFFCFCFC" TextAlignment="Center" TextWrapping="Wrap" FontSize="32" FontFamily="Fonts/Fonts.zip#Virginie"><Run Text="00"/><LineBreak/><Run Text=""/></TextBlock>
    <TextBlock x:Name="MinuteTextBox" Height="61" HorizontalAlignment="Right" Margin="0,274,360,0" VerticalAlignment="Top" Width="51" Foreground="#FFFCFCFC" TextAlignment="Center" TextWrapping="Wrap" FontSize="32" FontFamily="Fonts/Fonts.zip#Virginie"><Run Text="00"/><LineBreak/><Run Text=""/></TextBlock>
    <TextBlock x:Name="SecondTextBox" Height="61" HorizontalAlignment="Right" Margin="0,274,297,0" VerticalAlignment="Top" Width="51" Foreground="#FFFCFCFC" TextAlignment="Center" TextWrapping="Wrap" FontSize="32" FontFamily="Fonts/Fonts.zip#Virginie"><Run Text="00"/><LineBreak/><Run Text=""/></TextBlock>
</Grid>

One thing of note in the XAML that I have not mentioned. There is a statement Loaded=”StartTime” in the Legend textbox (the footer mentioned); I have bolded it in the code above. This is a method in the C# code, which we will cover in a moment. If you try to run the code with this statement, you will have to add the following to your MainPage.Xaml.cs file, or remove the Loaded="StartTimer" from the XAML:

        public void StartTimer(object o, RoutedEventArgs sender)
        {
        }

You can now test the page and it should work, although it will not countdown.

Before moving to code, there is one more item. I have added some fonts from http://simplythebest.net/fonts/. These are freeware/donateware fonts. In particular, I have used Planet Benson and Virginie. In order to have them in my Silverlight app, I have to add them with the Font Manager. There are two ways to do this:

  1. Tools menu >> Font Manager
  2. With a textbox element selected, click on the Font Manager … button in the Text section of the Properties window

Creating the Countdown Code

I am a strong proponent of separating out concerns, both in tiers and inside individual classes. I did not start this way with this app, but every time I found a dupe, I refactored. Thus, I am not going to do a straightforward step by step here. Instead, I am going to cover regions of the code.

First, the using statements. The only one I added was the threading statement (the bottommost (bolded) statement), as that is where our timer class is:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;

Next, I have some “global” elements. I am not fond of global bits, but this is a quick, down and dirty project, and the global bits help avoid adding too much of a perf hit to the project. Essentially, I have one “counter” for each of the time elements (day, hour, minute and second), plus a dispatcher timer, which is why I added the threading namespace.

        private int seconds = 0;
        private int minutes = 0;
        private int hours = 0;
        private int days = 0;
        private DispatcherTimer dispatcherTimer;

One of hte bits I refactored out, due to dupes, is a routine that takes a number and makes sure it is two in length (in my code). The routine is flexible enough to be any length, however, so you could conceivably have a millisecond textbox in your code (with the repaint every second, it would be largely worthless, however). This “helper” routine looks like this:

        private string CreateNumericStringOfSetLength(int unit, int length)
        {
            if (unit.ToString().Length == length)
                return unit.ToString();
            else
                return unit.ToString().PadLeft(length, ‘0’);
        }

Fairly simple. If the string is already the right length it is returned, else it is padded to length with a leading zero (or leading zeros, if you are displaying milliseconds). Another refactored routine is my BindPage() routine, which will be used from my StartTimer routine and the event handler that handles updating the countdown timer. It is fairly simple, as well.

        private void BindForm()
        {
            HourTextBox.Text = CreateNumericStringOfSetLength(hours, 2);
            MinuteTextBox.Text = CreateNumericStringOfSetLength(minutes, 2);
            DayTextBox.Text = CreateNumericStringOfSetLength(days, 2);
            SecondTextBox.Text = CreateNumericStringOfSetLength(seconds, 2);
        }

Note how it uses the helper routine for the display.

To create the counter, I use my countdown date, as well as DateTime.Now to determine the initial values to bind. I am using the global day, hours, minutes, seconds to hold the values.

        public void StartTimer(object o, RoutedEventArgs sender)
        {
            DateTime tourDate = new DateTime(2009, 9, 1, 18, 10, 0, 0);
            DateTime startDate = DateTime.Now;
            TimeSpan diff = tourDate – startDate;
            days = diff.Days;
            hours = diff.Hours;
            minutes = diff.Minutes;
            seconds = diff.Seconds;

            BindForm();
        }

I can now test the form and it binds the initial values, but no countdown. To add a coundown, I need to create a routine for the countdown. here I could either repeat the steps above (and eliminate most of the globals), or I can simply countdown each second and adjust. I chose the later, as it should be less of a perf hog (untested assumption, however). The timer_Tick routine is below:

private void timer_Tick(object sender, EventArgs e)
{
    if (days + hours + minutes + seconds == 0)
    {
        dispatcherTimer.Stop();
        return;
    }

        if (seconds == 0)
        {
            seconds = 59;

            if (minutes == 0)
            {
                minutes = 59;

                if (hours == 0)
                {
                    hours = 23;
                    days–;
                }
                else
                {
                    hours–;
                }
            }
            else
            {
                minutes–;
            }

        }
        else
        {
            seconds–;
        }

        BindForm();
}

The logic is this.

  1. Check if everything is zero. If so, stop wasting cycles (stop the timer)
  2. Roll down in reverse order. Essentially decrement seconds until you get to zero, then make it 59 and decrement minutes.
  3. Repeat for minutes. When minutes are zero, then make them 59 and decrease hours.
  4. Hours are essentially the same, but reset to 23. When 0, set to 23 and decrement days.
  5. When days reach zero, they will not go any further.

The form is then bound again, using the updated “counter” values. The code should still display a static set of numbers now, as the tick routine does not run. We do have to change StartTimer to get things rollling. The bolded lines are the ones added:

        public void StartTimer(object o, RoutedEventArgs sender)
        {
            DateTime tourDate = new DateTime(2009, 9, 1, 18, 10, 0, 0);
            DateTime startDate = DateTime.Now;
            TimeSpan diff = tourDate – startDate;
            days = diff.Days;
            hours = diff.Hours;
            minutes = diff.Minutes;
            seconds = diff.Seconds;

            dispatcherTimer = new DispatcherTimer();
            dispatcherTimer.Interval = new TimeSpan(10000000); // 1 second
            dispatcherTimer.Tick += new EventHandler(timer_Tick);
            dispatcherTimer.Start();

            BindForm();
        }

Fairly simple, once again. DispatherTimer is the class that does time functions in Silverlight 2 or later. You set the Interval to 10,000,000 ticks (1 second) and add an event handler for the tick event (which we have already coded). Then you start the timer. That is all there is too it. When I am done, I have the following page:

FinishedSite

If you want to see this running, just go to http://crazycancertour.com prior to September 1, 2009 at 6:10 PM (when the “tour” begins – I may change this time, depending). If you do not have Silverlight loaded, it will take less than a minute (a few second broadband) to download and install. I will be moving my blog entries over to the Developer section of the site once it goes live and I am aiming for videos of most of these entries. I have set up a Twitter account @crazycancerdev to Tweet out new entries that come out later this month and in September. For those more interested in childhood cancer awareness, there is Twitter @crazycancertour, as well.

Peace and Grace,
Greg

Twitter: @gbworld

Google Maps in ASP.NET using LINQ to SQL (tiered)


First, let me show the inspiration for this post. The site is located at http://www.wolfpil.de/anim.html. It is a simple, cheesy kind of animation using the Google Maps API. But, it is useful for a location piece. The page looks like this:

OriginalSite

In this blog post, I am going to cover the steps necessary to make a Google map that animates, using points from a database. It is the first step in creating a location update functionality that automatically updates on a site. I am going to use this on the Crazy Cancer Tour site to be able to update from a mobile device. This is a quick and easy “how to”, and should be easy to set up following through the example.

NOTE: Everything in the current version of this article assumes Visual Studio 2008. I will go back and check for the Express versions later.

To give you an idea where I am going with this post, here is the sample project in Solution Explorer:

ProjectInSolutionExplorer

Create the Database

First, we need a database of locations. The following script will create a tour table and a location table. The tour table is to limit the mapping, which is not included in this first demo. To create the database, open SQL Server Management Studio and create a new database. When done, run this script in the new database.

CREATE TABLE dbo.Tour(
    TourId int IDENTITY(1,1) PRIMARY KEY,
    TourName nvarchar(50) NOT NULL,
    CreatedDate datetime NOT NULL,
    CreatedUserId uniqueidentifier NOT NULL
)
GO

SET IDENTITY_INSERT dbo.Tour ON
INSERT dbo.Tour (TourId, TourName, CreatedDate, CreatedUserId)
VALUES (1, N’Daily’, CAST(0x00009C66018A60CE AS DateTime), N’5e82fe2e-c973-41b4-a1be-0e345a3607f6′)
SET IDENTITY_INSERT dbo.Tour OFF
GO

CREATE TABLE dbo.Location(
    LocationId int IDENTITY(1,1) PRIMARY KEY,
    TourId int NOT NULL,
    LocationName nvarchar(50) NOT NULL,
    Latitude float NOT NULL,
    Longitude float NOT NULL,
    CreatedDate datetime NOT NULL,
    CreatedUserId uniqueidentifier NOT NULL
)
GO

SET IDENTITY_INSERT dbo.Location ON
INSERT dbo.Location (LocationId, TourId, LocationName, Latitude, Longitude, CreatedDate, CreatedUserId)
VALUES (1, 1, N’Puttgarden, Fehmarn’, 54.503143, 11.229228, CAST(0x00009C65018ACB90 AS DateTime), N’5e82fe2e-c973-41b4-a1be-0e345a3607f6′)

INSERT dbo.Location (LocationId, TourId, LocationName, Latitude, Longitude, CreatedDate, CreatedUserId)
VALUES (3, 1, N’Rødbyhavn’, 54.653278, 11.349048, CAST(0x00009C66018B2B03 AS DateTime), N’5e82fe2e-c973-41b4-a1be-0e345a3607f6′)
SET IDENTITY_INSERT dbo.Location OFF
GO

Create Data Models

The way I do this is create a project called {ProjectName].Data.Models. I then made did the following steps to get to the database:

  1. Open Server Explorer (usually with the Toolbox). If missing, it is found by Control + Alt + L (or on View >> Server Explorer)
  2. Right click on Data Connections and choose Add Connection
    CreateDataConnection
  3. Click OK

You now have a connection to the database. Add a LINQ to SQL class (CrazyCancerTour) to the project and drag the two tables on the form. It will look like this:

CrazyCancerDBML

You now have data models to work with.

Create a Data Access Layer

We now are getting a bit more complex and I have borrowed code from an earlier blog entry called “Repository Pattern in LINQ to SQL (Disconnected)”. You can click if you want some information about how I created the Repository in question. This is a Generic Repository that can work with any LINQ table.

Before coding the Repository, I need to create a DataContextFactory. The reason for this is my final project has more than one LINQ context included. First step is to create an interface. The reason for the interface is so I can test this later. Yes, I should be test driven now, but it makes for a longer post. Assume I used TDD to create this. Once I get the Crazy Cancer Dev bits up, I will revamp this post there. You will see the interface used shortly, so this is not a total wash.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace CrazyCancer.Data.Access.interfaces
{
    public interface IDataContextFactory<T>
    {
        DataContext Context {get; }
    }
}

The DataContextFactory then looks like this:

namespace CrazyCancer.Data.Access.factory
{
    public class DataContextFactory<T> : IDataContextFactory<T>
        where T : class
    {
        public DataContext Context { get; set; }

        public DataContextFactory(string connString)
        {
            Type type = typeof(T);
            Context = GetDataContextType(type,connString);
        }

        public DataContext GetDataContextType(Type type, string connectionString)
        {
            string typeString = type.ToString();

            switch (typeString)
            {
                case "CrazyCancer.Data.Models.Location":
                case "CrazyCancer.Data.Models.Tour":
                default:
                    {
                        return new CrazyCancerTourDataContext(connectionString);
                    }
            }
        }

        #region IDataContextFactory<T> Members

        public void SaveAll()
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

You will notice a few “tricky” things here. I am using Generics with this class. The Get DataContextType uses the Type the DataContextFactory was initialized with to determine type of DataContext. In the future, I will change the GetDataContextType so it can use a more maintainable way of getting DataContext. This works, however, for now.

As you notice, the factory loads when it is instantiated. If this were real behavior, I would shoot this idea down, but I am merely loading the “factory” up so I can pull context over and over again without re-instantiating. I will have to think about the pattern when I have more time. To use this factory, you set it up like so:

string connString = "server=(local);database=CrazyCancerTour;UID=user;PWD=password;";
IDataContextFactory<Location> contextFactory = new DataContextFactory<Location>(connString);

You will have to change the connection string to your database, of course. And, no, my password is not password on my local machine, and yours should not be either.

Our next step is creating a generic repository. Rather than go through all of the details, as this was blogged before, I will post the final code. First, we have an interface:

namespace CrazyCancer.Data.Access.interfaces
{
    public interface IRepository<T> where T : class
    {
        List<T> All();
    }
}

This interface is actually far more complex, but we are looking at retrieval only.

namespace CrazyCancer.Data.Access.repository
{
    public class Repository<T> : IRepository<T>
      where T : class
    {
        protected IDataContextFactory<T> _dataContextFactory;

        public Repository(IDataContextFactory<T> dataContextFactory)
        {
            _dataContextFactory = dataContextFactory;
        }

        public List<T> All()
        {
            return GetTable.ToList<T>();
        }

        private Table<T> GetTable
        {
            get { return _dataContextFactory.Context.GetTable<T>(); }
        }
    }
}

This will pull all of the items in the Location table, which is what we want for the time being. What we are doing here is using a bit of basic LINQ to SQL. Using a DataContext, we choose GetTable<T>, which means get all from the table <T>. When we use this in code, we are specifying Location for the table. This looks like the following code:

string connString = "server=(local);database=CrazyCancerTour;UID=user;PWD=password;";
IDataContextFactory<Location> contextFactory = new DataContextFactory<Location>(connString);

Repository<Location> repository = new Repository<Location>(contextFactory);
IEnumerable<Location> locations = repository.All();

Notice that all of the types are generic and need to have a type. What this means, to you, is you only have to code them once. I will cover the cases where you need a less generic implementation in the future.

Google Maps API bits

The next project is CrazyCancer.Framework.GoogleMaps. All I need here is a class that uses the locations and creates a JavaScript block to emit on my UI. The output I am looking for is the following (NOTE: {key} means your own Google maps API key – get one). This is my goal.

<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key={key}&quot; type="text/javascript"></script>
<script src="js/CrazyCancer.GoogleMap.Anim.js" type="text/javascript"></script>
<script type="text/javascript">

var data = [
{ name: "Puttgarden, Fehmarn", date: "8/14/2009", lat: "54.503143", lng: "11.229228" }
, { name: "Rødbyhavn", date: "8/15/2009", lat: "54.653278", lng: "11.349048" }
];

var animRoute = true;
</script>

I have moved the rest of the script to CrazyCancer.GoogleMap.Anim.js file, which looks like this (warning long script):

var map, route;
var points = [];
var gmarkers = [];
var count = 0;
var stopClick = false;

function addIcon(icon) { // Add icon attributes

    icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
    icon.iconSize = new GSize(32, 32);
    icon.shadowSize = new GSize(37, 34);
    icon.iconAnchor = new GPoint(15, 34);
    icon.infoWindowAnchor = new GPoint(19, 2);
    icon.infoShadowAnchor = new GPoint(18, 25);
}

function addClickevent(marker) { // Add a click listener to the markers

    GEvent.addListener(marker, "click", function() {
        marker.openInfoWindowHtml(marker.content);
        /* Change count to continue from the last manually clicked marker
        *  Better syntax since Javascript 1.6 – Unfortunately not implemented in IE.
        *  count = gmarkers.indexOf(marker);
        */
        count = marker.nr;
        stopClick = true;
    });
    return marker;
}

function buildMap() {

    if (GBrowserIsCompatible()) {
        map = new GMap2(document.getElementById("map"));
        map.setCenter(new GLatLng(54.503143, 11.229228), 8);
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());

        // Light blue marker icons
        var icon = new GIcon();
        icon.image = "
http://www.google.com/intl/en_us/mapfiles/ms/icons/ltblue-dot.png";
        addIcon(icon);

        for (var i = 0; i < data.length; i++) {
            points[i] = new GLatLng(parseFloat(data[i].lat), parseFloat(data[i].lng));
            gmarkers[i] = new GMarker(points[i], icon);

            // Store data attributes as property of gmarkers
            var html = "<div class=’infowindow’>" +
                    "<strong>" + data[i].name + "</strong><p>" +
                    data[i].date + "</p></div>";
            gmarkers[i].content = html;
            gmarkers[i].nr = i;
            addClickevent(gmarkers[i]);
            map.addOverlay(gmarkers[i]);
        }
        // Draw polylines between marker points
        var poly = new GPolyline(points, "#003355", 3, .5);
        map.addOverlay(poly);

        route = setTimeout("anim()", 3600);

        if (animRoute) {
            // Open infowindow of first marker
            gmarkers[0].openInfoWindowHtml(gmarkers[0].content);
        }
        else {
            if (route) {
                clearTimeout(route);
                stopClick = true;
            }
            map.setCenter(new GLatLng(0.0, 0.0), 8);
            gmarkers[data.length – 1].openInfoWindowHtml(gmarkers[data.length – 1].content);
        }
    }
}

function haltAnim() {

    if (route) {
        clearTimeout(route);
        stopClick = true;
    }
}

function carryOn() {

    if (stopClick == true) anim();
    stopClick = false;
}

function anim() {

    count++;
    if (count < points.length) {
        // Use counter as array index
        map.panTo(points[count]);
        gmarkers[count].openInfoWindowHtml(gmarkers[count].content);
        var delay = 3400;
        if ((count + 1) != points.length)
            var dist = points[count].distanceFrom(points[count + 1]);

        // Adjust delay
        if (dist < 10000) {
            delay = 2000;
        }
        if (dist > 80000) {
            delay = 4200;
        }
        route = setTimeout("anim()", delay);
    }
    else {
        clearTimeout(route);
        count = 0;
        route = null;
    }
}

function playAgain() {

    animRoute = true;
    GUnload();
    if (route) clearTimeout(route);
    stopClick = false;
    count = 0;
    buildMap();
}

My main reason for posting the whole thing is so you can duplicate this prior to me giving the download location. 🙂

Now let’s create a class that takes locations and produces the data var. To create the Google API line, I have the following routine:

public string GetGoogleMapsString(string apiKey, int versionNumber, bool useSensor)
{
    StringBuilder builder = new StringBuilder();
    builder.Append("<script src="
http://maps.google.com/maps?file=api&v=");
    builder.Append(versionNumber);
    builder.Append("&sensor=");
    builder.Append(useSensor.ToString().ToLower());
    builder.Append("&key=");
    builder.Append(apiKey);
    builder.Append("" type="text/javascript"></script>");
    builder.Append("rn");

    return builder.ToString();
}

This will create the  line:

<script src=http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=false&amp;key={key}” type="text/javascript"></script>

when you supply your apiKey, the version number (can be 3 now) and whether or not to use sensor (usually false). The next routine creates the path to the CrazyCancer.GoogleMaps.Anim.js file:

public string GetMapAnimationScriptString(string pathToJavascript)
{
    StringBuilder builder = new StringBuilder();

    builder.Append("<script src="");

    if(pathToJavascript==null)
    {
        builder.Append("js/CrazyCancer.GoogleMap.Anim.js");
    }
    else{
        builder.Append(pathToJavascript);
    }

    builder.Append("" type="text/javascript"></script>rn");

    return builder.ToString();
}

I have a default path in the class. If you use a js folder, this path could work for you. If not, you can supply one by adding the parameter. Finally, we need the bits that create the data var.

public string GetInitializeString(List<Location> locations, bool animateRoute)
{
    if (locations.Count == 0)
        return string.Empty;

    StringBuilder builder = new StringBuilder();
    builder.Append("<script type="text/javascript">rn");

    builder.Append(GetJsonDataString(locations));

    builder.Append("tvar animRoute = ");
    builder.Append(animateRoute.ToString().ToLower());
    builder.Append(";rn");

    //Build end of string
    builder.Append("</script>rn");

    return builder.ToString();
}

private static string GetJsonDataString(List<Location> locations)
{
    StringBuilder builder = new StringBuilder();
    //build up the points
    builder.Append("tvar data = [rn");

    for (int i = 0; i < locations.Count; i++)
    {
        Location location = locations[i];
        builder.Append("tt");
        if (i != 0)
            builder.Append(", ");

        builder.Append("{ name: "");
        builder.Append(location.LocationName);
        builder.Append("", date: "");
        builder.Append(location.CreatedDate.ToShortDateString());
        builder.Append("", lat: "");
        builder.Append(location.Latitude);
        builder.Append("", lng: "");
        builder.Append(location.Longitude);
        builder.Append(""  }rn");
    }

    builder.Append("t];rn");

    return builder.ToString();
}

Not a huge amount of code. Note that I have separated out the GetJsonDataString. This was largely for testing the routine in isolation.

To make things easier (one call to get script), I have created a consolidating routine:

public string GetEmitString(string apiKey, int versionNumber, bool useSensor, string pathToJavascript
    , List<Location> locations, bool animateRoute)
{
    StringBuilder builder = new StringBuilder();
    builder.Append(GetGoogleMapsString(apiKey, versionNumber, useSensor));
    builder.Append(GetMapAnimationScriptString(pathToJavascript));
    builder.Append(GetInitializeString(locations, animateRoute));
    return builder.ToString();
}

When I run this with the database at hand, I end up with:

<script src="http://maps.google.com/maps?file=api&v=2&sensor=false&key={key}&quot; type="text/javascript"></script>
<script src="js/CrazyCancer.GoogleMap.Anim.js" type="text/javascript"></script>
<script type="text/javascript">
   
var data = [
        { name: "Puttgarden, Fehmarn", date: "8/14/2009", lat: "54.503143", lng: "11.229228" }
        , { name: "Rødbyhavn", date: "8/15/2009", lat: "54.653278", lng: "11.349048" }
    ];

    var animRoute = true;
</script>

This is exactly what i wanted, so I am rolling now.

Testing in a Web Application

Now that I have the application logic done, I have to add a user interface. To do this create a new website. Change out the default.aspx tagged page for this:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"
http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="
http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head id="Head1" runat="server">
    <link rel="stylesheet" type="text/css" href="include.css" />
    <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
    <meta name="author" content="Wolfgang Pichler" />
    <meta name="URL" content="
http://www.wolfpil.de" />
    <title>Map Animation</title>
    <style type="text/css">
        body
        {
            font-family: Verdana, Sans-serif;
        }
        h3
        {
            margin-left: 8px;
        }
        #map
        {
            height: 300px;
            width: 500px;
            border: 1px solid gray;
            margin-top: 8px;
            margin-left: 8px;
            overflow: hidden;
        }
    </style>
</head>

<body onload="buildMap()" onunload="GUnload()">
    <form id="form1" runat="server">
    <h3>
        Map Animation</h3>
    <div id="map">
    </div>
    </form>
</body>
</html>

The code behind is fairly simple and code you have seen already in this post. The only change is I am taking the output of the LocationBuilder and emitting it as JavaScript.

protected void Page_Load(object sender, EventArgs e)
{
    string emitScript = GetEmitScript();
    ClientScript.RegisterStartupScript(typeof(Page), "GoogleMaps", emitScript);
}

private string GetEmitScript()
{
    //Code already covered
    string connString = "server=(local);database=CrazyCancerTour;UID=sa;PWD=pass@word1;";
    IDataContextFactory<Location> contextFactory = new DataContextFactory<Location>(connString);
    Repository<Location> repository = new Repository<Location>(contextFactory);
    List<Location> locations = repository.All();

    //variables for the location builder
    string apiKey = "{key}";
    int versionNumber = 2;
    bool useSensor = false;
    string pathToJavascript = "js/CrazyCancer.GoogleMap.Anim.js";
    bool animateRoute = true;

    LocationBuilder builder = new LocationBuilder();
    string emitString = builder.GetEmitString(apiKey, versionNumber, useSensor
                       
, pathToJavascript, locationList, animateRoute);

    return emitString;
}

Remember to replace {key} with your key in the GetEmitScript() routine. You can now run the page and it looks like this:

FinalPage

You can add back in the animation buttons, if you are so inclined. Look at the source on the original page to determine how to do this. Hope you had fun with this one.

Peace and Grace,
Greg

Twitter: @gbworld

Developers: You are part of the solution or part of the problem


This entry came from a conversation I had with a friend today about the state of development. Part of the conversation was on out of work developers catching up on Oprah and another on how few books the average developer buys (a "best seller" in the computer world might sell 50,000 copies) and even some on how many developers just do enough to get by and never step out.

We got into this conversation because he asked if I could help a friend of his with a simple form. I fell asleep last night realizing I had forgotten and got up a bit after 1 AM wide awake with a "I forgot" conscience crisis. Byu 1:23 AM, I was back in bed with two versions of the form (DataSet and LINQ) returned. He stated something about how quick I could get things done and I stated:

In life, you are either adding value or taking it away.

This is like the age old saying "You are either a part of the solution or a part of the problem", but it fits nicely with development. Either you are doing something to improve the business you are in, or you are making it worse. When I first stated this to another friend, he answered “but what if I am simply leaving it the same?” Then you are making it worse, as they are paying you to get things done.

Let me explain. When you go to work, whether it is a full time job or a contact, you are being paid for something. If you simply leave things exactly the way you left them, and make no improvement, then the business has not really gained anything from your employment. Yes, they might have gotten work out of you, but you are probably way over paid if you have not added value.

Where I find this most true is when people take on a code base for “maintenance” and ignore the fact that the code is really bad. Rather than take a bit of time to understand the flow and refactor the code a bit, they leave it as is and simply bolt a few more parts on top of the application. This goes on through group after group of developers until someone finally comes along who takes it on himself to understand the code rather than simply bolt something else on it. this person finally makes a difference.

There are some people who wonder why certain consultants get paid so well while they are struggling. In general, it is either due to a lack of confidence or a lack of initiative to add value to the business. Once you get a reputation for adding value, the hourly rate goes up tremendously. You should make it your mission to always leave a place better than how it was when you found it. If not, you are simply part of the problem.

What can you do if you are not adding value? Either spend time figuring out how to improve yourself or pack up and go home. Here are some suggestions

  1. Spend time reading. Even if you only get one new thing out of the book, that is one technique you now can use.
  2. Learn to Google very well. There are so many answers out there at your fingertips if you will only learn how to find them
  3. Avail yourself of developer blogs. Use the RSS features in your mail program so you are alerted.
  4. Watch tweets from frequent bloggers. Many will let you know when there is something new you can try.
  5. Play with betas, albeit in a safe enivornment and not your production box.
  6. Practice code kata when you have downtime at work or, better yet, learn the business
  7. Find ways to give back to the developer community: open source, answering questions in forums, newsgroups and even stack overflow are great ways to cement knowledge and possibly even learn something new
  8. Take a moment to learn the code you are editing and figure out how to improve it. Sometimes management will not let you, but try to add value when ever you can.
  9. Donate some time developing applications/sites for non-profits. You will learn and give back.

    AND

  10. Don’t be afraid to leave a job where you cannot add value.

Someone asked me once if I would really leave an assignment I was not adding value to. The answer is yes. I left a contract once due to the fact I had already completed the work necessary to get the job done. I made sure there was an employee who could take over the management duties and left. I would like to say the manager was grateful, but it was a state agency and it was necessary to keep the position filled to ensure a higher budget the next year. Your tax dollars at work. But I still think I did the right thing. 🙂

Peace and Grace,
Greg

Twitter: @gbworld

An objective look at the Healthcare bill (HR 3200)


I have been reading a lot of misinformation about the health care bill lately, and I decided to post a few things I have found from reading the bill myself. Here are my findings, organized by topic. I am using the version posted at http://energycommerce.house.gov/Press_111/20090714/aahca.pdf, which is up to date, as far as I can tell. I am not going to get into the Palin they are going to create a death commission for old people or Hulabaloo’s Republicans believe it is more immoral to raise taxes than have people dying in the streets with no health coverage, as both are worthless reactionary. I want to hit a couple of topics that are useful to real Americans and approach the bill in a non-passionate way. If you feel I have made a mistake, let’s talk about it, but please be willing to show me real numbers rather just rhetoric.

I have quoted the bill directly, and stated page numbers so you can read entire sections in context. I am not going to post the whole bill or do a line by line, as that is a worthless exercise for me.

What Will Government Healthcare Cost Me?

I cannot definitively answer, as there is no set formula for calculating costs in the bill, unless you fit between 133% and 400% of the poverty level. At these levels, you get what are called "affordability credits" to bring down the costs of national health insurance. Assuming that the actual costs will be somewhere near the max, we can start looking at the metrics mentioned and calculate the costs for an average family. First, let’s look at what the average person pays for health insurance now:

According to the National Coalition on Healthcare, the average cost for health insurance is $12,700, with $3,400 paid by the employee ($9,300 paid by the employer). A Mercer study shows the average deductible was $1,000 for a family in 2008. And the out of pocket max, according to a Market Watch article, were $5,000. Here is a summary table

Total Costs $12,700
Employer Share $9,400
Employee Share $3,400
Deductible $1,000
Out of Pocket max $5,000
Employee theoretical max $8,400

NOTE: I say "Employee theoretical max" from experience, as I have seen how co-pays can still add up after hitting out of pocket max. There may be a way to recoup them, but it is a fight I am not willing to participate in. Over the past few years, our out of pocket costs, premiums, co-pays and other bills, have been around $13,000, but we have dealt with childhood cancer and some expenses that simply were not covered.

To calculate the costs of the healthcare plan (HR 3200), we need to know the cost of premiums and the cost of deductible and out of pocket max. The government combines everything in a category called cost sharing. The cost sharing for families and individuals are spelled out on page 29 (lines 9-16):

9 (B) APPLICABLE LEVEL.—The applicable
10 level specified in this subparagraph for Y1 is
11 $5,000 for an individual and $10,000 for a
12 family. Such levels shall be increased (rounded
13 to the nearest $100) for each subsequent year
14 by the annual percentage increase in the Con15
sumer Price Index (United States city average)
16 applicable to such year.

So, we can see that a family will have a cost share of $10,000. Now we need the premiums. They are only published for familes making 133% to 400% of the National Poverty Level (NPL) and outlined on page 137. According to page 137, lines 1-3, the percentages are:

Percent of Poverty Level Initial Max % Final Max % Actuarial Value %
133% through 150%  1.50% 3% 97%
150% through 200%  3% 5% 93%
200% through 250%  5% 7% 85%
250% through 300%  7% 9% 78%
300% through 350%  9% 10% 72%
350% through 400%  10% 11% 70%

The government definition of the poverty level is also published. The following charts show what the poverty level is. The first two columns were copied directly from the site, I aadded the others to show you how much money each of the other percentages represent. This is so you can easily calculate your own percentage. I am in one of the upper categories.

49 Continguous States and the District of Columbia

Persons in family Poverty guideline 133% 200% 250% 300% 350% 400%
1 $10,830 $14,404 $21,660 $27,075 $32,490 $37,905 $43,320
2 $14,570 $19,378 $29,140 $36,425 $43,710 $50,995 $58,280
3 $18,310 $24,352 $36,620 $45,775 $54,930 $64,085 $73,240
4 $22,050 $29,327 $44,100 $55,125 $66,150 $77,175 $88,200
5 $25,790 $34,301 $51,580 $64,475 $77,370 $90,265 $103,160
6 $29,530 $39,275 $59,060 $73,825 $88,590 $103,355 $118,120
7 $33,270 $44,249 $66,540 $83,175 $99,810 $116,445 $133,080
8 $37,010 $49,223 $74,020 $92,525 $111,030 $129,535 $148,040
Per Addl $3,740 $4,974 $7,480 $9,350 $11,220 $13,090 $14,960

Alaska

Persons in family Poverty guideline 133% 200% 250% 300% 350% 400%
1 $13,530 $17,995 $27,060 $33,825 $40,590 $47,355 $54,120
2 $18,210 $24,219 $36,420 $45,525 $54,630 $63,735 $72,840
3 $22,890 $30,444 $45,780 $57,225 $68,670 $80,115 $91,560
4 $27,570 $36,668 $55,140 $68,925 $82,710 $96,495 $110,280
5 $32,250 $42,893 $64,500 $80,625 $96,750 $112,875 $129,000
6 $36,930 $49,117 $73,860 $92,325 $110,790 $129,255 $147,720
7 $41,610 $55,341 $83,220 $104,025 $124,830 $145,635 $166,440
8 $46,290 $61,566 $92,580 $115,725 $138,870 $162,015 $185,160
Per Addl $4,680 $6,224 $9,360 $11,700 $14,040 $16,380 $18,720

Hawaii

Persons in family Poverty guideline 133% 200% 250% 300% 350% 400%
1 $12,460 $16,572 $24,920 $31,150 $37,380 $43,610 $49,840
2 $16,760 $22,291 $33,520 $41,900 $50,280 $58,660 $67,040
3 $21,060 $28,010 $42,120 $52,650 $63,180 $73,710 $84,240
4 $25,360 $33,729 $50,720 $63,400 $76,080 $88,760 $101,440
5 $29,660 $39,448 $59,320 $74,150 $88,980 $103,810 $118,640
6 $33,960 $45,167 $67,920 $84,900 $101,880 $118,860 $135,840
7 $38,260 $50,886 $76,520 $95,650 $114,780 $133,910 $153,040
8 $42,560 $56,605 $85,120 $106,400 $127,680 $148,960 $170,240
Per Addl $4,300 $5,719 $8,600 $10,750 $12,900 $15,050 $17,200

We can now calculate maximum premiums under the health care plan and compare them. First, let’s find an average family of 4, so we know what we are dealing with. This is a tricky figure. According to the Census bureau, the average income for a family was $58,407 in 2006, with average of 3.13 per family. Using the table above, this family sits in the 300% to 350% percent of NPL. Below is a chart of premium costs using the health care tables. Those lines that are highlighted will pay more, on average, than they pay today in premiums.

  133% 200% 250%
Persons in family Salary Initial (1.5%) Final (3%) Salary Initial (3%) Final (5%) Salary Initial (5%) Final (7%)
1 $14,404 $216 $432 $21,660 $650 $1,083 $27,075 $1,354 $1,895
2 $19,378 $291 $581 $29,140 $874 $1,457 $36,425 $1,821 $2,550
3 $24,352 $365 $731 $36,620 $1,099 $1,831 $45,775 $2,289 $3,204
4 $29,327 $440 $880 $44,100 $1,323 $2,205 $55,125 $2,756 $3,859
5 $34,301 $515 $1,029 $51,580 $1,547 $2,579 $64,475 $3,224 $4,513
6 $39,275 $589 $1,178 $59,060 $1,772 $2,953 $73,825 $3,691 $5,168
7 $44,249 $664 $1,327 $66,540 $1,996 $3,327 $83,175 $4,159 $5,822
8 $49,223 $738 $1,477 $74,020 $2,221 $3,701 $92,525 $4,626 $6,477
  300% 350% 400%
Persons in family Salary Initial (7%) Final (9%) Salary Initial (9%) Final (10%) Salary Initial (10%) Final (11%)
1 $32,490 $2,274 $2,924 $37,905 $3,411 $3,791 $43,320 $4,332 $4,765
2 $43,710 $3,060 $3,934 $50,995 $4,590 $5,100 $58,280 $5,828 $6,411
3 $54,930 $3,845 $4,944 $64,085 $5,768 $6,409 $73,240 $7,324 $8,056
4 $66,150 $4,631 $5,954 $77,175 $6,946 $7,718 $88,200 $8,820 $9,702
5 $77,370 $5,416 $6,963 $90,265 $8,124 $9,027 $103,160 $10,316 $11,348
6 $88,590 $6,201 $7,973 $103,355 $9,302 $10,336 $118,120 $11,812 $12,993
7 $99,810 $6,987 $8,983 $116,445 $10,480 $11,645 $133,080 $13,308 $14,639
8 $111,030 $7,772 $9,993 $129,535 $11,658 $12,954 $148,040 $14,804 $16,284

Let’s calculate our average family in the United states. To give the best benefit of the doubt, I am going to calculate two ways: income and adjusted gross income. There is nothing in the bill that suggests adjusted gross income, but it is only fair to look at both sides of the coin. According to the IRS, adjusted gross income in the United States, for all tax filers, was $31,987. This would be low for our average family, but we will use it to hit a rock bottom figure of costs for this family under the new plan. I am also going to add deductible and out of pocket max, although that is not really how insurance works. But it gives a good idea of what a family with some health concerns could face.

Gross Income Adjusted Gross Income
Current Initial Final Initial Final
Premiums $3,400 $5,256.63  $    5,840.70  $        479.81  $        959.61
Deductible $1,000 $0.00 $0.00 $0.00 $0.00
Max Out Of Pocket $5,000 $0.00 $0.00 $0.00 $0.00
Cost Sharing $6,000 $10,000.00 $10,000.00 $10,000.00 $10,000.00
TOTAL $9,400 $15,257 $15,841 $10,480 $10,960
No illness $1,856.63 $2,440.70 -$2,920.20 -$2,440.39
Medical Issues $5,857 $6,441 $1,080 $1,560

This means our average family, with very few doctor’s visits, will save as much as $2,920.20 if the premium max is based on adjusted gross income, but will pay as much as $2,440.70 more if it is based on real income. If this family has medical issues, they will pay as low as $1,080 more to $6,441 more in out of pocket medical expenses. In reality, based on how insurance works, this family, at max comes out $1,440.39 ahead ($27 per week), but could come out as much as $7,441 behind.

If you would like to calculate your situation, it is an easy formula. Take your salary and adjusted gross income (from your tax return last year) and figure what category you fit in based on your family size. Take the percentages from the HR 3200 chart and multiply the two figures by initial and final percentages. These are your max premiums. Then add $10,000 to find your max out of pocket for expenses. to compare, take the amount you pay per paycheck and multiply it by 26 (if on a two week schedule). This is your premium amount. Then add your max out of pocket. This should be your true expense. If you want to give the best benefit of the doubt, add your deductible amount. This will help you better understand more catestrophic medical care.

In case you are curious, my current salary and family size would put my initial premium at about $9,500 initial and $10,500 final (round figures). With a $10,000 cost share, assuming that it covers everything that my current medical sometimes does not, I have a net loss, to my family of $6,500 to $7,500 dollars. This is a sizeable extra chunk of change for me personally. Calculate your own costs and see what the bill means to you, however.

Will My Company Dump Their Health Insurance Plan?

I can’t answer this one definitely either. Based on our average family insurance scenario, the company pays out $9,300 on a salary of $58,407. This amounts to 15.9227% of the person’s salary. The Kaiser family foundation has cost out healthcare at an average of $2.59 per hour per employee, or $5,283.60 (9.046% of the average family income) in 2005, with healthcare rising about $.20 per hour per employee. That would put the current costs, if the trend continued, at around $2.98 per hour per employee ($6,079.20 or 10.4% of the average family income). Studies have shown the smaller companies pay even higher percentages than large companies, due to smaller group size. Looking at various sites, I find the average expenditure for health insurance to be around 9% of payroll, but I cannot determine if this is 9%, but remember this is a percentage of the entire payroll and does not factor out the part time employees who do not receive healthcare benefits.

HR 3200 states that the government has a "contribution" amount of 8% of payroll for companies that do not have a company health insurance plan (page 149, lines 14-20+):

14 SEC. 313. EMPLOYER CONTRIBUTIONS IN LIEU OF COV
15 ERAGE.
16 (a) IN GENERAL.—A contribution is made in accord
17 ance with this section with respect to an employee if such
18 contribution is equal to an amount equal to 8 percent of
19 the average wages paid by the employer during the period
20 of enrollment …

If the total payroll for the preceding calendar year does not exceed $400,000, the percentage is subsidized (page 150, lines 9-13). I added the dollar amounts after the percentage, the rest of the lines are copied verbatim from the bill.

9 (1) IN GENERAL.—In the case of any employer
10 who is a small employer for any calendar year, sub
11 section (a) shall be applied by substituting the appli
12 cable percentage determined in accordance with the
13 following table for ‘‘8 percent’’:

If the annual payroll of such employer for                 The applicable
the preceding calendar year:                                      percentage is:

Does not exceed $250,000 ……………………………….     0 percent  ($0)
Exceeds $250,000, but does not exceed $300,000       2 percent ($5,000 – $6,000 total)
Exceeds $300,000, but does not exceed $350,000       4 percent ($12,000 – $14,000 total)
Exceeds $350,000, but does not exceed $400,000       6 percent ($21,000 – $24,000 total)
$400,000                                                                     8 percent ($32,000 total)

Now to the question of your employer. I see the following dumping healthcare group benefits, if they have it:

  1. Employers with low payrolls (those subsidized above)
  2. Employers with mostly full time employees that make below, and perhaps at, the average salary
  3. Employers who are not competing heavily for employees (using healthcare benefits as a perk to get talent)
  4. Employers with lots of part-time employees, if they are forced to cover them with benefits, as well (not spelled out either way in the bill)

On the other hand, the following will not dump policies

  1. Employers who have a healthy number of very highly paid employees
  2. Employers with a great deal of part-time employees, unless they have to provide them benefits, as well (not spelled out either way in the bill)
  3. Employers for whom having company insurance will be a great attraction for the best talent

The 8% figure appears to have come from a government study that shows healthcare costing 7.8% per family, but I cannot find the link right now and I cannot tell if it includes all American families or just those insured. I would imagine, looking at the other sites, 7.8% means all families, not just those covered by employers.

If you want to calculate your risk, figure out what you think the average salary in your company is and calculate the total payroll. If you think the average is much lower, you will have to adjust this percentage up. Multiply this total number by 8%. Now remove part time employees from the mix, as they do not cost the company benefits and multiple by 9% if the average is about $59,000 per year in salary. If you think it is less, you have to add more percentages.

If you have an employer who has 25 employees each making about $59,000, the total payroll is $1,475,000. The health insurance costs are $132,750 and the healthcare plan is $118,000, for a savings of $14,750. Unless this company can get rid of a few HR people by dumping the insurance plan, for greater savings, they probably will not. Even if we take the 10.4% figure, it is only $35,400 saved per year (plus any HR person they can get rid of when benefits are reduced). If you multiply this by 10 (250 employees), with a total of $350,400 in savings (plus probably at least one HR person), it becomes more attractive.

Will the Health Insurance Plan Cover Undocumented Workers

The undocumented worker/illegal alien question has spurred a lot of bad information. The people negative towards the bill point to SECTION 152 (pages 50-51), which states:

21 SEC. 152. PROHIBITING DISCRIMINATION IN HEALTH CARE.
22 (a) IN GENERAL.—Except as otherwise explicitly per
23 mitted by this Act and by subsequent regulations con
24 sistent with this Act, all health care and related services
25 (including insurance coverage and public health activities)

1 covered by this Act shall be provided without regard to
2 personal characteristics extraneous to the provision of
3 high quality health care or related services.
4 (b) IMPLEMENTATION.—To implement the require
5 ment set forth in subsection (a), the Secretary of Health
6 and Human Services shall, not later than 18 months after
7 the date of the enactment of this Act, promulgate such
8 regulations as are necessary or appropriate to insure that
9 all health care and related services (including insurance
10 coverage and public health activities) covered by this Act
11 are provided (whether directly or through contractual, li
12 censing, or other arrangements) without regard to per
13 sonal characteristics extraneous to the provision of high
14 quality health care or related services.

What is a high quality health care service? Once you answer that, you can determine whether "high quality" means anyone who needs health care has a card. If so, then undocumented workers/illegal aliens will be able to participate. But, as proponents of the bill have stated, they won’t get affordability credits:

3 SEC. 246. NO FEDERAL PAYMENT FOR UNDOCUMENTED
4 ALIENS.
5 Nothing in this subtitle shall allow Federal payments
6 for affordability credits on behalf of individuals who are
7 not lawfully present in the United States.

This is the only thing in the bill that talks about undocumented workers. As I have read it, affordability credits only apply to individuals between 133% and 400% above the National Poverty Level. The question is whether or not someone can include undocumented workers/illegal aliens in the under 133% category. Overall, I would agree with the proponents on this one.

Will Health Care Expenses Go Down?

According to a CNN/Money article, the United States currently has a $2.2 billion medical industry, with around $1.2 billion in waste. It is this waste that is causing the incredible expenses related to health care. The following chart was on the site
health care waste chart

Just looking at the bill alone, it is unlikely overtesting will be solved by any of the sections in the bill. The expense of process claims will likely go up, especially if the filing system is designed like Medicare. The bill will do nothing about ignoring doctor’s orders either. There are some provisions that might help some with ineffective use of technology, but the problem is growing and the bill does not address the real problem here. Hospital readmissions will likely go down, but hospitals, which will be "fined" under provisions in the bill for too many readmissions might keep their more risky patients in the hospital, raising waste in admissions while reducing the waste in readmissions. Medical errors are not addressed directly in the bill. Unnecessary ER visits will go down. They might be replaced by some unnecessary doctor’s visits, but doctor’s visits cost less than ER visits. And there is nothing to address hospital acquired infections.

If you ask me, the improvement is largely in a small bucket, while one of the largest buckets will likely grow larger. The most likely outcome is an increase in health care costs and waste, not a decrease. With everyone having insurance cards, I am almost certain ER visits will reduce, however. But even a reduction of 100% will not offset a 10% increase in processing claims expense, which is also very likely.

I am done with the novel for now. I might get back with some more interesting tidbits later.

Peace and Grace,
Greg

Twitter: @gbworld

Creating a Short Url Hash


I was a bit bored today and thought about creating a simple hash to create Tiny URL type endings. This is largely led by a multiple blog idea I am toying with. I wanted to be able to make my own TinyUrl. Initially, I was going to set up a TinyURL library, but this was a bit of fun.

Essentially, what I am doing is creating a Base62 converter. I found some algorithms on the web, but they were a bit too long or used VB training wheels libraries, so I had to pitch them. Great for research however. Playing around a bit, I came up with this idea.

Converting to AlphaNumeric “hash”

To convert to Base62, the easiest way is to set up a base 62 string and start poking at it. The string looks something like this:

private readonly string startingBaseString = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

To convert to base62 is fairly easy.

  1. Create a empting working string
  2. If number = 0, then return “0”, else reduce number until it hits 0
  3. Get the modulus of the number divided by 62 and find the value in the string
  4. Append this to the front of the string

The routine looks like this:

public string ConvertToBase(long num)
{
    string working = string.Empty;

    if (num != 0)
    {
        while (num > 0)
        {
            int modulo = (int)num % 62;
            working = startingBaseString.Substring(modulo, 1) + working;
            num /= 62;
        }
    }
    else
        working = "0";

    return working;
}

After playing a bit, I wanted to make this a bit more useful, so I threw in the ability to convert to other bases (and even change the base string you use). the coverted code starts with the constructor. For a simple, vary the base string, I have the following:

private string baseChars;
private int numberBase;

public BaseConverter(int numBase)
{
    if (numberBase > 62)
        throw new ApplicationException("Can only go to base 62");

    baseChars = base62String.Substring(0, numBase);
    numberBase = numBase;
}

But what if you want to change the order of the numbers so you can have alphabetic characters first or only alpha characters. You could do this:

public BaseConverter(int numBase, string charString)
{
    if (charString.Length < numBase)
        throw new ApplicationException(
       
"You must have at least as many characters in your string as the base you are converting to.");

    startingBaseString = charString;

    baseChars = base62String.Substring(0, numBase);
    numberBase = numBase;
}

Now we have a refactor, as there is the code smell of duplicate code. Right click in Visual Studio and choose Refactor and Extract method on the last two lines. The result is this:

private string baseChars;
private int numberBase;

public BaseConverter(int numBase)
{
    if (numberBase > 62)
        throw new ApplicationException("Can only go to base 62");

    LoadConverter(numBase);
}

public BaseConverter(int numBase, string charString)
{
    if (charString.Length < numBase)
        throw new ApplicationException("You must have at least as many characters in your string as the base you are converting to.");

    startingBaseString = charString;

    LoadConverter(numBase);
}

private void LoadConverter(int numBase)
{
    baseChars = startingBaseString.Substring(0, numBase);
    numberBase = numBase;
}

But we should have a Base62 default constructor. This can be coded by chaining the default constructor, like so:

public BaseConverter()
    : this(62)
{
}

Now we can alter the converter to allow any base.

public string ConvertToBase(long num)
{
    string working = string.Empty;

    if (num != 0)
    {
        while (num > 0)
        {
            int modulo = (int)num % numberBase;
            working = baseChars.Substring(modulo, 1) + working;
            num /= numberBase;
        }
    }
    else
        working = "0";

    return working;
}

Pretty cool so far. Now let’s get back numbers from a string.

Converting From Base62

To return back to a number is a bit more complex (a few more lines of code). It follows this logic:

  1. Create a character array of the string
  2. Get the length of this array
  3. Loop through the array and do the following
    1. Create a Regex class with the current working value
    2. Search the Base 62 string for the Regex value
    3. Take the index of the match and multiply it by 62 to the power of (hashLength minus 1) minus the loop value
    4. Add to your return value

I am fairly certain there is some way to simplify this even farther, but here it is:

public long FromBase62(string hash)
{
    char[] hashChars = hash.ToCharArray();
    int hashLength = hashChars.Length;
    long returnValue = 0;

    for (int i = 0; i < hashLength; i++)
    {
        char working = hashChars[i];
        Regex regex = new Regex(working.ToString());
        Match match = regex.Match(baseChars);
        double multipland = Math.Pow(numberBase, (hashLength – 1) – i);
        returnValue += (long)(match.Index * multipland);
    }

    return returnValue;
}

The final step is using the library.

Blogging with the Hash

To get a number from the converter, you can use any of the following constructors:

BaseConverter converter = new BaseConverter();
BaseConverter converter2 = new BaseConverter(32);
BaseConverter converter3 = new BaseConverter(52, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");

You then take the number you want to convert and use ConvertToBase. Here is a little test to ensure the algorithm is working correctly:

[TestMethod]
public void should_convert_to_number_and_back()
{
    for(long l=0;l<1000;l++)
    {
        TestSpecificNumber(num);
    }
}

private void TestSpecificNumber(long num)
{
    Converter converter = new Converter();
    string hash = converter.ConvertToBase(num);
    long convertBackNum = converter.ConvertFromBase(hash);

    Assert.AreEqual(num, convertBackNum, "The converted number does not match the original");
}

To use this in a blog, just convert the primary key to the hash and you can then use that hash in a short url like:

http://mysite.com/1yq

I will cover how to make the routing work in a blog entry in the next few days.

Peace and Grace,
Greg

Twitter: @gbworld

FIX: Media File Not Playing – Windows 7, Internet Explorer 8 and Windows Media Player


I thought this was something that was a beta (or RC) issue, but I have found it happens in the RTM, as well. When you go to click a movie file in Internet Explorer 8 on Windows 7 you get a page stating the following:

——————————————————————————————

Internet Explorer cannot display the webpage

What you can try:

Diagnose Connection Problems


More information

This problem can be caused by a variety of issues, including:

  • Internet connectivity has been lost.
  • The website is temporarily unavailable.
  • The Domain Name Server (DNS) is not reachable.
  • The Domain Name Server (DNS) does not have a listing for the website’s domain.
  • There might be a typing error in the address.
  • If this is an HTTPS (secure) address, click Tools, click Internet Options, click Advanced, and check to be sure the SSL and TLS protocols are enabled under the security section.

For offline users

You can still view subscribed feeds and some recently viewed webpages.
To view subscribed feeds

  1. Click the Favorites Center button , click Feeds, and then click the feed you want to view.

To view recently visited webpages (might not work on all pages)

  1. Click Tools , and then click Work Offline.
  2. Click the Favorites Center button , click History, and then click the page you want to view.

——————————————————————————————

I have had multiple installs of Windows 7 and the file type has changed. Some times it is MPEG, sometimes WMV, etc. When you first install windows, things work fine, so I was a bit stumped.  I figured it must be a registry problem and I found a fix.

For some reason, the install of certain programs changes the default string value for a media type. The latest culprit was Windows Live programs, but I think this also happens when you do a default install of Quicktime, so it could happen with a variety of programs.

Take the following lines and copy them to a text file and name the file videoTypes.reg.. If you use notepad, make sure to change from .txt files to all file types, as notepad will add the .txt extension.

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT.asf]
@="WMP11.AssocFile.ASF"

[HKEY_CLASSES_ROOT.asx]
@="WMP11.AssocFile.ASX"

[HKEY_CLASSES_ROOT.au]
@="WMP11.AssocFile.AU"

[HKEY_CLASSES_ROOT.avi]
@="WMP11.AssocFile.AVI"

[HKEY_CLASSES_ROOT.cda]
@="WMP11.AssocFile.CDA"

[HKEY_CLASSES_ROOT.m1v]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.M2V]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.MOD]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mov]
@="WMP11.AssocFile.MOV"

[HKEY_CLASSES_ROOT.mp2]
@="WMP11.AssocFile.MP3"

[HKEY_CLASSES_ROOT.mp2v]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mp3]
@="WMP11.AssocFile.MP3"

[HKEY_CLASSES_ROOT.mp4]
@="WMP11.AssocFile.MP4"

[HKEY_CLASSES_ROOT.mpa]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mpe]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mpeg]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mpg]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.mpv2]
@="WMP11.AssocFile.MPEG"

[HKEY_CLASSES_ROOT.wm]
@="WMP11.AssocFile.ASF"

[HKEY_CLASSES_ROOT.wma]
@="WMP11.AssocFile.WMA"

[HKEY_CLASSES_ROOT.WMD]
@="WMP11.AssocFile.WMD"

[HKEY_CLASSES_ROOT.wmv]
@="WMP11.AssocFile.WMV"

[HKEY_CLASSES_ROOT.wmx]
@="WMP11.AssocFile.ASX"

[HKEY_CLASSES_ROOT.wmz]
@="WMP11.AssocFile.WMZ"

[HKEY_CLASSES_ROOT.wpl]
@="WMP11.AssocFile.WPL"

[HKEY_CLASSES_ROOT.wvx]
@="WMP11.AssocFile.WVX"

This is from manually checking the file types. If you want to do a more thorough list, I would do the following:

  1. Install Windows 7
  2. Click on HKEY_CLASSES_ROOT and choose export
  3. Delete out any keys without a Content Type of video/{name of video type}, like this
  4. [HKEY_CLASSES_ROOT.wmv]
    @="WMP11.AssocFile.WMV"
    "PerceivedType"="video"
    "Content Type"="video/x-ms-wmv"

  5. Run this file any time you have a problem.

One caveat here. If you install programs like Quicktime, you may want to delete out items like this:

[HKEY_CLASSES_ROOT.mov]
@="WMP11.AssocFile.MOV

as this is a file normally associated with Quicktime, but this is your choice.

Peace and Grace,
Greg

Twitter: @gbworld

Creating a simple HTTP Communication class


This is a follow up to my last post about my first CodePlex project (http://shorturllibrary.codeplex.com/). As mentioned in that post, the short url API is part of a bigger project and will eventually lead to tweet on blog bits where the URL of the blog entry are automatically short urled according to your specs. This means there will be a factory pattern in there eventually (got your interest?).

The first step for me was to create a communication library.

Communication

When we communicate with the short url sites, the APIs are generally REST, JaSON or similar. Regardless of which of these they use, you will use HTTP Communication to reach the libraries. But, following proper practice, and so we can later test, let’s create a communication interface. It looks like this:

public interface ICommunicator
{
    WebResponse SendRequest(string requestUrl, RequestMethod requestMethod);
    WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password);
}

Now, since I am using HTTP, I can go ahead and create the enumeration for RequestMethod (I may regret this later if I create something a bit more generic as a comm library, but it is great for now). The enumeration looks like this:

namespace CrazyCancer.Framework.Communication.Enums
{
    public enum RequestMethod
    {
        GET,
        POST
    }
}

Contract first development. What a novel concept! (For those not seeing I am being a bit sardonic here, Contract First development is a well established concept).

Now that I have a contract, let’s rough in the class:

public class HttpCommunicator : ICommunicator
{
}

If you add this to a project, you will see that the ICommunicator is not implemented, so Visual Studio complains at you. To fix this, I am going to create the two methods. Since the more explicit method makes more sense, I will have it actually run all of the code. When initially implemented, it will look like this:

public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod)
{
    return SendRequest(requestUrl, requestMethod, null, null);
}

public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password)
{
    throw new NotImplementedException
}

At this time, I really should be using TDD, but it is late and inversion of control is not a wavelength I am able to maintain, so I will approach that when I get to the ShortUrl library post (which was developed using Test Driven Development – ADD moment, forgot to tell what TDD meant at first mention). As a side note, many of my dev buddies, who know I am a TDD advocate are probably having a snicker at this post. 😉

There are a couple of methods I know I need in addition to the interface methods. First, I need something to turn the enum into a string, as the WebRequest class expects a string. You might say, this is not necessary as you can simply ToString() the RequestMethod passed in. Good point, but I will not do this for two reasons:

  1. I may eventually add other communication protocols and having a separate method allows my to filter out bad results
  2. It breaks SOLID principles (no time to explain this right now)

Here is my code for this method (extremely simple):

private string GetResponseMethodAsString(RequestMethod requestMethod)
{
    switch (requestMethod)
    {
        case RequestMethod.POST: { return "POST"; }
        default: { return "GET"; }
    }
}

I also am going to create a method to get Network Credentials, if necessary. When I start using this library with Twitter, this will be useful. Right now, it is extraneous (and I have broken one principle of Agile – only code what you need today – another ADD moment?).

private NetworkCredential GetNetworkCredentials(string userName, string password)
{
    NetworkCredential credential = new NetworkCredential(userName, password);
    return credential;
}

There is a temptation to put this in the SendRequest method (which may be badly named – have to think about this – oh, too late, it is published), and I agree with this temptation based on TDD/Agile principles. I have chosen not to, as I am thinking ahead to a yet unrealized future.

Now to SendRequest(). I need a request object that uses a GET or POST. Simple enough, I set up something like this:

WebRequest request = WebRequest.Create(requestUrl);
request.Method = GetResponseMethodAsString(requestMethod);

I also have the possibility of having to set up network credentials, but only if the userName and password are not null. This looks like the following:

if((userName != null)&&(password!=null))
{
    request.Credentials = GetNetworkCredentials(userName, password);
}

Now, since we are currently consuming the web request from the routine, all I have to do is get the request and return it. I have this in two lines, as I like to be able to peek at the object in case of an error while developing. If you feel safer, you can return the object directly from request.

WebResponse response = request.GetResponse();
return response;

Communication Class

Here is the entire code for the HttpCommunicator class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using CrazyCancer.Framework.Communication.Enums;
using CrazyCancer.Framework.Communication.Interfaces;

namespace CrazyCancer.Framework.Communication
{
    public class HttpCommunicator : ICommunicator
    {
        /// <summary>
        /// Gets a response from an HTTP fronted API
        /// </summary>
        /// <param name="requestUrl">URL to communicate with</param>
        /// <param name="requestMethod">Method for getting response (GET or POST)</param>
        /// <returns></returns>
        public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod)
        {
            return SendRequest(requestUrl, requestMethod, null, null);
        }

        public WebResponse SendRequest(string requestUrl, RequestMethod requestMethod, string userName, string password)
        {
            WebRequest request = WebRequest.Create(requestUrl);
            request.Method = GetResponseMethodAsString(requestMethod);

            if((userName != null)&&(password!=null))
            {
                request.Credentials = GetNetworkCredentials(userName, password);
            }

            WebResponse response = request.GetResponse();
            return response;
        }

        private string GetResponseMethodAsString(RequestMethod requestMethod)
        {
            switch (requestMethod)
            {
                case RequestMethod.POST: { return "POST"; }
                default: { return "GET"; }
            }
        }

        private NetworkCredential GetNetworkCredentials(string userName, string password)
        {
            NetworkCredential credential = new NetworkCredential(userName, password);
            return credential;
        }
    }
}

Not a lot of code, but this library will grow as we end up having to add headers. This is more for Twitter and I am not sure how I will easily handle this (some type of collection), but that is a subject for a later date.

Peace and Grace,
Greg

Twitter: @gbworld