public weka.core.Instance GenerateFeatures(PokerHand hand, int rIdx, int aIdx, weka.core.Instances data, bool generateClass = true) { // Check that we are using limit betting. Debug.Assert(hand.Context.BettingType == BettingType.FixedLimit); var results = new weka.core.Instance(data.numAttributes()); results.setDataset(data); int attIdx = 0; foreach (var method in typeof(LimitFeatureGenerator).GetMethods()) { // Get all the features of this class. var attributes = method.GetCustomAttributes(typeof(Feature), true); if (attributes.Length == 0) continue; // Get the feature attribute on this method. var attr = ((Feature)attributes[0]); // Get the name for this attribute string name = attr.Name; //Console.WriteLine("Hand: {0} Feature: {1}", hand.Context.ID, name); // Get the feature only if it's applicable to this situation. object feature = null; if(rIdx >= (int)attr.MinRound && rIdx <= (int)attr.MaxRound) feature = method.Invoke(this, new object[] { hand, rIdx, aIdx }); if (SkipMissingFeatures && (feature == null || feature.ToString() == "?")) continue; switch (attr.FType) { case FeatureType.Continuous: results.setValue(attIdx, (double)feature); break; case FeatureType.Discrete: results.setValue(attIdx, (int)feature); break; case FeatureType.Boolean: case FeatureType.Nominal: case FeatureType.Enum: { var attribute = data.attribute(attIdx); var attVal = attribute.indexOfValue(feature.ToString()); if(attVal < 0 || attVal > attribute.numValues()) throw new Exception(string.Format ("Invalid attribute value: {0} for attribute {1} (idx: {2} total values: {3}", feature.ToString(), name, attVal, attribute.numValues())); results.setValue(attribute, attVal); } break; case FeatureType.String: { var attribute = data.attribute(attIdx); results.setValue(attribute, feature.ToString()); } break; default: throw new Exception("Unspecified feature type for feature: " + method.Name); } attIdx++; } if(generateClass) { var classAttr = data.classAttribute(); switch (hand.Rounds[rIdx].Actions[aIdx].Type) { case ActionType.Bet: case ActionType.Raise: results.setClassValue(classAttr.indexOfValue("Raise")); break; case ActionType.Call: case ActionType.Check: results.setClassValue(classAttr.indexOfValue("Call")); break; case ActionType.Fold: results.setClassValue(classAttr.indexOfValue("Fold"));; break; default: break; } } return results; }
public override double classifyInstance(Instance instance) { if (m_mustValue.HasValue) return m_mustValue.Value; instance.setDataset(m_sampleInstances); instance.setClassValue(0); m_sampleInstances.clear(); m_sampleInstances.add(instance); double[] d = classifyInstances(m_sampleInstances); return d[0]; }