Carl’s Geek Notes

March 30, 2007

Follow-up to IE7 address bar issue

Filed under: Windows Administration — Carl @ 1:25 pm

Just a quick follow-up: apparently the fix that I described in a previous post for slow IE7 performance on Vista when entering an address bar also causes the Favorites auto-sensing to stop working.  If I start typing “ama” it finds Amazon.com in the AutoComplete list, and when I select that it puts http://amazon.com.url/ in the address bar (which obviously gives “Internet Explorer cannot display the webpage” since there is no address amazon.com.url).  Favorites work just fine from the Favorites menu, but be aware that you won’t be able to enter Favorites in the address bar.

Double-translation again!

Filed under: Just for Fun — Carl @ 10:44 am

Any guesses?

It is and it respects, or it respects–questions:
It undergoes the new gun and the anger flesh of the fortune which is outrageous
is nobler inside mind but trouble and it opposes
and the ocean to head it has eight and the thin tis them ends the thing.
In order it dies, that–flesh of–compared to above are in the successor,
we by the sleep which it talks in order self griefs
and thousand natural enemies end a shock.
Under piety ‘Tis the completion a desideratum.
To die to respect, in order to dream probably the–
th cup respect–it slept to respect,:
We fall this fate coil and dream which it will mix up must give,
rests in us, it comes the ay which it does not know,
it dies hazard it rubs inside that sleep, it is.

Rainbow Six Vegas: Best Action Game Ever?

Filed under: Video Games — Carl @ 10:34 am

In one frenetic week, I’ve completed the single player story mode of Rainbow Six Vegas on my Xbox 360.  It’s been an absolute blast (literally and figuratively), and it’s been a while since I’ve been this “into” a game.

First, I love the pacing of it.  RSV demands a deliberate strategy, movement, and setup followed by furious action.  There’s little more satisfying in action video games than planning a door breach, setting your targets, giving the order, and clearing the room before the enemy has a chance to take a single shot.  Or planning where your team sets up, where you set up, flanking the enemy, and going weapons free.  Or lining up and taking the perfect shot while the enemy is distracted by your team’s suppressing fire…

RSV is a game that supports different playing styles and tactics as well.  I’m a sniper at heart in video games; I enjoy dispatching opponents so they don’t know what hit them or where it came from.  Others like massive application of force, close-in combat, or using movement to lure enemys into ambushes.  RSV will satisfy all types of players–in fact, a flexible strategy is the best way to find success in the game.

The presentation is stunning.  Car doors come off.  Bullet holes appear on walls.  Slot machines spew coins when shot.  Tempered glass and plate glass break like their real-life counterparts.  Casino noises are dead-on.  The story is solid.  The missions flow well.

