Tuesday, October 7, 2008

Friday, September 19, 2008

Code Review Vol. 7 - Automated JS Loading, Reformatting and Injecting with ActionScript 3.0

Based on my previous post I then abstracted a bit further. Instead of having the JavaScript embedded directly in the ActionScript I read it in, reformat it to fit my needs and then inject it into the page. I use the same instance for all file loadings so I don't store any of the values in class properties and I make my own asynchronous token pattern since it's pure AS3 and not Flex. I'll do a full walk through at a later date.


public class JSInjector extends EventDispatcher
{
public function JSInjector()
{}


public function loadExternalJS(url:String):void
{
readFile(url);
}


public function readFile(url:String):void
{
var ldr:ASyncTokenURLLoader = new ASyncTokenURLLoader()
ldr.ASyncToken = url
ldr.addEventListener(Event.COMPLETE , loadComplete,false,0,true);
ldr.addEventListener(IOErrorEvent.IO_ERROR, jsloadError,false,0,true);

var urlReq:URLRequest = new URLRequest(url);
ldr.load(urlReq)
}

private function loadComplete(event:Event):void
{
var e:AsynTokenEvent = new AsynTokenEvent(AsynTokenEvent.ASYNC_LOADED)
e.token = event.target.ASyncToken
dispatchEvent(e);
formatJS(event.target.data)
}

private function jsloadError(e:IOErrorEvent):void
{

}

private function formatJS(js:String):void
{
js = formatFunctionDefinitions(js);
js = formatGlobalVarDefinition(js)
js = js.split("var ").join(" ")
injectJS(js)
}

private function formatGlobalVarDefinition(js:String):String
{
var gvarSCPattern:RegExp =/var\s\w+\s?[^=](?=;\r|\n)/gixm
js = js.replace(gvarSCPattern, '$& = ""')
return js
}

private function formatFunctionDefinitions(js:String):String
{

var functionPattern:RegExp =/function[\s?](\w+)/gim
var newFunctionSource:String = js.replace(functionPattern, "$1 = function")
return newFunctionSource
}

private function injectJS(js:String):void
{
var externalJS:String = "function(){ "+js+" }";

try{
ExternalInterface.call(externalJS);
}catch(e:Error){

}
}

Monday, September 8, 2008

Code Review Vol. 6 - Injecting JavaScript from ActionScript

A project that I have been working on at my new company - which I will post about soon, I've just been waiting to take pictures so I can document how incredible the facilities are - is an ActionScript video player that allows us to play videos from multiple sources, including videos from vendors who require us to load in their player for the actual video playback. The external players, of course, require JavaScript to interact with them. In order to make my player self contained I needed a way to source the JavaScript directly from the ActionScript - this player is to used in a multitude of applications and projects company-wide and I couldn't guarantee that each project would have these necessary .js files.

I found this excellent article by Peter McBride - JavaScript and VBScript Injection in ActionScript 3

I based my solution off of the methodology in the article and it worked beautifully.

I created several AS classes, each with static public functions that could be invoked to load their respective JS into memory. Like the article describes, anonymous functions assigned to variables.


import flash.external.ExternalInterface;

public class JSONInjector
{
public function JSONInjector()
{
}

static public function registerPlayer():void
{
var js:XML = <script>
<![CDATA[
function()
{
JSPLAYER = new Object()
JSPLAYER.obs = {}; // Observers
JSPLAYER.addListener = function( eventType, callbackObj, callbackFunc){ .. }


Rsize = function(divID, height, width)
{
var element = document.getElementById(divID);
element.style.height = height + "px";
element.style.width = width + "px";
}

OpenNewWindow = function(URLtoOpen, windowName, windowFeatures)
{
var newWindow=window.open(URLtoOpen, windowName, windowFeatures);
}

...
}
]]>
</script>
try{
ExternalInterface.call(js);
}catch(e:Error){}

}



Then within the init of the main application I simply called the functions:


JSONInjector.registerContainer()
JSONInjector.registerPlayer()


And within my external interface files, I simply called the JS objects through external interface:


ExternalInterface.call("JSPLAYER.pause",true)


It's as simple as that, and now the need for any peripheral .js files has been negated and we have a self-contained solution for all video playback.

Wednesday, September 3, 2008

New lesson plans

Over the long weekend, in between visiting my grandparents and hitting the shore, I wrote a few new lesson plans. One of the classes I'm teaching this semester is the Scripting Languages class that I re-worked. Previously the class was a VBA class, but I determined that VBA was out of place with the rest of the curriculum. I re-wrote it to cover PHP and .Net. But lately I'd been feeling unsatisfied by the class. It seemed that there really wasn't enough time in one semester to really get as far into each topic as I would like; including both only really allowed a brief primer of each, but I wanted more. So last year I changed it up and concentrated on PHP and it's interaction with MySQL. The results of that were good - except it became almost indistinguishable from my Database Management and Scripting class - which is in PHP and MySQL.

So this year I was determined to give the class an identity of its own while continuing to focus on PHP. This past weekend I got around to it. I wrote up one lesson plan purely as a primer to web services, what they are, how they are used, with examples to several real world ones - specifically last.fm and amazon's. I then concentrate one week going over SOAP and PHP and then finally another week on REST and PHP. I need to create some labs around those topics, and then a multi-week assignment and that will take up the last quarter of the semester.

I'm pretty happy with the results. The next thing I want to do is add some more JavaScript lessons to my HTML/JavaScript class. The class was originally written assuming no prior experience with either technology, but the past few years I've seen the students are all at least comfortable with HTML, so I feel that I can de-emphasize that part and maybe write some more advance topics in JavaScript. I'd love to cover some JSON or Dojo. Hopefully I can work that in this semester as well.

Wednesday, August 27, 2008

Code Review Vol. 5 - DRM Profile Generator in VB.Net

Here is a follow up to the Windows Media Encoder and DRM script I posted previously. I mentioned in the article that I had to export a DRM profile from the DRM server, but I never really elaborated on that. Here is the script that I wrote that I ran on the server which generated the DRM profile.


Imports WMEncoderLib
Imports WMRMOBJSLib
Imports System.IO
Imports System.Xml

Public Class Generate
Shared Sub Main()
Dim profValue
CreateProfile()
End Sub

Shared Sub CreateProfile()
' Create a WMEncoder object.
Dim Encoder As WMEncoder
Encoder = New WMEncoder

' Create an IWMDRMContentAuthor object.
Dim DRM As IWMDRMContentAuthor
DRM = Encoder.EncoderDRMContentAuthor

' Retrieve the collection of DRM profiles.
Dim DRMProColl As IWMDRMProfileCollection
Dim KeyObj = New WMRMKeys


DRMProColl = DRM.DRMProfileCollection

' Declare variables. Specify the provider's Web site, and certificate and
' signing values. The other variables are returned.
Dim sPublicKey As String
Dim sWebURL As String
Dim vProfileID As Object
Dim vSeed As Object
Dim sPrivateKey As String
Dim sSignedPublicKey As String
Dim sSigLSCert As String
Dim sSigRootCert As String
Dim sProfilePublicKey As String

Dim sContentID As String

sContentID = KeyObj.GenerateKeyID()

KeyObj.GenerateSigningKeysEx(sPrivateKey, sPublicKey, sSignedPublicKey)

sWebURL = "http://license3.musicchoice.com/XXXX.asp"

sSigLSCert = KeyObj.GetCertificate("LSLicenseSigningCert")
sSigRootCert = KeyObj.GetCertificate("LSRootCert")

' Create the DRM profile. The public key, DRM profile ID, and
' license key seed are returned.
sProfilePublicKey = DRM.CreateDRMProfile(sWebURL, sPrivateKey, sSignedPublicKey, sSigLSCert, sSigRootCert, vProfileID, vSeed)

' Create an IWMDRMProfile object and retrieve a profile.
Dim DRMPro As IWMDRMProfile
DRMPro = DRM.GetDRMProfile(vProfileID)

' Set the rest of the properties for the DRM profile.
DRMPro.Description = "DRM for MC portable content"
DRMPro.LicenseAcquisitionURL = "http://license3.musicchoice.com/XXXX.asp"
DRMPro.Name = "MC Portable DRM"
DRMPro.V1LicenseAcquisitionURL = "http://go.microsoft.com/fwlink/?LinkId=10141"

' Add the required individualization version as an attribute.
Dim ProAttr As IWMDRMAttributes
ProAttr = DRMPro.Attributes
ProAttr.Add("SECURITYVERSION", "2.2")

ProAttr.Add("ContentID", sContentID)

Dim sDetails As String

Dim oXMLWriter As New XmlTextWriter("C:\Inetpub\wwwroot\wm\IssuedDetails.xml", System.Text.Encoding.UTF8)

oXMLWriter.WriteStartElement("Details")
oXMLWriter.WriteStartElement("Detail")

oXMLWriter.WriteAttributeString("ContentID", sContentID)
oXMLWriter.WriteAttributeString("Seed", vSeed)
oXMLWriter.WriteAttributeString("Key", sProfilePublicKey)
oXMLWriter.WriteAttributeString("PrivateKey", sPrivateKey)


oXMLWriter.WriteEndElement()
oXMLWriter.WriteEndElement()

oXMLWriter.Close()

DRMPro.Update()

DRM.ExportDRMProfile(DRMPro.ID, "password", "C:\Inetpub\wwwroot\wm\ExportProfile.drm")

End Sub

Shared Sub SaveInfo(ByVal nSeed As String, ByVal nPath As String)
Dim objStreamWriter As StreamWriter
objStreamWriter = New StreamWriter(nPath)
objStreamWriter.WriteLine(nSeed)
objStreamWriter.Close()


End Sub

End Class

Saturday, August 23, 2008

Code Review Vol. 4 - Perl Recursive Directory Stepper

Here is a recursive directory browser I wrote in Perl. I later decorated it a bit and used it for a project back at Toll Brothers. The goal was to create a shared directory for the IT Training department, where trainers for each department could store their respective white papers without the admin for IT Training having to manage those documents.

So this script simply reads the contents of the shared directory and recursively steps through all folders inside and lists out all documents.


#!/usr/bin/perl

use DBI;
use CGI;


my $q = new CGI;
my $logFile = "exceptions.txt";
my $showDir= "/EASYT/TRAINING/manuals";
print $q->header( "text/html" );
peruseDir($showDir, '0');

exit(0);

sub peruseDir{
#create local copy of parameters
#second parameter of which is an indirect file handle
#so we can keep making recursive calls to peruseDir
#increment the indirect fhandle as we go so that we
#arent stuck on the same file through each iteration
local($currDir, $input) = @_;
$input++;
if($currDir !~ m/.*\..*/){
opendir($input, $currDir) || die print "Can't open $currDir $!
\n\n";
my @tempArr = grep { $_ ne '.' and $_ ne '..' } readdir($input);
foreach $myDir(@tempArr){
if(-d $currDir."/".$myDir){
#if its a directory make another recursive step
print "$input $myDir
";
peruseDir($currDir."/".$myDir, $input);
}else{
#otherwise its a file, show file
my $linkDir = $currDir;
$linkDir =~ s/\/EASYT\/TRAINING\///;
print "$myDir
";
}
}
closedir($input);
}
}


sub logExceptions{
open(LOG, ">> $logFile") || die print "Couldn't write to log $!";
foreach $exception(@_){
print LOG "$exception\n";
}
close(LOG);
}

Friday, August 22, 2008

Code Review Vol. 3.01 - WMEncode and DRM Walkthrough


Imports WMEncoderLib
Imports System.Windows.Forms
Imports System.IO


Module Module1
Dim WithEvents Encoder As WMEncoder
Dim glbQuitBool As Boolean = False
Dim baseURL As String
Dim DRMProfilePass As String = "XXX"
Dim DRMProfile As String = "ExportProfile.drm"


Sub Main()
Init()
SearchDir(baseURL)
End Sub

Sub Init()
Dim sr As StreamReader = New StreamReader("baseLoc.ini")
Dim line As String
line = sr.ReadLine()
sr.Close()
baseURL = line
End Sub

Function DoEncode(ByVal sourceFile As String, ByVal outputFile As String, ByVal thisProfile As WMEncProfile2, ByVal fileType As String) As Boolean
Try
Encoder = New WMEncoder
Dim SrcGrpColl As IWMEncSourceGroupCollection = Encoder.SourceGroupCollection
Dim SrcGrp As IWMEncSourceGroup = SrcGrpColl.Add("SG_1")
Dim newFile As IWMEncFile = Encoder.File

If fileType = "video" Then
Dim vidFile As IWMEncVideoSource = SrcGrp.AddSource(2)
vidFile.SetInput(sourceFile)
End If


Dim audFile As IWMEncAudioSource = SrcGrp.AddSource(1)



Up until this point it's fairly standard WMEncoder SDK code - create a sourcegroup collection, create a sourcegroup, and add a video or audio source to the source group - but here we introduce the DRM element. It follows the same template



Dim DRM As IWMDRMContentAuthor
Dim DRMProColl As IWMDRMProfileCollection
Dim tempDRMPro As IWMDRMProfile

DRM = Encoder.EncoderDRMContentAuthor

' Retrieve the collection of DRM profiles.
DRMProColl = DRM.DRMProfileCollection

'First remove any DRM Profiles that may still linger
tempDRMPro = DRMProColl.Item(0)
DRM.RemoveDRMProfile(tempDRMPro.ID)

' Import a DRM profile.
DRM.ImportDRMProfile(DRMProfilePass, DRMProfile)

DRMProColl = DRM.DRMProfileCollection
Dim DRMPro As IWMDRMProfile
DRMPro = DRMProColl.Item(0)



Essentially the DRM set up follows the same format as the Encoder, create a ProfileCollection, create a profile object which references the literal .drm profile file that I had exported from the DRM server. A DRMContentAuthor is pulled from the base WMEncoder object and everything is imported into that.



' Set the current DRM profile into the encoding session.
Dim vKeyID As Object = "XXXXX
DRM.SetSessionDRMProfile(DRMPro.ID, vKeyID)

Dim newProfile As WMEncProfile2 = New WMEncProfile2
audFile.SetInput(sourceFile)
newFile.LocalFileName = outputFile
newProfile = thisProfile

' newProfile.LoadFromFile(thisProfile)
SrcGrp.Profile = newProfile
Encoder.AutoStop = True
Encoder.RemoteAdmin = True
Encoder.PrepareToEncode(True)
Encoder.Start()

Dim x As Integer



For the longest time the code didn't work. Until I found out that I needed to put a slight wait before encoding. And even while its encoding down below inside the while loop it still needs a pause between each iteration to register events and change states when necessary.



'HACK - needs this to actually work, bug in WM SDK
For x = 0 To 30
Application.DoEvents()
x = x + 1
Next


While Encoder.RunState = WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING
Dim temp = Encoder.RunState
Dim y As Integer
For y = 0 To 300
y = y + 1
Next
Application.DoEvents()
End While

Encoder.Stop()
Return True

Catch ex As Exception
Console.WriteLine(ex)
Dim errFile As String = outputFile + ".error"
File.Create(errFile)
File.Delete(outputFile)
Return False
End Try

Encoder = Nothing

End Function



Here I grab the .drm file from the filesystem and load it into the WMEncProfile2 object.



Function RetrieveProfile(ByVal nFile) As WMEncProfile2
Try
Dim BasicEdit As WMEncBasicEdit
BasicEdit = New WMEncBasicEdit

' Specify the input, output, and configuration files.
BasicEdit.MediaFile = nFile

' Retrieve the duration of the input file, in seconds.
Dim lFileDur As Long
lFileDur = BasicEdit.Duration / 1000

' Retrieve the profile used by the input file.
Dim Pro As WMEncProfile2
Pro = BasicEdit.Profile

Return Pro
Catch ex As Exception
Console.WriteLine(ex)
End Try


End Function




And here is the engine - I essentially read the directory that was set aside as the publishing directory, where all raw files to be encoded and distributed were deposited, and encode and drm them.



Sub SearchDir(ByVal dir)
'Environment.CurrentDirectory
Dim di As New DirectoryInfo(dir)
' Create an array representing the files in the current directory.
Dim fi As FileInfo() = di.GetFiles()
Dim tempFile As FileInfo
For Each tempFile In fi
Dim currentProfile As WMEncProfile2
Dim currentSourceFile As String = baseURL + "\" + tempFile.Name
Dim currentOutputFile As String = baseURL + "\DRMed\" + tempFile.Name
Dim currentFType As String
Dim currentFTypeArr = Split(tempFile.Name, ".")
If currentFTypeArr(1) = "wma" Then
currentFType = "audio"
ElseIf currentFTypeArr(1) = "wmv" Then
currentFType = "video"
End If

currentProfile = RetrieveProfile(currentSourceFile)
DoEncode(currentSourceFile, currentOutputFile, currentProfile, currentFType)
Next tempFile

End Sub


End Module


And that's it. Pretty straightforward, but by automating the encoding process and combining it with the DRMing process I was anble to integrate that into the automated workflow that I was building as the infrastructure to the overall Music Choice broadband product.

Wednesday, August 20, 2008

Code Review Vol. 3 - Encode and DRM Audio and Video Content With Windows Media Encoder SDK and VB.Net

Here is a snippet of code I wrote several years ago to encode and DRM content to WMV format. Back when I worked at Music Choice one of my initial tasks was to come up with a DRM solution for all videos on the web. My initial solution was clunky, basically following Microsoft's sample code - what little there actually was for the subject. But over time I revisited the solution and came up with a more elegant solution. Essentially I encapsulated the transcoding and DRMing of raw content to WMVs to a single console application. I exported a DRM profile from our DRM servers and used that to generate the DRM envelope. The console application was included in the automated work flow when new content was distributed to our clients.


Imports WMEncoderLib
Imports System.Windows.Forms
Imports System.IO


Module Module1
Dim WithEvents Encoder As WMEncoder
Dim glbQuitBool As Boolean = False
Dim baseURL As String
Dim DRMProfilePass As String = "XXX"
Dim DRMProfile As String = "ExportProfile.drm"


Sub Main()
Init()
SearchDir(baseURL)
End Sub

Sub Init()
Dim sr As StreamReader = New StreamReader("baseLoc.ini")
Dim line As String
line = sr.ReadLine()
sr.Close()
baseURL = line
End Sub

Function DoEncode(ByVal sourceFile As String, ByVal outputFile As String, ByVal thisProfile As WMEncProfile2, ByVal fileType As String) As Boolean
Try
Encoder = New WMEncoder
Dim SrcGrpColl As IWMEncSourceGroupCollection = Encoder.SourceGroupCollection
Dim SrcGrp As IWMEncSourceGroup = SrcGrpColl.Add("SG_1")
Dim newFile As IWMEncFile = Encoder.File

If fileType = "video" Then
Dim vidFile As IWMEncVideoSource = SrcGrp.AddSource(2)
vidFile.SetInput(sourceFile)
End If


Dim audFile As IWMEncAudioSource = SrcGrp.AddSource(1)

Dim DRM As IWMDRMContentAuthor
Dim DRMProColl As IWMDRMProfileCollection
Dim tempDRMPro As IWMDRMProfile

DRM = Encoder.EncoderDRMContentAuthor

' Retrieve the collection of DRM profiles.
DRMProColl = DRM.DRMProfileCollection

'First remove any DRM Profiles that may still linger
tempDRMPro = DRMProColl.Item(0)
DRM.RemoveDRMProfile(tempDRMPro.ID)

' Import a DRM profile.
DRM.ImportDRMProfile(DRMProfilePass, DRMProfile)

DRMProColl = DRM.DRMProfileCollection
Dim DRMPro As IWMDRMProfile
DRMPro = DRMProColl.Item(0)

' Set the current DRM profile into the encoding session.
Dim vKeyID As Object = "XXXXX"
DRM.SetSessionDRMProfile(DRMPro.ID, vKeyID)

Dim newProfile As WMEncProfile2 = New WMEncProfile2
audFile.SetInput(sourceFile)
newFile.LocalFileName = outputFile
newProfile = thisProfile

' newProfile.LoadFromFile(thisProfile)
SrcGrp.Profile = newProfile
Encoder.AutoStop = True
Encoder.RemoteAdmin = True
Encoder.PrepareToEncode(True)
Encoder.Start()

Dim x As Integer

'HACK - needs this to actually work, bug in WM SDK
For x = 0 To 30
Application.DoEvents()
x = x + 1
Next


While Encoder.RunState = WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING
Dim temp = Encoder.RunState
Dim y As Integer
For y = 0 To 300
y = y + 1
Next
Application.DoEvents()
End While

Encoder.Stop()
Return True

Catch ex As Exception
Console.WriteLine(ex)
Dim errFile As String = outputFile + ".error"
File.Create(errFile)
File.Delete(outputFile)
Return False
End Try

Encoder = Nothing

End Function



Function RetrieveProfile(ByVal nFile) As WMEncProfile2
Try
Dim BasicEdit As WMEncBasicEdit
BasicEdit = New WMEncBasicEdit

' Specify the input, output, and configuration files.
BasicEdit.MediaFile = nFile

' Retrieve the duration of the input file, in seconds.
Dim lFileDur As Long
lFileDur = BasicEdit.Duration / 1000

' Retrieve the profile used by the input file.
Dim Pro As WMEncProfile2
Pro = BasicEdit.Profile

Return Pro
Catch ex As Exception
Console.WriteLine(ex)
End Try


End Function

Sub SearchDir(ByVal dir)
'Environment.CurrentDirectory
Dim di As New DirectoryInfo(dir)
' Create an array representing the files in the current directory.
Dim fi As FileInfo() = di.GetFiles()
Dim tempFile As FileInfo
For Each tempFile In fi
Dim currentProfile As WMEncProfile2
Dim currentSourceFile As String = baseURL + "\" + tempFile.Name
Dim currentOutputFile As String = baseURL + "\DRMed\" + tempFile.Name
Dim currentFType As String
Dim currentFTypeArr = Split(tempFile.Name, ".")
If currentFTypeArr(1) = "wma" Then
currentFType = "audio"
ElseIf currentFTypeArr(1) = "wmv" Then
currentFType = "video"
End If

currentProfile = RetrieveProfile(currentSourceFile)
DoEncode(currentSourceFile, currentOutputFile, currentProfile, currentFType)
Next tempFile

End Sub


End Module

Tuesday, August 12, 2008

Code Review Vol. 1.01 - Calendar Class Walkthrough


import flash.display.*;
import net.com.calendar.Day;

public class AbstractCalendar extends Sprite
{
private static var _dayIDSequence:Number = 0;

private var _dayHeight:Number = 50;
private var _dayWidth:Number = 50;
private var _startX:Number = 10;
private var _startY:Number = 10;

private const WEEKDAYCOUNT:Number = 7;

private var _bgColor:uint = 0xCCCCCC;
private var _borderColor:uint = 0x666666;
private var _borderSize:uint = 1;

public function AbstractCalendar(month:Number)
{}



CreateDay instantiates a Day object and sets all of its properties. Date is the date object for the specific day, Name is used to getChildByName and Display is the string value to be stored in the textfield in the Day. OriginalStackIndex is exactly what it sounds like, the original index in the display list that the object was first created. I get this at runtime by pulling from a sequence of my own creation - I'm enamored with the Oracle concept of sequences. It really isn't used in this example, its a remnant from my actual implementation where I change the child index when a user clicks on a day.



private function createDay(today:Date,name:String, display:String, dayNum:Number):Day
{
var tempDay:Day = new Day()
tempDay.name = getNewDayID();
tempDay.setDate(today)
tempDay.setName(name);
tempDay.setDisplay(display);
tempDay.setDayNumber(dayNum)
tempDay.drawDay(_bgColor, _borderSize,_borderColor, _dayWidth, _dayHeight);
tempDay.originalStackIndex = Number(tempDay.name)
return tempDay
}



getNewDayID is my version of the Oracle sequence. It gives unique ids for the objects and tells me their stack index


private function getNewDayID():String
{
return (_dayIDSequence++).toString();
}



DrawMonth is the engine for this implementation. Essentially you pass in a number for the month you want to render. With that month number I create a date object for the first day of the month. I assume its the current year, change at your own discretion. Once I have the date object for the first day I just keep iterating and incrementing the date object one day at a time. I check several things - if its the first day of the month and the day of the week isn't Sunday I back fill for however many days away from Sunday the actual day is. I check to make sure we are still on the month we're supposed to be rendering, if we aren't, then I find out what day it is and front-fill the current week with as many days as we are away from Saturday. If we are still in the month then I keep drawing days. I check if the current day is Sunday, if it is I reset the x coordinate back to 0 to start a new week. I also check if the current dayStepper - which is just an incrementor to keep track of how many times we've looped through, to account for the back and front-filling we've been doing - gives a remainder when divided by 7 (the number of days in a week) if it doesn't I know a full week has been rendered and I need to increment the y coordinate by the height of the day to start a new line.



public function drawMonth(tempMonth:Number,tempDay:Day, backDay:Day):void{
var currentDay:Number = 1
var dayStepper:Number = 0
var tempDate:Date = new Date(tempMonth + "/"+currentDay+"/" + new Date().getFullYear());
var tempMonthChecker:Number = tempDate.getMonth()
//check for current month to step through each day in the month
while(tempDate.getMonth() + 1 == tempMonth){

tempDate = new Date(tempMonth + "/"+currentDay+"/" + new Date().getFullYear());
tempMonthChecker = tempDate.getMonth()

// check for day num, at each zero
// reset startX back to 0
if(tempDate.getDay() == 0){ _startX = 10}

//figure out the day number for the first day only
if(tempDate.getDay() > 0 && currentDay == 1 )
{
for(var x:Number = 0;x < tempDate.getDay(); x++)
{
//backfill previous days
backDay = createDay(tempDate,"","",x)
backDay.x = _startX
backDay.y = _startY
_startX += _dayWidth
addChild(backDay);
dayStepper++
}
}

if(tempDate.getMonth() + 1 == tempMonth){
tempDay = createDay(tempDate, "",currentDay.toString(),tempDate.getDay())
tempDay.x = _startX
tempDay.y = _startY
_startX += _dayWidth
addChild(tempDay);
dayStepper++

// increment startY by the _dayHeight
if(dayStepper % WEEKDAYCOUNT == 0){_startY += _dayHeight}

currentDay++
}else{
for(var y:Number = tempDate.getDay(); y < WEEKDAYCOUNT;y++)
{
//front fill the next months days
backDay = createDay(tempDate,"","",x)
backDay.x = _startX
backDay.y = _startY
_startX += _dayWidth
addChild(backDay);
}
}
}
}
}


And that's it. When taken apart and examined the logic is fairly straightforward. Yet it's extensible and powerful. You can extend the Day class to do almost anything and encompass any kind of custom logic. You can change the basic engine to draw a single day or draw a week or a set window of weeks.

Friday, August 8, 2008

man me pt. 5

After Toll I went to a small software firm right outside of Philadelphia. What I found there was a small team of really talented people who had formed this great bond and work dynamic, seemingly in-spite of an oppressively micromanaging and confused management team. The management team was comprised of three investors who each had a say and a stake, yet none of which had any understanding of software or how to make it. It was confusing because their dynamic would change at seemingly random times, one taking the lead from the other and roles being changed and priorities following suit. Meetings frequently became discussions of the same topic over and over again, each time with different results.

This tumultuous environment had served to strengthen the team's internal dynamic. Everyone was fiercely loyal to the team. This actually back-fired on the management team towards the end of my tenure there, as work from home had been taken away company-wide - a mandate intended to strengthen communication and team unity when one of the partners asserted controlf from another - almost everyone in the company began to leave. But not just random job searches, they each communicated with each other, with several members going to the same company. By the time I left there was no one left from the original team when I had started.

My responsibilities there were:

First to serve as Lead. At first I was lead for several products but as time went on I assumed lead of all technology at the company. By the end of my time there I was in a Director position setting the technology strategy company-wide and leading a department of developers and interns that I had personally hired.

Second, to serve as Architect and Sr Engineer. I architected solutions to migrate the company's two legacy products to a Service Oriented Architecture, using .Net web services and Flex front-end. I architected a blue-print for the company to create mobile pieces to plug into their newly forming enterprise. I also created a plan to create build servers where database topography and pre-built templates would be used to generate code and build new instances of products for client installs.

When I left, the development department was rebuilt and energized with a good technology road map to lead them well into the next two years.

Wednesday, August 6, 2008

man me pt. 4

I was originally hired by Toll Brothers to maintain and update an internal legacy application for the Land Development department. But after a couple weeks I found that task would realistically only take a fraction of my potential bandwidth. So I turned my attention to the state of the company's application infrastructure. I saw a young IT department still finding it's legs in a mature company. I saw many different departments having different applications, some .Net apps, some Java apps, a Perl app, some apps using Oracle, some SQL Server and one using MySQL. No shared class libraries and minimal if any code re-use. This heterogeneous environment was a result of different departments within the company acting independently of IT, hiring outside contractors and even in-house developers working exclusively for their department, to build their applications for their immediate needs, not concerned with adhering to or establishing standards.

Seeing this, I began a series of weekly meetings with the leads of the different applications to try and find points of commonality. With the sheer volume and scope of applications it would be unrealistic to re-write the applications under one technology - instead I proposed that we move the business logic that the apps had in common to a central repository: a series of web services that would use abstract base classes and interfaces to allow departments to inherit and implement their own specialized classes while data that any other application on the enterprise could access and have a hook into. After all, Toll's main business model was project based - projects being tracts of land and each department had their own view on the tract of land. Land Purchasing focused on buying the land, Land Development focused on what to do with the land (twenty estates homes or seventy townhomes?), Sales focused on selling the homes built on the land. Land was even kept as an asset for potential liquidity. So projects were the biggest point of commonality, even if departments had access to different views of a project, at least they would still be talking about the same project and any changes to that project would be reflected real-time in every other app in the enterprise.

Having the business logic be available via web services then opened up the possibility of expanding the services that were offered to clients (from a Toll IT perspective clients were other internal departments). Specifically creating mobile applications, or mobile extensions to existing applications, that would consume the web services and feed data back to the enterprise for real time exception reporting.

Once we had decided on a company-wide standard for mobile phones, ie what specific phone, OS and carrier we would use, I started to create the base skeletal functionality. More r&d and proof of concept than actual business implementation, I fleshed out routines for authenticating the web services with the Novell servers and the core store and forward patterns that all new apps would use for offline use.

When the first mobile project was then approved I served as the technical lead for an off-shore team of developers who fleshed out the business logic on top of the skeletal structure I provided.

Toll was both a really good and very interesting experience for me.  It was the first large company I worked for, the first publicly traded company.  My first exposure to SOX compliance, the first time I was in-house in such a heterogenous environment.   Had the housing market not taken a dump when it did, making staying at Toll a volatile prospect, I would probably still be there to this day.  

I made a lot of friends while I was at Toll, some of which have become very good friends that I still see to this day.  One of which then brought me on to my next company with him.

Code Review Vol. 2 - Day Class, used with Calendar in ActionScript 3.0

For the sake of completion, and because I'm too exhausted from teaching late last night and getting up at 5:30 this morning to really walk through yesterday's code review, here is the source for the Day class. Again, I pared it down from its actual implementation, took out the tweens, events and filters, as well as the custom business logic and the interface that it implements. The idea of the calendar is to be a collection of Day objects, and depending on the aim of the calendar, the Day objects can be extended to do almost anything. I've made derived classes from this base class that tweened open when clicked on. Others that pull data from REST services.



import flash.display.Sprite;
import flash.text.TextField;

public class Day extends Sprite
{
private var _name:String;
private var _myDate:Date;
private var _dayNumber:Number;
private var _display:TextField

public function Day(h:Number, w:Number)
{
super();
_display = new TextField()
_display.height=h
_display.width=w
addChild(_display)
}

public function drawDay(bgColor:uint, borderSize:uint,
borderColor:uint, dayWidth:Number,
dayHeight:Number):void
{
graphics.beginFill(bgColor);
graphics.lineStyle(borderSize, borderColor,50);
graphics.drawRect(0, 0, dayWidth, dayHeight);
graphics.endFill();
}



public function getName():String
{
return _name;
}

public function getDayNumber():Number
{
return _dayNumber;
}

public function getDate():Date
{
return _myDate;
}

public function setDayNumber(dnum:Number):void
{
_dayNumber = dnum;
}

public function setName(name:String):void
{
_name = name
}

public function setDate(date:Date):void
{
_myDate = date
}


public function setDisplay(txt:String):void
{
_display.text = txt;
}


}
}

Tuesday, August 5, 2008

Code Review Vol. 1 - Calendar Class in ActionScript 3.0


I'd like to do switch gears for a moment and focus on some code. I'll name these sections, for lack of a better term, Code Review and I'll number them in volumes for ease of reference. The template that I'll follow will be as follows: whole numbers are the full source code, dot releases will be a walk through of the code. So for example this is Code Review Vol. 1 and I will follow up this post with a code walk through that I will title Code Review Vol. 1.01

Here's something interesting that I made recently in ActionScript 3.0. It's a calendar that uses the system date as the data source, the Model, and assembles a collection of Days in correct order, back filling and front-filling empty days. In the final implementation of this I have it being interfaced with a Controller that tells it to switch from month, week, or day View and passes it the month or date to render. For the below code I only show the month renderer, because the week renderer is just a subset of the month anyway.

I won't post the full implementation, because it has tween effects, events, and business logic that, if included, would only serve to obfuscate the actual intention of the code review. Also I de-normalized, if you will, re-coupled a bit for readability and succinctness. In total, I pared down a 300 line abstract class to an actual class that is less than 100 lines. Also I reference a Day class which I'm not including right now, but for the purposes of this example it can be thought of as a class that just extends the Sprite class, draws a rectangle and adds a TextField control to itself when it's drawn.


import flash.display.*;
import net.com.calendar.Day;

public class AbstractCalendar extends Sprite
{
private static var _dayIDSequence:Number = 0;

private var _dayHeight:Number = 50;
private var _dayWidth:Number = 50;
private var _startX:Number = 10;
private var _startY:Number = 10;

private const WEEKDAYCOUNT:Number = 7;

private var _bgColor:uint = 0xCCCCCC;
private var _borderColor:uint = 0x666666;
private var _borderSize:uint = 1;

public function AbstractCalendar(month:Number)
{}

private function createDay(today:Date,name:String, display:String, dayNum:Number):Day
{
var tempDay:Day = new Day()
tempDay.name = getNewDayID();
tempDay.setDate(today)
tempDay.setName(name);
tempDay.setDisplay(display);
tempDay.setDayNumber(dayNum)
tempDay.drawDay(_bgColor, _borderSize,_borderColor, _dayWidth, _dayHeight);
tempDay.originalStackIndex = Number(tempDay.name)
return tempDay
}

private function getNewDayID():String
{
return (_dayIDSequence++).toString();
}

public function drawMonth(tempMonth:Number,tempDay:Day, backDay:Day):void{
var currentDay:Number = 1
var dayStepper:Number = 0
var tempDate:Date = new Date(tempMonth + "/"+currentDay+"/" + new Date().getFullYear());
var tempMonthChecker:Number = tempDate.getMonth()
//check for current month to step through each day in the month
while(tempDate.getMonth() + 1 == tempMonth){

tempDate = new Date(tempMonth + "/"+currentDay+"/" + new Date().getFullYear());
tempMonthChecker = tempDate.getMonth()

// check for day num, at each zero
// reset startX back to 0
if(tempDate.getDay() == 0){ _startX = 10}

//figure out the day number for the first day only
if(tempDate.getDay() > 0 && currentDay == 1 )
{
for(var x:Number = 0;x < tempDate.getDay(); x++)
{
//backfill previous days
backDay = createDay(tempDate,"","",x)
backDay.x = _startX
backDay.y = _startY
_startX += _dayWidth
addChild(backDay);
dayStepper++
}
}

if(tempDate.getMonth() + 1 == tempMonth){
tempDay = createDay(tempDate, "",currentDay.toString(),tempDate.getDay())
tempDay.x = _startX
tempDay.y = _startY
_startX += _dayWidth
addChild(tempDay);
dayStepper++

// increment startY by the _dayHeight
if(dayStepper % WEEKDAYCOUNT == 0){_startY += _dayHeight}

currentDay++
}else{
for(var y:Number = tempDate.getDay(); y < WEEKDAYCOUNT;y++)
{
//front fill the next months days
backDay = createDay(tempDate,"","",x)
backDay.x = _startX
backDay.y = _startY
_startX += _dayWidth
addChild(backDay);
}
}
}
}
}

Monday, August 4, 2008

man me pt. 3

Before I get in to my time at Toll Brothers, I should take a step back and talk about my other career.  In the summer of 2003 I was approached by the owners of the advertising firm where I worked, one of the photographers that they used had a husband who was a director at Philadelphia University.  He needed someone to fill in for an HTML and JavaScript class for the upcoming semester, and they had recommended me for the position.  I was 25 at the time, had no real public speaking experience, certainly no teaching experience, but I knew that to get anywhere in my field I would need to be able to speak in front of large groups - either in company meetings or speaking arrangements at conferences or what have you.  So I accepted the offer.  And I enjoyed it.  I mean the first day of class I sweated uncontrollably, but each day after that it got easier and easier.

After my first class was over the University asked me to teach another class for the next semester, an ActionScript and Lingo class.  So for a few years I taught those two classes, but in talking with the students and seeing the curriculum I identified several needs and authored a number of classes to fill those needs.  I took the Scripting Languages class and re-worked that, re-writing it to cover .Net and PHP, I authored a Database Management and Scripting course, using PHP and MySQL.  I also authored a Web 2.0 class, which I then re-worked into an ActionScript 3.0/Flex course.  All of my authored classes were worked into the graduate curriculum, and I just piloted my AS3/Flex course this summer.  So for the past couple years now I've been teaching around two classes a semester.

I love teaching.  I mean some days I just want to go home after a long day, but its always worth it.  I've been lucky in that almost all of my students over the past five years have been really into the subject, really interested in learning and worked really hard to get the subject matter.  It's rewarding watching the lightbulb go off when they get something, or watching the slow build up to understanding.  It's also very beneficial for me, as a working professional, to go over these topics that I might not think about too often, it reenforces them and makes my understanding of the subjects that much stronger.  It's also taught me how to mentor and guide, which I was able to take with me to my main career.

Sunday, August 3, 2008

man me pt. 2

Music Choice was for me where my career became interesting. My role there was to architect a product that was to be a mirror of their full proposed television product for the web. This included, the live streaming audio channels, as well as the on-demand music videos and user customization features of creating play lists and run-time generated channels based on genre preferences. It was a living, breathing product the scope of which included not just the customer facing product, but the entire infrastructure: pl/sql stored procs to pull scheduling and meta data from the Oracle db, shell scripts to FTP the data to the web db servers, DTS packages in SQL Server to import the data, WScript to pull the data and export to xml nightly, front-end caching routines to hold the data client-side to ensure that the only trips to the database for an average session were mainly to transmit usage data, console applications using the Windows Media Encoder SDK and Windows Media Rights Management SDK to transcode and DRM videos for distribution, license generating scripts on the DRM server, scripts to distribute the content to the providers, web services to abstract business logic, usage gathering and reporting scripts. And finally once the application was done I had to come up with a mechanism to monitor each step of the piece and report it to a 24/7 operations department.

This was a two and a half year project, where I led a team of four core developers with several other developers cycling on and off for one-off tasks. To this day it's easily my favorite project.

Once the application and infrastructure were complete we began doing R&D, which was really fun. I set up an infrastructure to make use of the web services to feed a mobile component. I created a demo of an iTunes-like application that used the BITS SDK to sync up user playlist information created on the web app with mobile devices they might have connected to their pc.

My time at Music Choice was one of the best experiences in my career. I made many friends there, became a mentor and met my own mentor there. It was the first time I managed a large group of developers as well as external interfaces. It was my first exposure to web services and the power they have. The first time I created a mobile application, and the first time I had R&D time to really go nuts with the technology.

It also gave me a template for migrating enterprise applications to an SOA architecture and expanding product offerings to mobile applications, which I took with me when I moved on to Toll Brothers.

man me

I'm setting this up mainly as a repository for my thoughts and ideas about what I do. If these are helpful to anyone else, that's great. If any feedback is helpful to me at all, even better.

As for what I do, I've been a developer, engineer, architect, and technical lead for the last ten years. I mainly focus on web development, but the past five years or so has seen the web become so ubiquitous that its the back-bone for nearly everything. With the widespread acceptance of SOA the cloud is the delivery mechanism for a huge amount of information sharing, linking intranet to mobile, web app to web app, enterprise to enterprise. My definition of web development encompasses all of these technologies that go over IP and over time I'll be talking about and sharing code snippets for all of them.

For perspective on where I'm coming from and what I've done in the past :

I spent the first five years of my career working for two different advertising and marketing firms in the suburban Philadelphia area. From what I've seen of those types of companies, specifically the design boutiques that have a small development presence for either web apps or interactives, need a certain type of developer. They promote a philosophy of language agnosticism just through the nature of their business. One project could be an interactive for a trade show done in Director (this was ten years ago), another could be a small web site for a new product launch, another could be a banner game done in ActionScript, or even updates or new content for a JSP intranet site. We have a proposal meeting tomorrow to discuss a new project that will be a portal environment to integrate into their install of Lotus Notes - read up enough about it overnight to bullshit your way through the meeting.

That's the positive about those types of environments - you get a huge amount of exposure to a large number of technologies and experience in the full life cycle of a software project. The negative is the breakneck speed that you have to go through projects - since they usually are timelined out working backwards from the client's drop-dead deadline - isn't conducive to good architecture and code-reuse. Not to say that it can't be done, just that the emphasis is on meeting the deadline not on creating interfaces for standardizing interchangeable components.

From there I moved on to a company called Music Choice and moved into my first management role. More to come...