The Neanderthal Versus the Professor

For months now I have been struggling with a nasty problem, and it is all the fault of Facundo Dominguez. In programming SWAT, he created an elegant, highly flexible system for handling personality traits. My old system was simple and stupid. There were three basic personality traits: Good, Honest, and Powerful. For each of these, there were three arrays, representing the intrinsic value, the perceived value of each of the other actors, and the P3:

Good[a]
PGood[a][b]
P3Good[a][b][c]

But for Swat, we wanted something more flexible, something that would permit the author to define new traits. This required an editor and a data structure capable of handling this kind of variability. Facundo, who is a top-notch programmer as well a degreed computer scientist, came up with a truly elegant system for handling the problem. The problem with his system is that it is so elegant that I can’t understand it. In this essay, I shall attempt to explain his system, in the hope that the effort will help me understand it. And if I can’t properly explain it here, then I shall contemplate a lobotomy (for the code, not me).

Property Maps
The core data structure he uses is the class PropertyMap. This class wraps three EnumMaps into a single class, with overloading that permits the programmer to make a single call always returns the correct value. Thus, a single get() method can return the value from which of the three internal maps is specified by the trait passed as a parameter. As Facundo states in a comment:

* get(FloatTrait t)  returns things of the first map
* get(P2FloatTrait t)
  returns things of the second map
* get(KnowsTrait t)  returns things of the third map

OK, I can understand that. Where I stumble is with the simpler concept of an EnumMap. I think I grasp the basic concept of an EnumMap: the key is a set of constants defined in an EnumClass, and a get() using a key will return its associated value. But Facundo’s EnumMaps have three parameters — what the hell is going on here? Here is one of his EnumMap declarations:

private EnumMap<TraitType,ArrayList<ValueT>> ft = new EnumMap<TraitType,ArrayList<ValueT>>(TraitType.class);

There are four parameters specified in this declaration: TraitType, ArrayList<ValueT>, ValueT, and TraitType.class

public static enum TraitType { NormalWeightAccord }

But here’s the killer: nowhere in the project is ValueT declared as a class. It’s definitely a class as demonstrated by this method:

public void set(MoodTrait t,ValueT f){ mt.put(t,f); }

The Java find feature in Eclipse finds 16 references to ValueT, all in the same file, and not one of them defines the class. There is this cryptic comment:

* where ValueT, P2ValueT, and KnowsValueT are type parameters
* that you instantiate whatever you like.

So is ValueT an Abstract Class? It certainly doesn’t show up anywhere in the project as such. So I did a little experimenting. In the set() method above, I replaced “f” with “27”. That got a reaction: an error described as “Syntax error, VariableDeclaratorId expected after this token”. So I searched around the Web to find descriptions of the error message and figured out that f, whatever it is, must be a variable of some sort. So I searched the code some more and found a case where this set() method was called. The call had a String for the variable “f”. When I replaced the String value with the number 27, I got another error message: Java wanted a String there. What god declared that ValueT must be a String? And if they want it to be a String, why not just use “String” instead of “ValueT”? Oh, well, at least I now know that ValueT is a String.

The final item to figure out is TraitType.class. I already know that TraitType is an Enum, but what does TraitType.class mean? More Web research reveals a genuine problem: the Java documentation for Class EnumMap does not provide a constructor of the type Facundo is using. The closest version in the documentation is

EnumMap(Class<K> keyType)

So TraitType.class is the key for the EnumMap, but what the hell is the gobbledygook inside angle brackets? What does <TraitType, ArrayList<ValueT>> mean? Are these the two values that the key value maps to? That doesn’t make sense to me: why map a TraitType to TraitType.class?

On top of this is the question, where’s the numeric value that is supposed to be stored in the map? I know that I can ask the property map to give me the value of a particular variable, but I don’t see it in the code. Here’s what the method

public ValueT get(TraitType tt,FloatTrait t){
   
final ArrayList<ValueT> ts = ft.get(tt);
   
if (t.getValuePosition()<ts.size())
      
return ts.get(t.getValuePosition());
   
else 
      
return null;
}

Here the code returns a value of class ValueT. But I learned above that ValueT is a String. Apparently ValueT is some sort of metaclass that could mean any class. But how does that work? I have no idea what’s going on here.

Time for the scalpel
I therefore conclude that I cannot figure out any of this stuff; it is over my head. I must, accordingly, devise a new system that works reliably for me. At present, I do have a truly clumsy system in place, but it entails all sorts of nonsense. Here, for example, is the code used for one of the calculations in my current task:

float p3 = 0;
float u3 = 0;
for (int j = i; (j < dk.getActors().size()); ++j) {
   
if ((j!=_4Actor) & (j!=dirObject)) {
      
if (traitName.equals("Good")) {
         u3 =
dk.getActor(dirObject).getU3Good(i, _4Actor);
         p3 =
dk.getActor(dirObject).getP3Good(i, _4Actor);
      }
      
else if (traitName.equals("Honest")) {
         u3 =
dk.getActor(dirObject).getU3Honest(i, _4Actor);
         p3 =
dk.getActor(dirObject).getP3Honest(i, _4Actor);
      }
      
else if (traitName.equals("Powerful")) {
         u3 =
dk.getActor(dirObject).getU3Powerful(i, _4Actor);
         p3 =
dk.getActor(dirObject).getP3Powerful(i, _4Actor);
      }
      
else {
         
System.out.println("pushCorrespondingP3Value bad trait name: "+traitName);
      }
      netMean = combinedMeans(netMean, netUncertainty,  p3, u3);
      netUncertainty = combinedUncertainties(netUncertainty,  u3);
   }
}

This is truly ugly, nasty code; I’m embarrassed to let the world see how stupid a programmer I am. However, I can claim good intentions: I’d like to improve this code. What I’d like is an indexable system that allows me to reference each of these values by a variable. For example, this would be an ideal situation for an EnumMap with the key being an EnumType of { Good, Honest, Powerful } Thus, I could refer to a P3Value as follows:

p3 = dk.getActor(actorIndex).get(Good, p2ActorIndex, p3ActorIndex);

I could overload the get() method like so:

p2 = dk.getActor(actorIndex).get(Honest, p2ActorIndex);

These data would be stored in simple arrays:

p3Array[virtue][8][8];
p2[virtue][8];
p1[virtue];

Even *I* can understand this arrangement. I’ll have to hand-insert these traits into the Operator List, but otherwise it will be easy to implement.

OK, decision made.