Here are some tactical tips that helped me through the game:

  • Always go high.  Covering an enemy from above gives you every advantage possible.  There are several points in the game (dam control room, Fremont Street, Vertigo Spire casino floor) that are difficult to accomplish by coming in on the main level but really not that difficult if you “soften” your entry with some sniper rifle work from above.
  • Use your team to command the enemy’s attention while you flank and dispatch them (or vice-versa).  I like the situation where I’m perpendicular to the line of fire between my team and the enemy–I can see both the other Rainbows and the terrorist, and it’s very effective.  Conventional military doctrine is to never split your force in the face of stronger opposition.  Throw this out the window; the Rainbows are as far from conventional as you can get.
  • Combine the first couple of tips for devastating effect.  I’m thinking especially of the trainyard stage and the one where you have to hack and blow up the terrorist’s van–you can stay high (and pretty covered) while directing your team’s movements below.
  • Use the “peek” ability from behind cover to line up your shot, then duck out from cover and pull the trigger.
  • Use the “tag” ability judiciously, not necessarily as a target designator for your team but to keep an enemy identified and (perhaps more importantly) to let you know when they’ve shuffled off this mortal coil.
  • Advance, then retreat, repeat.  This has two advantages: it draws enemies out of cover and it allows you to return to a position that’s known.  Sometimes you’ll hit a “spawn point” that causes enemies to be generated, so you can trigger that and then retreat to a spot where obviously the cover was good enough for you to survive previously.  Several of the more difficult door breaches can be accomplished this way.  Send the command to open the door, then order your team back behind the door.
  • If a Rainbow (or both!) is hit and downed, you have more time than you think to heal them.  Continue to calmly perforate the enemies from cover until you can safely heal–as my Boy Scout lifesaving training said, first rule of victim rescue is don’t make yourself a victim too!  You don’t need to stress about healing a teammate until they turn red, and some of my favorite moments were when both teammates were down under withering fire and I managed to kill all the enemies and heal them.
  • Door breach protocol should be as follows, in this priority order:
    • Hostages: Flash and Clear only, after designating targets.
    • Opponents next to or in front of the door: Breach and Clear
    • Opponents with backs turned to door: Frag and Clear
    • All other situations: Open and Clear.  Realistically, frag and clear takes too long for enemies paying attention to the door and breach and clear is only effective when people are right next to it.  You could probably switch to Infiltrate, Flash and Clear, and then back to Assault, but most breaches are easier with giving the team a wide latitude to dispose of terrorists.
  • Leave some lovely C4 presents behind for terrorists when they come at you in waves over turf you’ve already covered (especially at the computer hack after the dam control room or in Dante’s Theater where you can tuck some behind the benches in the back of the theater and detonate when the fast-rope enemies come).
  • It’s a fine line between using your team as an asset and relying on them too much (and missing out on the fun of the game).  Use them to your advantage, but don’t make them do all the work…
  • If you die more than a few times, your strategy is wrong.  Check the tactical map for alternate routes, better cover, or a side door that helps you out.

Hope the tips help!  All in all, it’s one of the most satisfying action games that I’ve played.  It’s not run-and-gun like Halo or Call of Duty.  Ghost Recon Advanced Warfighter stresses long-range combat more–RSV is more up-close and personal.  And RSV has more action than Splinter Cell.

Here’s one of the best parts: I can use the Xbox Live Vision Camera and put my own ugly mug as my multiplayer avatar!

The best part is, the ending leaves the game wide open for the next one.  I can’t wait!

March 28, 2007

Array.Resize warning

Filed under: C#/.NET, Computers, Programming — Carl @ 9:26 am

The .NET Framework 2.0 addition of Array.Resize as a generic method is a big plus.  One of the really nice things about it is that if the array passed to it is a null reference, it creates a new array.  That makes a call like this seem natural:

MyArrayType[] MyArray;
Array.Resize<MyArrayType>(ref MyArray, MyArray.Length + 1);

However, you’ll get a null reference exception if you do that and the array is null.  Here’s how to make the call safely:

Array.Resize<MyArrayType>(ref MyArray, (null == MyArray) ? 1 : MyArray.Length + 1);

March 23, 2007

Another double-translation…

Filed under: Just for Fun, Language — Carl @ 2:04 pm

Guess the source! The translation was English to Korean and back.

It sleeps equally all men create and before 87 years it was thought inside freedom, that, it gave in proposition and the new nation got this by our fathers in the continent.

Now we are thought that nation, or like this and the what kind of nation which we give like this, it will be able to endure for a long time and multi inside company one civil war which it examines it is engaged. We meet in the company one battlefield of that warfare. We came in order to give the portion of that field, with the hazard last rest thread here flesh n them to whom that nation gives their life. That we this, the whole it is suitable and it is suitable.

