Questions about Robots

In the future, when you have your first humanoid robot servant and you decide to have some fun with it, and you tell it to do something stupid and arbitrary like go stand in the corner for no reason, put itself in embarrassing poses, or anything generally “abusive”, will you feel bad afterwards? Should you? Why?

I think I would, perhaps depending on the severity and arbitrariness. I asked my wife. She said definitely yes, and that regardless of whether the machine can “feel” embarrassment or frustration, it reveals a character deficiency in yourself. She compared it to abuse against animals.

I think it may also depend on how humanized the robot is. You would feel bad doing it to Data (ignoring his free will), but maybe not to a mute, grotesque car welder.

Thankfully, South Korea has come up with a robot code of ethics.

Volunteers for Change Fairfax, VA

Leticia has been interested in getting us involved more in the community so she’s been hunting around for local service opportunities. She finally found a great program in our area that I thought I’d share for anybody looking for volunteer experiences in the DC metro region.

Fairfax City runs a division called Volunteer Fairfax that provides volunteers for numerous events through the year. They also organize team-building service activities for your company, up to thousands of people.

Volunteer Fairfax runs a specific program called Volunteers for Change. This program provides hundreds of weekend and evening volunteer opportunities, organized over the web. It’s perfect for people who can’t commit to regular hours every week or month, but want to do something when they can.

Events from their sample calendar:

  • Dinner prep at Ronald McDonald house
  • Bowling with the mentally/physically disabled
  • Bag groceries
  • Thrift store sorting
  • Tutoring
  • theater ushers
  • special city events
  • medical supply sorting

How it works:

  1. Attend an orientation at their building in the Fairfax County Court Complex
  2. Fill out some simple paperwork, sign a release
  3. Wait a day for your info to be added to their system
  4. Log into the web-site, find an event you can do, and sign up online.

Review: Pragmatic Unit Testing in C# with NUnit, 2nd Ed.

I saw this book when I bought Programming WPF a few weeks ago and it looked promising enough to buy. I’ve been doing unit testing in C# for a few years now, but I thought there were always things to learn and maybe I’d pick up a few new ideas.

It is easy to contrast this book with Beck’s Test Driven Development: By Example, and the two books definitely have a very different feel.

Beck’s book has a very evangelical feel to it, and it’s main purpose is to teach a mind set more than technical details. I believe this is important–maybe of first importance–but once you understand that, the rest of the book is a little simplistic for more experienced developers.

Pragmatic Unit Testing, on the other hand, focuses much more on the practical aspects (hmmm….I highly suspect that’s where the title comes from….) of unit testing. I liked the ideas on how to use categories and attributes to segregate tests that take too long to run on a regular basis. I also liked the section on singletons and getting around time-dependencies. The DateTime.Now problem is something I’ve had to deal with quite a bit in our server-side software that has a lot of time-dependant behavior. (In most cases, the problems were solved with refactoring the time into a function parameter.)

There are also good discussions of more mundane issues like how to deploy NUnit, where to put tests in a project, team practices, GUIs, threading, and C#-specific issues.

The discussion about mock objects (a very basic introduction) is also quite clear and understandable–more so than many resources I’ve seen on the web, which often assume you already know all about them.

Something I don’t like: the acronyms (BICEP, CORRECT, A TRIP). They kind of bug me. I like the ideas behind the acronyms and I think it’s more important and effective (for me, anyway) to internalize the principles of testing rather than remembering specific acronyms and the words they go with. YMMV.

Last Word…

I will probably only read Test Drive Development: By Example once,  but I will definitely come back to Pragmatic Unit Testing occasionally to refresh my ideas.

We Need More Growth of Nuclear Power

With this post, I’m beginning a new series or category of bog posts that I’m loosely terming “A Better Future.”


I’ve been thinking a lot about the grail of infinite power, coupled with the enormous rise in gas prices this week.

While I am all in favor of reducing wasteful consumption, increasing efficiency, and generally being smarter about everything, I do not believe we will ever reduce our energy requirements in the long-term. We are always inventing, always creating, and most things we create require power in some form. It’s a fool’s errand to try to reduce the actual energy we’ll use overall. This doesn’t even take into account all of the peoples of the world who are just now beginning to participate in the global economy. There will always be something to eat up the energy we produce. Fighting against this trend seems to me, in a way, trying to run evolution and progress backwards. Our race as a whole won’t do that. Given this, it makes much more sense to develop clean, efficient, abundant, cheap sources of energy.

