Tuesday, November 03, 2015

Op stap naar de Acerta Ekiden

In de categorie "doe eens iets met je werk" zijn we niet zo lang geleden met 12 man van Infohos Services naar Brussel getrokken om mee te doen met de Acerta Ekiden!

De Ekiden, een aflossingsmarathon, is een traditie die overgewaaid is uit Japan, en die nu meer en meer wordt georganiseerd in onze contreien. Brussel is hier wel de grootste van en ook deze keer deden niet minder dan 1650 teams (van 6 personen elk) hier aan mee.

Aangezien de loopkriebel blijkbaar ons bedrijf geïnfecteerd heeft (cfr eerdere deelname aan de 'Wings for Life' in Ieper), werd er beslist om ook hier aan mee te doen, en we slaagden erin om twee teams samen te stellen (wat zeker niet slecht is, 12 man op een bedrijf van 90).

Zoals altijd vereist in Brussel geraken een beetje organisatie, maar gelukkig was het op een zaterdag waardoor de E40 niet zo erg is als gebruikelijk.
Als eerste stap Cyriel naar zijn peter gebracht voor een korte babysit, tot Nele klaar was met werken (merci Bert&Lot).
Daarna een tussenstap in Heule om Jesper, collega #1, op te pikken.
Daarna een tussenstap in Deinze om zelf van auto te wijzigen en met Wim, collega #2, en zijn vrouw mee te rijden naar de Heyzel.
Eenmaal geparkeerd, was het nog een wandeling van 10 minuten van parking C naar het stadion, maar dan waren we er eindelijk.


First things first, iedereen kostuum aantrekken en de obligate groepsfoto!


Daarna was het tijd om het stadion te bekijken, voor mensen die dit nog nooit gezien hebben was dit best indrukwekkend, al waren er toch ook mensen die het groter verwacht hadden.


Daarna was het tijd voor de serieuze zaken! Onze eerste lopers van elk team vertrokken buiten het stadion, en de rest van onze teams posteerden zich in de tribunes dicht bij onze wisselzone. Dit ging niet zo eenvoudig, aangezien zowat iedereen blijkbaar dit idee had en de doorgang van tribune naar tribune niet echt ... optimaal is in het Heyzel stadion. Laat ons zeggen dat ik een nieuw begrip heb opgedaan van hoe het Heyzel drama in de tijd is kunnen ontstaan... Maar uiteindelijk stonden we toch klaar.


De eerste lopers kwamen al puffend terug; blijkbaar is Brussel nogal aan de heuvelachtige kant. Iedereen die al de 20km van Brussel heeft gelopen kan dit beamen.

In het begin ging het vrij op en neer tussen onze twee teams (een beetje interne concurrentie is altijd leuk), in zoverre zelfs dat onze 4de lopers quasi gelijktijdig uit de wisselzone vertrokken! Spannend, maar daarna was het een beetje naar de knoppen gezien de loper van het 'andere' team vlotjes 40 minuten liep op de 10km en onze loper 'slechts' 51 minuten kon halen. Dus de kloof was geslagen, en werd nog een 6-tal minuten uitgediept door de volgende loper.

Daarna was het eindelijk aan mezelf; dus op naar de wisselzone, samen met Jesper die laatste loper was voor het andere team.


Er zijn duidelijk voor-en nadelen om als laatste loper te starten. Voordeel is dat je de rest van je team goed kan aanmoedigen, en voldoende tijd hebt om je klaar te maken. Nadeel is dat je daar wel een paar uur staat te draaien, en dreigt een beetje te verkleumen.

