Using Git With Visual Studio

I am starting to use Git with Visual Studio 2013 on my home projects.  I have been using Git lightly for pushing code samples into GitHub, but never on projects with other people.  This is a pretty good set of articles about setting up Git with Visual Studio and well worth the read before doing it (like who reads instructions). 

I created a project on Visual Studio Online and selected Git as the source control.  I then cloned the empty project locally.  Next, I created a brand-new Web Api 2 solution in Visual Studio and pushed the files over to that repository.  I then pushed those changes up to VSO.  Finally, I went over to another machine and cloned the repository and pulled down the files.

This was all well and good until I made a change on one machine and I wanted to pull down the changes into the solution that I had open on the other machine.  I was getting an “uncommitted changed being overwritten by merge” exception.  The frustrating thing was that there was nothing in the Visual Studio 2013 tooling/add-ins that allowed me to discard my local changes.  I wrote this post to stack overflow and it turns out I had a problem because I made the mistake of adding file to the repository that I didn’t want to.  I needed to do this –> add the .suo file to gitIgnore BEFORE committing the 1st change.  The problem was that adding it to the gitIgnore after the commit means the file was still being tracked and there is nothing in the out of the box VS2013 tools that can help you resolve the problem. 

The best advice from SO was to use git extensions because when I installed it, I could do all of the things I wanted to do without learning the git commands.  Indeed, I installed it and holy cow, this is awesome:

image

Implementing (Parts Of) ASP.NET Identity Using F#

I started working though this and this article for implementing security in a new Web Api 2 site I am spinning up.  Everything is working out OK – not great but better than prior ASP.NET implementations I have done.  I do think the ASP.NET team has made security better and I am really excited about token based security.  My biggest gripe is that there is still too much magic going on and it is still hard to introduce non-out of the box implementations.  For example, the sample code that you can add via Nuget has a placeholder for en email provider.  The article has the code for a specific implementation of a company called SendGrid (the sample is here and the email is here).
The CSharp implementation looks like this (I did add some constructor injection b/c I am opposed to touching the Configuration (or any part of the file system for that matter) outside of Main on sanity grounds):
1 public class SendGridEmailProvider: IIdentityMessageService 2 { 3 String _mailAccount = String.Empty; 4 String _mailPassword = String.Empty; 5 String _fromAddress = String.Empty; 6 7 public SendGridEmailProvider(String mailAccount, String mailPassword, String fromAddress) 8 { 9 _mailAccount = mailAccount; 10 _mailPassword = mailPassword; 11 _fromAddress = fromAddress 12 } 13 14 public System.Threading.Tasks.Task SendAsync(IdentityMessage message) 15 { 16 var sendGridMessage = new SendGridMessage(); 17 sendGridMessage.From = new MailAddress(_fromAddress); 18 List<String> recipients = new List<string>(); 19 recipients.Add(message.Destination); 20 sendGridMessage.AddTo(recipients); 21 sendGridMessage.Subject = message.Subject; 22 sendGridMessage.Html = message.Body; 23 sendGridMessage.Text = message.Body; 24 25 var credentials = new NetworkCredential(_mailAccount, _mailPassword); 26 var transportWeb = new Web(credentials); 27 if (transportWeb != null) 28 return transportWeb.DeliverAsync(sendGridMessage); 29 else 30 return Task.FromResult(0); 31 } 32 }

I then decided to implement a SMS Text Provider along the same lines.  The 1st company I came to was CDyne but when I went to their sample code, they are still using a SOAP-based service and the last thing I wanted to do was to clutter up my project with all of the WSDL and files that you needs when consuming a service like that.
I then thought, this is stupid.  I might was well use FSharp type providers to do the implementation.  Less Code, less files, less clutter, more goodness.  I first swapped out the Email to a FSharp implementation:
1 type SendGridEmailService(account:string, password:string, fromAddress:string) = 2 interface IIdentityMessageService with 3 member this.SendAsync(identityMessage) = 4 let sendGridMessage = new SendGridMessage() 5 sendGridMessage.From = new MailAddress(fromAddress) |> ignore 6 let recipients = new List<string>() 7 recipients.Add(identityMessage.Destination) 8 sendGridMessage.AddTo(recipients) 9 sendGridMessage.Subject <- identityMessage.Subject 10 sendGridMessage.Html <- identityMessage.Body 11 sendGridMessage.Text <- identityMessage.Body 12 13 let credentials = new NetworkCredential(account, password) 14 let transportWeb = new Web(credentials) 15 match transportWeb with 16 | null -> Task.FromResult(0):> Task 17 | _ -> transportWeb.DeliverAsync(sendGridMessage)