Increasingly, I am convinced that the way to build out a vast network of nuclear reactors powering our grid. We have an enormous network of power distribution–we should be taking more advantage of it.

According to the US Department of DOE, our 103 active nuclear plants provide 20% of the nation’s electricity. You can even get the operational status of each one.

Worldwide, the IAEA predicts that the electric power generation capacity of the world in 2015 will be roughly 20,000 billion kilowatt hours. In that year, nuclear generation will provide roughly 2,972 billion kilowatt hours, or less than 15%. That report has a lot of other information and I highly encourage you to read it.

We need to increase that percentage drastically–to the point where it supplies power not just to homes, but to plug-in hybrid cars, and everything else.

Nuclear power has gotten a bad rap in the US and other parts of the world for a long time. I think the attitudes are changing, but not quickly enough. At what point will the benefits outweigh the risks in most minds? I think that point is almost upon us.

With the increasing development of pebble-bed reactors, nuclear technology is advancing. We need to increase this development to promote further advances in the safety and efficiency of these promising power sources. None of the operational reactors in the US are pebble-bed reactors (aka HTGR–high temperature gas-cooled reactors), nor are any planned. There is a research reactor at Idaho National Laboratory. All of the commercial HTGR development is taking place for other countries. These reactors, while not universally acclaimed, seem to be safer, cheaper, and the spent fuel less able to be repurposed as weapons-grade material.

We can’t wait for others to do these things–we need to do them. Our country needs to get in on the act at a higher level of commitment than ever. We can’t wait for these technologies to become perfected, either–that will happen over time. As we use a technology more, we will learn new techniques, ways to improve efficiency, and how to lower costs further.

There is no excuse for the US not  to be a leader in this area–we have one of the largest energy demands, the most capital, the most to gain by investing in it, and the most  to lose by not doing it.

The next generation of nuclear technology may not be the ultimate energy savior we’re looking for, but it’s a huge step in the right direction–a step we’ve delayed taking for too long.

Nuclear certainly has some down sides, but I’ll discuss those in a future entry.

Relevant Links:

  1. Pebble-bed reactors at wikipedia
  2. Energy Information Administration / Department of Energy
  3. International Atomic Energy Agency (IAEA)
  4. Inconvenient  Truths: Get Ready to Rethink What It Means to Be Green (Wired Magazine)
  5. Idaho National Laboratory
  6. Module Pebble Bed Reactor (MIT)

Virtual PC 2007 Tips and Tricks

 

This release of Virtual PC 2007 SP1 provides updates to existing features and introduces support for the following:

  • Windows Vista with Service Pack 1 (SP1) Business, Ultimate, and Enterprise operating systems as a host operating system

  • Windows Vista with SP1 Business, Ultimate, and Enterprise as a guest operating system

  • Windows Server 2008 Standard as a guest operating system

  • Windows XP with Service Pack 3 as both a guest and host operating system

  • Read The Virtual PC Guy’s Weblog
  • If you need, say, two virtual machines, one with Windows Vista and one with Windows Vista SP1, install Vista onto a new machine, then copy the machine files and install SP1 on one copy–much faster than installing Vista twice.
  • Need a screen shot of what’s in the virtual machine? Look at the Edit menu and choose “Select All” then “Copy”–a bitmap of the VM window will be on the clipboard. (This is how I got the capture of my BASIC graphics output from a previous post).

Custom data source for Google Earth

Using just these links as a guide, we quickly (less than a day) put up a data source over https for our customers to download GIS data to Google Earth.

KML reference and tutorial – KML is the XML language used to describe features that can be displayed in Google Earth and Google Maps.

Sample code to generate KML from a web service or web page (it’s VB.Net).

How to implement a custom authentication provider for IIS in .Net. Very useful if you need to authenticate your KML-generating web page and you don’t want to use Active Directory.

Formational Experiences

When I was 9, I started playing with GW-BASIC by typing in programs found in the old kid’s 3-2-1 Contact magazine. This soon progressed to QBASIC, where I mostly made cool graphics with lines and circles.qbasic_output

(click for larger image)

QBASIC is not included in Windows anymore, but you can still get it.

 qbasic_lines

(click for larger image)

I had also tried modifying the including GORILLAS.BAS and NIBBLES.BAS, but I was still a little too new at this.

