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

25Jan/122

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/120

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/120

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
19Dec/110

Never Thought of It Like That

Posted by Charles Chen

From the comments section of a CNN article.

16Dec/110

Force File Name in SharePoint 2010 Search Results

Posted by Charles Chen

There are a few resources on this for 2007, but I thought I'd add a small update for 2010.

First, start by following the instructions in the links above for the IsDocument property.  You can get to it from the search service administration and it's under Metadata Properties:

Find the IsDocument property in here

Now go to your site and create a new web part page (header, left nav, right body) and call it CustomSearchResults.aspx (or whatever you'd like).  On the right hand side, add a " web part and on the left hand side, add a Refinement Panel web part.

Search web parts available - add Search Core Results and Refinement Panel

Now you need to edit the results web part.

  1. Under the Core Results settings panel, expand the Display Properties sub-panel.
  2. Uncheck Use Location Visualization to enable the Fetched Properties and XSL Editor options.
  3. Modify the Fetched Properties XML string to include <Column Name="Filename"/> (strongly recommend copying the string out and editing it in a text editor).
  4. Click the XSL Editor button to modify the XSL.  Again, I strongly recommend copying the XSL out to a text editor.
  5. Around line 206-207, you should see the following line:
    <xsl:template match="Result">
        <xsl:variable name="id" select="id"/>
  6. Modify it to look like so:
    <xsl:template match="Result">
        <xsl:variable name="id" select="id"/>
        <xsl:variable name="filename" select="filename"/>
        <xsl:variable name="isdocument" select="isdocument"/>
  7. Next, around (new) line 324, you should see the following XSL:
    <xsl:otherwise>
        <a id="{concat($currentId,'_Title')}">
            <xsl:attribute name="href">
                <xsl:value-of  select="$url"/>
            </xsl:attribute>
            <xsl:attribute name="title">
                <xsl:value-of select="title"/>
            </xsl:attribute>
            <xsl:choose>
                <xsl:when test="hithighlightedproperties/HHTitle[. != '']">
                    <xsl:call-template name="HitHighlighting">
                        <xsl:with-param name="hh" select="hithighlightedproperties/HHTitle" />
                    </xsl:call-template>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:value-of select="title"/>
                </xsl:otherwise>
            </xsl:choose>
        </a>
    </xsl:otherwise>
  8. Update this to the following:
    <xsl:otherwise>
        <a id="{concat($currentId,'_Title')}">
            <xsl:attribute name="href">
                <xsl:value-of  select="$url"/>
            </xsl:attribute>
            <xsl:attribute name="title">
                <xsl:value-of select="title"/>
            </xsl:attribute>
    
            <xsl:if test="$isdocument">
                <xsl:value-of select="filename"/>
            </xsl:if>
            <xsl:if test="not($isdocument)">
                <xsl:choose>
                    <xsl:when test="hithighlightedproperties/HHTitle[. != '']">
                        <xsl:call-template name="HitHighlighting">
                            <xsl:with-param name="hh" select="hithighlightedproperties/HHTitle" />
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="title"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:if>
        </a>
    </xsl:otherwise>

Now hook up your custom search results page by clicking on Site Settings and then Search Settings. In the Site Collection Search Results Page text box, enter the full relative path to your page (including sub-site paths and such).  For example: /sites/site_xyz/pages/mycustomsearchresults.aspx.

That should do it.  Unfortunately, I haven't figured out how to turn on hit highlighting for the file name yet.

Filed under: SharePoint No Comments
29Nov/110

Home Office 2011 Edition

Posted by Charles Chen

Finally got around the cleaning up my office (after 4 years...) .  Love the way it turned out and much more work space with much less clutter.

Shot of the office from the foyer

Alternate view.

Ergotron Lx Dual Stacking arms to free up desk space.

For reference, this is what it looked like previously.

Filed under: Awesome, DevLife No Comments
1Nov/11Off

Airline Boarding and How to Make It Suck Less

Posted by Charles Chen

Caught an unexpected segment in the news on airline boarding (ending is great):

I've mostly had (terrible) experiences with boarding Continental flights and I've often thought why the process is so screwed up.  I've come up with the following conclusions myself:

  1. Problem: Last time I flew out of John Wayne International, literally 3/4 of the flight was "Elite" status.  So when they did the pre-boarding, it was a huge throng of people boarding the plane at once, which negated the whole point of boarding the plane from the back first. There's something broken about the system here because it creates a weird paradox.  Being able to board the plane faster is a "benefit" of Elite status, but by using this system, it extends the overall boarding time, thereby actually making those with Elite status spend an overall longer period of time sitting on the plane.  Solution: Elite status is only used in consideration for upgrades and seat selection at check-in, not boarding order.
  2. Problem: Gate reps don't actually check the size of carry-ons.  In some cases, preemptively removing larger carry-ons and forcing gate-checks would dramatically reduce overall boarding time since the large bag causes an additive delay effect.  That is that it not only slows down the individual with the large bag, but also affects every passenger that boards after that passenger because a large bag taking up too much space forces "bin hunting".  Solution: Actually enforce the existing rules?  Seems too simple to be true.
  3. Problem: No one keeps their outerwear until the boarding process is over.  Nothing more frustrating than people stuffing their outerwear in the overhead before everyone has boarded.  This takes up valuable overhead bin space and, again, delays the boarding process for everyone that comes afterwards by forcing bin hunting. Solution: Add coat hooks on the seats and people will more likely just hook their outerwear on the back of the seat for easy access.
  4. Problem: Some people just don't give a damn what the gate rep calls -- they're just going to get onto the plane anyways. Solution: See below.
  5. Problem: Because of a combination of the above, it often causes folks to end up back-tracking and bin-hunting.  Sometimes, it also causes folks to preemptively place their carry-ons in forward rows, thinking that there is no space in the back rows, which only further exacerbates the situation. Solution: See below

The whole process is generally full of chaos, completely inefficient, and seems dated -- as if no one has stopped to think about these issues and how to solve them for decades.  So it's interesting to see this guy -- Dr. Steffen -- propose something new.  But it got me thinking that this guy's method still has an issue: it's not realistic for gate reps to call out this seating scheme (one row, one aisle at a time).  Yet this is what it demands as the process breaks down if you have passengers in row n-2 blocking passengers in row n.  Furthermore, the Steffen method makes an assumption about the nature of people: that they will obey order and think in the best interest of everybody.  When the gate rep calls the aisles for rows n, n-2, n-4, n-6, all of those folks are going to rush the counter at once in a single mass.

So I think an extension or more realistic approach to this method is necessary to get it to work: a new passenger queue system at the gate.  It should be -- like a plane -- one center aisle with several color-coded lines on each side of the aisle and just have people queue up in "bins" first.  It shouldn't match the rows in count, but should be at a 1:3 ratio per bin.  In essence, it's a modified block boarding pattern, but we break it down within the block so that, for example, window aisle passengers in the block are in bin "Purple", middle seat passengers are in bin "Blue", and aisle seat passengers are in bin "Green".

The gate rep would call bin "Purple 1" to board the window seat passengers in the rear of the plane.  Then call "Purple 2" to queue the passengers in the window seat in the middle of the plane, then call "Purple 3" to queue the passengers in the window seat near the front of the plane.  However, the real efficiency is in having the folks get into the bins first, before they are queued up.  The current Continental system results in 60 people all standing around, blocking the entrance of the queue when all that's needed is a bin system so they know where to line up.

This system acknowledges that the ideal boarding pattern cannot be achieved in real life and thus only attempts to gain efficiency by segmenting the users by zone in a pre-boarding line first.  Now everyone isn't standing around in one big mass, blocking the boarding line and rushing the line as soon as their block is called.  It's a hybrid of block and WILMA (which is what the Steffen method is) but not as granular as the Steffen method and adds an extra layer of organization at the gate to account for real-world considerations.

25Oct/11Off

Isaacson on Jobs on Craftsmanship

Posted by Charles Chen

From an NPR interview with Walter Isaacson, Jobs' biographer:

On Jobs' father, who rebuilt cars, and held design and craftsmanship in high regard:

"He would show Steve the curve of the designs and the interiors and the shapes ... and even have pictures of the cars he liked the most in the garage. He put a little workbench in the garage, and he said, 'Steve, this is now your workbench.'

"One of the most important things he taught Steve was [that] it's important to be a great craftsman, even for the parts unseen. When they were building a fence, he said, 'You have to make the back of the fence that people won't see look just as beautiful as the front, just like a great carpenter would make the back of a chest of drawers ... Even though others won't see it, you will know it's there, and that will make you more proud of your design.'"

I can't begin to compare myself to Jobs, but I think this is a value that's important to me, personally, from a software development perspective.  There is an aesthetic and a beauty to well written code or framework not to mention the pride of the author in crafting a clear, concise, and elegant design -- even in the "parts unseen" by the end user.

I once got into a heated debate about code quality with a CEO who was, at the time, bent on fixing nail pops and seams on the walls of his recently built and painted house.  I asked why he didn't see the same need to put an effort into addressing analogous issues in our code that disturbed the overall quality and aesthetics of the codebase, which seemed to me even more important than a few nail pops.  "That's different" is the only response that I got, but to me, it's the same.  There's a personal pride in building a product with exemplary craftsmanship.  There's a team's pride to being able to walk into a code review with a customer and know that they will be wowed.  There's a developer's own pride in writing software that takes design and usability of the framework into account.

This gets lost in the age of outsourcing and rent-a-coders, but great software is still -- and likely will always be -- a craft that requires skilled craftsmans to build (of course, great software requires more than that like vision and an understanding of the problem domain as well).

Filed under: DevLife 1 Comment
28Sep/11Off

SharePoint 2010 Service Applications Thoughts

Posted by Charles Chen

I can't say that I can add much more to the tutorials and articles already out there on the Net on this topic, but I'd like to point to the definitive example of how to implement one: http://msdn.microsoft.com/en-us/library/gg193964.aspx

David Taylor's blog also has a good 10 part walkthrough with a bit more explanation; however, I would caution that the example he provides is broken as heck and was part of the problem that it took me a good part of 3-4 days to get something so simple to work right.

One bit of knowledge that I'd like to impart is that you will -- more than likely, 99.99% guaranteed -- run into errors with WCF.  In these cases, the errors will:

  • Not show up in any level of detail in the SharePoint logs
  • Not show up at all in the system event logs
  • Not show up in the IIS logs with any level of detail

You'll want to use SvcConfigEditor to enable tracing and of course, SvcTraceViewer to view your logs.  Part of my problem was that I had an error in the configuration file for the service and part of the problem was that I had an error in the VirtualPath of the service in my service application.  I was only able to track these two down through the usage of the aforementioned WCF utilities so keep them handy!

Filed under: Dev, SharePoint, WCF No Comments
23Sep/11Off

Thoughts from Switzerland

Posted by Charles Chen

Unorganized thoughts from Switzerland:

  • It reminds me a little of Taipei, oddly enough.  I can't quite put my finger on it, but it has a similar feel (except it's not 98% Asian and things are a lot more expensive).  I think it's the way the shops are built, the little markets, the meandering back alleys, the smaller cars, the bicycles (though in Taiwan, it's mostly motor scooters), the closeness of everything.  Of course, the air is much nicer here and the buildings much older.
  • There racial diversity is pretty surprising.  I would have thought it more like Utah, to be honest, but there is a noticeable presence of minorities here.
  • Things are expensive.
  • Lots of bicycles...everywhere.  Men, women, professionals, students, young, old-- all sorts of folks can be seen riding their bicycles in the morning.  Also, people don't generally lock their bicycles; they just park them and go.  A fellow American traveler commented that in the US, they'd probably all be on the back of a pickup truck in under 10 minutes...
  • Basel, where I'm staying, is very small and very walkable.  However, the free tram system here is superb and traveler friendly.  They are frequent and accessible from nearly everywhere in the city - no need to purchase tickets.
  • As a consequence of the previous two bullet points, there aren't very many cars here for a metropolitan and business center.
  • Maybe I notice it more because I back up to the woods at home, but there is a surprising lack of insects.
  • The toilet paper is much thicker and the sheets are longer (yes, these sorts of mundane things interest me).
  • The city is very clean compared to other metropolitan areas I've visited.
  • The coffee is fantastic nearly everywhere I've had coffee (maybe this is a general European characteristic).  Even the hotel coffee is superb!  It surprised me to see several Starbucks in my wanderings in the city given the general quality of the coffee I've had here exceeded the coffee I've had at any of the US Starbucks I've had.  A fellow Danish traveler said that it's because it's "American" and folks like the flavored coffees, which is absurd to me.
  • The McDonald's here is the most expensive McDonald's I've ever had.  That said, the Big Tasty was huge and had bacon and the bun had caramelized onions on top.  Way better than in the US.
  • Smoking - it's everywhere.  I guess I'm not used to this anymore as there's pretty much no open areas where people can smoke back in NJ.  I will tell you this: I do not miss that aspect of New Jersey.
  • The aforementioned Danish traveler mentioned that he never eats breakfast at hotels here in Europe but never skips them in the US.  I can understand why.  The breakfast fare here is mostly bread, cheese, bread, cereal, and more bread.  Not quite as satisfying as some bacon, sausages, scrambled eggs, and hash browns.

A water fountain near Claraplatz. There were some pigeons bathing in it moments before this picture.

A random side street with little shops along the side

A mural of pop/rock legends

Buildings along the river Rhine

Another fountain.

Caught these kids breakdancing at the University of Basel

A picturesque building facade

My $15 Big Tasty meal....

Bicycles, bicycles, bicycles everywhere

Filed under: Life No Comments