Monday, November 28, 2011

Dynamics Dexterity

A little over a month ago I was trained on our old legacy products. This includes Dynamics Dexterity. It's a scripting language. The language itself is not too bad, but the development environment is horrible, especially since I'm used to working in the fancy Visual Studios.

I've now fixed many bugs and we're ready for a release. Thank God I can finally get out of that and hopefully look at the beautiful C#. I will never take Visual Studio / C# for granted again.

Thursday, September 1, 2011

Dynamically create instances of Forms (or any type)

Problem
I have a form that has a dropdownlist which has "Name of Form", frmObject.

            Dictionary<string, Form> dictForms = new Dictionary<string, Form>(3);
            dictForms .Add("Form 1", new frmOne());
            dictForms .Add("Form 2", new frmTwo());
            dictForms .Add("Form 3", new frmThree());
             comboBoxForms.DataSource = new BindingSource(dictForms , null);
             comboBoxForms.DisplayMember = "Key";
             comboBoxForms.ValueMember = "Value";
             comboBoxForms.SelectedIndex = 0;

Then when the user clicks Open
            Form frm = (Form)comboBoxForms.SelectedValue;
            frm.Show();

The problem with this is after frm.Show(), the frm object is disposed, which means if you try to open the same form it will throw an exception.


Solution
Instead of storing instances of each form object, you can store the type instead, and then use reflection to generate an instance of the form object. This means the form object is created locally, which solves the "disposed of" problem.

            Dictionary<string, Type> dictForms = new Dictionary<string, Type>(3);
            dictForms .Add("Form 1", typeof(frmOne));
            dictForms .Add("Form 2", typeof(frmTwo));
            dictForms .Add("Form 3", typeof(frmThree));
            comboBoxForms.DataSource = new BindingSource(dictForms , null);
            comboBoxForms.DisplayMember = "Key";
            comboBoxForms.ValueMember = "Value";
            comboBoxForms.SelectedIndex = 0;
        }

Then when the user clicks Open
            Form frm = (Form)Activator.CreateInstance((Type)comboBoxForms.SelectedValue);
            frm.Show();

Note:
You can accomplish my original goal by typing in the form name into the combo box, then using a switch to determine which form to open. Doing the way described below means adding a new form only requires 1 line of code to be added, instead of ~5 lines, and also you don't need to sync the names of the forms in the dropdown with the names in the switch

Note 2: 
There's an overload for Activator.CreateInstance  that takes a param array. The solution above will work if all forms use the same parameter or have no parameters at all. It won't work if they require different parameters that have to be assembled right before the call. In other words, if they require a value from the calling form, then this solution will result in needing to check the type first, which defeats the purpose of storing the type.

Tuesday, August 30, 2011

How to show current elapsed time on a WinForm using background workers and stopwatch

Problem:
I wanted to show the time elapsed for time-consuming SQL command. This is so the user could see that something is actually happening.

Solution:
I accomplished this by using two BackgroundWorkers, a status strip, two status strip labels, and a stopwatch. This will update the time label every half second and stop when the data thread is done.


 //Make sure to add these two
using System.Diagnostics;
using System.Threading;
        private void btnSQLCommand_Click(object sender, EventArgs e)
        {
                lblDataStatus.Text = lblStatus.ToolTipText = lblDataStatus.ToolTipText = "";
                lblStatus.Text = "00:00:00";
                button1.Enabled = false; //So user cant click button while operation is running
                bgWorkerTime.RunWorkerAsync();
                bgWorkerData.RunWorkerAsync();

            }           
          
        }

        private void bgWorkerTime_DoWork(object sender, DoWorkEventArgs e)
        {
            Stopwatch sw = Stopwatch.StartNew();
            while (!bgWorkerTime.CancellationPending)
            {
                TimeSpan ts = sw.Elapsed;
                bgWorkerTime.ReportProgress(0, String.Format("{0:00}:{1:00}:{2:00}",
                    ts.Hours, ts.Minutes, ts.Seconds));
                Thread.Sleep(500);
            }
            sw.Stop();
        }

        private void bgWorkerTime_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            lblStatus.Text = e.UserState.ToString();
        }

        private void bgWorkerData_DoWork(object sender, DoWorkEventArgs e)
        {
            string status = "";
                        /*
                        ...Execute SQL Command...
                              Update lblDataStatus.Text to show what's going on
                        */
                if (status != "Success")
                {
                    lblDataStatus.ToolTipText = status;
                    lblDataStatus.Text = "Error occurred";
                    break;
                }
            }
            if (status == "Success")
                lblDataStatus.Text = "Operation completed successfully";
           
        }

        private void frmDemo_FormClosing(object sender, FormClosingEventArgs e)
        {
          //Only attempt to close the form if both bg workers are not working 
            if (bgWorkerTime.IsBusy || bgWorkerData.IsBusy)
                e.Cancel = true;
            if(bgWorkerTime.IsBusy)
                bgWorkerTime.CancelAsync();
            if(bgWorkerData.IsBusy)
                bgWorkerData.CancelAsync();
        }

        private void bgWorkerData_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
                     //When the background worker executing the SQL command is completed,
                     //it will shutdown the timer bg worker, and enable the button
            bgWorkerTime.CancelAsync();
            btnSQLCommand.Enabled = true;

        }
References
1. Mainly this http://stackoverflow.com/questions/2067919/objectdisposedexception-running-stopwatch-in-gui-thread

Thursday, August 4, 2011

Connecting to TFS 2010 with VS 2008

1. install VS 2008 Team Explorer
2. install VS 2008 Service Pack 1
3. install the Visual Studio Team System 2008 Service Pack 1 Forward Compatibility Update for Team Foundation Server 2010 (VS90SP1-KB974558-x86.exe)
4. Edit registry
  1. Start->Run->Regedit
  2. Navigate to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\TeamFoundation\Servers
  3. Right-click and add a string with Name="Whatever the hell you want",                              Value=http://<ip or hostname of tfs server>:<port>/tfs/<collection name>
 5. Restart VS