When I was 14 I was getting into C/C++ via Borland C++ 3.1 in a big way and spent hours coding prank programs. I had two that I remember:

First was a program called Camels that displayed “I Love Camels!!!” in a vertical, colorful scrolling sine wave down the screen. It trapped Ctrl-Break/Ctrl-C so you couldn’t break out of it. If you hit Ctrl-K, it brought up a password screen that allowed you to exit if you knew the password. Then I put it on a lab at school, set AUTOEXEC.BAT to run it, and modified CONFIG.SYS with “switches /n” to disallow the user hitting F5 to skip processing of AUTOEXEC.BAT. This stunt kind of got me in trouble–the day after school ended, I got a call from my computer science teacher that he couldn’t access the computer and if I wanted a grade I had better get over there and remove that program because he couldn’t get onto the computer. So I had to bike a few miles to school (my parents were out of town) and remove it. Why didn’t the instructor just use a boot disk? No idea… By the way, I got an A.

One of my first Windows programs was something called “Chucky” (why? I don’t know…). Chucky liked to eat….hard disk space. He would startup with no Window, run in the background, and every few minutes it would add a few thousand lines of text to  the file C:\Windows\Chucky.txt. It was probably something like “I am Chucky, I am hungry.”

I even eventually convinced my parents to get me Turbo C++ so I could build Windows programs (suing OWL).

v6upWhen I was in college, I got Visual C++ 6 and thought a fun program would be a desktop utility that occasionally changed your Outlook signature to include a random quotation. You could build up a little database of quotes you liked, and the program would change it on a regular schedule. A friend of mine and I stayed up for nearly 3 days straight working on it. I did most of the programming–he was thinking of new ideas, ways to do things. It was great fun.

These important formational periods are what got me excited about programing. The learning that goes on during a 72-hour hacking session is something that can’t be duplicated in a classroom. The glee at creating pranks is not matched (often) by homework assignments. Sometimes when I’m feeling the drudgery of the current code I work on, I need to remember the excitement I felt back then.

I also need to find something equivalently exciting to work on. One of the things I’m going to do to “get the magic back” (so to speak) is to make sure I’m always experimenting with the latest and great .Net stuff coming out. I need to finally get into WPF, and I’ve even got a fun project to apply it to.

Lots of Good Movies This Year

We might have to make a few exception this year to our decision not to go the theater anymore…hopefully won’t have experiences like the last time

Tracking database changes using triggers

Tracking changes in database tables is an incredibly useful feature–especially for operational data that can change often. Having recently had to implement this feature, I thought I’d share some of the techniques I learned.

Sample Database

First, let’s conceptualize a very simple database consisting of user information (name, date of birth), and e-mails. A user can have more than one e-mail.

 

Table: UserData

Field Type
ID int (PK, identitiy)
FirstName varchar
LastName varchar
birthdate date

Table: UserEmails

Field Type
UserID int (FK)
email varchar

 

 

We want to track all changes to the FirstName, LastName, and birthdate fields. In addition we want to track when e-mails are added or removed from a user. As we’ll see, these aims are accomplished using two different methods.

My implementation is done in SQL Server 2000 and C#, but any database that supports triggers can be used.

Changes in a Single Table

With this method we want to track the changes to all fields of a table. In our example, we want to know when FirstName, LastName, and birthdate change values in the UserData table.

To accomplish this we need another table to track the history. This table is going to have the exact same fields as UserData, plus a few extra for the change tracking.

Table: UserDataChanges

Field Type
ChangeID int (PK, identity)
ChangeTime datetime
ChangeUser varchar
ID int (FK)
FirstName varchar
LastName varchar
birthdate date

Now the automated part–adding a trigger to populate this automatically:

CREATE TRIGGER UserDataChangeTrigger ON UserData FOR UPDATE, INSERT
AS    
    IF (UPDATE (FirstName) OR UPDATE(LastName) OR UPDATE(birthdate))    
    BEGIN     
        INSERT UserDataChanges 
            (ChangeTime, ChangeUser, ID, FirstName, LastName, birthdate)
            (SELECT GetUtcDate(), user, ID, FirstName,LastName,birthdate 
                FROM inserted)     
    END     

