<CharlieDigital/> Programming, Politics, and uhh…pineapples

25Jan/12Off

The Pineapple Finally Fruits!

Posted by Charles Chen

It's finally happened!  My pineapple is finally flowering WOOOOOOOOOOO! :-D I can't even believe it.  I didn't even notice it until I randomly looked over and took note that I probably need to water it.

I started this plant some 3-4 years ago now (after my previous one died due to exposure to the cold) and it's FINALLY bearing a flower (in the middle of frickin' winter no less!).  I am very much looking forward to eating this pineapple :D

23Jan/12Off

Browser MapReduce + Charting

Posted by Charles Chen

Having dabbled in Mongo a bit, I was curious if there was an analog for MapReduce style functionality in browser JavaScript.

I found a small script as a starting point, but made some minor modifications to support array inputs:

// mapper should return an array of [{key:'somekey', value:'somevalue'}]
// reducer should return a single {key:'somekey', value:'somevalue'}
function mapReduce(i, mapper, reducer, property) {
    var intermediate = [];
    var output = [];

    if(i && i.constructor == Array)
    {
        for(var x = 0; x < i.length; x++)
        {
            var value = i[x][property];
            var key = property;

            intermediate = intermediate.concat(mapper(key, value));
        }
    }
    else
    {
        for (var key in i)
        {
            var value = i[key];

            intermediate = intermediate.concat(mapper(key, value));
        }
    }

    var groups = groupBy(intermediate);

    for (var key in groups)
    {
        var values = groups[key];
        output.push(reducer(key, values));
    }

    return output;
}

// list should be [{key:k, value:v}, ....] where key may be repeated.
// returns [{key, [v1, v2, v3...]}, ...] where key is *not* repeated.
function groupBy(list) {
    var ret = {};
    for (var i = 0; i < list.length; i++) {
        var key = list[i].key;
        var value = list[i].value;
        if (!ret[key]) {
            ret[key] = [];
        }

        ret[key].push(value);
    }
    return ret;
}

I then  plugged in my custom map/reduce functions:

// Random data set -- could come from anywhere.
var data = [
    {Country: "US", Type:"B", ProductCode: "001"},
    {Country: "US", Type:"B",  ProductCode: "001.A"},
    {Country: "US", Type:"Z",  ProductCode: "001.B"},
    {Country: "UK", Type:"A",  ProductCode: "002"},
    {Country: "US", Type:"Z",  ProductCode: "003"},
    {Country: "FR", Type:"B",  ProductCode: "003.A"},
    {Country: "DE", Type:"B",  ProductCode: "003.C"},
    {Country: "DE", Type:"T",  ProductCode: "004"},
    {Country: "UK", Type:"R",  ProductCode: "004.R"},
    {Country: "UK", Type:"B",  ProductCode: "005"}
];

// Custom mapper
function _map(key, value)
{
    var result = [];

    result.push({key:value, value:1});

    return result;
}

// Custom reducer
function _reduce(key, values)
{
    var sum = 0;

    for(var i = 0; i < values.length; i++)
    {
        sum += values[i];
    }

    return {key: key, value: sum};
}

Now can I call it like so:

// Basic "group by - count"
var out = mapReduce(data, _map, _reduce, "Country");

This yields the following result:

[{"key":"US","value":4},
{"key":"UK","value":3},
{"key":"FR","value":1},
{"key":"DE","value":2}]

Pretty nifty!  And this data can then be fed into flot for charting purposes.

Sample (with flot example) is attached: MapReduce.zip

Filed under: Dev No Comments
16Jan/12Off

Externalizing Build Configuration

Posted by Charles Chen

While PowerShell is great, I still do a lot of my build automation using plain old batch scripts when it comes to managing my SharePoint development workflow.  Because I do my development outside of my SharePoint environment (develop on my host OS but SharePoint is in my guest OS), it requires some nifty batch scripts to keep the flow tight as no plugins or tools support this development model (dunno why...).

One of the challenges is making it easy to externalize environmental configuration information on a developer-by-developer basis.

In the past, I've relied on having team members create environment variables, but I decided to try out an external configuration file.

It worked out great :D

The following script reads a file and sets four variables:

@ECHO OFF
ECHO ______________________________________________
ECHO Setting up build environment...
ECHO ______________________________________________
For /F "tokens=1-4* delims=;" %%A IN (..\build-configuration.txt) DO (
SET SERVER=%%A
SET LOGIN=%%B
SET PASSWORD=%%C
SET APPPOOL=%%D
)

ECHO SERVER = %SERVER%
ECHO LOGIN = %LOGIN%
ECHO PASSWORD = %PASSWORD%
ECHO APPPOOL = %APPPOOL%

And the file looks like this:

vm1;administrator;P@ssw0rd;SharePoint - DM App Pool

Now I can use the variables like so:

ECHO ______________________________________________
ECHO Copy to remote server...
ECHO ______________________________________________
IF NOT EXIST \\%SERVER%\_ic\ctmo\ GOTO END

DEL \\%SERVER%\_ic\ctmo\binaries /q /s
XCOPY ..\..\pkgs\*.* \\%SERVER%\_ic\ctmo /Y /I /S

It even works when calling to psexec:

ECHO ______________________________________________
ECHO Start psexec...
ECHO ______________________________________________
::// Deploys the binaries only (doesn't reinstall .wsp).
..\..\tools\sysinternals\psexec.exe \\%SERVER% -u %LOGIN% -p %PASSWORD% -e -d -w C:\_ic\ctmo\binaries cmd /c \\%SERVER%\_ic\ctmo\binaries\gac-install.bat

The best part is that each developer only has to create the text file and all of the environment specific information (like the target SharePoint server) are configured in one tiny file, allowing the automation scripts to be ready for any developer.

Filed under: Dev No Comments