now when you go to add a project to source control you should see "Whatever the hell you want" in the server list, and the url will be the value of the regkey you put in.

References
1. http://www.jmedved.com/2009/11/visual-studio-2008-and-team-foundation-server-2010/
2. http://stackoverflow.com/questions/1925512/visual-studio-2008-cant-connect-to-known-good-tfs-2010

Wednesday, August 3, 2011

Citrix XenApp installation / config guide reference

This is a really good guide for installing Citrix XenApp 5:
http://carlwebster.com/learning-the-basics-of-xenapp-5-for-windows-server-2008-part-1-of-7/

There's 7 different parts with a step by step processing including screenshots. This is great for a Citrix noob like me!

Friday, July 29, 2011

Optimizing use of page persisted properties by using session variables and local pointers

You have a variable that needs to be persisted between postbacks. How do you do this?
Your first instinct might be to use static variables. This is WRONG!

I am maintaining (and fixing lots of bugs) a website where I discovered that almost every page had a big bug in it. The following is what's wrong:

In Page class
protected static Account acct = new Account();

The problem is when multiple people are currently on this page, when Person1 sets fields in acct, it's going to change Person2's acct field too. This is because it's declared as static, which means it's shared between all instances of the page class!

So how do you handle this? Simple, use the Session variable like this:

//First create a const string that represents the location in Session
private const string SESSION_ACCT = "PAGENAME_ACCT";
//Now create a property that looks in the Session and creates a new object if it's
//not found
protected Account part
{
get
{
Account ad = null;
if (Session[SESSION_ACCT] == null)
{
ad = new Account();
Session[SESSION_ACCT] = ad;
}
else
ad = (Account)Session[SESSION_ACCT];
return ad;
}
set
{
Session[SESSION_ACCT] = value;
}

}

You will most likely want to populate the acct variable during page load. This is assuming you're pulling the account id out of QueryString and that you have a data access layer class called AccountDB with the method Account GetAccount(Guid AcctId).

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
acct = AccountDB.GetAccount(new Guid(Request.QueryString["id"]));
}
}

This is simply going to the acct property's set method. So it's going to do Session[SESSION_ACT] = AccountDB.GetAccount(new Guid(Request.QueryString["id"]));

Here's how you use acct

public void showAccountDetails()
{
Account localAcct = acct;
txtName.Text = localAcct.Name;
txtCreated.Text = localAcct.Created;
}

Why did I use Account localAcct instead of just using acct? This is because using acct means calling the getter everytime. So the above code would make two calls to the getter, meaning it runs through this code twice:
get
{
Account ad = null;
if (Session[SESSION_ACCT] == null)
{
ad = new Account();
Session[SESSION_ACCT] = ad;
}
else
ad = (Account)Session[SESSION_ACCT];
return ad;
}
This is alot more expensive than just creating a local pointer and directly accessing the fields. Every time it calls the getter it's going to be pulling out of Session and converting to Account. Whereas creating Account localAcct means you're storing the result of acct's getter in a local pointer and then directly accessing its fields.

Wednesday, July 27, 2011

Refactoring data access layer

I refactored a highly used data access layer method and achieved 50% reduction in lines of code, 20% reduction in execution time, and increased readability and error checking.

Optimizations:
1. Combined several separate SQL statements into one long statement with multiple joins. This reduces the number of trips to the SQL Server.

2. Former code was using multiple separate try catch blocks to test for null values in the output. I removed all of these and replaced them with ISNULL in the sql statement.

3. Moved SQL statement to a stored proc instead of building a big statement in the code. This reduces the amount of data traveling over the network, because I'm only passing in the stored proc's name, and reduces execution time because stored procs are compiled and reused, as opposed to rebuilding a command text string every execution

4. Instead of doing "if (statement) boolval = true else boolval = false; I did boolval = statement instead. This is a readability issue more than anything.

Thursday, July 21, 2011

String.Format formatting options in C#

Found a good site for this here: http://www.dijksterhuis.org/formatting-strings-stringformat/


Here's a trivial example showing the difference between Java and C#:

Java:
String.Format("Hello %s", "World");

C#:
String.Format("Hello {0:G}", "World");

Wednesday, July 20, 2011

Geolocation with SQL Server 2008 and geocoding an address

Let's say you have a mobile app / website and you want to allow the user to search for whatever within X miles. To find the distance between two points, you first need the coordinates of the two points.

If you're using a device that has GPS, this is easy. It's just a call to the system API or whatever. If you're using a website that asks the user for their address then you need to do something called geocoding. Luckily there are several web services available to do this for you. So on your website, if you were using Google's web service, you would use this javascript:
        function btnGeocode_onclick() {
            var geocoder = new google.maps.Geocoder();
            var address = document.getElementById("txtAddress").value;
            geocoder.geocode({ 'address': address },
            function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {

                    document.getElementById("txtGeolocation").value = results[0].geometry.location;
                }
                else {
                    document.getElementById("lblResults").value = status;
                }
            }

            );
        }

What this does is takes the address in the txtAddress TextBox, and then puts the coordinates of that address in the txtGeolocation TextBox.

So now you have the points, now you need a way to determine the distance between two points. Well, this is really easy with SQL Server 2008, using the new geography data type.

So first, here's how you would insert the coordinates into the database:
latlong is type geography

INSERT INTO [test]
           ([latlong])
     VALUES
(geography::Point(37.7926969,  -122.405512, 4326))


Next, get all whatevers that are within 2 miles of (37.7926969, -122.405512)
For this you use the STDistance function, creating a geography point from a passed in value (37.7926969, -122.405512)

SELECT latlong.STDistance(geography::Point(37.7926969,  -122.405512, 4326))/1609.344 as [miles] FROM test
WHERE latlong.STDistance(geography::Point(37.7926969,  -122.405512, 4326))/1609.344 < 2
ORDER BY lat.STDistance(geography::Point(37.7926969,  -122.405512, 4326))


Saturday, July 16, 2011

File IO and bit counting