This trigger will insert a new row into the UserDataChanges table whenever a row in the UserData table is updated or inserted. The IF (UPDATE(FirstName)…. ) is not strictly required in this scenario, but in other cases I did not want a change recorded when certain fields were updated (i.e., you have a field that tracks the last change time of that row, or the number of orders, or any other field that can change frequently and isn’t important to track–you don’t want to create too much noise in this or it will not be useful). The GetUtcDate() and user are SQL Server functions that retrieve the current UTC time and the username of the process that caused the change–very useful for tracking responsibility. The inserted table is created by the server for use by the trigger and contains all the new values.

Changes in a Foreign Key Table

The UserEmails has to be handled differently because there can be multiple e-mails for each user and we can assume they can be added, or removed at will (Remove + Add = Update, so I won’t consider direct updates here).

The solution I landed on was to have a generic event log table that stores manual log entries as well as “special” entries denoting adding or removing e-mails.

Table: UserEventLog

Field Type
EventID int (PK, identity)
ID int (FK)
EventTime datetime
EventType int
ChangeUser varchar
Notes varchar

This table can be used for both adding text notes to a user and, by using the EventType field, special events. In our example, we have two events we need to track:

 

Event Value
EmailAdded 1
EmailRemoved 2

(In code, I’ve made these enumerations)

Next we add a trigger on the UserEmails table:

CREATE TRIGGER UserEmails_EmailAddedTrigger
ON UserEmails
FOR INSERT
AS
 BEGIN
     INSERT UserEventLog(ID, EventTime, EventType, ChangeUser, Notes)
        (SELECT ID, GetUtcDate(), 1, user, '{'+email+'}' FROM inserted)
 END

The value 1 stands for EmailAdded. I’ve added braces around the actual e-mail address to set it apart from regular notes (we’ll see how to integrate everything later).

To handle the deletion of e-mails add another trigger:

CREATE TRIGGER UserEmails_EmailRemovedTrigger
ON UserEmails
FOR DELETE
AS
 BEGIN
     INSERT UserEventLog(ID, EventTime, EventType, ChangeUser, Notes )
        (SELECT ID, GetUtcDate(), 2, user, '{'+email+'}' FROM deleted)
 END

The only things different: FOR DELETE (instead of INSERT), changed the EventType to 2 (EmailRemoved), and the values are taken from the SQL Server-supplied deleted table.

That’s enough to get a pretty good change-tracking system in place, but you’ll still have to build a UI to display it effectively.

Displaying the Changes in the UI

With the above work done, you end up with two types of entities: changes and events. While it would be possible to integrate all functionality into a single event/change table using a lot more logic in the SQL Trigger code, I’m personally more comfortable with the change logic being in my application code. I think this way the database is kept more “pure” and open to changes down the line.

That means we will need to integrate these two types of entities into a single list, ordered by date/time. I’m going to assume the existence of two classes or structs that represent each of these entities. They’ll be called UserChange and UserEvent. I’ll also assume that the lists of each of these are already sorted by time, since that’s trivial to do in a SQL query.

Given that, we need a function that takes both of these lists and produces a sorted, combined list with an easy-to-understand list.

How the function works:

  1. Go through both lists, and pick whichever one is next, time-wise.
  2. Translate the object into a string/list-view representation of that object.
  3. If it’s a UserChange object, compare it to the previous one to figure out what changed.
  4. Sort the list in reverse order to put newer items at the top.

Here’s the C# code which I’ve adapted from our production system. Don’t get hung up on the details:

 

