Friday, February 25, 2011

My First Hack at Functional Programming

I'm learning that with every new bug I learn something. If you've been keeping up, I use my Symantec.DataFactories to code against SSAS OLAP cubes. It's very rare, but I discovered that it is possible (and I didn't take into account) for the query to result in a dataset with no data, i.e. a list of people with null values. I have to present those values as averages and standard deviations. It came as a nasty surprise when I found out that the DataTable.Compute() method doesn't handle a column of all nulls very gracefully. So, I coded up a solution, thanks to some Googling, which I believe lends itself to functional programming, something I just got introduced to by Chris Eargle at the last Orlando DotNet UG meeting. Here's my initial stab and maybe I'll get some feedback on how to improve.

using System;
using System.Collections.Generic;

namespace MathLib
{
    /// 
    /// Container class for all statistics values which may be set by the Statistics class
    /// 
    public class StatTypes
    {
        public double? Average { get; set; }
        public double? StdDev { get; set; }
    }

    public static class Statistics
    {
        /// 
        /// Gets the average and standard deviation of a set in one pass
        /// 
        /// The set to be operated on        /// A StatTypes object with the Average and StdDev values 
        ///    for the set operated on
        public static StatTypes GetAvgAndStdDev(this IEnumerable<double> values)
        {
            StatTypes avgAndStdDev = new StatTypes();

            // ref: http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
            double mean = 0.0;
            double sum = 0.0;
            double stdDev = 0.0;
            int count = 0;
            foreach (double val in values)
            {
                count++;
                double delta = val - mean;
                mean += delta / count;
                sum += delta * (val - mean);
            }
            if (1 < count)
            {
                stdDev = Math.Sqrt(sum / (count - 1));
            }
            if (count > 0)
            {
                avgAndStdDev.Average = mean;
                avgAndStdDev.StdDev = stdDev;
            }

            return avgAndStdDev;
        }

        /// 
        /// Gets the average and standard deviation of a set in one pass
        /// 
        /// The set to be operated on        /// A StatTypes object with the Average and StdDev values 
        ///    for the set operated on
        public static StatTypes GetAvgAndStdDev(this IEnumerable<int> values)
        {
            StatTypes avgAndStdDev = new StatTypes();

            // ref: http://warrenseen.com/blog/2006/03/13/how-to-calculate-standard-deviation/
            double mean = 0.0;
            double sum = 0.0;
            double stdDev = 0.0;
            int count = 0;
            foreach (double val in values)
            {
                count++;
                double delta = val - mean;
                mean += delta / count;
                sum += delta * (val - mean);
            }
            if (1 < count)
            {
                stdDev = Math.Sqrt(sum / (count - 1));
            }
            if (count > 0)
            {
                avgAndStdDev.Average = mean;
                avgAndStdDev.StdDev = stdDev;
            }

            return avgAndStdDev;
        }
    }
}

Usage is made simple this way:

string metric = "DaysWorked";
StatTypes avgAndStdDev = (from row in table.AsEnumerable()
                          where row.Field<double?>(metric) != null
                          select row.Field<double>(metric)).GetAvgAndStdDev();
calculatedTarget["Mean"] = (object)avgAndStdDev.Average ?? DBNull.Value;
calculatedTarget["StdDev"] = avgAndStdDev.StdDev;

As an aside, I had no idea how to name the class or namespace for any usefulness. However, I learned that I never use the class name, anyway, so perhaps it doesn't matter. *shrug*

Wednesday, February 23, 2011

Silly Trick of the Quarter

Ok, the title would have sounded better as Silly Trick of the Day, but let's be honest; I don't post that often. :-) That said, here's something someone might enjoy. I've been working a lot with AJAX recently to improve the performance of a dashboard. No matter how fast I make the queries run, though, there will be times where we have to wait. So, the inevitable progress indicator comes up...boring, annoying, time for a cup of coffee.

I decided to reward those who grin and bear it with an iconic symbol of activity, Pacman being chased by ghosts until he goes offscreen and then returns the favor by chasing the suddenly blue ghosts back off where they came from. However, I didn't want it to do this every time. Here's the cool trick, code provided below.

/// 
/// Extends the Base.Render() method to randomly choose which image to show 
/// for Loading panel
/// 
/// protected override void Render(HtmlTextWriter writer)
{
    Image loadingImage = (Image)UpdateProgress1.FindControl("imgLoading");
    if (loadingImage != null)
    {
        int pacmanFlag = new Random().Next(1, 10);
        loadingImage.ImageUrl = pacmanFlag == 1
                                ? "~/Images/indicator-pm.gif"
                                : "~/Images/indicator-big.gif";
    }
    base.Render(writer);
}

The key is to create a Render() method which overrides the base class' method. Your asp:Image in your UpdatePanel on the page, named imgLoading in my case, gets randomly set to the specified ImageUrl.

Note: As my project is neither publicly facing nor used in the pursuit of any profit, I don't believe I'm breaking any copyright laws. If you wish to use Pacman as I have, I'm willing to share my graphic but be aware of how the copyright laws may affect your application.

Common Error, Simple Solution

Have you ever seen this error?
Message: Sys.ArgumentNullException: Value cannot be null.  
Parameter name: panelsCreated[2]
I struggled for quite some time trying to figure out what to do about it. If you do a Google search, you'll come across lots of people struggling with this error and the responses pointing at the AJAX Toolkit. However, in my case, I wasn't using the AJAX Toolkit directly. Rather, I was using Telerik's ASP.NET/AJAX controls.

What I was doing seemed simple enough. I needed certain RadPanels to show up on the page while others are hidden (<- a="" ajax="" and="" as="" be="" behind="" big="" browser.="" by="" c="" cannot="" class="brush: cpp; toolbar: false" code-behind="" code="" control="" controls="" css="" d="" didn="" display="" displayed.="" do="" don="" error="" false.="" find="" foreshadowing="" frankly="" hidden="" hiding="" i="" if="" in="" include="" instead="" interface="" is="" issue.="" it="" key="" like="" look="" may="" modify="" no-no.="" not="" of="" or="" out="" pops="" pre="" property="" radpanel="" render="" root="" s="" same="" setting="" should="" simple="" so="" solution="" something="" t="" tag="" telerik="" that="" the="" their="" then="" this:="" this="" to="" toolkit.="" true="" turns="" up="" use="" visible="" want="" wants="" was="" when="" whether="" with="" you="">radDock.Style.Remove("display"); // Visible = true
radDock.Style.Add("display", "none"); // Visible = false