I then did a SMS text provider using type providers.
1 type cDyneService = Microsoft.FSharp.Data.TypeProviders.WsdlService<"http://sms2.cdyne.com/sms.svc?wsdl"> 2 3 type CDyneSMSService(licenseKey:Guid) = 4 interface IIdentityMessageService with 5 member this.SendAsync(identityMessage) = 6 let cDyneClient = cDyneService.Getsms2SOAPbasicHttpBinding 7 let client = cDyneService.Getsms2SOAPbasicHttpBinding() 8 match client with 9 | null -> Task.FromResult(0):> Task 10 | _ -> client.SimpleSMSsendAsync(identityMessage.Destination,identityMessage.Body,licenseKey):> Task

Compared to a CSharp implementation, this is joyous.  Less noise, more signal.  And thanks to Lee on Stack Overflow for helping with the upcast of Task…

Adopting F# in a C# Shop

I have been speaking to different groups in both large and small companies about adopting FSharp as part of their .NET stack and the resistance ranges from the understandable to the head-scratching.  I posted a similar question to the Google group here and got some pretty interesting responses.  The funniest was this video.  Scott Wlaschin offers several convincing reasons to use FSharp here  as well as  several ways to try and work around the walls thrown up in a “C Sharp shop” here.

I have recently implemented a project using FSharp in a large insurance company that is a  “CSharp shop” using the following technique and hopefully someone else can get some use out of it.  My first premise is that FSharp is not the end, it is the means.  Therefore, you don’t want to walk into any meeting and say something like “hey, I heard of this great new language, we should try it out.”  That kind of statement will be dead in the water with the layers of project managers, architectural review committees, etc….  Rather, you need to walk into the meeting and way “As you know, our company is supposed to be ‘innovative’ and I have been experimenting outside of work with different ways to reduce the number of bugs in our code and deliver software faster.”

(Jamie note, since I wrote this, this study came out pointing out that functional programming does produce better code quality.  However, its benefits are not as important as having a high performing team with the appropriate process (team size, project size, and commit size)).  One more thing to mention to the PM.

The next step is to realize that one of the most overlooked benefits of FSharp is that since it is a .NET language, you can slide a FSharp project into a Visual Studio Solution with just a couple of button clicks and the existing CSharp code will just work with it.  Use this to your advantage by creating an interface to an existing CSharp class that has some conditional logic.  For example,CSharp implementation of a class that creats a customer for an order