I made this problem up to practice doing file IO, bit manipulation, and using data structures.

Problem:
1. Generate a file where each line is a random integer
2. Read the file
3. For each line count the number of set bits (1's) in the integer, and order the output in ascending order of most bits set.

Example:
File=
4
1
6
2
1
5
1
7
0
6


Output should be this:
-------------
Ones=0
0
-------------
-------------
Ones=1
4
1
2
1
1
-------------
-------------
Ones=2
6
5
6
-------------
-------------
Ones=3
7
-------------

Solution


In Main
       int[] arr = getRandomArray(10);
       String fileName = "D:/Test/BitManip.txt";
       FileIO.Write(fileName, arr);
       FileIO.OrderByNum1s(fileName);

In FileIO.java
public class FileIO {

    public static void Write(String fileName, int[] arr)
    {
        try
        {
           BufferedWriter bw = new BufferedWriter(new FileWriter(new File(fileName)));
           for(int i = 0; i < arr.length; i++)
           {
               bw.append(String.valueOf(arr[i]));
               bw.newLine();
           }
           bw.close();
        }
        catch(IOException io)
        {
            System.out.println(io);
        }
       
    }
    public static void OrderByNum1s(String fileName)
    {
        try
        {
            BufferedReader br = new BufferedReader(new FileReader(new File(fileName)));
            Integer i = 0;
            TreeMap<Integer, ArrayList<Integer>> tree = new TreeMap<Integer, ArrayList<Integer>>();
            String input = null;
            while((input = br.readLine()) != null)
            {
                i = Integer.parseInt(input);
                int count = countOnes(i);
                if(!tree.containsKey(count))
                {
                    ArrayList<Integer> numList = new ArrayList<Integer>();
                    numList.add(i);
                    tree.put(count, numList);
                }
                else
                {
                    tree.get(count).add(i);
                }
                   
            }
            br.close();
            ArrayList<Integer> ints = new ArrayList<Integer>();
            for(Map.Entry<Integer, ArrayList<Integer>> entry : tree.entrySet())
            {
                System.out.printf("-------------\nOnes=%d\n", entry.getKey());
                for(Integer k : entry.getValue())
                    System.out.println(k);
                System.out.printf("-------------\n");
            }
           
        }
        catch(IOException io)
        {
            System.out.println(io);
        }
    }
    private static int countOnes(Integer i)
    {
        int count = 0;
        for(int j = 0; j < Integer.SIZE; j++)
        {
            int bitmask = 1<<j;
            if((bitmask & i.intValue()) == bitmask)
                count++;
        }
        return count;
    }
}
 

Friday, July 15, 2011

Sort algorithm implementations and comparison

I implemented several sorting algorithms: bubble, insertion, selection, bucket, quick, and merge. I generated a random int[] and passed it to each sort. The sorts first created a local copy of the array, and then performed sort. I used NetBeans profiler on various input sizes to compare the speeds.


Comparison from NetBeans profiler
1. Elements =  1,000, Variation = 100,000,000

2. Elements = 10,000, Variation = 100,000,000







3. Elements = 100,000 Variation = 100,000,000, I left out Selection() and Bubble() because they were so much worse than the others that they made it hard to see the results





4. Elements = 100,000 Variation = 10,000




Conclusion
Timewise, with large variation in the data Quicksort is the fastest, while with small variation Bucketsort is the fastest. Spacewise, Insertion/Selection/Bubble are all better, whereas Quick/Merge recurse, therefore creating a tree in memory, meanwhile Bucket sort creates an extra array for the buckets, whose size depends on the variation in the data. So when choosing which sort algorithm to use you should compare time and space complexity based on your expected # elements and variation in data values.


Implementation

In Main
       int[] arr = getRandomArray(1000);
       Sorts s = new Sorts(arr);
          s.Merge();
          s.Quick();
          s.Selection();
          s.Insertion();
          s.Bubble();
          s.Bucket();
In Sorts.java
public class Sorts {
    private int[] arr;
    public Sorts(int[] arr)
    {
        this.arr = arr;
    }
  
    public int[] Insertion()
    {
        int[] a = copy();
      
        for(int i = 1; i < a.length; i++)
        {
            int tmp = a[i];
            int j = i - 1;
            while(j >= 0 && a[j] > tmp)
                a[j + 1] = a[j--];
            a[j + 1] = tmp;
        }
        return a;
      
    }
    public int[] Selection()
    {
        int[] a = copy();
        for(int i = 0; i < a.length; i++)
        {
            int minIdx = i;
            for(int j = i + 1; j < a.length; j++)
            {
                if(a[j] < a[minIdx])
                    minIdx = j;
            }
            int tmp = a[i];
            a[i] = a[minIdx];
            a[minIdx] = tmp;
        }
        return a;
    }
    public int[] Bubble()
    {
        int[] a = copy();
        for(int i = 0; i < a.length; i++)
        {
            for(int j = 0; j < a.length - 1; j++)
            {
                if(a[j] > a[j + 1])
                {
                    int tmp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = tmp;
                }
            }
        }
        return a;
    }
    public int[] Bucket()
    {
        /*
         * Create a bucket array with minimized number of
         * buckets, which is Minimum Value to Maximum Value
         * use the minimum value as an offset
         *
         * For example,
         * [8][5][3][4][7][3][6][4][5][6]
         * min = 3, max = 8
         * So at most we need 6 buckets (8 - 3 + 1 = 6)
         * and 3 is the offset, so every value is stored in Value - 3
         *
         */
        int[] a = copy();
      
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int m = 0; m < a.length; m++)
        {
            max = Math.max(max, a[m]);
            min = Math.min(min, a[m]);
        }
        //Create bucket with minimized number of buckets
        int[] buckets = new int[max - min + 1];
      
        //Put integers into buckets
        for(int i = 0; i < a.length; i++)
            buckets[a[i] - min]++;
      
        //output the buckets
        int index = 0;
        for(int b = 0; b < buckets.length; b++)
        {
            for(int k = 0; k < buckets[b]; k++)
            {
                a[index++] = b + min;
            }
        }
        return a;
    }
    public int[] Merge()
    {
        int[] a = copy();
        mergesort(a, new int[a.length], 0, a.length - 1);
        return a;
    }
    private void mergesort(int[] a, int[] helper, int left, int right)
    {
        if(left >= right)
            return;
        int mid = (left + right)/2;
        mergesort(a, helper, left, mid);
        mergesort(a, helper, mid + 1, right);
      
        //merge results
        int leftPos = left,
                leftEnd = mid,
                rightPos = leftEnd + 1,
                rightEnd = right,
                tmpPos = left;
        while(leftPos <= leftEnd || rightPos <= rightEnd)
        {
            if(leftPos <= leftEnd && rightPos <= rightEnd)
            {
                if(a[leftPos] < a[rightPos])
                    helper[tmpPos++] = a[leftPos++];
                else
                    helper[tmpPos++] = a[rightPos++];
            }
            else if (leftPos <= leftEnd)
                helper[tmpPos++] = a[leftPos++];
            else
                helper[tmpPos++] = a[rightPos++];
        }
        //copy back into a
        for(int i = left; i <= right; i++)
            a[i] = helper[i];
      
    }
    public int[] Quick()
    {
        int[] a = copy();
        quick(a, 0, a.length - 1);
        return a;
    }
    private void quick(int[] a, int left, int right)
    {
        int pivot = (left + right)/2;
        int pivotVal = a[pivot];
        int i = left;
        int j = right;
        while(i <= j)
        {
            while(a[i] < pivotVal)
                i++;
            while(a[j] > pivotVal)
                j--;
            if(i > j)
                break;
            int tmp = a[j];
            a[j] = a[i];
            a[i] = tmp;
            i++;
            j--;
          
        }
        if(left < i - 1)
            quick(a, left, i - 1);
        if(right > i)
            quick(a, i, right);
      
    }
    private int[] copy()
    {
        int[] copyarr = new int[arr.length];
        System.arraycopy(arr, 0, copyarr , 0, arr.length);
        return copyarr;
    }
    public boolean same(int[] a, int[] b)
    {
        if(a.length != b.length)
            return false;
        for(int i = 0; i < a.length; i++)
        {
            if(a[i] != b[i])
                return false;
        }
        return true;
    }
}