Het eigenlijke lopen ging vrij goed, rekening houdende met het inderdaad extreem heuvelachtige terrein. Hoogtepunt was toen ik Tia Hellebaut kon inhalen! Toegegeven, ze is ook al even gestopt met topsport, en dat ging waarschijnlijk niet gelukt zijn in haar hoogdagen. Maar toch, ingehaald is ingehaald. Sympathieke madam overigens, Tia, die me spontaan aansprak wanneer ik haar inhaalde om te weten hoe ver we al gelopen hadden (en nogal teleurgesteld was dat het 'nog maar 3 km was :D).

Uiteindelijk afgeklokt op een respectabele 34.45, en aangezien ik verre van een heuvelloper ben, was ik daar best tevreden van.


Daarna nog wat post-run schmoozen met de collega's, in de file staan aan parking C en uiteindelijk toch thuisgeraakt. Een lange, maar leuke dag!

Monday, September 26, 2011

Preparing for the half marathon

Because life is about trying new things, I've undertaken the task of running not one but two half marathons in 2 consecutive weeks, one in Kuurne and one in Oostende.

Now, the 'serious' runner is going to scoff at this and boast that he or she once ran 4 marathons in 4 days or similar. Fair enough, but keep in mind that running is but one aspect of my life. Between a fulltime job, a girlfriend, a busy social life, other sports and the horrid Belgian weather, I count myself lucky to get 2-3 solid running sessions in one week (and that's counting weekends!). So maybe 2 1/2 marathons are not that trivial after all.

Having said that, I'm fairly sure I can do it, I've been training quite dilligently (for my doing anyway ;) and have succeeded in varying my training load as well, alternating long distance runs (10k, 15k) with interval runs (speed work). I'm hoping the combination of the two will give me good endurance and some decent speed as well. Because, since we're a bit ambitious as well, just finishing them is not enough, secretly I'd like to come in under 2 hours as well. A feat which is not impossible, but will require a good deal of concentration and (especially) enough discipline not to go running off like a madman from the start, and paying the price later.

We'll see in the next two weeks.

(Also if I don't update in the next 3 weeks, call an ambulance pls :).

Thursday, September 15, 2011

Run Run!

Finally managed to get myself running again tonight.

http://runkeeper.com/user/polkadragon/activity/52339199

Slow eh? Now keep in mind, it was an interval training. Which means you run for a certain period at maximum capacity, and then follow that up with a slow period to recover. Then fast again, then slow again. Rince, repeat.

In my case it was:
5 minute warmup slow-ish
1 minute fast
1 minute slow
(repeat 10x)
5 minute cooldown slow-ish

I can assure you that by the third fast bout, you feel like dying, that one fast minute feels like half an hour and that slow minute whizzes by!
The general idea is that interval training improves your aerobic capacity (increasing your speed), the high intensity intervals are supposed to boost your metabolism.

For sure, my metabolism is telling me something now. Although it might be "call the hospital", not entirely sure.

Thursday, October 15, 2009

Reading data from a closed Stream

Problem:
Sometimes you need to read data from a Stream, either to save it or to process it in other layers, but you really don't want to open or pass along the Stream for too long.

Solution:
At first glance, the GetBuffer() method of the Stream object would seem ideal, since it copies the text to a byte array, allowing you to close the underlying stream without any issues.

However, GetBuffer has some definite issues, the biggest one being that he will pad the resulting byte array with "\0" (nulls), depending on how big the data in your stream is. Which can lead to all kinds of nasty side-effects (in particular when working with XML data).

Never fear, in comes the rescuer, in this case the ToArray() method of the Stream object. This basically does everything GetBuffer does, minus the padding. And likewise, you can simply dispose of the Stream and do whatever you need to do with the data.

How to retrieve an old version of your project in Sourcesafe

Open Command Prompt

Set Sourcesafe Directory

C:\Program Files\Microsoft Visual Studio\VSS\win32>set SSDIR=<unc path to your sourcesafe root>

Execute GET command

ss get $/ -R -Vd5/6/2009;5:16a -I-N -W -GLD:\temp\<your project name>-GTM –GWR

- Project: $/Projects/<your project>: naam van het project die je wilt hebben
- -Vd5/6/2009;5:16a: tijdstip van de bestanden die je wilt terugkrijgen (DD/MM/YYYY formaat, dus 5 juni in dit geval)
- -GLD:\temp\<your project>: lokale folder waar de files in moeten terechtkomen

Friday, October 09, 2009

Quick Linq tip

When you crete a construction such as

if (list.Count > 0)
{
// do stuff
}


its actually much more efficient to use LINQ as such:

if (list.Any())
{
// do stuff
}


Advantage: ANY will stop after the first hit, while COUNT will traverse the entire enumerator. This can be significant for larger lists.

Validation for ComponentArt datepicker

External DatePicker Controls can be useful, and the ComponentArt sure is, except for the annoying lack of client-side validation. Nevertheless, its not too hard to integrate your own javascript and validate your date entries.

This sample uses Prototype, but you can simply replace the '$' by 'document.getElementById' and you should be okay.

(This also assumes you have encapsulated your date picker in a user control)


1.Add a (hidden) div element to your user control


<div style="display:none" id="validationdiv<%=ClientID%>">
<asp:TextBox ID="ValidationTextBox" runat="server" EnableViewState="false"></asp:TextBox>
</div>


2. Add a RequiredFieldValidator, pointing to our hidden TextBox

<asp:RequiredFieldValidator Enabled="false" ID="dateValidator" ControlToValidate="ValidationTextBox" runat="server" ErrorMessage="***" Display="None"></asp:RequiredFieldValidator>

3.Expand your javascript handlers, to change your textbox values when the Calendar/Picker values change.

function MarkAsValidationOk<%=ClientID%>()
{
$('<%=ValidationTextBox.ClientID%>').value = true;
}

function MarkAsValidationNOk<%=ClientID%>()
{
$('<%=ValidationTextBox.ClientID%>').value = “”;
}


function Picker1_onSelectionChanged(sender, eventArgs)
{
sender.AssociatedCalendar.setSelectedDate(sender.getSelectedDate());
MarkAsValidationOk<%=ClientID%>()}

function Calendar_OnSelectionChanged(calendar)
{
calendar.AssociatedPicker.SetSelectedDate(calendar.GetSelectedDate());
MarkAsValidationOk<%=ClientID%>()}

function ClearCalendar<%= Calendar1.ClientObjectId %>()
{
<%= Calendar1.ClientObjectId %>.ClearSelectedDate();
<%= Picker1.ClientObjectId %>.ClearSelectedDate();
MarkAsValidationNOk<%=ClientID%>()
}


4. Add some configuration settings to your user control Codebehind.

public bool EnableValidation { set { dateValidator.Enabled = value; } }
public string ValidationErrorMessage { set { dateValidator.ErrorMessage = value; } }
public string ValidationGroup { set { dateValidator.ValidationGroup = value; } }


5. Expand your 'setdate' server-side functionality to flag validation as ok.

public void SetDate(DateTime date)
{
Calendar1.SelectedDate = date;
Picker1.SelectedDate = date;
timeSelectorControl.DefaultHour = date.Hour;
timeSelectorControl.DefaultMinute = date.Minute;

Page.ClientScript.RegisterStartupScript(GetType(), "datejs" + ClientID, "MarkAsValidationOk" + ClientID + "();", true);
}


6. All done, now you can simply enable validation by setting some properties in the page that uses your control:

<uc1:CalendarPicker ID="birthdayPicker" EnableValidation="true" ValidationGroup="EmployeeValidationGroup" ValidationErrorMessage="BirthDate_Required" runat="server" ShowTimePart="false" />

Selecting all checkboxes with Prootype

For creating a "Select All Checkboxes" link in javascript:

function CheckAll()
{
var allCheckboxes = $$('input[type=checkbox]');
allCheckboxes.each(function(e) { e.click(); });
}


Don't use e.checked = true, because it doesn't trigger the Grid_Item_CheckChanged events of the ComponentArt grid.

Wednesday, January 30, 2008

Mind your callbacks

These days I'm using quite a lot of Callbacks, that is requests to the server that don't refresh the entire page, but only a specific section, creating the illusion of a snappier user interface. As such, they are becoming a necessity in these days of Users 2.0 (ie users who have gotten used to Web 2.0 functionalities, much as I loathe the term).

Google were one of the main early adopters of callbacks, but now everyone is doing it, and so are the main out-of-the-box software vendors such as Telerik or ComponentArt. These days the challenge would be to find a grid that does not implement the latest AJAX-style gadgets.

Our 3rd party vendor of choice is currently ComponentArt, and I've been using their Callback mechanisms quite extensively lately. They're quite good, although sometimes its still necessary to go down to the nitty-gritty of client-side scripting, which is not for the faint of hearted.

Of course, while callbacks are great, they tend to have a big impact on they way your applications are constructed, amongst others interfering with what we consider "best practices", such as:

* Strong Typing (hello Mr JavaScript)
* Error Handling (an alert window does not make an error handler)
* Intellisense (maybe not a best practice, but damn handy to have anyway)

Anyway, in the end its just (yet) another technology paradigma shift and most of those "best practice" challenges can be solved decently enough, given a little time and effort. Lets take error handling as an example:

Problem: When an error occurs during a Callback, the typical error message is "Data cannot be loaded", delivered in the form of a javascript alert. Not too useful, not to mention the fact that your page is potentially left in a compromised state.

Solution: In the end, the Callback method is just another server-side method, so encapsulate it in an try/catch block and provide adequate error handling. After that, generate some client-side script to redirect the user away from the page to some nice error page.

protected void MyCallBack(object sender, CallBackEventArgs e)
{
try
{
BindGrid();
panel.RenderControl(e.Output);
}
catch(Exception ex)
{

new ErrorReporter().HandleError(Request, ex);
CallBackErrorHandler.RedirectToErrorPage("Error.aspx", panel, e.Output);
}
}


and then in our CallBackErrorHandler class:

public static class CallBackErrorHandler
{
public static void RedirectToErrorPage(string redirectUrl, Control container, HtmlTextWriter output)
{
string str = "<script type='text/javascript'>";
str += "window.location = '" + redirectUrl + "'</script>";
Literal lit = new Literal();
lit.Text = str;
container.Controls.Add(lit);
container.RenderControl(output);
}
}


Old tricks, new techology :)

Monday, January 21, 2008

Dynamic Services

Something useful I recently learned:

While you can without any problem attach parameters to a .NET Windows Service (by means of a configuration file), how the heck am I supposed to enter parameters into the INSTALL program itself (such as, the service name...).

The answer was simple: InstallUtil.exe (the installer program) can actually be called with command-line parameters appended to it. These can then easily be processed in the installer class itself.

installutil /DisplayName=Sam " WindowsService1.exe"


And then in your installer.cs file:

protected override void OnBeforeInstall(IDictionary savedState)
{
base.OnBeforeInstall(savedState);
string name = Context.Parameters["DisplayName"];
if (name != null)
serviceInstaller1.ServiceName = name;
}


Take care: this needs to happen in your OnBeforeInstall handler, after that your Context will be NULL!