About Me

My photo
Northglenn, Colorado, United States
I'm primarily a BI Developer on the Microsoft stack. I do sometimes touch upon other Microsoft stacks ( web development, application development, and sql server development).

Friday, March 29, 2013

Exporting to Excel in SSIS

How to export data to excel. I did follow other blogs, but they leave out vital information to get it working, so here is my attempt.

Preview of what's to come from Control Flow view:
 




















You're going to need to first create a Execute SQL Task, because this is going to be used to create your sheet in excel. The syntax is similar to SQL Server's Create Table, except that it uses the accent quote `  instead of squaring the names in brackets i.e.: [name]. It also seems to have a problem with numeric and character cell size limits.





In this case, I'm creating an excel sheet called Process:



CREATE TABLE `Process`(
 `SuperClientVendorID` INT,
 `LoanNumber` varchar(25),
 `OpenIndicator` char(3),
 `CloseIndicator` char(3),
 `UpdateIndicator` char(3),
 `ParentRefID` INT,
 `Open_RailDescription` varchar(200),
 `AssignedVendorID` INT ,
 `CloseReason` varchar(200) ,
 `RefID` numeric(18, 0),
 `CloseDate` date ,
 `InheritedAttribute` varchar(3) ,
 `ProcessorCd` varchar(50) ,
 `ProcessStartDate` date ,
 `ReOpenIndicator` varchar(3) ,
 `NoteType` varchar(255) ,
 `Note` text
)

Now, lets create a Excel Connection Manager to dynamically create our file. You're going to need a dummy file to initially create an connection instance. In this dummy file, I had my first rows of names, but I'm not sure if this is really needed.

 You're going to point the connection to the excel file for now. Right click on the newly created connection and select properties. In this window, under expressions you're going to create a ExcelFilePath expression:













My text, I use a variable called Processed to represent the file path and folder. I then add a datetime string to the end of the file.

@[User::Processed] + "\\FileName " + RIGHT("0" + (DT_STR,2,1252)DATEPART("MM" ,GETDATE()), 2) +
 RIGHT("0" + (DT_STR,2,1252)DATEPART("DD" ,GETDATE()), 2) + (DT_STR,4,1252)DATEPART("YYYY" ,GETDATE())  + "_"  + Right("0" + (DT_STR,4,1252) DatePart("hh",getdate()),2) + "" + Right("0" +  (DT_STR,4,1252) DatePart("n",getdate()),2)  +""+ ".xls"


I had a problem with the connection at this point, I took the ExcelFilePath name from properties and moved my dummy excel there and renamed it. This won't be a problem when it runs, since the name will change given the time. If you need to edit the file, you will need to recreate/rename your dummy file.

Now create a Data Flow Task and inside that task, create your source file, where you will be pulling the data from. Setup your query to pull the data, etc.... And create your destination excel file.




















Point it to your dummy excel file and dummy sheet name.


Run the program, and hope for no errors.



Helpful resources on the same thing:
http://geekepisodes.com/sqlbi/2011/creating-excel-files-xls-dynamically-from-ssis/
http://jandho.blogspot.com/2012/03/ssis-package-to-export-to-new-excel.html

Excel Error in SSIS - 64bit runtime error

Running a very simple SSIS 2012; which pulls data from an excel file. I've done this a million times, but all of a sudden I ran into this tidbit when running on a new machine:

Errors:



  • [Excel Source [39]] Error: SSIS Error Code DTS_E_CANNOTACQUIRECONNECTIONFROMCONNECTIONMANAGER.  The AcquireConnection method call to the connection manager "Excel Connection Manager" failed with error code 0xC0209303.  There may be error messages posted before this with more information on why the AcquireConnection method call failed.
  • [SSIS.Pipeline] Error: Excel Source failed validation and returned error code 0xC020801C.
  • [SSIS.Pipeline] Error: One or more component failed validation.
  • Error: There were errors during task validation.
  • [Connection manager "Excel Connection Manager"] Error: The requested OLE DB provider Microsoft.Jet.OLEDB.4.0 is not registered. If the 64-bit driver is not installed, run the package in 32-bit mode. Error code: 0x00000000.
    An OLE DB record is available.  Source: "Microsoft OLE DB Service Components"  Hresult: 0x80040154  Description: "Class not registered".


On the blogs, people say to download the 64-bit version of the drivers at: http://www.microsoft.com/en-us/download/details.aspx?id=13255
I still had trouble getting it to work, so I changed it to run "not" in 64-bit. Just go to Project/[Name of Project] Properties/Configuration Properties/Debugging under Debug Options and change "Run64BitRuntime" from default value of true to false.




This also means, if you are going to run it in 32-bit, you also have to tell the SQL Agent to run in 32-bit as well. Edit your job and then edit the right job step. Go to the Execution Options pane and check "Use 32 bit runtime". This property will only effect the package (+child packages) called in this job step.

Friday, March 22, 2013

Quick Reminder: Add 3rd PartyJavascript API Intellisense to Visual Studio

For third party JavaScript api, it helps to have intellisense. In this case I was using Tableau Software's JavaScript API.

1) Download the JavaScript files and place them locally.
2) Add reference at top of your JavaScript file
/// <reference path="tableau_v8.debug.js" />
Before:
















After:



















More info on creating intellisense can be found here: http://msdn.microsoft.com/en-US/library/vstudio/hh874692.aspx

Friday, March 15, 2013

Just for kicks: Project Euler Problem #1

Just wanted to try a variety of methods to a solution. I wanted to do a variety of parallel, plinq, and straight forward logic test. I also wanted to implement a extension method and use func<> for better refactoring. As a test, I considered doing Euler's #1:
http://projecteuler.net/problem=1


Here are the several methods I created:
Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Threading;
  7.  
  8. namespace ProjectEuler
  9. {
  10.     /*
  11.      *   Q: If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
  12.      *      Find the sum of all the multiples of 3 or 5 below 1000.
  13.      *
  14.      *   A: 233168
  15.      *   
  16.      *   Results:
  17.                     Method 1 Avg Time:  0.000007768
  18.                     Method 2a Avg Time: 0.000040169
  19.                     Method 2b Avg Time: 0.000029314
  20.                     Method 2c Avg Time: 0.000347431
  21.                     Method 2d Avg Time: 0.000175544
  22.                     Method 3a Avg Time: 0.00017445
  23.                     Method 3b Avg Time: 0.000144669
  24.                     Method 3c Avg Time: 0.002392947
  25.                     Method 3d Avg Time: 0.001309331
  26.      *   
  27.      */
  28.     class Problem1
  29.     {
  30.         int[] items = Enumerable.Range(1, 999).ToArray();
  31.         ReaderWriterLockSlim rw = new ReaderWriterLockSlim();
  32.         int sum = 0;
  33.  
  34.         //KISS Logic
  35.         public int RunMethod1()
  36.         {
  37.             sum = 0;
  38.  
  39.             foreach(int s in items)
  40.             {
  41.                 if (s % 3 == 0 || s % 5 == 0)
  42.                 {
  43.                     sum += s;
  44.                 }
  45.             };
  46.  
  47.             return sum;
  48.         }
  49.  
  50.         //Lazy Method
  51.         public int RunMethod2a()
  52.         {
  53.             return items.Where(n => n % 3 == 0 || n % 5 == 0).Sum();
  54.         }
  55.  
  56.         //Lazy Method on the fly
  57.         public int RunMethod2b()
  58.         {
  59.             return Enumerable.Range(1, 999).Where(n => n % 3 == 0 || n % 5 == 0).Sum();
  60.         }
  61.  
  62.         //Parallel Lazy Method
  63.         public int RunMethod2c()
  64.         {
  65.             return items.AsParallel().Where(n => n % 3 == 0 || n % 5 == 0).Sum();
  66.         }
  67.  
  68.         //Parallel Lazy Method on the fly
  69.         public int RunMethod2d()
  70.         {
  71.             return Enumerable.Range(1, 999).AsParallel().Where(n => n % 3 == 0 || n % 5 == 0).Sum();
  72.         }
  73.  
  74.         //Basic Parallel Method
  75.         public int RunMethod3a()
  76.         {
  77.             List<int> multOf3Or5 = new List<int>();
  78.  
  79.             Parallel.ForEach(items, s =>
  80.                 {
  81.                     if (s % 3 == 0 || s % 5 == 0)
  82.                     {
  83.                         lock (multOf3Or5)
  84.                         {
  85.                             multOf3Or5.Add(s);
  86.                         }
  87.                     }
  88.                 }
  89.             );
  90.  
  91.             return multOf3Or5.Sum();
  92.         }
  93.  
  94.         //Parallel it, but slice the work up
  95.         public int RunMethod3b()
  96.         {
  97.             List<int> multOf3Or5 = new List<int>();
  98.  
  99.             Parallel.ForEach(items.Slice(100), s =>
  100.             {
  101.                 foreach (int item in s)
  102.                 {
  103.                     if (item % 3 == 0 || item % 5 == 0)
  104.                     {
  105.                         lock (multOf3Or5)
  106.                         {
  107.                             multOf3Or5.Add(item);
  108.                         }
  109.                     }
  110.                 }
  111.             });
  112.  
  113.             return multOf3Or5.Sum();
  114.         }
  115.  
  116.  
  117.         //Basic Parallel Method just sum it
  118.         public int RunMethod3c()
  119.         {
  120.             sum = 0;
  121.  
  122.             Parallel.ForEach(items, s =>
  123.             {
  124.                 if (s % 3 == 0 || s % 5 == 0)
  125.                 {
  126.                     rw.EnterWriteLock();
  127.                     sum += s;
  128.                     rw.ExitWriteLock();
  129.                 }
  130.             });
  131.  
  132.             return sum;
  133.         }
  134.  
  135.         //Basic Parallel Method just slice & sum it
  136.         public int RunMethod3d()
  137.         {
  138.             sum = 0;
  139.             
  140.             Parallel.ForEach(items.Slice(100), s =>
  141.             {
  142.                 foreach (int item in s)
  143.                 {
  144.                     if (item % 3 == 0 || item % 5 == 0)
  145.                     {
  146.                         rw.EnterWriteLock();
  147.                         sum += item;
  148.                         rw.ExitWriteLock();
  149.                     }
  150.                 }
  151.             });
  152.  
  153.             return sum;
  154.         }
  155.     }
  156. }

Method 1: is the straight forward logic I would have used, and seems to be the quickest.
Method 2s: is probably something I would use as well, and to clean code up.
Method 3s: using Parallel programming, doesn't always speed things up. Depends on how much work needs to be done. I used an Extension method called Slice which expands the use of enumerable. I mainly got the idea to do this after reading about extention methods from http://www.blackrabbitcoder.net/archive/2013/03/08/c.net-little-wonders-extension-methods-demystified.aspx

For the Slice Extension, I used this:
Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. namespace ProjectEuler
  7. {
  8.     public static class EnumerableExtensions
  9.     {
  10.         //Source and Inspiration: http://www.blackrabbitcoder.net/archive/2013/03/08/c.net-little-wonders-extension-methods-demystified.aspx
  11.  
  12.         public static IEnumerable<IEnumerable<T>> Slice<T>(this IEnumerable<T> source, int size)
  13.         {
  14.             // can't slice null sequence
  15.             if (source == null) throw new ArgumentNullException("source");
  16.             if (size < 1) throw new ArgumentOutOfRangeException("size", "The size must be positive.");
  17.  
  18.             // force into a list to take advantage of direct indexing. Could also force into an
  19.             // array, use LINQ grouping, do a Skip()/Take(), etc...
  20.             var sourceList = source.ToList();
  21.             int current = 0;
  22.      
  23.             // while there are still items to "slice" off, keep going
  24.             while (current < sourceList.Count)
  25.             {
  26.                 // return a sub-slice using an iterator for deferred execution
  27.                 yield return sourceList.GetRange(current, Math.Min(size, sourceList.Count - current));
  28.                 current += size;
  29.             }
  30.         }
  31.     }
  32. }

The Main program. I hate repeating myself, so after some refactoring I came up with this to use delegates.
Code Snippet
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Diagnostics;
  6.  
  7. namespace ProjectEuler
  8. {
  9.     class Program
  10.     {
  11.         public static Stopwatch sw = new Stopwatch();
  12.         public delegate int fPointer();
  13.  
  14.         static void Main(string[] args)
  15.         {
  16.             //Initialize Problem(s)
  17.             Problem1 p1 = new Problem1();
  18.  
  19.             Func<fPointer,int, double> timeIt = (d,runCount) =>
  20.             {
  21.                 List<double> times = new List<double>();
  22.  
  23.                 for (int i = 0; i < runCount; i++)
  24.                 {
  25.                     sw.Reset();
  26.                     sw.Start();
  27.                     d();
  28.                     sw.Stop();
  29.                     times.Add(sw.Elapsed.TotalSeconds);
  30.                 }
  31.                 return times.Average();
  32.             };
  33.  
  34.             //Get Times of Running Methods
  35.             Console.WriteLine("Method 1 Avg Time: " + timeIt(p1.RunMethod1,100));
  36.             Console.WriteLine("Method 2a Avg Time: " + timeIt(p1.RunMethod2a, 100));
  37.             Console.WriteLine("Method 2b Avg Time: " + timeIt(p1.RunMethod2b, 100));
  38.             Console.WriteLine("Method 2c Avg Time: " + timeIt(p1.RunMethod2c, 100));
  39.             Console.WriteLine("Method 2d Avg Time: " + timeIt(p1.RunMethod2d, 100));
  40.             Console.WriteLine("Method 3a Avg Time: " + timeIt(p1.RunMethod3a, 100));
  41.             Console.WriteLine("Method 3b Avg Time: " + timeIt(p1.RunMethod3b, 100));
  42.             Console.WriteLine("Method 3c Avg Time: " + timeIt(p1.RunMethod3c, 100));
  43.             Console.WriteLine("Method 3d Avg Time: " + timeIt(p1.RunMethod3d, 100));
  44.  
  45.             Console.ReadKey();
  46.         }
  47.     }
  48. }

Thursday, March 14, 2013

SQL-Server Cell Level Encryption Examples

This could come be handy to know, encrypting sensitive data (at cell level) in SQL-Server.
- Source: Basit Farooq (http://basitaalishan.com/) - http://www.sqlmag.com/article/sql-server/sql-server-encryption-144904

His article goes into a lot of good details, but here is a small recap on how:

Demo on creating Symmetric Keys using Asymmetric Keys:

Code Snippet
  1. --DEMO ON CREATING SYMETRIC KEYS
  2. --ENCRYPTING USING ASYMMETRIC KEY
  3.  
  4. USE [master]
  5. GO
  6. --Create Database
  7. CREATE DATABASE [EncryptedDB]
  8. GO
  9.  
  10. USE [EncryptedDB]
  11. GO
  12.  
  13. --Create Table
  14. CREATE TABLE [dbo].[CreditCardInformation]
  15. (
  16.     [PersonID] [int] PRIMARY KEY,
  17.     [CreditCardNumber] [varbinary](max)
  18. )
  19. GO
  20.  
  21. --Create Database Master Key (DMK)
  22. CREATE MASTER KEY ENCRYPTION BY PASSWORD = '$tr0nGPa$$w0rd'
  23. GO
  24.  
  25. --Create asymmetic key encrypted by passphase
  26. CREATE ASYMMETRIC KEY MyAsymmetricKey
  27. WITH ALGORITHM = RSA_2048
  28. ENCRYPTION BY PASSWORD = 'StrongPa$$w0rd!'
  29. GO
  30.  
  31. --Create symmetric key using asymetric encryption
  32. CREATE SYMMETRIC KEY MySymmetricKey
  33. WITH ALGORITHM = AES_256
  34. ENCRYPTION BY ASYMMETRIC KEY MyAsymmetricKey
  35. GO
  36.  
  37. --Open symmetric key and use asymmetric for it's decryption
  38. OPEN SYMMETRIC KEY MySymmetricKey
  39. DECRYPTION BY ASYMMETRIC KEY MyAsymmetricKey
  40. WITH PASSWORD = 'StrongPa$$w0rd!'
  41. GO
  42.  
  43. --Verify key is open
  44. SELECT * FROM [sys].[openkeys]
  45.  
  46. --Insert Credit Card Info into Table, encrypting it using symetric key
  47. DECLARE @SymmetricKeyGUID AS [uniqueidentifier]
  48. SET @SymmetricKeyGUID = KEY_GUID('MySymmetricKey')
  49.  
  50. IF(@SymmetricKeyGUID IS NOT NULL)
  51. BEGIN
  52.     INSERT INTO dbo.CreditCardInformation VALUES (01,ENCRYPTBYKEY(@SymmetricKeyGUID, N'9876-1234-8765-4321'))
  53.     INSERT INTO dbo.CreditCardInformation VALUES (02,ENCRYPTBYKEY(@SymmetricKeyGUID, N'9876-8765-8765-1234'))
  54.     INSERT INTO dbo.CreditCardInformation VALUES (03,ENCRYPTBYKEY(@SymmetricKeyGUID, N'9876-1234-1111-2222'))
  55. END
  56.  
  57. --View Table all cc info is in binary format
  58. SELECT * FROM dbo.CreditCardInformation
  59.  
  60. --Use decryptbykey to view data
  61. SELECT
  62. [PersonID],
  63. CONVERT([nvarchar](32),DECRYPTBYKEY(CreditCardNumber)) AS CreditCardNumber
  64. FROM [dbo].[CreditCardInformation]
  65. GO

Demo on Creating Symmetric Keys using Certificate:


Code Snippet
  1. --CREATE Symmetric Key
  2. --Using Certificate
  3.  
  4. USE [EncryptedDB]
  5. GO
  6.  
  7. -- Create the certificate.
  8. CREATE CERTIFICATE [CertToEncryptSymmetricKey]
  9. WITH SUBJECT = 'Self-signed certificate to encrypt symmetric key.'
  10.  
  11. -- Create a symmetric key that's encrypted
  12. -- with the certificate.
  13. CREATE SYMMETRIC KEY [SymmetricKeyEncryptedWithCert]
  14. WITH ALGORITHM = AES_256
  15. ENCRYPTION BY CERTIFICATE [CertToEncryptSymmetricKey]
  16.  
  17. -- Open the symmetric key.
  18. OPEN SYMMETRIC KEY [SymmetricKeyEncryptedWithCert]
  19. DECRYPTION BY CERTIFICATE [CertToEncryptSymmetricKey]
  20.  
  21. -- Truncate the CreditCardInformation table.
  22. TRUNCATE TABLE [dbo].[CreditCardInformation]
  23.  
  24. -- Insert the data into the table.
  25. DECLARE @SymmetricKeyGUID AS [uniqueidentifier]
  26. SET @SymmetricKeyGUID =
  27. KEY_GUID('SymmetricKeyEncryptedWithCert')
  28.  
  29. IF (@SymmetricKeyGUID IS NOT NULL)
  30. BEGIN
  31. INSERT INTO [dbo].[CreditCardInformation] VALUES (01, ENCRYPTBYKEY(@SymmetricKeyGUID,N'9876-1234-8765-4321'))
  32. INSERT INTO [dbo].[CreditCardInformation] VALUES (02, ENCRYPTBYKEY(@SymmetricKeyGUID,N'9876-8765-8765-1234'))
  33. INSERT INTO [dbo].[CreditCardInformation] VALUES (03, ENCRYPTBYKEY(@SymmetricKeyGUID,N'9876-1234-1111-2222'))
  34. END
  35.  
  36. --View data in table
  37. SELECT * FROM [dbo].[CreditCardInformation]
  38.  
  39. --Use decryptbykey to view data
  40. SELECT
  41. [PersonID],
  42. CONVERT([nvarchar](32),DECRYPTBYKEY(CreditCardNumber)) AS CreditCardNumber
  43. FROM [dbo].[CreditCardInformation]
  44. GO

Note:
He states that cell level may not be an option because of schema changes are necessary for the encrypted field to be varbinary format. Instead use Transparent Data Encryption.

Wednesday, March 13, 2013

Langton's Ant written in Typescript

Found this on Wikipedia: http://en.wikipedia.org/wiki/Langton's_ant about Langton's Ant. Using this as a intro to typescript, would be great. It's a very simple algorithm:

  • At a white square, turn 90° right, flip the color of the square, move forward one unit
  • At a black square, turn 90° left, flip the color of the square, move forward one unit

  • Typescript:

    Code Snippet
    1. class Point {
    2.     constructor(public X: number,public Y: number) {
    3.     }
    4. }
    5.  
    6. enum Color {
    7.     WHITE,
    8.     BLACK
    9. }
    10.  
    11. enum Direction {
    12.     NORTH,
    13.     EAST,
    14.     SOUTH,
    15.     WEST
    16. }
    17.  
    18. class Ant{
    19.     orientation: Direction;
    20.     precision: number;
    21.  
    22.     constructor(public location: Point, precision: number, orientation:Direction = Direction.NORTH) {
    23.         this.orientation = orientation;
    24.         this.precision = precision;
    25.     }
    26.  
    27.     Move() {
    28.         var canvas = <HTMLCanvasElement> document.getElementById("myCanvas");
    29.         var ctx = canvas.getContext('2d');
    30.         var imgData = ctx.getImageData(this.location.X, this.location.Y, this.precision, this.precision);
    31.         var pix = imgData.data;
    32.         var color: Color;
    33.  
    34.         if (pix[0] == 255 && pix[1] == 255 && pix[2] == 255) { //White
    35.             color = Color.WHITE;
    36.         }
    37.         else {
    38.             color = Color.BLACK;
    39.         }
    40.  
    41.         if (color == 0) {
    42.             //Change Color
    43.             ctx.fillStyle = "Black";
    44.             ctx.fillRect(this.location.X, this.location.Y, this.precision, this.precision);
    45.  
    46.             //rotate 90 to right
    47.             if (this.orientation < 3) {
    48.                 this.orientation = this.orientation + 1;
    49.             }
    50.             else {
    51.                 this.orientation = 0;
    52.             }
    53.         }
    54.         else {
    55.             //Change Color
    56.             ctx.fillStyle = "White";
    57.             ctx.fillRect(this.location.X, this.location.Y, this.precision, this.precision);
    58.  
    59.             //rotate 90 to left
    60.             if (this.orientation > 0) {
    61.                 this.orientation = this.orientation - 1;
    62.             }
    63.             else {
    64.                 this.orientation = 3;
    65.             }
    66.         }
    67.  
    68.         //move forward one unit
    69.         switch (this.orientation) {
    70.             case 0: //North
    71.                 this.location = new Point(this.location.X, this.location.Y - this.precision);
    72.                 break;
    73.             case 1: //East
    74.                 this.location = new Point(this.location.X + this.precision, this.location.Y);
    75.                 break;
    76.             case 2: //South
    77.                 this.location = new Point(this.location.X, this.location.Y + this.precision);
    78.                 break;
    79.             case 3: //West
    80.                 this.location = new Point(this.location.X - this.precision, this.location.Y);
    81.                 break;
    82.         }
    83.     }
    84. }
    85.  
    86.  
    87. window.onload = () => {
    88.     var ant = new Ant(new Point(100, 100), 2, Direction.NORTH);
    89.  
    90.     for (var i = 0; i < 11000; i++) {
    91.         ant.Move();
    92.     }
    93. };

     How it's converted to JavaScript:


    Code Snippet
    1. var Point = (function () {
    2.     function Point(X, Y) {
    3.         this.X = X;
    4.         this.Y = Y;
    5.     }
    6.     return Point;
    7. })();
    8. var Color;
    9. (function (Color) {
    10.     Color._map = [];
    11.     Color._map[0] = "WHITE";
    12.     Color.WHITE = 0;
    13.     Color._map[1] = "BLACK";
    14.     Color.BLACK = 1;
    15. })(Color || (Color = {}));
    16. var Direction;
    17. (function (Direction) {
    18.     Direction._map = [];
    19.     Direction._map[0] = "NORTH";
    20.     Direction.NORTH = 0;
    21.     Direction._map[1] = "EAST";
    22.     Direction.EAST = 1;
    23.     Direction._map[2] = "SOUTH";
    24.     Direction.SOUTH = 2;
    25.     Direction._map[3] = "WEST";
    26.     Direction.WEST = 3;
    27. })(Direction || (Direction = {}));
    28. var Ant = (function () {
    29.     function Ant(location, precision, orientation) {
    30.         if (typeof orientation === "undefined") { orientation = Direction.NORTH; }
    31.         this.location = location;
    32.         this.orientation = orientation;
    33.         this.precision = precision;
    34.     }
    35.     Ant.prototype.Move = function () {
    36.         var canvas = document.getElementById("myCanvas");
    37.         var ctx = canvas.getContext('2d');
    38.         var imgData = ctx.getImageData(this.location.X, this.location.Y, this.precision, this.precision);
    39.         var pix = imgData.data;
    40.         var color;
    41.         if(pix[0] == 255 && pix[1] == 255 && pix[2] == 255) {
    42.             //White
    43.             color = Color.WHITE;
    44.         } else {
    45.             color = Color.BLACK;
    46.         }
    47.         if(color == 0) {
    48.             //Change Color
    49.             ctx.fillStyle = "Black";
    50.             ctx.fillRect(this.location.X, this.location.Y, this.precision, this.precision);
    51.             //rotate 90 to right
    52.             if(this.orientation < 3) {
    53.                 this.orientation = this.orientation + 1;
    54.             } else {
    55.                 this.orientation = 0;
    56.             }
    57.         } else {
    58.             //Change Color
    59.             ctx.fillStyle = "White";
    60.             ctx.fillRect(this.location.X, this.location.Y, this.precision, this.precision);
    61.             //rotate 90 to left
    62.             if(this.orientation > 0) {
    63.                 this.orientation = this.orientation - 1;
    64.             } else {
    65.                 this.orientation = 3;
    66.             }
    67.         }
    68.         //move forward one unit
    69.         switch(this.orientation) {
    70.             case 0:
    71.                 //North
    72.                 this.location = new Point(this.location.X, this.location.Y - this.precision);
    73.                 break;
    74.             case 1:
    75.                 //East
    76.                 this.location = new Point(this.location.X + this.precision, this.location.Y);
    77.                 break;
    78.             case 2:
    79.                 //South
    80.                 this.location = new Point(this.location.X, this.location.Y + this.precision);
    81.                 break;
    82.             case 3:
    83.                 //West
    84.                 this.location = new Point(this.location.X - this.precision, this.location.Y);
    85.                 break;
    86.         }
    87.     };
    88.     return Ant;
    89. })();
    90. window.onload = function () {
    91.     var ant = new Ant(new Point(100, 100), 2, Direction.NORTH);
    92.     for(var i = 0; i < 11000; i++) {
    93.         ant.Move();
    94.     }
    95. };



    Resulting:


    Looking at the wiki, it seems if I had a few more rules and colors I can up with different, and interesting patterns.


    Edit: Some more pics I created by changing pattern and colors:

     

    Tuesday, March 05, 2013

    Reminder: Setting up MVC4 Async Service in Controller

    A quick reminder: I call a Json formatted file as a Service, that I placed in the App_Data folder. I then pull the contents needed using AsyncController.


    Code Snippet
    1. using System;
    2. using System.Collections.Generic;
    3. using System.Linq;
    4. using System.Web;
    5. using System.Web.Mvc;
    6. using MadLibs.Models;
    7. using System.Net.Http;
    8. using Newtonsoft.Json;
    9.  
    10.  
    11. namespace MadLibs.Controllers
    12. {
    13.     public class MadLibController : AsyncController
    14.     {
    15.         //
    16.         // GET: /MadLib/
    17.  
    18.         public ActionResult StoryService()
    19.         {
    20.             return this.File("~/App_Data/StoriesDB.json", "application/json");
    21.         }
    22.  
    23.         public void IndexAsync()
    24.         {
    25.             String uri = Url.Action("StoryService", "MadLib", null, Request.Url.Scheme);
    26.             HttpClient client = new HttpClient();
    27.             var response = client.GetStringAsync(uri).Result;
    28.  
    29.             AsyncManager.Parameters["stories"] = JsonConvert.DeserializeObject<List<Story>>(response);
    30.         }
    31.  
    32.         public ActionResult IndexCompleted(List<Story> stories)
    33.         {
    34.             return View(stories);
    35.         }
    36.     }
    37. }