private void FillLog(IList<UserEvent> events, IList<UserChange> changes)
{
    List<ListViewItem> tempItems = new List<ListViewItem>();
 
    int currentEventIdx = 0;
    int currentChangeIdx = 0;
    eventLogListView1.Items.Clear();
 
    while (currentEventIdx < events.Count
    || currentChangeIdx < changes.Count)
    {
    UserChange currentChange = null;
    UserChange prevChange = null;
    UserEvent currentEvent = null;
 
    DateTime changeTime = DateTime.MaxValue;
    DateTime eventTime = DateTime.MaxValue;
 
    if (currentChangeIdx < changes.Count)
    {
        currentChange = changes[currentChangeIdx];
        changeTime = currentChange.ChangeDate;
        if (currentChangeIdx > 0)
        {
        prevChange = changes[currentChangeIdx - 1];
        }
 
    }
 
    if (currentEventIdx < events.Count)
    {
        currentEvent = events[currentEventIdx];
        eventTime = currentEvent.EventDate;
    }
    string dateStr;
    string userStr;
    string eventTypeStr="";
    string notesStr;
 
    if (changeTime < eventTime)
    {
        dateStr = Utils.FormatDateTime(changeTime);
        userStr = currentChange.UserName;
        notesStr = GetChangeString(currentChange, prevChange);
        currentChangeIdx++;
    }
    else
    {
        dateStr = Utils.FormatDate(eventTime);
        userStr = currentEvent.UserName;
        notesStr = currentEvent.Notes;
        eventTypeStr = currentEvent.EventType.ToString();
        currentEventIdx++;
    }
 
    if (notesStr.Length > 0)
    {
        ListViewItem item = new ListViewItem(dateStr);
        item.SubItems.Add(userStr);
        item.SubItems.Add(eventTypeStr);
        item.SubItems.Add(notesStr);
        item.ToolTipText = notesStr;
        item.BackColor = (tempItems.Count % 2 == 0) ? 
            Color.Wheat : Color.White;
        tempItems.Add(item);
 
    }
 
    }//end while
    eventLogListView1.BeginUpdate();
    for (int i = tempItems.Count - 1; i >= 0; i--)
    {
    eventLogListView1.Items.Add(tempItems[i]);
    }
 
    eventLogListView1.AutoResizeColumn(0, 
        ColumnHeaderAutoResizeStyle.ColumnContent);
    eventLogListView1.AutoResizeColumn(1, 
        ColumnHeaderAutoResizeStyle.ColumnContent);
    eventLogListView1.AutoResizeColumn(2, 
        ColumnHeaderAutoResizeStyle.ColumnContent);
    eventLogListView1.Columns[3].Width = eventLogListView1.Width - 
    (eventLogListView1.Columns[0].Width +
    eventLogListView1.Columns[1].Width +
    eventLogListView1.Columns[2].Width +10);
 
    eventLogListView1.EndUpdate();
}

Now we need to define GetChangeString, which figures out the differences in successive UserChange objects and displays only pertinent information.

 

private string GetChangeString(
    BuoyDataChange currentChange, 
    BuoyDataChange prevChange)
{
    StringBuilder sb = new StringBuilder();
 
    if (prevChange == null)
    {
        CompareAndAdd(sb, "First Name", 
            null, currentChange.FirstName);
        CompareAndAdd(sb, "Last Name", 
            null, currentChange.LastName);
        CompareAndAdd(sb, "Birth Date", 
            null, currentChange.BirthDate);
    }
    else
    {
        CompareAndAdd(sb, "First Name", 
            prevChange.FirstName, currentChange.FirstName);
        CompareAndAdd(sb, "Last Name", 
            prevChange.LastName, currentChange.LastName);
        CompareAndAdd(sb, "Birth Date", 
            prevChange.BirthDate, currentChange.BirthDate);
    }
    return sb.ToString();
}

And one last helper function which compares two objects and if different appends the change to a StringBuilder object.

 

private void CompareAndAdd(StringBuilder sb, string field, 
    object oldVal, object newVal)
   {
       if (oldVal == null && newVal == null)
           return;
 
       if (oldVal == null || !oldVal.Equals(newVal))
       {
           if (sb.Length > 0)
           {
               sb.Append(", ");
           }
           sb.AppendFormat("{0}:{1} -> {2}", field, oldVal, newVal);
       }
   }

In this way you can end up with an automated system that displays all changes in an easy-to-understand format.

Here’s a sample of what our system looks like (click to enlarge):

Change log screenshot

Other ways to accomplish this? Better ways? Please leave a comment!

kick it on DotNetKicks.com

Opening Visual Studio solutions from Explorer in Vista

You’ve installed Visual Studio 2005 on Vista and dutifully changed it to run as administrator, like you’re supposed to. And then…

Problem: Visual Studio 2005 solutions no longer open when you double-click them in Windows Vista. In fact, when you double-click nothing happens.

Solution: Change them to open with Visual Studio 2005 directly instead of the vslauncher.exe (which opens up the solution with the correct version of Visual Studio if you have more than one).

Caveat: Only makes sense if  you use only Visual Studio 2005.

How-to:

  1. Right-click on a solution file.
  2. Choose “Open With…”
  3. Choose “Browse…”
  4. Browse to file “C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe” (or wherever you installed Visual Studio)
  5. Click “Open” button
  6. Check “Always use the selected program to open this kind of file”

openwith

Now your solutions will load Visual Studio, bring up the UAC prompt, and it all works great.

Found via here and here.