In a but, big consideration, us us the possibility of doing under dedicating which is not us the possibility of doing the new star which is not it does and ground the possibility of doing it is not under. Here it fought hard, the man who is brave, existence and thing additional one which dies it dedicated up it of the force which us whom it damages is poor, far. We think from here talking and world-wide will the enemy week, the for a long time when is not, but assuredly the possibility of forgetting here it is not. Us hazard existence, rather, here it fights and to be like this it is noble till now and here in order to give at the incomplete day which advances it is. It this lion of here to this nation, in the providence lower part, by the government of the person from the endurance freedom will be new birth, by the person, hazard the person, in cry of distress gruel highland Anh – inside becoming Hus, not dying from the lion which gives this honor us them that last in that cause which gives the devotion which is sufficient in the devotion which increases us on the front of us whom it takes away in the remainder company one business will give hazard rather is and – we decide here highly.

Double-translation fun

Filed under: Just for Fun, Language — Carl @ 9:27 am

Slow day programming-wise, so I’ve had fun double-translating with AltaVista’s BabelFish (i.e., English to other language, then the results back to English).  I thought I’d share some wonderful translations of Robert Frost’s Stopping by Woods on a Snowy Evening.  Of course, the original:

Whose woods these are I think I know,
His house is in the village though.
He will not see me stopping here,
To watch his woods fill up with snow.

My little horse must think it queer,
To stop without a farmhouse near,
Between the woods and frozen lake,
The darkest evening of the year.

He gives his harness bells a shake,
To ask if there is some mistake.
The only other sound’s the sweep,
Of easy wind and downy flake.

The woods are lovely, dark and deep,
But I have promises to keep,
And miles to go before I sleep,
And miles to go before I sleep.

First, English-to-Japanese and back:

But as for me having known think of someone’s forest where these are I,
As for that house in the village it is.
He does not look at that I am stopped here
In order to observe at that that forest is full with the snow.

As for the horse where I am small,
When the forest it stops soon between the lake
Which freezes, without the farmer queer,
Evening that year is darkest must think.

He gives the vibration, to the bell of that harness
In order to ask whether or not there is the mistake.
The only other things the extent of the thin layer
The easy wind of sound and like the cotton wool.

The forest is beautiful, is deep darkly,
But before I sleep, I sleep,
And before possessing mile which goes,
As for me the promise which is maintained and mile which goes.

Then we try Russian:

Whose of wood, these they will be which me think 4 he knows,
Its house is located in the village however.
He will not see, that I stopped here,
In order to observe, as its woods they filled upward with the snow.

My small horse must think it queer,
In order to stop without farmhouse nearly,
Between the woods and the frozen lake,
The darkest evening of year.

It gives to its bells of installation shake,
In order ask if a certain error is.
Sweepback of only another of sound,
Of light breeze and downy of khlop’.

Woods are likable, dark and deep,
But I have promises to hold,
And miles, is which necessary to go before I I sleep,
And mile, is which necessary to go before I I sleep.

(I debated whether or not to edit a little of the translation, since it translated я сплю as I I sleep, since I is both literally stated (я) and implied from the conjugation of the verb (сплю), but decided against it because I lack the facility to make such corrections to the other languages I’m using here. Khlop’ should be flakes (хлопья, transliterated to khlopya), and I don’t know where “think 4 he knows” comes from.)

Now for the French version:

With which drink that it is me think that I know,
Its house is in the village however.
It will not see me ceasing here,
To observe its wood fill of snow.

My small horse must think it fag,
Almost to stop without farm,
Between wood and the frozen lake,
The most sunk evening year.

It gives to its bells of harness a jolt,
To ask whether there is a certain error.
Only other the field noise,
Easy wind and duveteux flake.

Wood are beautiful, dark and deep,
But I have promises to keep,
And miles with going before I sleep,
And of the miles to going before I sleep.

(No, I’m not making up what the small horse thinks of it–try it for yourself!)

And the German:

Whom wood, which you these think I are the fact that I know
Is its house in the village.
He does not see me to stop here
To fill in order to watch out its wood, with snow above.

My small horse must think it sonderling,
In order to stop without a farmhouse,
Between the wood and the frozen lake close,
The darkest evening of the yearly.