Learning Integration Services

Follow this tutorial:
http://msdn.microsoft.com/en-us/library/ms169917.aspx

Gotchas
1. If your server instance isn't the default then you'll need to update the ODBC connection in every lesson. It's set to by default, which points to the default (unnamed) instance of SQL
2. In lesson 3 where you create a package configuration, make sure to keep two variables, one for folderName and one for fileName. FolderName is pulled out of the XML config file, while the filename is gotten by traversing the folderName.

Wednesday, July 13, 2011

Graph, Path, Node, and Edge classes in Java, along with algorithms

I created Graph, Path, Node, and Edge classes for playing around with graph algorithms. I didn't use best practices when designing the access etc... example: Node's members are all public. This is strictly for learning purposes!

Note: I forgot to escape the generic left/right brackets in LinkedList, so it's not showing up here. Add them if you're gonna use them

In Graph.java
public class Graph {
    private class Path implements Cloneable
    {
        GNode start = null;
        LinkedList edges = new LinkedList();
        private int weight = 0;
        public Path(GNode start)
        {
            this.start = start;
        }
        public void AddEdge(GEdge e)
        {
            weight += e.weight;
            edges.add(e);
        }
        @Override public String toString()
        {
            StringBuilder sb = new StringBuilder(1 + edges.size() * 2);
            sb.append("(" + start.data + ")");
            
            for(GEdge e : edges)
                sb.append(String.format("-%d->(%s)", e.weight, e.n.data));
            sb.append(" total weight=" + weight);
            return sb.toString();
        }
        @Override public Object clone() throws CloneNotSupportedException
        {
            Path p = new Path((GNode)start.clone());
            p.edges = (LinkedList)edges.clone();
            p.weight = this.weight;
            return p;
        }
    }


    
    public LinkedList nodes = new LinkedList();
    private Path searchPath = null;
    public void DFS(int value)
    {
        
        if(nodes.isEmpty()){
            System.out.println(
        "No nodes exist");
            return;
        }
        searchPath = null;
        DFS(value, nodes.getFirst(), new Path(nodes.getFirst()));
        System.out.println(searchPath.toString());
    }
    private void DFS(int value, GNode cur, Path curPath)
    {
        if(searchPath != null)
            return;
        if(value == cur.data)
        {
            searchPath = curPath;
            return;
        }
        else
        {
            for(GEdge e : cur.adjacent)
            {
                try{
                Path newPath = (Path)curPath.clone();
                newPath.AddEdge(e);
                DFS(value, e.n, newPath);
                }
                catch(CloneNotSupportedException c)
                {
                    System.out.println(c);
                    return;
                }
            }
        }
    }
    public void BFS(int value)
    {
    }
    public void Dijkstra(int fromVal, int toVal)
    {
    }
    
}