1 public class CustomerCreator 2 { 3 Boolean alreadyHasAnAccount = false; 4 5 public Customer CreateCustomerForAnOrder(Order order, String firstName, String lastName) 6 { 7 //Actual implementation is not important 8 return new Customer(); 9 } 10 }

 

The actual implementation is not important because as a FSharp dev, you don’t really want to look at the CSharp code.  All you really want  to do is extract the interface:

image

1 interface ICustomerCreator 2 { 3 Customer CreateCustomerForAnOrder(Order order, string firstName, string lastName); 4 }

With the interface in place, you can now create a FSharp project in the solution and begin your implementation of it:

1 namespace ChickenSoftware.CustomerManagementExt 2 3 open ChickenSoftware.CustomerManagement 4 5 type BetterCustomerCreator() = 6 interface ICustomerCreator with 7 member this.CreateCustomerForAnOrder(order, firstName, lastName) = 8 new Customer()

(Note I wouldn’t call it ‘BetterCustomerCreator’ for real, even if it is better). 

You then can enter your next meeting saying, something like “I created functional equivalence with the enhancements of fewer bug, better readability, and mutli-threading support.”  The PM will say, “that is awesome” and the developers who no longer code (typically called architects in large companies) will protest that it is in a different language.  But now you have the PM on your side and you can have a discussion about finding qualified people to work in F#.  My experience there is that the developers you want to work with will jump at the chance and the devs you don’t want on the project will balk at learning a new language/mindset.  You can also mention that the really good C# devs are already using linq an lambdas so they are already transitioning to FSharp.

The last point is that you need to back up the statement you made originally that FSharp reduces the number of bugs and delivers software faster.  If you are a .NET dev,  I would recommend listening to Bob Martin when he says that you need to spend 20 hours a week outside of your primary job (as he mentions here) and learning a functional language (as he mentions here) learning FSharp.  That effort, coupled with the FSharp community (the best community you will find) will certainly allow you to walk the walk.  There will be detractors at every turn who will point to any slowdown to a FSharp codebase as proof that CSharp would have been perfectly fine.  The only thing I can say there is “Don’t let the turkeys get you down.” and manage expectations that FSharp is not a silver bullet and that there are places where CSharp is more appropriate.  Be the voice of innovation and reason, don’t be the functional dogmatic in the room.  So far it was worked for me, and I hope it works for you.

Halloween Project (Garage Of Mystery)

For this years Halloween, the kids and I decided to do something out of the opening scene of Indiana Jones, without the big rock.  We wanted to give kids a choice when they came to the house –> either get a small “fun” size candy bar or enter the garage of mystery for the chance of a full sized candy bar.  (Incidentally, whoever thought it would be a good idea to name the smallest candy size on earth “fun” obviously was never a kid.  When I was growing up, we called it four size, being that if took four of them to make a normal candy bar)

So if the kid wants to go into the garage of mystery, they have to get to the alter of snickers without the motion detector or the laser beam trip wires catching them.  The full-size Snickers would disappear if the kid was picked up by the Kinect motion detector or if they tripped too many beams.  In the diagram below, the red dots are the lasers crossing in front of the alter

image

The first thing we did was construct the alter.  

imageimage

Once the frame was set, we added a servo with a trap door to the top.  We control the servo via a Phidget Servo Controller with some basic code from the Phidget SDK (if the SDK, you know, had F# in it)

1 member this.servoController_Attached(args:Events.AttachEventArgs) = 2 let _servoController = args.Device :?> AdvancedServo 3 _servoController.servos.[0].Engaged <- true 4 _servoController.servos.[0].Position <- 110. 5 _isServoControllerReady <- true 6 7 member this.initializeController() = 8 _servoController.Attach.Add(this.servoController_Attached) 9 _servoController.``open``() 10 11 member this.moveController(position:float) = 12 if _isServoControllerReady then 13 _servoController.servos.[0].Position <- position 14

And you can see it in action here:

 

With the alter ready, we turned our attention to the laser trip wires.  We purchased a whole bunch of dollar store pen lasers and got some Phidget light sensors.  We then created a frame for both sides of the garage –> one to mount the laser and 1 to mount the light sensor

imageimage

And then we added some basic code from the Phidget SDK (if the SDK, you know, had F# in it)

1 member this.interfaceKit_Attached(args: Events.AttachEventArgs) = 2 let _interfaceKit = args.Device :?> InterfaceKit 3 _interfaceKit.sensors 4 |> Seq.cast 5 |> Seq.map(fun s -> s :> InterfaceKitAnalogSensor) 6 |> Seq.map(fun s -> s.Sensitivity <- 20) 7 |>ignore 8 _isInterfaceKitReady <- true 9 10 member this.interfaceKit_SensorChange(e: SensorChangeEventArgs ) = 11 let eventArgs = new LightSensorChangeEventArgs(e.Index,e.Value) 12 lightSensorChange.Trigger(eventArgs) 13 14 member this.initializeInterfaceKit() = 15 _interfaceKit.Attach.Add(this.interfaceKit_Attached) 16 _interfaceKit.SensorChange.Add(this.interfaceKit_SensorChange) 17 _interfaceKit.``open``() 18 _interfaceKit.waitForAttachment() 19

Note that we are trapping the event from the light sensor and then raising it up in our own event. 

With the light sensor in place, we turned our attention to the Kinect motion sensor.  I first considered Rob Miles’s ides to compare the different color frames to see if there was movement but because I am using F# and F# does not support pointers like C#, the performance was too choppy.  You can see the Stack Overflow thread here.  So I could have either jumped to over to C# or figure out a different way using F#.  I went with option B by using the skeleton frame, which has a Z index.  By comparing the Z index over time, I can see how fast a person is moving towards to alter.  The Kinect code was pretty much from the SDK (if the SDK, you know, had F# in it)

1 member this.kinectSensor_ColorFrameReady(args: ColorImageFrameReadyEventArgs) = 2 use colorFrame = args.OpenColorImageFrame() 3 if not (colorFrame = null) then 4 let colorData = Array.zeroCreate<byte> colorFrame.PixelDataLength 5 colorFrame.CopyPixelDataTo(colorData) 6 let width = colorFrame.Width 7 let height = colorFrame.Height 8 let stride = colorFrame.Width * colorFrame.BytesPerPixel 9 let eventArgs = new ColorDataReadyEventArgs(colorData,width,height,stride) 10 colorDataReady.Trigger(eventArgs) 11 () 12 13 member this.KinectSensor_SkeletonFrameReady(args: SkeletonFrameReadyEventArgs) = 14 use skeletonFrame = args.OpenSkeletonFrame() 15 if not (skeletonFrame = null) then 16 let skeletons = Array.zeroCreate<Skeleton> skeletonFrame.SkeletonArrayLength 17 skeletonFrame.CopySkeletonDataTo(skeletons) 18 let skeletons1 = skeletons |> Array.filter (fun s -> s.TrackingState = SkeletonTrackingState.Tracked) 19 if skeletons1.Length > 0 then 20 skeletonChanged.Trigger(skeletons1.[0]) 21 () 22 () 23 24 member this.initializeKinect() = 25 _kinectSensor.ColorStream.Enable() 26 _kinectSensor.ColorFrameReady.Subscribe(this.kinectSensor_ColorFrameReady) |> ignore 27 _kinectSensor.SkeletonStream.Enable(); 28 _kinectSensor.SkeletonFrameReady.Subscribe(this.KinectSensor_SkeletonFrameReady) |> ignore 29 _kinectSensor.Start() 30

In the UI, I then checked for the skeleton movement and if the person moved too fast, they would trigger the snickers trap door to open

1 void garage_SkeletonChanged(object sender, Skeleton skeleton) 2 { 3 if(_skeletonPoint.Z > 0) 4 { 5 float zDelta = _skeletonPoint.Z - skeleton.Position.Z; 6 if (zDelta >= _zDeltaThreshold) 7 { 8 _numberOfSkeletonHits += 1; 9 skeletonChangedProgressBar.Dispatcher.Invoke(new Action(() => skeletonChangedProgressBar.Value = _numberOfSkeletonHits)); 10 11 } 12 if(_numberOfSkeletonHits >= _numberOfHitsForAlarm) 13 { 14 _garage.moveController(_openPosition); 15 } 16 17 skeletonCanvas.Children.Clear(); 18 drawSkelton(skeleton); 19 } 20 _skeletonPoint = skeleton.Position; 21 } 22

With the result like this:

With the hard parts done, it was time to create a UI.  I went with C# here because I am using WPF and the support for WPF and the Kinect is best in C#.  I created a WPF application and built a UI

1 <Window x:Class="ChickenSoftware.Halloween.UI.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 Title="MainWindow" Height="600" Width="650" > 5 <Grid Height="600" Width="650" VerticalAlignment="Top" HorizontalAlignment="Left" > 6 <Image Name ="kinectVideo" Height="480" Width="640" Margin="10,0,0,120" /> 7 <Canvas Name="skeletonCanvas" Height="480" Width="640" Margin="10,0,0,120" /> 8 <Rectangle x:Name="sensor0Rectange" Fill="Lime" HorizontalAlignment="Left" Height="40" Margin="10,480,0,0" Stroke="Black" VerticalAlignment="Top" Width="82"/> 9 <Rectangle x:Name="sensor1Rectange" Fill="Lime" HorizontalAlignment="Left" Height="40" Margin="189,480,0,0" Stroke="Black" VerticalAlignment="Top" Width="83"/> 10 <Rectangle x:Name="sensor2Rectange" Fill="Lime" HorizontalAlignment="Left" Height="40" Margin="367,480,0,0" Stroke="Black" VerticalAlignment="Top" Width="82"/> 11 <Rectangle x:Name="sensor3Rectange" Fill="Lime" HorizontalAlignment="Left" Height="40" Margin="537,480,0,0" Stroke="Black" VerticalAlignment="Top" Width="83"/> 12 <ProgressBar x:Name="skeletonChangedProgressBar" HorizontalAlignment="Left" Height="40" Margin="10,528,0,0" VerticalAlignment="Top" Width="392" Foreground="#FFB00606"/> 13 <Button x:Name="resetButton" Content="Reset" HorizontalAlignment="Left" Height="37" Margin="537,528,0,0" 14 VerticalAlignment="Top" Width="83" Click="resetButton_Click"/> 15 <Button x:Name="EjectButton" Content="Eject!" HorizontalAlignment="Left" Height="37" Margin="429,528,0,0" 16 VerticalAlignment="Top" Width="83" Click="EjectButton_Click"/> 17 </Grid> 18 </Window>

I then added some code to handle all of the events that the Phidgets and Kinect are sending to the UI and do something useful with it.    For example, the light sensor change fills in the appropriate box on the screen (note that Phidgets use a different thread so you need to use Dispatcher.Invoke)

1 void garage_LightSensorChange(object sender, LightSensorChangeEventArgs args) 2 { 3 switch (args.SensorIndex) 4 { 5 case 0: 6 if (args.SensorIndex == 0 && args.LightAmount < _lightSensorThreshold) 7 { 8 _sensor0Tripped = true; 9 sensor0Rectange.Dispatcher.Invoke(new Action(()=>sensor0Rectange.Fill = new SolidColorBrush(Colors.Red))); 10 } 11 break; 12 case 1: 13 14 if (args.SensorIndex == 1 && args.LightAmount < _lightSensorThreshold) 15 { 16 _sensor1Tripped = true; 17 sensor1Rectange.Dispatcher.Invoke(new Action(() => sensor1Rectange.Fill = new SolidColorBrush(Colors.Red))); 18 } 19 break; 20 case 2: 21 if (args.SensorIndex == 2 && args.LightAmount < _lightSensorThreshold) 22 { 23 _sensor2Tripped = true; 24 sensor2Rectange.Dispatcher.Invoke(new Action(() => sensor2Rectange.Fill = new SolidColorBrush(Colors.Red))); 25 } 26 break; 27 case 3: 28 if (args.SensorIndex == 3 && args.LightAmount < _lightSensorThreshold) 29 { 30 _sensor3Tripped = true; 31 sensor3Rectange.Dispatcher.Invoke(new Action(() => sensor3Rectange.Fill = new SolidColorBrush(Colors.Red))); 32 } 33 break; 34 } 35 CheckForIntruder(); 36 } 37

With this associated method

1 private void CheckForIntruder() 2 { 3 Int32 numberOfSensorsTripped = 0; 4 5 if (_sensor0Tripped == true) 6 numberOfSensorsTripped += 1; 7 if (_sensor1Tripped == true) 8 numberOfSensorsTripped += 1; 9 if (_sensor2Tripped == true) 10 numberOfSensorsTripped += 1; 11 if (_sensor3Tripped == true) 12 numberOfSensorsTripped += 1; 13 if (numberOfSensorsTripped >= _numberOfSensorsForAlarm ) 14 _garage.moveController(0); 15 16 }

This code would be so much better in F# using pattern matching but b/c of the UI code, I kept it in C#.  I might refactor the non-visual components later.  The one thing that did surprise me is that how the Kinect V1 SDK makes it very hard to separate the UI components from the domain components.  Phidgets, on the other hand, had a very clear separation of concerns

So we then added some sides to the alter of snickers

image

And we were good to go.  The final result looks like this (the smoke machine was an added touch):

All of the code is on github here.  If you create your own garage of mystery, please drop me a line –> I would love to see what other makers come up with. 

Parsing Microsoft MVP Pages Part 2

As a final piece of the Terminator App (V1) is to associate MVP Names to the pictures I uploaded to Sky Biometry via the MVPId.  I already blogged about how to parse the MVP search page and get the photos for sky biometry and this was a similar task.  The key for each photo is the MVPId.  Once a person’s photo is sent to Sky Biometry, the response is the photo used to match and their Id.  Ideally, we would also see the person’s name

The first step was to parse the MVP list the same way I did before:

1 let getPageContents(pageNumber:int) = 2 let uri = new Uri("http://mvp.microsoft.com/en-us/search-mvp.aspx?lo=United+States&sl=0&browse=False&sc=s&ps=36&pn=" + pageNumber.ToString()) 3 let request = WebRequest.Create(uri) 4 request.Method <- "GET" 5 let response = request.GetResponse() 6 let stream = response.GetResponseStream() 7 let reader = new StreamReader(stream) 8 reader.ReadToEnd()

Next, once the page is laoded, I needed a way of parsing the name.  I used the tag like this <a href="/en-us/mvp/Jamie%20Dixon-5000814" to identify MVPs.  I then layered in a regex like this

1 let getMVPInfoFromPageContents(pageContents:string) = 2 let pattern = "(us\\/mvp\\/)([A-Z])(.+?)(-)(\\d+)" 3 let matchCollection = Regex.Matches(pageContents, pattern) 4 matchCollection 5 |> Seq.cast 6 |> Seq.map(fun (m:Match) -> m.Value) 7 |> Seq.map(fun s -> s.Split('-')) 8 |> Seq.map(fun a -> a.[0],a.[1]) 9 |> Seq.map(fun (n,i) -> n.Substring(7),n,i) 10 |> Seq.map(fun (n,ln,i) -> n.Replace("%20"," "),ln,i) 11 |> Seq.map(fun (n,ln,i) -> n,"mvp.microsoft.com/en-"+ln+"-"+i,i) 12 |> Seq.distinctBy(fun (n,uri,i) -> n) 13

And this is a great site in terms of building regexs.

With the list parsed, I then put each page together and saved it to disk

1 let getGetMVPInfos(pageNumber: int) = 2 let pageContents = getPageContents(pageNumber) 3 getMVPInfoFromPageContents pageContents 4 5 let pageList = [1..17] 6 let mvpInfos = pageList 7 |>Seq.collect(fun i -> getGetMVPInfos(i)) 8 9 let outFile = new StreamWriter(@"c:\data\mvpList.csv") 10 mvpInfos |> Seq.iter(fun (n,uri,i) -> outFile.WriteLine(sprintf "%s,%s,%s" n uri i)) 11 outFile.Flush 12 outFile.Close()

And with that in place, the terminator can use the FSharp csv provider to load the list (and also find Esther Lee, the one non-MVP the terminiator is scanning for)

1 namespace ChickenSoftware.Terminator.Core 2 3 open System 4 open FSharp.Data 5 6 type nameMappingContext = CsvProvider<"C:/data/mvpList.csv"> 7 8 type LocalFileSystemMvpProvider () = 9 member this.GetMVPInfo (mvpId:int) = 10 if mvpId = 1 then 11 new MVPInfo(1,"Esther Lee","NA","https://pbs.twimg.com/profile_images/2487129558/3DSC_0379.jpg") 12 else 13 let nameList = nameMappingContext.Load("C:/data/mvpList.csv") 14 let foundInfo = nameList.Rows 15 |> Seq.filter(fun r -> r.``21505`` = mvpId.ToString()) 16 |> Seq.map(fun r -> new MVPInfo(Int32.Parse(r.``21505``),r.``Bill Jelen``, 17 r.``mvp.microsoft.com/en-us/mvp/Bill%20Jelen-21505``, 18 "http://mvp.microsoft.com/private/en-us/PublicProfile/Photo/" + r.``21505``)) 19 |> Seq.toArray 20 if foundInfo.Length > 0 then 21 foundInfo.[0] 22 else 23 new MVPInfo(-1,"None","None","None") 24

And then compare the 2 photos and get the person’s name

1 LocalFileSystemMvpProvider mvpProvider = new LocalFileSystemMvpProvider(); 2 var mvpInfo = mvpProvider.GetMVPInfo(mvpId); 3 4 compareImage.Source = new BitmapImage(new Uri(mvpInfo.PhotoUri)); 5 facialRecognitionTextBox.Text = mvpInfo.FullName + " identified with a " + matchValue.Confidence + "% confidence."; 6

And it (kinda works)

image

and kinda not

image

Parsing Microsoft MVP Pages and Uploading Photos to Sky Biometry

As a piece of the Terminator project that I am bringing to the MVP Summit, I wanted to load in all of the MVP photographs to Sky Biometry and if a person matches the photo at a high level, terminate them.  I asked my Microsoft contact if I could get all of the MVP photos to load into the app and they politely told me no.

Not being one who takes no lightly, I decided to see if I could load the photos from the MVP website.  Each MVP has a profile photo like here and all of the MVPs are listed here with their MVP IDs specified.  So if I can get the Id from the search page and then create a Uri to the photo, I can then load it into Sky Biometry.

I first created a new FSharp project and fired up a script window.  I created a function that gets the entire contents of a page with the only variable being the index number of the pagination.

1 let getPageContents(pageNumber:int) = 2 let uri = new Uri("http://mvp.microsoft.com/en-us/search-mvp.aspx?lo=United+States&sl=0&browse=False&sc=s&ps=36&pn=" + pageNumber.ToString()) 3 let request = WebRequest.Create(uri) 4 request.Method <- "GET" 5 let response = request.GetResponse() 6 let stream = response.GetResponseStream() 7 let reader = new StreamReader(stream) 8 reader.ReadToEnd() 9

I then parsed the page for all instances of the MVPId.  Fortunately, I found this post that helped me understand how the pattern match works in .NET.  Note that the regex for the tag mvpid=123456 is “mvpid=\d+”

1 let getMVPIdsFromPageContents(pageContents:string) = 2 let pattern = "mvpid=\d+" 3 let matchCollection = Regex.Matches(pageContents, pattern) 4 matchCollection 5 |> Seq.cast 6 |> Seq.map(fun (m:Match) -> m.Value) 7 |> Seq.map(fun s -> s.Split('=')) 8 |> Seq.map(fun a -> a.[1]) 9

With that out of the way, I could get a Seq of all MVP IDs (at least from America and then collect each of the pages together:

1 let getGetMVPIds(pageNumber: int) = 2 let pageContents = getPageContents(pageNumber) 3 getMVPIdsFromPageContents pageContents 4 5 let pageList = [1..17] 6 let mvpIds = pageList 7 |>Seq.collect(fun i -> getGetMVPIds(i)) 8

so far so good:

image

I then could create a method that generates the MVP Photo Uri:

1 let getMvpImageUri(mvpId: int) = 2 new Uri("http://mvp.microsoft.com/private/en-us/PublicProfile/Photo/" + mvpId.ToString()) 3

With that out of the way, it was time to point the photos to Sky Biometry for facial detection and tagging.  I used the code found in this post with a couple of changes to account that a face might not be found in the photo (hence the choice type) and that bad things might happen (like too big of a photo)

1 type skybiometryFaceDetection = JsonProvider<".\SkyBiometryImageJson\FaceDetection.json"> 2 type skybiometryAddTags = JsonProvider<".\SkyBiometryImageJson\AddTags.json"> 3 type skybiometryFaceTraining = JsonProvider<".\SkyBiometryImageJson\FaceTraining.json"> 4 5 let detectFace (imageUri:string) = 6 let stringBuilder = new StringBuilder() 7 stringBuilder.Append(skyBiometryUri) |> ignore 8 stringBuilder.Append("/fc/faces/detect.json?urls=") |> ignore 9 stringBuilder.Append(imageUri) |> ignore 10 stringBuilder.Append("&api_key=") |> ignore 11 stringBuilder.Append(skyBiometryApiKey) |> ignore 12 stringBuilder.Append("&api_secret=") |> ignore 13 stringBuilder.Append(skyBiometryApiSecret) |> ignore 14 try 15 let faceDetection = skybiometryFaceDetection.Load(stringBuilder.ToString()) 16 if faceDetection.Photos.[0].Tags.Length > 0 then 17 Some faceDetection.Photos.[0].Tags.[0].Tid 18 else 19 None 20 with | :? System.Exception -> None 21

I then added the other two methods to tag and recognize

1 let saveTag(uid:string, tid:string)= 2 let stringBuilder = new StringBuilder() 3 stringBuilder.Append(skyBiometryUri) |> ignore 4 stringBuilder.Append("/fc/tags/save.json?uid=") |> ignore 5 stringBuilder.Append(uid) |> ignore 6 stringBuilder.Append("&tids=") |> ignore 7 stringBuilder.Append(tid) |> ignore 8 stringBuilder.Append("&api_key=") |> ignore 9 stringBuilder.Append(skyBiometryApiKey) |> ignore 10 stringBuilder.Append("&api_secret=") |> ignore 11 stringBuilder.Append(skyBiometryApiSecret) |> ignore 12 let tags = skybiometryAddTags.Load(stringBuilder.ToString()) 13 tags.Status 14 15 let trainFace(uid:string)= 16 let stringBuilder = new StringBuilder() 17 stringBuilder.Append(skyBiometryUri) |> ignore 18 stringBuilder.Append("/fc/faces/train.json?uids=") |> ignore 19 stringBuilder.Append(uid) |> ignore 20 stringBuilder.Append("&api_key=") |> ignore 21 stringBuilder.Append(skyBiometryApiKey) |> ignore 22 stringBuilder.Append("&api_secret=") |> ignore 23 stringBuilder.Append(skyBiometryApiSecret) |> ignore 24 let training = skybiometryFaceTraining.Load(stringBuilder.ToString()) 25 training.Status 26

Upon reflection, this would have been a perfect place for Scott W’s ROP, but I just created a covering function

1 let saveToSkyBiometry(mvpId:string, imageUri:string) = 2 let tid = detectFace(imageUri) 3 match tid with 4 | Some x -> saveTag(mvpId + "@terminatorChicken",x) |> ignore 5 trainFace(mvpId + "@terminatorChicken") 6 | None -> "Failure" 7 8 let results = mvpIds 9 |> Seq.map(fun mvpId -> mvpId, getMvpImageUri(Int32.Parse(mvpId))) 10

I then created a Seq.Map to call all of the photos in order but I quickly ran into this:

Capture

So I changed my Seq.Map to a Loop so I could throttle the requests:

1 for (mvpId,uri) in results do 2 let result= saveToSkyBiometry(mvpId, uri.ToString()) 3 printfn "%s" result 4 Thread.Sleep(TimeSpan.FromMinutes(1.)) 5

And sure enough

Capture1Capture2

And you can see the load every hour

Capture3

You can see the full code here.

Hacking the Dream Cheeky Thunder Missile Launcher, Part 2

One of the things that the Terminator will have is a missile launcher, which I started hacking here.  The missile launcher Api is controlled by time.  Specifically, you tell it to turn in a certain direction for a certain amount of time. 

1 member this.moveMissleLauncher(data, interval:int) = 2 if devicePresent then 3 this.SwitchLed(true) 4 this.sendUSBData(data) 5 Thread.Sleep(interval) 6 this.sendUSBData(this.STOP) 7 this.SwitchLed(false) 8

The challenge is converting that duration into X,Y Cartesian coordinates the way the Kinect and the phidget laser system does.  And before getting Cartesian coordinates, we needed to get the polar coordinates.  This is how we did it.

First, we tackled the pan (X coordinate) of the missile launcher.  The launcher is a on a square base and the full range of the launcher is 45 degrees to 315 degrees.

image

With some experimentation, we determined that the total time it takes the turret to traverse from 45 degrees to 315 degrees (270 total degrees) is 6346 Milliseconds.  Assume that the motor is consistent (which is a big if using cheap electronics), it takes the motor about 23.5 milliseconds to move 1 degree on the X axis. 

The tilt was more of a challenge.  We needed a way of measuring the total range along the Y axis.  To that end, we placed the turret 300 millimeters away from the wall.  We then placed a laser pointer on the turret and put a level on it to ensure that it was a 0 degrees and marked the wall.  We then moved the turret to its highest position and then to its lowest, marking the wall with those points.  We then measured the distance to the highest and lowest point on the wall.

WP_20141010_002WP_20141010_001

 

image

Assuming the wall was vertical, we could then use this site to figure out the angle of the turret.  We first calculated the length of the unknown side using the Pythagorean theorem (3002 + 2352 = X2) =  Sqrt(90000 + 55225) = 381

With all three sides known, we went over to this great site to use some basic trigonometry to help solve the angle problem.  Since we are looking at the angle between adjacent and hypotenuse, we need to determine the  inverse cosine via this formula: cos(θ) = Adjacent / Hypotenuse.  cos(θ) = 300/381 or cos(θ) = .7874 or (θ) = cos-1.7874 or .6642.  This means our rocket launcher can move up about 66 degrees and by doing the same calculation for down, it can move down about -8 degrees.  Since 66+8 equals 74, we decided to round to 75.

We then determined that the total time it takes the rocket launcher to traverse from its max up position to level was 710 milliseconds.  Dividing 66 into 710, each degree takes about 10.7 milliseconds.

So with handy chart in place, we are ready to map the polar coordinates to the Missile Launcher

image

I added the adjustment values to the type

1 let tiltMultiplier = 10.7 2 let panMultiplier = 23.1 3

So now it is a question of keeping track of where the launcher is pointed at and then calling the correct adjustments.  To that end, I created a couple of mutable variables and set them to 90 when the missile launcher initializes

1 let mutable currentPan = 0. 2 let mutable currentTilt = 0. 3

1 member this.Reset() = 2 if devicePresent then 3 this.moveMissleLauncher(this.LEFT,6346) 4 this.moveMissleLauncher(this.RIGHT,3173) 5 this.moveMissleLauncher(this.UP,807) 6 this.moveMissleLauncher(this.DOWN,710) 7 currentPan <- 90. 8 currentTilt <- 90. 9 ()

I then implemented the method for the interface to acquire the target.  Note that I am pretty liberal with with my use of explanatory variables.

1 member this.AquireTarget(X:float, Y:float) = 2 match X = 0.0, Y = 0.0 with 3 | true,true -> false 4 | true,false -> false 5 | false,true -> false 6 | false, false -> 7 let tilt = X 8 let pan = Y 9 10 let tiltChange = currentTilt - tilt 11 let panChange = currentPan - pan 12 13 let tiltChange' = int tiltChange 14 let panChange' = int panChange 15 16 let tiltChange'' = abs(tiltChange) 17 let panChange'' = abs(panChange) 18 19 match tiltChange' with 20 | tiltChange' when tiltChange' > 0 -> this.Down(tiltChange''); currentTilt <- tilt 21 | tiltChange' when tiltChange' < 0 -> this.Up(tiltChange''); currentTilt <- tilt 22 | tiltChange' when tiltChange' = 0 -> () 23 | _ -> () 24 25 match panChange' with 26 | panChange' when panChange' > 0 -> this.Left(panChange''); currentPan <- pan 27 | panChange' when panChange' < 0 -> this.Right(panChange''); currentPan <- pan 28 | panChange' when panChange' = 0 -> () 29 | _ -> () 30 true 31

And with that, we have another weapons system we can add to our kinect Terminiator

Follow

Get every new post delivered to your Inbox.