Google Analytics

Tuesday, December 16, 2014

What Does That Have to do With the Price of Oil?

One thing that I really haven't heard anyone talk about concerning this precipitous drop in the price of oil is how OPEC hasn't cut their production. In years past when the price of oil threatened to drop liek this, OPEC would only need to threaten to cut production to keep prices stable. Now, even in the face of plummeting prices, OPEC has said they will not cut production. (http://www.bloomberg.com/news/2014-12-14/u-a-e-says-opec-won-t-change-output-even-if-price-drops-to-40.html)

The result of this is that Russia's economy, so dependent on oil, is going right down the crapper. (http://www.bloomberg.com/quote/RUBUSD:CUR) I don't think this is any accident. Of course, one can only speculate the conversations that go on behind closed doors between U.S. politicians and Arabian sheikhs, but certainly no one is in any hurry to throw Vladimir Putin a life ring. For as much as Putin kicked around Obama this summer, maybe Obama deserves some consideration for throwing a haymaker of his own.

Friday, December 5, 2014

I want to get this down in writing, though it is certainly only a half-baked idea. It isn't even really an idea, but a stream of thoughts. And this is why I need to get it down: it's a thought experiment, or a series of thought experiments, a hypothesis that needs to be held up to scrutiny in order to be refined.It's on the nature of good and evil, morality, right and wrong. I've been ruminating on it, turning over this big ball of dough in my mind, adding ingredients here and there, throwing out the entire batch at times and remixing it. Now it's time for me to throw these into the oven, bake it, and see how it tastes, see how others think it tastes.

As with baking, putting these ideas out there for public scrutiny is final. Final in a sense that once it's out there, especially on the internet, you can't just take it back. Just as once a cookie is baked, if it's terrible, you just can't break it back down and get your eggs, flour, sugar, and chocolate chips back. However, you can take the entire batch, throw it into the garbage and start again. I need to actually try this and see how it tastes finally.

So here goes: Good exists.

Good exists inherently in the universe. It wasn't invented by humans, but I'm not sure that I can positively say that it existed before humans. It wasn't invented by humans anymore than intelligence or creativity was invented by humans. It goes hand-in-hand with those things, so whether it existed before humans, I guess is one of those points of debate. I'll assert that it did, but that's for a later time. 

Good exists. That is my little leap of faith at which I start. It is the basis upon which I say I am a religious person. Science is based in fact. Theories that support certain facts are studied and tested until some fact, some evidence comes along to make that theory in its current state invalid. The theory changes and is re-evaluated until it no longer supports the evidence and must be again re-evaluated, ad infinitum. Philosophy and mathematics incorporate logic. "I think therefore I am." Logic is baked into that statement. Socrates used logic to prove that non-truths failed in their logical absurdity. Taking the logical inverse of some truth, he whittled it down to a point where it made no sense, thus the opposite of that case must be true. (I'm saying this badly, but again, this is just a thought experiment.) I have no evidence to disprove that Good does not exist. We can start with the premise that it does not exist and follow the logic through, and there is nothing that I think I can come up with that would make it a logical fallacy. Good may not exist. It's an examination that I want to work through later. However, I know that if Good does not exist in this world, then it is no ta world I want to be part of. And that is frightening. Too frightening for now, so I am starting with the premise that it does exist.

If good does not exist, then morality does not exist. Again, it's an assertion that I would like to examine later through its inverse, but provided I am making the assumption that Good exists, then I will also say that it is upon that assumption that morality is based. Let's now also assert that Evil then also exists being the negative counterpart or exact opposite of Good, Murder is evil. Rape is evil. Theft is evil. (As an aside, I think another idea to examine is that theft is at the heart of all crime, murder being the theft of life, rape the theft of sex and so forth.) One can argue that the idea that these things are bad or evil have emerged as a necessity of human evolution, that we are repulsed by the concept of murder or rape because it has been hard-wired into our DNA. If we were murdering and raping each other, we'd never evolve as a species in the first place. One can argue that the laws against theft were key inventions to us being able to live in an organized society (and thus not murder each other). This may be. Perhaps our sense of Good vs. Evil is some evolutionary necessity, that our sense of morality springs from us all trying to get along together. However, that begs the question. Perhaps we are evolving, but to what end? What's to say that evolving at all is good? Again, I simply have faith that it is. I believe, have mere faith in the fact, that we are being drawn toward some higher... purpose, for lack of a better term. And it is this higher purpose, this THING, that is not just the idea of Good, the Form of Good in the Platonic sense, but is God itself.

Tuesday, July 22, 2014

Begging Your Pardon

I have to get something off my chest, and it's petty and trite just as all my little pet peeves are. Consider it a public service announcement: "Begging the question" and "raising the question" are not the same, and normally when people say the former, they mean the latter.

Begging the question means to assume the very conclusion that you are trying to prove. Here's this example from the Wikipedia entry:

"To allow every man an unbounded freedom of speech must always be, on the whole, advantageous to the State, for it is highly conducive to the interests of the community that each individual should enjoy a liberty perfectly unlimited of expressing his sentiments."

Basically the above quote is saying "Freedom of speech in society is good because it is good to have a society with free speech." The argument begs the question of what makes free speech good in the first place. It is circular reasoning.

I don't fault and don't correct people who use "begs the question" to mean "raises the question". I used to do it as well until relatively recently. Now that I've been set right, when I hear it, and how often I hear it, it grates on me; just as fewer v. less and who v. whom are like sandpaper to my eardrums when I hear them. It's just personal, and I'm a grammatical jerk (uh... to coin a phrase).

Tuesday, July 15, 2014

Configuring GhostDoc Pro, part 1 - File, Class, and Properties Headers

I started this post back in the beginning of 2013. I apparently tossed my exported rules(*), so am redoing them and thought I would revisit my own, hopefully useful, advice.

I swear, why is it so hard to find documentation on doing some of the simplest programming things? Why is it that these companies can create such a relatively useful product, and yet it is impossible to find any real sort of documentation on how to use them? I have multiple blog entries brewing on my frustrations using Infragistics Reporting in their NetAdvantage suite. Today though, I'm going to rail against SubMain's GhostDoc Pro.

GhostDoc, a VisualStudio extension for automatically generating XML documentation and code comments, is a total time saver when it is properly configured. Because of the government certification our products generally go through, our code has to be meticulously commented in very specific ways. At one point my rules were properly configured and I had spent about half a day configuring the templates as well as I could, so that all I had to do was go to Tools > GhostDoc > Document File and my code file would be properly documented including headers, properties and fields. Unfortunately when I chose to upgrade my current version of GhostDoc it apparently took my desire to "Upgrade" my current rules file and merely used that as a "suggestion", which it then ignored, and I ended up with the default GhostDoc Rules templates. *So my first suggestion to you is that as soon as you have the templates the way you want them, export them to avoid having go through the hassle of re-creating them.

Secondly, bookmark this blog post as reference to refer back to later. The extent of SubMain's online documentation for creating your own templates seems to be to simply rely on the community of GhostDoc users creating blog posts in their community pages (http://community.submain.com/) and on StackOverflow. If you go to the tutorials on SubMain's site you will notice there are no tutorials for GhostDoc. (I take it back. Since I first began writing this blog article way long ago, a simple tutorial has been added. It is a very quick overview of all of GhostDoc Pro's features.) The help file that is downloaded for GhostDoc Pro contains an Introduction to T4 Templates and a description of each of the different templates that are used.

Editing T4 Templates
To edit the GhostDoc Pro T4 Rules templates, in Visual Studio go to Tools > GhostDoc Pro > Options > Rules and select the template you want to update. The template will open into an editor that does provide some Intellisense and color-coding.

Adding Global Properties
Global properties, accessible through the GetGlobalProperty of the Context object, can be added in the GhostDoc Pro options window under Global Properties. Here you can enter the key-value pairs for commonly used properties throughout your templates.

File Header

By necessity, our standard file header looks like this:

// -----------------------------------------------------------------------------
// <copyright company="Dominion Voting Systems" file="ElectionDataService.cs">
//     Copyright (c) 2013 Dominion Voting Systems, Inc. All Rights Reserved.
//     Any distribution of source code by others is prohibited.
// </copyright>
// <summary>
//    This file contains the Election Data Service Class
// </summary>
// <revision date="1/11/2013" revisor="ben.rice">
//     File created.
// </revision>
// -----------------------------------------------------------------------------

In order to create this I am using the following template.

<#@ template language="C#" #>
// -----------------------------------------------------------------------------
// ">
//     Copyright (c) <#= Context.DestinationFileCreationDateTime.ToString("yyyy") #> <#= Context.GetGlobalProperty("CompanyName") #>. All Rights Reserved.
//     Any distribution of source code by others is prohibited.
//
//









//     This file contains the <#= System.IO.Path.GetFileNameWithoutExtension(Context.DestinationFile) #> class.
//
// " date="<#= Context.DestinationFileCreationDateTime.ToString("MM/dd/yyyy") #>">
//     File created.
//
// -----------------------------------------------------------------------------

You can see that the Context object is perhaps the most useful in creating these templates. It's use is based on the template in which it is used. In this case, for example, the Context.Exceptions would be empty since the context of its use here is the File and Exceptions enumerates only any exceptions thrown by a method or property. You can also see the use of Context to retrieve our Global Properties. Of course, this can be done in whatever template you are editing. Also note that I can use the standard .Net objects and methods to get the file name without the file extension, for example. 

I need to modify the rule yet to add the "File modified." revision note. For now I throw that on manually.

Class Header
Our standard class header:

///









///     Interaction logic for navigating views within the Ballot Viewer.
///
///
///     Class created.
///

For this I am basically using the default class template for GhostDoc Pro.

<#@ template language="C#" #>
<#  CodeElement codeElement = Context.CurrentCodeElement; #>
///









///<# GenerateSummaryText(); #>
///
<#  if(codeElement.HasTypeParameters) 
{
for(int i = 0; i < codeElement.TypeParameters.Length; i++) 

TypeParameter typeParameter = codeElement.TypeParameters[i]; 
#>
/// <# GenerateTypeParamText(typeParameter, i); #>
<# }

#>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRemarksText(); #>

<#+
private void GenerateSummaryText()
{
if(Context.HasExistingTagText("summary"))
{
this.WriteLine(Context.GetExistingTagText("summary"));
}
else if(Context.CurrentCodeElement.IsSealed)
{
this.WriteLine("TODO: Add summary for Class " + Context.CurrentCodeElement.Name + ". This class cannot be inherited." + Context.ExecMacro("$(End)"));
}
else
{
this.WriteLine("TODO: Add summary for Class " + Context.CurrentCodeElement.Name + "." + Context.ExecMacro("$(End)"));
}
}
    
private void GenerateTypeParamText(TypeParameter typeParameter, int index)
{
if(Context.HasExistingTagText("typeparam", index)) 

this.Write(Context.GetExistingTagText("typeparam", index));

else 
{
string typeParameterName = typeParameter.Name;
if(typeParameterName != null)
{
if(typeParameterName.Length == 1)
{
this.Write("");
}
else
{
this.Write("The type of " + Context.ExecMacro(typeParameterName, "$(TheAndAll)") + ".");
}            
}          

}

private void GenerateRemarksText()
{
if(Context.HasExistingTagText("remarks"))
{ #>
/// <#= Context.GetExistingTagText("remarks") #>
<#+    }
else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))

            // Should you require a default comment, set it in
// Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <#= Context.GetGlobalProperty("DefaultBlankRemarksText") #>
<#+    }
}
#>

Notice that within the template I can call C# methods coded below. In this case we are generating type parameter elements for each type parameter if there are any. If a summary element or remarks element already exists in the header, that text is preserved, else some default text is inserted. Mine has a TODO reminder in the summary text to highlight that I need to change that.

I'm going to skip ahead now to the Properties rule

Our property header will look something like this:
///









///     Gets or sets the name of the election.
///
/// The name of the election.
///
///     Member created.
///
///
///     Changed to allow public setter.
///

I added to the default property generated in order to set the revision element.

<#@ template language="C#" #>
///









///<# GenerateSummaryText(); #>
///
<# GenerateValueText(); #>
<# if(Context.HasExceptions) 
{
foreach (System.Collections.Generic.KeyValuePair> pair in Context.ExceptionDictionary)
{
string exceptionText = Context.GetExistingExceptionTagText(pair.Key); #>
/// <#= ((exceptionText != null && exceptionText.Length > 0) ? exceptionText : Context.GetExceptionTagText(pair.Value)) #>
<# }
}  #>
<#= Context.GetNonGeneratedExceptionTags() #>
<#= Context.GetNonGeneratedTags() #>
<# GenerateRevisionTag(); #>
<# GenerateRemarksText(); #>

<#+
private void GenerateSummaryText()
{
CodeElement codeElement = Context.CurrentCodeElement;
   
if(Context.HasExistingTagText("summary"))
{
this.WriteLine(Context.GetExistingTagText("summary"));
}
else if(Context.HasInheritedTagText("summary"))
{
this.WriteLine(Context.GetInheritedTagText("summary"));
}
else if(IsBooleanProperty()) 
{
if(IsStateCheckBooleanProperty())
{
// state check boolean property
this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether this instance $(PropertyName.Words.All)."));
}
else if(IsSingleWordBooleanProperty())
{
// single word boolean property
this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether this $(DeclaringTypeName.ShortNameAsSee) is $(PropertyName.Words.First)."));
}
else
{
// boolean property
this.WriteLine(Context.ExecMacro("$(PropertyAccessText) a value indicating whether $(End)[$(PropertyName.Words.All)]."));
}
}
else if(Context.ContainsOfTheReordering(codeElement.Name)) 
{
this.WriteLine(Context.ExecMacro(codeElement.Name, "$(OfTheReordering)", Context.ExecMacro("$(PropertyAccessText)")));
}
else
{
this.WriteLine(Context.ExecMacro("$(PropertyAccessText) $(PropertyName.Words.TheAndAll)."));
}
}
        
private void GenerateValueText()
{
CodeElement codeElement = Context.CurrentCodeElement;
        
if(Context.HasExistingTagText("value"))

#>
/// <#= Context.GetExistingTagText("value") #>
<#+
}
else if(Context.HasInheritedTagText("value"))

#>
/// <#= Context.GetInheritedTagText("value") #>
<#+
}
else /*if(Context.CurrentCodeElement.HasSet) - commented for StypeCop compliance (SA1609) */
{
if(IsBooleanProperty()) 
{
.....
}
}

.... 
    
private bool IsBooleanProperty()
{
CodeElement codeElement = Context.CurrentCodeElement;  
return (bool)(codeElement.ReturnType != null && 
codeElement.ReturnType.FullName != null &&
codeElement.ReturnType.FullName.Length > 0 && 
(string.Compare( codeElement.ReturnType.FullName, "System.Boolean", true) == 0 ||
string.Compare( codeElement.ReturnType.FullName, "System.Nullable", true) == 0));
}  

private void GenerateRemarksText()
{
if(Context.HasInheritedTagText("remarks"))
{ #>
/// <#= Context.GetInheritedTagText("remarks") #>
<#+    }
else if(Context.HasExistingTagText("remarks"))
{ #>
/// <#= Context.GetExistingTagText("remarks") #>
<#+    }
else if (!string.IsNullOrEmpty(Context.GetGlobalProperty("DefaultBlankRemarksText")))

            // Should you require a default comment, set it in
// Options -> Global Properties -> DefaultBlankRemarksText
#>
/// <#= Context.GetGlobalProperty("DefaultBlankRemarksText") #>
<#+    }
}

private void GenerateRevisionTag()

if( Context.HasExistingTagText("summary")) {#>
/// <revision revisor="<#= Context.GetGlobalProperty("UserName") #>" date="<#= DateTime.Now.ToString("MM/dd/yyyy") #>">
///     TODO: Add Revision
/// </revision>
///
<#+
} else { #>
/// " date="<#= DateTime.Now.ToString("MM/dd/yyyy") #>">
///     Member created.
///
<#+ }
}
#>

Please note that in the interest of space, I omitted code that determines how to word the value element of a boolean property. In the custom "GenerateRevisionTag" method I did a check to see if the summary has already been written. If it hadn't been (prior to this GD call), I assume the property has just been created and add "Member created." to the revision text. Otherwise, I assume that the property already existed, but is being revised and add the reminder to myself to update what the revision was. Also note that the GenerateRevisionTag call is made after Context.GetNonGeneratedTags is written. This makes later revisions appear below previously written ones.

Monday, June 2, 2014

Wix and Feature Install Levels

I was just doing some digging for a colleague to find information on Wix and installing separate features by default or within a typical or custom install. This article does a comprehensive job of covering the topic. So for my own future reference and rather than rehash it, I will just post it here. (http://blogs.technet.com/b/alexshev/archive/2008/08/23/from-msi-to-wix-part-4-features-and-components.aspx). Note: I haven't actually tried the sample code yet.

Thursday, April 17, 2014

Amongst the Sinners

Tomorrow morning we are headed to Las Vegas for Viva Las Vegas, Rockabilly Weekend. VLV is a combined, car show, concert festival, burlesque show, and generally a scene for women to dress up like pinup models. Jen and I have gone now for years. It's always held on Easter weekend, and we kid, "Hey, where else would Jesus want us to be other than in Sin City for Easter, amongst the sinners, preaching His message?"

Okay, neither Jen nor I are the preaching type. In fact, we aren't exactly church-going types, though I think both of us wouldn't mind that changing. I feel like I am a very religious person, but not in a conventional sense. Maybe I would identify with being more "spiritual" than religious, except that for the fact that those who say they are "spiritual" often just use that as an excuse for either not wanting to think about it too much or not wanting to risk telling people they are religious.

I just don't identify with a particular religion, but in a way I identify with ALL of them, well, all the major ones. To me, they all carry the same message, just put into words that the people of a particular time and place could identify with. I have an entire treatise on this somewhere within me, but I don't want to get into that now, not on the eve of flying out to Las Vegas. Basically though I believe every religion says "Be good to each other." OR in the words of Bill & Ted, "Be Excellent to each other." What being good really means is perhaps what we all get hung up on. However, I simply believe that "goodness" exists, and that we should strive for that.

In doing that, in striving to be good, I feel I too often fall short. On the way home while driving today I was thinking about it. I was thinking about how hard I have been working to try and be better, and still falling short, wondering what I really need to do to become a better person. And I realize I have really been trying to do it on my own. Once in a while I can confide to Jen, or my brothers, or a close friend, but mostly I felt like I had to do everything on my own.

Then the thought, and the feeling came over me -- I don't have to do it alone. I'm not saying that I'm going to start calling upon God to make me a better person. I don't believe in Him like that. To say I believe in a Him at all in a conventional sense would be incorrect . But there is a reason that so many people find strength in prayer, in meditation, in the Bible, in the Koran, in going to church, in the buddha, dharma, and sangha. There is wisdom in religion.

We'll see where this really takes me. Happy Easter to all of you, however you plan to celebrate!

Thursday, March 20, 2014

More Random Status

Confession: big childhood crush was Martha Davis of The Motels.... Following up on that, I made a Guilty Pleasures playlist on Spotify (The Motels aren't on it. No guilt in loving me some Motels). At first I just left it public, because I was like, I don't care what people think of my Guilty Pleasures, but then it was even too embarrassing for me, so I hid it....I've mostly stayed away from the social media, but sometimes I just habitually browse to FB. I suppose this is why I had to give it up for a while in the first place.... I don't get why the Rockies want me to pay something like $30-40 / game for at least 20 games just to get Opening Day tickets. I know that a third of the way through the season I will be able to get those same tickets for about $10 apiece because no one is going to wan to go watch this team. It irritates me that they want you to pay all this money and then you go to the park at mid-season and they've completely closed off the third level except for right behind the plate....Northwestern, still undefeated in NCAA tournament play....What is CNN going to air when they finally find that plane?.... Where we are staying in Paris in June: https://www.airbnb.com/rooms/497695. This is going to be awesome!..... Also have tickets again for VLV. It's going to be a short trip this time, and overshadowed by the Paris trip, but I am still REALLY looking forward to it. Need a bit of a break from the routine.

Wednesday, March 12, 2014

WiX Questions

If you've posted some question about WiX to me on here, I haven't forgotten about you. I just haven't made it a priority to try and find the answer for you. :) I post here because I am discovering how to use some of these things just as many of you are, and admittedly there isn't a wealth of information out there.

Seriously, though, I appreciate the questions and want to take some time, even out of my own curiosity, to find the answers. Between work and life and trying to get ready for the fantasy baseball season, and flossing my gerbil's teeth, however, there just hasn't been much time. If you've posted questions and subsequently found the answers out there in the Tubes somewhere, I'd appreciate if you could post your answer here. "Make this your action item." Thanks!

.Net Reactor and WiX

Okay, here's the situation: ("My parents went away on a week's vacation...") I need to obfuscate the code of a project I am working on using .Net Reactor. The project is in .Net (obviously) and we're using VS 2012 and WiX 3.7 to create the installer. Obfuscating code with .Net Reactor is relatively simple as well as powerful. In a side-by-side comparison with dotfuscator we found that Reactor did a better job particularly in control flow obfuscation than its more expensive counterpart. The issue before me is getting WiX to do this obfuscation before creating the installer.

Actually the project is broken up into several solutions, a client and several services that get packaged together. Obfuscating the initial project, the client, was relatively straightforward. First I created a .Net Reactor project specifying the protection options, settings, and files I wanted to obfuscate. I added that project file to my solution as a resource to copy into the output directory. The solution builds a number of projects including some shared libraries, so it was just easiest to copy the project into the output directory and run it from there. I edited the wixproj file (in VisualStudio you can right-click the project file and select 'Edit Project File') and overwrote the BeforeBuild target as such:


 

The .Net Reactor command-line help here, http://www.eziriz.com/help/source/command_line.htm, is useful, though if you are using the project file as I am, most of the settings will come from it. I added the -q[uiet] flag to keep Reactor's notification window from popping up. I should note here that by default a Reactor project will have \_secured\ as the Target File setting. That setting results in each obfuscated assembly being tucked away neatly in its own directory, which I would then have to pick through to pack back into the installer. To remedy this, I just had the obfuscated files overwrite the originals by removing the subdirectory of the Target File:
\. That has worked pretty well for me except that I need to be sure to rebuild the VS solution before building the WiX installer each time, else Reactor finds the previously obfuscated file and chokes.

For each of the services then I built a Reactor project and added multiple elements to the BeforeBuild of the wixproj that builds that installer. I also had to separately build a few other DLLs where I needed to have a lower level of obfuscation. It was simple just to create their own separate Reactor project and execute them in the BeforeBuild as well.
Random thoughts since I'm withdrawing from posting random, meaningless FB status updates:

I feel awful for the families of those who were on the Malaysian Airlines flight, but c'mon, CNN. I don't need hourly updates on its last known radar blip.... I wasn't blown away by the ending of Breaking Bad like some said they were. Don't get me wrong, it was quality. The overall series, however, was amazing. Easily unseated The Sopranos as my favorite television show ever.... I took in the finale of True Detective last night too. The acting in that show, especially by McConaughey, was great. The writing and directing were equally on point. It was a haunting series.... Tom Waits' "Martha" is a devastating song. Replace "Martha" with any hope or dream you've ever had.... Jeff Buckley singing "Hallelujah" is pretty devastating too, but you already knew that.

Wednesday, February 12, 2014

Empathy

In so much of what I've read from the Dalai Lama, he preaches time and time again that we must have empathy for our fellow humans. Empathy brings us closer to others, it leads to compassion, and, not to get all Buddhist on you but, helps to end suffering. In non-Buddhist terms, having empathy for other people makes us and them happier.

I need to be better about this in practice in so many areas in my life, but especially right now at work. I've certainly not hidden that I am irritated with my job and there are days I am flat-out angry. (Full disclosure, there have been more days recently when I've been able to put aside the irritants and focus on what I like about it, which is solving problems to help people vote.) When I get angry and irritated, however, I've been bad about putting my co-workers in the line of fire. Generally, it shows in passive-aggressive behavior by me, which I don't even realize I'm doing. There have been a handful of embarrassing moments when that aggressive behavior isn't so passive. Even a couple times where I was yelling full-voiced at a co-worker without even really realizing it.

My co-workers are definitely not the issue I have with work. I think that to a person the people I work with are all underpaid and underappreciated by "the powers that be" for what we do. We grouse about it, and sometimes I grouse louder than others, but it isn't like we are underpaid like our nation's teachers are underpaid. Maybe I just speak for myself, but I think it is the underappreciated part of the equation that is worse than the underpaid part.

With the people I work with both day-to-day and only occasionally what I've come to realize is that every one of us is trying our best. Okay, maybe we're not at our best every moment of every day because humans just can't be (except for Meryl Davis and Charlie White. I mean, am I right? They're like robots on the ice.). When I take a step back and acknowledge that everyone else around me is really working just the best they can as am I, how can I fault that? Programming voting machines and election software for U.S. elections is hard work. I mean, it's no putting a man on Mars hard or cracking Verizon wireless encryption so that the NSA can listen in on your phone calls hard, but it ain't easy, Sally. There are a lot of people that I work with that are very good at what they do and care about what they do, and I need to have more empathy for them and forget my own issues at times.

I was reminded of this tonight. At about 4:30 PM MST that call came in. You know the one: "I have a demonstration to the some of the largest counties in California tomorrow, and I can't get the software to work. Can I talk to a developer there?" Of course none of us really WANTED to take that call. I won't go into the specifics why other than to say it was 4:30PM already. However, I was in the same boat last month. I was supposed to do a demonstration to the State of Florida and the test project that I was given didn't work. One of my colleagues in Belgrade stepped up and worked, on Christmas (maybe the day after) I believe (since they celebrate Orthodox Christmas), to get me what I needed. I knew how stressed I was then, so volunteered to help with today's predicament.

Listen, I may have stepped up and volunteered, but I won't say that I did it cheerfully. There may have been some choice words thrown in. Putting myself in that guy's shoes though, I couldn't just walk away and say, Not my problem. When you have empathy for someone, that person's problems become your problems too. The good thing is that having two people to work on a problem is much better than one struggling through it themself. The issue turned out to be a series of relatively minor things, and we got things squared away. My colleague in California was grateful that he wasn't going to be tarred and feathered by the State of California, and I actually appreciated being able to re-familiarize myself with a couple parts of our system I hadn't used in a while.