He gives to his wire bells a vibration
To ask over whether it any error gives.
Only different the loop of the clay/tone,
The simple wind and downy the flake.

The wood is attractive deeply, darkly and,
But I have promises to hold
And the miles to go, before I sleep,
To go and the miles to before I sleep.

And a last one, in Italian:

Of who wood these are I tasks that I know,
Its house is in the village however.
That it will not see it to stop here,
To watch its wood to fill up itself in on snow.

My small horse must think it finocchio,
In order to arrest without one near small farm,
Between the wood and the lago frozen,
The darker evening of the year.

It gives to its flange of the wiring a jolt,
In order to ask if there is a sure error.
The swept one of only the other sound,
easy wind and the lanuginoso ribbon.

The wood is beautiful, dark and deep,
But I have the promises to maintain
And the miles to go before that it sleeps
And miles to go before that sleeps.

March 22, 2007

Popping up a different edit control in .NET DataGridView

Filed under: C#/.NET, Computers, Programming, Winforms — Carl @ 1:41 pm

I’ve been working the past few days with changing behaviors of the DataGridView, where the displayed contents are formatted strings that are determined by conditionally-created combo boxes, checked list boxes, and prompts.  After a misguided attempt using CellEnter that resulted in numerous infinite loops, stack overflows, and “reentrant call to the SetCurrentCellAddressCore function” error messages, I found this solution by Mark Rideout, Microsoft’s DataGridView Program Manager, that overrides either CellBeginEdit or EditingControlShowing (I used CellBeginEdit).  He describes the drawback that the keystroke used to enter edit mode will not be sent to the control, and suggests deriving DataGridViewCell and overriding InitializeEditingControl and KeyEntersEditMode.  Here’s how I implemented it without deriving a separate class.

I overrode the form’s ProcessCmdKey function like this:

protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, System.Windows.Forms.Keys keyData)
{
    // Get the value of the key that was pressed
    int KeyValue = msg.WParam.ToInt32();
    // See if the key is a letter or digit (i.e., something to pass to the next control
    if (Char.IsLetterOrDigit(((char)KeyValue)))
    {
        // Store the integer value of the last key press
        m_LastKeyPressed = KeyValue;
        // Store whether the datagrid had focus or not
        m_LastKeyPressDataGridHasFocus = dgLineItems.Focused;
        // Store the cell that is being typed into
        m_LastKeyPressCell = m_LastKeyPressDataGridHasFocus ? dgLineItems.CurrentCell : null;
    }
    // Allow normal processing of the keystroke
    return base.ProcessCmdKey(ref msg, keyData);
}

And the CellBeginEdit like this:

void MyDataGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
{
    // See which column is being edited
    switch (dgLineItems.Columns[e.ColumnIndex].Name)
    {
        case "MyCustomEditControlColumn":
            // Don't let the DataGridViewCell be edited
            e.Cancel = true;
            /// TODO: Add code here to show custom control; either need to have the control update the underlying data or wait for it after sending the keypress
            // Replay the last keypress to the new control
            if (m_LastKeyPressCell == MyDataGrid.CurrentCell)
            {
                SendKeys.Send(((char)m_LastKeyPressed).ToString());
            }
            break;
    }
}

I don’t think it’s necessary to use the BeginInvoke anonymous delegate; using e.Cancel seemed to do the trick.

March 21, 2007

DataRow adaptation to IDataRecord

Filed under: C#/.NET, Computers, Programming — Carl @ 12:07 pm

I’ve been wanting to write generic functions for a while to handle reads from data readers and tables.  The problem is that DbDataReader and DataTable don’t have much commonality.  Then I ran across Chris McKenzie’s post, where he creates an adapter for a DataRow to the IDataRecord interface.  I’ve converted Chris’ class to C# and created a full implementation:

public class DataRowAdapter : IDataRecord
{
    #region Members
    private DataRow _Row;
    #endregion

