private static IDecisionNode NodeToDecisionTree(IDataNode node)
 {
     if (node is DataLeaf)
     {
         DataLeaf leaf   = (DataLeaf)node;
         Tactic   tactic = EnumUtils.GetEnumValues <Tactic>().MaxBy(t => leaf.ClassDistribution[(int)t]);
         return(new DecisionLeaf(tactic));
     }
     else if (node is AttributeSplit)
     {
         AttributeSplit attributeSplit = (AttributeSplit)node;
         return(new DecisionNode {
             Partitioner = new ContinuousPartitioner((ContinuousAxis)attributeSplit.Axis, attributeSplit.SplitValue),
             Left = NodeToDecisionTree(attributeSplit.Left),
             Right = NodeToDecisionTree(attributeSplit.Right),
         });
     }
     else if (node is CategoricalSplit)
     {
         CategoricalSplit categoricalSplit = (CategoricalSplit)node;
         return(new DecisionNode {
             Partitioner = new CategoricalPartitioner(
                 (CategoricalAxis)categoricalSplit.Axis,
                 PolicyHelper.BitsToCategories((CategoricalAxis)categoricalSplit.Axis, categoricalSplit.Categories).ToArray()),
             Left = NodeToDecisionTree(categoricalSplit.Left),
             Right = NodeToDecisionTree(categoricalSplit.Right),
         });
     }
     else
     {
         throw new ArgumentException("Unknown node type: " + node);
     }
 }
 private static List <DataPoint> EpisodesToDataPoints(List <Episode> episodes)
 {
     return(episodes.AsParallel().Select(episode => new DataPoint {
         Episode = episode,
         Class = (byte)episode.Tactic,
         Weight = (float)episode.Weight,
         Attributes =
             EnumUtils.GetEnumValues <ContinuousAxis>()
             .Select(axis => (float)ContinuousAxisEvaluator.Evaluate(axis, episode.World, episode.Hero))
             .ToArray(),
         Categories =
             EnumUtils.GetEnumValues <CategoricalAxis>()
             .Select(axis => PolicyHelper.CategoriesToBits(CategoricalAxisEvaluator.Evaluate(axis, episode.World, episode.Hero)))
             .ToArray(),
     }).ToList());
 }