In GNode.java
public class GNode implements Cloneable
{
    public int data = 0;
    public boolean visited = false;
    public LinkedList adjacent = new LinkedList();
    public GNode(int data)
    {
        this.data = data;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException
    {
        GNode gnode = new GNode(this.data);
        gnode.adjacent = (LinkedList)this.adjacent.clone();
        gnode.visited = this.visited;
        return gnode;
    }
    
}
In GEdge.java
public class GEdge implements Cloneable
{
    public int weight = Integer.MIN_VALUE;
    public GNode n = null;
    public GEdge(int weight, GNode N)
    {
        this.weight = weight;
        this.n = N;
    }
    @Override public Object clone() throws CloneNotSupportedException
    {
        GEdge gedge = new GEdge(this.weight, (GNode)this.n.clone());
        return gedge;
        
    }
}
 
Example of building a graph and running depth-first search for an element
public static void main(String[] args) {
        Graph g = new Graph();
        GNode node1 = new GNode(1);
        GNode node2 = new GNode(2);
        GNode node3 = new GNode(3);
        GNode node4 = new GNode(4);
        node1.adjacent.add(new GEdge(2, node3));
        node1.adjacent.add(new GEdge(1, node2));
        node2.adjacent.add(new GEdge(2, node3));
        node3.adjacent.add(new GEdge(3, node4));
        node4.adjacent.add(new GEdge(1, node1));
        g.nodes.add(node1);
        g.nodes.add(node2);
        g.nodes.add(node3);
        g.nodes.add(node4);
        g.DFS(3);
        
    }
This will print out: (1)-2->(3) total weight=2

Tuesday, July 12, 2011

Mergesort in Java

private static void mergesort2(int[] arr, int[] helper, 
int left, int right)
    {
        if(left < right)
        {
            int center = (left + right)/2;
            mergesort2(arr, helper, left, center);
            mergesort2(arr, helper, center + 1, right);
            int rightPos = center + 1;
            int tmpPos = left;
            int i = left;
            while(left <= center || rightPos <= right)
            {
                if(left <= center && rightPos <= right)
                {
                    if(arr[left] < arr[rightPos])
                        helper[tmpPos] = arr[left++];
                    else
                        helper[tmpPos] = arr[rightPos++];
                }
                else if (left <= center)
                    helper[tmpPos] = arr[left++];
                else
                    helper[tmpPos] = arr[rightPos++];
                tmpPos++;
            }
            for(; i <= right; i++)
                arr[i] = helper[i];
            
        }
    }

Friday, July 1, 2011

Generate scripts for multiple databases for the same table

Problem:
How do you delete the same table and stored procs from a bunch of different databases all in one instance? For example, we have 100 companies in an organization, and we install our product on a per company basis. If we have 20 tables for our product and it's installed on every database, we have 2000 tables to delete. There's no way I'm doing this by hand! *Note: We can't just delete the database, because our product is only a module within a larger system containing multiple products.I did this with some vicious looking SQL. For each company database it executes dynamic SQL creating a cursor on dynamic SQL statements for dropping tables. The reason i'm dynamically creating cursors is because they have to be in the context of the company database. This has to be dynamic SQL otherwise i'd have to know the name of the database beforehand, and remember how I have 100 companies? Yeah, definitely not going to do 100 different use statements by hand.

Solution:


USE <SharedSystemDatabase>
DECLARE @dbName varchar(500), @sql varchar(500), @dropTbl varchar(500)
--Get all company databases + system database
DECLARE DBs CURSOR FOR
SELECT INTERID FROM SY01500 UNION SELECT '<SharedSystemDatabase>'
OPEN DBs

WHILE 1=1
BEGIN
FETCH NEXT FROM DBs INTO @dbName
IF @@FETCH_STATUS != 0
BREAK
--Generate drop statements for all this DB's specified tables
SET @sql =
'USE ' + @dbName +
' DECLARE tbls CURSOR FOR SELECT ''USE ' + @dbName + ' DROP TABLE ['' + TABLE_NAME + '']'' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE ''<Our Product Tables System-unique Prefix>%'''
EXEC(@sql)
OPEN tbls

WHILE 1=1
BEGIN
FETCH NEXT FROM tbls INTO @dropTbl
IF @@FETCH_STATUS != 0
BREAK
print(@dropTbl) -- Change this exec(@dropTbl)
END
CLOSE tbls
DEALLOCATE tbls


--Notice, the loop is unrolled. This is because it would've been a pain to try to concat @sql even --more than it already is
SET @sql =
'USE ' + @dbName +
' DECLARE tbls CURSOR FOR SELECT ''USE ' + @dbName + ' DROP PROCEDURE ['' + SPECIFIC_NAME + '']'' FROM INFORMATION_SCHEMA.ROUTINES WHERE SPECIFIC_NAME LIKE ''zDP_
Our Product Tables System-unique Prefix%'''
EXEC(@sql)
OPEN tbls

WHILE 1=1
BEGIN
FETCH NEXT FROM tbls INTO @dropTbl
IF @@FETCH_STATUS != 0
BREAK
print(@dropTbl) -- Change this exec(@dropTbl)
END
CLOSE tbls
DEALLOCATE tbls

END
CLOSE DBs
DEALLOCATE DBs

Thursday, June 30, 2011

TopCoder SRM 165 Div 2 500-pt

http://www.topcoder.com/tc?module=Static&d1=match_editorials&d2=srm165

We are trying to see which number of processors requires the least amount of time to process K tasks. We are told it takes 1 ms for 1 processor to process 1 task. So it takes N processors K / N ms to process K tasks. But parallelization requires time to sync the processors. We are told it takes OVERHEAD ms per pair of processors to sync up initially. How many pairs are there? There are n choose 2 pairs, which is n!/(2!(n-2)!). So we can calculate the total time for N processors as (n choose 2)*overhead + K / N. Ok, so this is easy, we just loop through and plug in a different N every iteration, and then return the best one. But don't forget, n! can become a very big number, so you have to protect against overflow. There's two ways: 1) use a bigger type, like long or BigInteger 2) Notice that with n!/2!(n-2)! you can cancel out alot of the top numbers because they appear on the bottom. I did 1. Another thing to worry about is the fact that computing n! is a recursion that computes the value of n*(n-1)... The thing to notice about this is that n! is actually n * (n - 1)!. Well since your main loop is going from 2 to n, you've already computed the value of (n - 1)! in the last loop. All you need to do is store the result in a hash table and look it up instead of recomputing everytime. Instead of doing N deep recursion through every loop, it's reduced to looking up the previous value in a hash table, or O(1). Another optimization is the fact that the function has a minimum point (the shortest time). So once you find that you can return. In fact, adding that last optimization my execution time from ~50 ms to ~5 ms.


import java.util.HashMap;
import java.math.BigInteger;
public class ParallelSpeedup
{
    HashMap<Integer, BigInteger> facts = new HashMap<Integer, BigInteger>();
    public int numProcessors(int k, int overhead)
    {
   
        //(n!/(2!(n-2)! x overhead + k/n is the function
       
        BigInteger bestTime = BigInteger.valueOf(k);
        BigInteger prevTime = BigInteger.valueOf(k);
        int bestN = 1;
        int diff = 0;
        for(int n = 2; n < 1000; n++)
        {
            BigInteger newTime = getTime(n, k, overhead);
            //check if we passed the minimum
            if(newTime.compareTo(prevTime) > 0)
                return bestN;
            diff = newTime.compareTo(bestTime);
            if(diff < 0){
                bestTime = newTime;
                bestN = n;
                }
            prevTime = newTime;
        }
        return bestN;
    }
    private BigInteger getTime(int n, int k, int overhead)
    {
        BigInteger nchoose2 = fact(n).divide(fact(2).multiply(fact(n-2)));
        BigInteger perPro = BigInteger.valueOf((int)Math.ceil((double)k / (double)n));
        return nchoose2.multiply(BigInteger.valueOf(overhead)).add(perPro);
    }
    private BigInteger fact(int n)
    {
        if(n <=1)
            return BigInteger.valueOf(1);
        else if (facts.containsKey(n))
        {
            return facts.get(n);
        }
        else
        {
            BigInteger n1 = BigInteger.valueOf(n).multiply(fact(n-1));
            facts.put(n, n1);
            return n1;
        }
    }
}

Sunday, June 26, 2011

Multi-threaded Quicksort using Java




NOTE: There was a bug in the initial code. The insertion sort portion had for(int i = left; i < right; i++), but right is already an index, not a size, so we need to change < to <=.

 I'm in the process of learning parallel programming. The first thing I wanted to do to learn it is to actually use threading in Java. So I created a multi-threaded version of quicksort. I compared it to single-threaded quicksort. Running it with 10 million elements i got 1300 ms for multi-threaded, and 1991 ms for single-threaded running on a quad-core processor.

Notice that insertion sort is done if the size of the array is less than 20. Two reasons:
1. Insertion sort is better on small amounts of data compared to quick sort
2. This reduces the number of threads spawned.

Here's the code...


//Use it by creating the QuickSorter object and calling start().
    public static void main(String[] args) {
        ArrayList<Integer> arr = new ArrayList<Integer>();
        for(int i = 10000000; i > 0; i--)
            arr.add(i);
        ThreadGroup group = new ThreadGroup("QuickSorter");
        Thread t = new QuickSorter(arr, 0, arr.size() - 1, group);
        t.start();
        while(t.isAlive())
        {
        }
 }

public class QuickSorter extends Thread{
    private ArrayList<Integer> arr;
    int left;
    int right;
    public QuickSorter(ArrayList<Integer> arr, int left, int right, ThreadGroup g)
    {
        super(g, "QuickSorter");
        this.arr = arr;
        this.left = left;
        this.right = right;
       
    }
    public void run()
    {
        if(left >= right || left < 0 || right >= arr.size())
        {
            return;
        }
        if(right - left < 20)
        {
            for(int i = left; i <= right; i++)
            {
                int tmp = arr.get(i);
                int j = i;
                for(; j > 0 && tmp < arr.get(j - 1); j--)
                    arr.set(j, arr.get(j - 1));

                arr.set(j, tmp);//[j] = tmp;
            }
            return;
        }
        int pivotIdx = (right + left) / 2;
        int pivot = arr.get(pivotIdx);
        int i = left;
        int j = right;
       
        while(i < j)
        {
           while(arr.get(i) < pivot)
               i++;
          
           while(arr.get(j) > pivot)
               j--;
           if(i >= j)
               break;
           int tmp = arr.get(i);
           arr.set(i, arr.get(j));
           arr.set(j, tmp);
        }
        QuickSorter leftQS = new QuickSorter(arr, left, i - 1, this.getThreadGroup());
        leftQS.start();
        QuickSorter rightQS = new QuickSorter(arr, i + 1, right, this.getThreadGroup());
        rightQS.start();
       
    }

Tuesday, June 21, 2011

How to strip out the time of a DateTime and set it to what you want in SQL Server

Let's say I have two parameters @StartDate and @EndDate. I want to get all records with modifications between these DateTimes, but only the date part matters. If I don't know for sure what the Time part of the parameters are then i'm going to get bad results. So the best solution is to strip out the current time and add the time i want. In this case i want @StartDate's time to be 00:00:00 so it includes all records in that day, and @EndDate's time to be 23:59:59 so it includes all possible values in that day.

So here's how do that
SET @StartDate = DATEADD(dd, DATEDIFF(dd, 0, @StartDate),0)
SET @EndDate = DATEADD(dd, DATEDIFF(dd, 0, @EndDate),0) + '23:59:59'


The alternatives to this are not ideal. For example, you could use DATEPART and compare the year, month, and day of the record to the parameter. This means for every record you're executing DATEPART 3 times (i think it would cache the dateparting of the parameter, since it's on the right side, but I'm not entirely sure). That's going to be really slow compared to the solution above.

how it works
Start from the inside out. DATEDIFF(dd, 0, @StartDate) returns the total number of days since the minimum date ("0") in the system. So let's call this DAYS. The next part is DATEADD(dd, DAYS, 0). This is adding the number of days to the minimum date, thus stripping out the time.

Tuesday, May 24, 2011

System.MissingMethodException was caught Message=Method not found

Problem
System.MissingMethodException was caught
  Message=Method not found: 'Void <method name>'

Solution
This problem was caused by the application loading the WRONG version of the DLL from an unexpected location. I used <object from missing method's dll>.GetType().Assembly.Location to discover where it was loading the DLL from.  So use that, then put the correct version of the DLL you're using in that location.

Monday, May 9, 2011

How to add wordperfect full-text search on SharePoint 2010

1. Run this iFilter installer on all your SharePoint servers: http://www.corel.com/servlet/Satellite/us/en/Content/1157481830100?pid=1216666054364

2. In RegEdit navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\ContentIndexCommon\Filters\Extension\

3. Add key .wpd, then modify Default and add {25BDCAE0-8028-11d1-8ACC-0060670C457D}

3. In RegEdit navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\

4. Add key .wpd, then add string Extension=wpd, DWORD FileTypeBucket=1, string MimeTypes=application/wordperfect

5.Open SharePoint Central Admin ->Manage Service Applications->Search Service Application

6. On the left side under Crawling, click File Types, and add wpd

7. Start->Run, type IISRESET /restart

8. Open Services, restart SharePoint Server Search 14, SharePoint Foundation Search V4

Now WordPerfect docs will be indexed by crawling. If you want to test it out then initialize a full crawl or wait for the next scheduled crawl.

Note: This is the same process for adding search support for PDFs and any other file type that isn't supported by default, just need to add different GUIDs and install different iFilters.

References.
1. This site shows you how to do it but isn't complete for SharePoint 2010, https://msmvps.com/blogs/shane/archive/2005/11/29/77181.aspx

2. This site shows you how to do it for PDFs, http://www.sharepointgeoff.com/scblogspace/Lists/Posts/Post.aspx?ID=101

Friday, May 6, 2011

0 search results in SharePoint 2010

If you have configured Search Service and have successfully ran the crawler and are still getting 0 results returned in search, then I highly recommend following this step by step guide(like me):To be sure, follow this excellent step by step guide: http://sharepointgeorge.com/2010/configuring-enterprise-search-sharepoint-2010/


Friday, April 29, 2011

3 steps to enable automatic sorting of business object using BindingList

1. Create these 2 classes, just COPY AND PASTE!
You need to have "using System.ComponentModel" wherever you put these


    internal class SortComparer<T> : IComparer<T>
    {
        private PropertyDescriptor m_PropDesc = null;
        private ListSortDirection m_Direction = ListSortDirection.Ascending;

        public SortComparer(PropertyDescriptor propDesc, ListSortDirection direction)
        {
            m_PropDesc = propDesc;
            m_Direction = direction;
        }

        int IComparer<T>.Compare(T x, T y)
        {
            object xValue = m_PropDesc.GetValue(x);
            object yValue = m_PropDesc.GetValue(y);
            return CompareValues(xValue, yValue, m_Direction);
        }

        private int CompareValues(object xValue, object yValue, ListSortDirection direction)
        {
            int retValue = 0;
            if (xValue is IComparable) //can ask the x value 
            {
                retValue = ((IComparable)xValue).CompareTo(yValue);
            }
            else if (yValue is IComparable) //can ask the y value 
            {
                retValue = ((IComparable)yValue).CompareTo(xValue);
            }
            //not comparable, compare string representations 
            else if (!xValue.Equals(yValue))
            {
                retValue = xValue.ToString().CompareTo(yValue.ToString());
            }
            if (direction == ListSortDirection.Ascending)
                return retValue;
            else
                return retValue * -1;
        }
    }
    public class SortableBindingList<t> : BindingList<t>
    {
        private bool m_Sorted = false;
        private ListSortDirection m_SortDirection = ListSortDirection.Ascending;
        private PropertyDescriptor m_SortProperty = null;

        protected override bool SupportsSortingCore
        {
            get
            {
                return true;
            }
        }

        protected override bool IsSortedCore
        {
            get
            {
                return m_Sorted;
            }
        }

        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return m_SortDirection;
            }
        }

        protected override PropertyDescriptor SortPropertyCore
        {
            get
            {
                return m_SortProperty;
            }
        }

        protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
        {
            m_SortDirection = direction;
            m_SortProperty = prop;
            m_Sorted = true;
            var listRef = this.Items as List<t>;
            if (listRef == null)
                return;
            var comparer = new SortComparer<t>(prop, direction);

            listRef.Sort(comparer);

            OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }
    } 


2. In your business object that was formerly inheriting BindingList, it now needs to inherit SortableBindingList, like so:
public class BusinessObjList : SortableBindingList<BusinessObj>

3. In your DataGridView's Column Collection, set all the columns you want to be sortable to SortMode=Automatic


Reference
1. http://xiaonanstechblog.blogspot.com/2009/03/how-to-enable-column-sorting-on.html

Friday, April 22, 2011

FileSystemWatcher OnChange event fires twice

THIS IS A KNOWN BUG.

So here's what I did to deal with this:


I am only monitoring 1 file (a config file for a service, so it can update without having be restarted). The way I solved the 2 onchanged event firing problem is like this:

internal class ConfigFileWatcher
{
    private FileSystemWatcher fileSysWatcher;
    private bool eventFired;
    internal ConfigFileWatcher()
   {
      eventFired = false;
     //initialize fileSysWatcher with path and filter, and add OnChange event handler
   }
        private void fileSysWatcher_Changed(object sender, System.IO.FileSystemEventArgs e)
        {
            if (eventFired)
            {
                eventFired = false;
                return;
            }
            else
                eventFired = true;
           
            //do stuff with the file
}
}

Since we know for sure that the OnChange event is going to fire twice, it makes sense to use a bool like this.

I know this isn't what your problem is exactly, but maybe you could experiment by using a Dictionary with FullPath = key, EventFired Bool = value

So for example, Dictionary<string, bool> eventFireDict

In the OnChanged event check for that full path

//pseudo-code
if(Dictionary Contains Full Path)
{
  if (Key's Value = True)
   {
    set key's value to False
    return
   }
   else
  {
     set key's value to True
   }
}
else
Insert <Full Path, True> into Dictionary
}

Notice, you don't even need a Dictioanry<string, bool> if you're only looking for a change in that file once. If you're just looking for a change once, I'm pretty sure you could just use a List<string> like this

//pseudo-code

if(List<string> contains Full Path)
{
//event already fired for this full path, so remove the full path and return so it doesn't process that file //twice
List.remove(Full Path);
return;
}
else
{
//event hasn't fired yet for this Full Path, so put it in the List and then process the Full Path
List.add(Full Path);
process(Full Path);
}


References
http://weblogs.asp.net/ashben/archive/2003/10/14/31773.aspx

Tuesday, April 12, 2011

How to retrieve data from modal view

I have CardFormViewController and PickerViewController. CardFormViewController needs to ask the user for credit card type, such as "Visa" and "MasterCard". In order to ask the user I want to use a UIPickerView. However, the UIPickerView is TOO big to stick on a form with other elements.

The solution I use is to stick the UIPickerView onto it's own View (hence PickerViewController) and open it up modally via
    pickerView = [[PickerViewController alloc] autorelease];
    pickerView.mode = CardType;
    pickerView.view.backgroundColor = [UIColor clearColor];
    pickerView.modalTransitionStyle = UIModalTransitionStylePartialCurl;
    [self presentModalViewController:pickerView animated:YES];
I'm sure you have already done this considering you googled how to retrieve the data from it. So here's how to retrieve the data:

1. In CardFormViewController create a property, such as a UILabel. (don't forget to synthesize, release, link in IB :))

2. Make sure you have PickerViewController set as a UIPickerViewDelegate like @interface PickerViewController : UIViewController <UIPickerViewDelegate>. Also make sure you have implemented the required protocol (see UIPickerView.h or documentation on Apple's site for that if you need help)

3. Implement the UIPickerViewDelegate method - (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component





{
//IF YOU ARENT using NavigationController as your Root Controller, uncomment this code and comment out the other code
/*
    CardFormViewController *vc = (CardFormViewController*)self.parentViewController;
    vc.lblTest.text = [cardTypeArray objectAtIndex:row];



*/
//IF YOU ARE using NavigationController as your Root Controller, use code below
    UINavigationController *nc = (UINavigationController*)self.parentViewController;
   
   CardFormViewController *vc = (CardFormViewController*)[nc.viewControllers objectAtIndex:(nc.viewControllers.count - 1)];
    vc.lblTest.text = [cardTypeArray objectAtIndex:row];

}

Wednesday, February 23, 2011

Client-side timezone detection and using it server-side in ASP.NET

First of all, this is pretty complicated and took me alot of time to figure out, even after reading alot of stuff on it. So here's the steps to get this to work

1. JavaScript for getting the timezone info
I recommend sticking these javascript functions in a .js file, i put them in ../js/TimeZone.js
function TimezoneDetect() {//see references for credits for this function
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
    var intMonth;
    var intHoursUtc;
    var intHours;
    var intDaysMultiplyBy;

    //go through each month to find the lowest offset to account for DST
    for (intMonth = 0; intMonth < 12; intMonth++) {
        //go to the next month
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);

        //To ignore daylight saving time look for the lowest offset.
        //Since, during DST, the clock moves forward, it'll be a bigger number.
        if (intOffset > (dtDate.getTimezoneOffset() * (-1))) {
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }

    return parseFloat(intOffset / 60)
    ;
}
function setHiddenVal(hiddenId) {
    var hiddenObj = document.getElementById(hiddenId);
    hiddenObj.value = TimezoneDetect().toString();
  
}
 2. Call JavaScript from ASP.NET page
I figured the best way to do this is to stick the javascript call on my login page. So on the login page you need to add a HiddenField, Button, and a script tag.

Hidden Field:   <input runat='server' id="hiddenField" type="hidden" />

Button:   <asp:Button ID="btnLogin" runat="server"
        Text="Login" CssClass="button" OnClientClick="setHiddenVal('[hiddenField's ID]')" onclick="btnLogin_Click" />

Notice, the button has a server-side click event called btnLogin_Click, and a client-side on click event. In the on click event, you call setHiddenVal with the HiddenField's id as the parameter. You will need to find the assigned ID by loading the page and looking at the page source. If you are using master pages w/ content place holder's it will not be what you expect.

Script tag:  <script type="text/javascript" src="../js/TimeZone.js"></script>
As mentioned before ../js/TimeZone.js is where I put the javascript functions

3. Store the HiddenField value in the Session["UtcOffset"]
In the login button's server-side onclick event, btnLogin_Click, you can retrieve the HiddenField's value, and store it in the Session variable like this:
protected void btnLogin_Click(object sender, EventArgs e)
    {
//auth code...

            Session["UtcOffset"] = hiddenField.Value;
//redirect to user's profile...
        }
    }
 4. Use Session["UtcOffset"] to calculate future UTC times and convert back to the user's timezone

First, how to convert a UTC DateTime to a DateTime in the user's timezone. Let's assume we have a function called getStartTimeUtcFromDatabase() which returns a UTC DateTime from the database. *Note: There's no error handling for clarity purposes

 //pull the UtcOffset which we saved in the Session in section 3 above
double utcOffset =  Convert.ToDouble(Session["UtcOffset"]); 

DateTime StartTime = getStartTimeUtcFromDatabase();
StartTime = StartTime.AddHours(utcOffset);

//For example, StartTime = 2/24/11 12:30 AM, and UtcOffset= -8 (PST)
//The end result would give us StartTime = 2/23/11 4:30 PM



Second, how to convert user input datetime to the equivalent UTC time. Let's assume we have already collected the date and time and concated them together into a DateTime object called userStartTime.
double utcOffset  = Convert.ToDouble(Session["UtcOffset"]) * -1;
userStartTime = userStartTime.AddHours(utcOffset);

//For example, user start time = 2/23/11 4:30 PM, and UtcOffset= -8 (PST)
//So because we are multiplying by -1, we are actually adding 8 to the datetime,
//this results in userStartTime = 2/24/11 12:30 AM



I hope this helps anyone who is trying to figure this out. It took me quite a bit of time to pull this all together.... . Here's the sources:
  1.  http://www.michaelapproved.com/articles/timezone-detect-and-ignore-daylight-saving-time-dst
  2. http://www.velocityreviews.com/forums/t70738-calling-client-side-javascript-from-a-server-side-button.html
There was an error in this gadget