    #region Properties
    public DataRow Row
    {
        get { return _Row; }
    }
    #endregion

    #region Constructors
    public DataRowAdapter(DataRow row)
    {
        _Row = row;
    }
    #endregion

    #region IDataRecord Implementation
    public object this[string name]
    {
        get { return _Row[name]; }
    }

    public object this[int i]
    {
        get { return _Row[i]; }
    }

    public int FieldCount
    {
        get { return _Row.Table.Columns.Count; }
    }

    public bool GetBoolean(int i)
    {
        return Convert.ToBoolean(_Row[i]);
    }

    public byte GetByte(int i)
    {
        return Convert.ToByte(_Row[i]);
    }

    public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
    {
        throw new NotSupportedException("GetBytes is not supported.");
    }

    public char GetChar(int i)
    {
        return Convert.ToChar(_Row[i]);
    }

    public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
    {
        throw new NotSupportedException("GetChars is not supported.");
    }

    public IDataReader GetData(int i)
    {
        throw new NotSupportedException("GetData is not supported.");
    }

    public string GetDataTypeName(int i)
    {
        return _Row[i].GetType().Name;
    }

    public DateTime GetDateTime(int i)
    {
        return Convert.ToDateTime(_Row[i]);
    }

    public decimal GetDecimal(int i)
    {
        return Convert.ToDecimal(_Row[i]);
    }

    public double GetDouble(int i)
    {
        return Convert.ToDouble(_Row[i]);
    }

    public Type GetFieldType(int i)
    {
        return _Row[i].GetType();
    }

    public float GetFloat(int i)
    {
        return Convert.ToSingle(_Row[i]);
    }

    public Guid GetGuid(int i)
    {
        return (Guid)_Row[i];
    }

    public short GetInt16(int i)
    {
        return Convert.ToInt16(_Row[i]);
    }

    public int GetInt32(int i)
    {
        return Convert.ToInt32(_Row[i]);
    }

    public long GetInt64(int i)
    {
        return Convert.ToInt64(_Row[i]);
    }

    public string GetName(int i)
    {
        return _Row.Table.Columns[i].ColumnName;
    }

    public int GetOrdinal(string name)
    {
        return _Row.Table.Columns.IndexOf(name);
    }

    public string GetString(int i)
    {
        return _Row[i].ToString();
    }

    public object GetValue(int i)
    {
        return _Row[i];
    }

    public int GetValues(object[] values)
    {
        values = _Row.ItemArray;
        return _Row.ItemArray.GetLength(0);
    }

    public bool IsDBNull(int i)
    {
        return Convert.IsDBNull(_Row[i]);
    }
    #endregion
}

Implementing GetChars() and GetBytes() seems to be a little overboard, so I haven’t done those.  Now I have a generic GetDataRecordBool function:

public static bool GetDataBool(IDataRecord data, string columnName, bool defaultValue)
{
    bool ReturnValue = defaultValue;
    int FieldValueAsInteger;
    int ColumnOrdinal;
    ColumnOrdinal = data.GetOrdinal(columnName);
    if (typeof(bool) == data.GetFieldType(ColumnOrdinal))
    {
        ReturnValue = data.GetBoolean(ColumnOrdinal);
    }
    else
    {
        FieldValueAsInteger = GetDataInt(data, columnName, defaultValue ? 1 : 0);
        ReturnValue = IntToBool(FieldValueAsInteger);
    }
    return ReturnValue;
}

where I can control how it handles different data types, that is easily implementable for both a DbDataReader:

public static bool GetReaderBool(DbDataReader reader, string columnName, bool defaultValue)
{
    return GetDataBool(reader, columnName, defaultValue);
}

and a DataTable:

public static bool GetTableBool(DataTable table, int row, string columnName)
{
    return GetDataBool(new DataRowAdapter(table.Rows[row]), columnName);
}

