Monday, January 08, 2007

Online simulation games and learning

I really like the concept of using games to learn something.

Games are fun, and can take a subject that a person may find boring, and put a fun slant on it.

My kids are interested in this MMORPG game called Dofus right now. We did the 7 day free trial and then I bought a month of play time for them. I think they like to concept it shares with Pokemon and other fantasy games: characters that can "evolve" in some way. Gain knowledge and skill, new powers, etc.

I remember when I was a kid, this character development was a powerful thing for me. I used to have loads of fun just talking through being different characters with my friends.

Now, the Dofus game does not have a direct educational element to it. But there are lots of lessons in there.

  • How to work together as a group for a common goal
  • Evaluating risk -- knowing when not to battle with another character because it is too powerful
  • Working toward a long-term goal -- they see other characters further along and see that they can get there too if they work at it

The tough nut to crack is how to make an intentionally educational game as appealing as the entertainment games are for kids.

The first 6 months of the year, I worked on a project funded by a grant from the National Science Foundation. We created a prototype of an online, multiplayer game for kids dealing with Global Warming. We called it C02FX

CO2FX is a web based multi-user educational game which explores the relationship of global warming to economic, political and science policy decisions. The game is driven by a systems dynamics model and is presented in a user friendly interface intended for the high school user.

I think in the 6 month time period we had, we did a pretty good job on this game. We used a STELLA model to drive the simulation, and Flash to build the user interface.

Dofus uses Flash as the interface as well, and it is very slick. It is the best looking Flash application I have ever seen. Something to work towards if the team can take C02FX on further.

We are still looking for funding for the next phase of development. We may be awarded a phase 2 grant from NSF, but we need to demonstrate the ability for the application or platform to be productized.

Anyone have any good examples of this?

High Performance Systems used to have a relationship with Harvard Business School Publishing and created a few Learning Environments that were used in course study and sold as stand alone applications. These Learning Environments were CD ROM based and had ithink models driving them.

HPS also created other Learning Environments, that I think were ahead of their time. Maybe now the world is ready for this sort of thing...

Reflection in .NET

A couple of days ago I used Reflection for the first time in a .NET project. Very cool.

I have always known the System.Reflection namespace was there and a very high level understanding of what it does, but never actually used it or seemed to have a need to.

Well, on Wednesday I had a need for it. I was trying to map bits of XML structure into strongly-typed .NET classes. So I'd have something like this:


weirdo-stuff
3
XR34R
278.42

...that I wanted to turn into a .NET class.

So my dilemma was this: I had to write virtually the same piece of code over and over for each node in the XML to map it to the appropriate property in the class I was building and cast the value from the XML to the appropriate type.

So I thought, "...what I need is a function where I can pass in the property name, the XML node name and data type and have it populate the correct property with the correct type". And then I said it out loud to Ryan. And he said, "..in Java you'd use Reflection." "Ahhh..." I said.

With Reflection you can query an object for meta data at run-time.

In .NET everything that inherits from System.Object, gets a method called getType(). This returns a "System.Type" type. Then on that type object, you can ask for information about a property of the object by passing a string of the property name. Then you can tell the reflected property information to set a value for that property by passing an object for the value and a reference to object instance that contains the property.

Here is a snippet of the code:

Type theType = obj.GetType();
PropertyInfo propInfo = theType.GetProperty(propertyName);
//To hold the value of the property we wish to set
object propValue = new Object();
//The type of the property we wish to set
Type propType = propInfo.PropertyType;
//The string value from the XML, which we will convert to the appropraite type
//for the property we wish to set
string xmlValue = xmlMarkupRoot[childNodeName].InnerText;
//Here we'll need to test for the basic types
if(propType == (Type.GetType("System.Double")))
{
propValue = Convert.ToDouble(xmlValue);
}
else if (propType == (Type.GetType("System.String")))
{
propValue = xmlValue;
}
else if (propType == (Type.GetType("System.Int16")))
{
propValue = Convert.ToInt16(xmlValue);
}
else if (propType == (Type.GetType("System.Int32")))
{
propValue = Convert.ToInt32(xmlValue);
}
else if (propType == (Type.GetType("System.Single")))
{
propValue = Convert.ToSingle(xmlValue);
}
else if (propType == (Type.GetType("System.Boolean")))
{
propValue = Convert.ToBoolean(xmlValue);
}
propInfo.SetValue(obj, propValue, null);
Pretty sweet.

ASP.NET -- Cleaning up objects that live in the Session when the session ends

I spent a while coming up with this solution, so here it is for all the world to enjoy.

So you have some object that needs to be persisted between pages, so you pop it into the Session. This object may need to have some clean up done to it when it's done being used to free up resources -- like say calling the Dispose() method or similar clean up to take care of unmanaged resources.

No problem, just wire some code to the old Session_End event in Global.asax and call Dispose(). Well, that is wrong as you probably know. When Session_End fires, you can no longer reference the Session, which means you can get a reference to your object.

So here is what I did -- I put my object in the Cache instead. The Cache is Application wide, so I key the object by the users SessionID. When I insert the object in the Cache, I set a sliding expiration that is equal to the Session timeout.


string sessionKey = HttpContext.Current.Session.SessionID;
TimeSpan sessionTimeout = TimeSpan.FromMinutes(HttpContext.Current.Session.Timeout)
CacheItemRemovedCallback onRemove = new CacheItemRemovedCallback(someClass.SomeStaticMethod);

HttpContext.Current.Cache.Insert(sessionKey, /* key */
mySessionObject, /* the object */
null, /* dependency - file, folder or other keys */
Cache.NoAbsoluteExpiration, /* Absolute Expiration */
sessionTimeout, /* Sliding expiration */
CacheItemPriority.NotRemovable, /* Priority */
onRemove /* Callback function when removed */);

The key here is the sliding expiration. The timer counts down and is reset every time the object is accessed. So when the user closes the browser or leaves the site, the timer will eventually count down and expire the object from the Cache. That's when the callback function is fired. The callback function passes the key, the object and a reason why it expired to the handler. So you can grab the object at that point and call Dispose() or what have you to do the clean up you need to do.


public static void onRemoveObjectFromCache(string key, object value, CacheItemRemovedReason r)
{
MyCoolObject obj (MyCoolObject) value;
obj.Dispose();
obj.CleanUp();
obj.WhateverElseNeedsToBeDone();
}