That’s nice because several of my data tool libraries have custom handling for the type.  For example, my GetDataString class formats the return value as currency for money types, short date for datetime types without a time, longdate for datetime types without time, etc.  Thanks Chris!

Floating points, precision, and significant digits

Filed under: Programming — Carl @ 7:56 am

I read Chris Vance’s blog entry about floating point numbers and inaccurate arithmetic.  It got me thinking about precision and significant digits, and a simple problem illustrates problems even with significance arithmetic.

Defining significant digits as all the digits that one knows precisely the value of and the first one that is an estimate (as it is typically the result of rounding subsequent digits), an example of 2222 means that we should consider the value to be between 2221.50 and 2222.50 (i.e., the set of values that equals 2222 to four significant digits, using round-to-even methodology).

Let’s take our value of 2222 and multiply by 444, to get a result of 986,568, which we should properly display as 987,000 (since the multiplicand 444 has 3 significant digits).  Properly expressed, 444 could be a value between 443.50 and 444.50, so I would expect the minimum value to be 2221.50 x 443.50 = 985,235.25 and the maximum value to be 2222.50 x 444.50 = 987,901.25, therefore even in this simple case the variation between the maximum and minimum values is greater than significance arithmetic can answer!

The rule of thumb that programmers should follow is this, IMO: Results should always be rounded to the number of digits that is the lesser of the float type’s precision and the least number of significant digits of the operand–and remember, accuracy suffers in the conversion of the decimal value to a binary value.  Even then, I wouldn’t trust it 100%!

More WSE Issues: Timestamp Validation and Clock Skew

Filed under: C#/.NET, Computers, Programming, WSE, Web Services, Windows Administration — Carl @ 7:34 am

My newly-deployed WSE 3.0-enabled site wasn’t working properly.  Invoking the service caused the following exception:

"WSE910: An error happened during the processing of a response message, and you can find the error in the inner exception.  You can also find the response message in the Response property."

Checking the InnerException, the real cause was this:

"WSE066: Timestamp is expired. This indicates a stale message but may also be caused by lack of synchronization between sender and receiver clocks. Make sure the clocks are synchronized or use the timeToleranceInSeconds element in the microsoft.web.services3 configuration section to adjust tolerance for lack of clock synchronization."

Step 1 was to make sure that the clock on the server was properly synchronized with an accurate NTP server.  I followed the steps in KB816042 to configure Windows Time service to use an external time source.  When that confirmed that the server time was accurate, I suspected that it had something to do with time zones, since the consumers of the service are in a different time zone.  Turning on WSE tracing let me look at the timestamp:

<wsu:Timestamp wsu:Id="Timestamp-4bd14e9e-37fa-4658-b1cb-43256498cb60">
  <wsu:Created>2007-03-20T17:34:31Z</wsu:Created>
  <wsu:Expires>2007-03-20T17:49:31Z</wsu:Expires>
</wsu:Timestamp>

confirming that it uses UTC for the timestamp.  Some more checking led me to an MSDN article on WS-I BSP Interoperability Guidance (Web Services-Interoperability Basic Security Profile, FYI) that discusses message age and clock skew.  I found these two statements:

“The <defaultTtlInSeconds> element specifies the number of seconds after creation that every outgoing SOAP message is valid. The default value is 5 minutes, but the WS-I SCM architecture document recommends that this is set to 900 seconds (15 minutes).”

“The <timeToleranceInSeconds> setting corresponds to the acceptable time difference (clock skew) between the sender and the recipient of a message. By default, it is configured to 300 seconds or 5 minutes. However, you can change this value in the service’s Web.config file if you require a different value. The WS-I SCM Architecture document recommends that this is set to 900 seconds (15 minutes).”

Setting the defaultTtlInSeconds to 900 on both server and client did the trick!  You can add these elements manually in web.config to the configuration/microsoft.web.services3/security section:

<defaultTtlInSeconds value="900" />
<timeToleranceInSeconds value="900" />

Older Posts »

Blog at WordPress.com.