3

I have an object that I need to send over the network using TCP. I had this working fine, but I have now expanded on my implementation and am having trouble working out how to define my FlatBuffer schema.

The object to be sent is this:

public class Prediction
{
    public PredictionMethod PredictionMethod { get; set; }
    public NGramPrediction NGramPrediction { get; set; }
    public DistancePrediction DistancePrediction { get; set; }
    public int NGramOrder { get; set; }
}

PredictionMethod is an enum:

public enum PredictionMethod
{
    Distance = 1,
    NGram = 2,
}

NGramPrediction looks like this:

 public class NGramPrediction
{
    public KeyValuePair<char, int> Gram { get; set; }
    public double Probability { get; set; }
    public string Pattern { get; set; }
    private int Total { get; set; }
    private int Order { get; set; }

    public NGramPrediction(Gram gram)
    {
        Total = gram.Total();
        var orderedKeyPosibilities = gram.Posibilities.OrderByDescending(x => x.Value);

        Gram = orderedKeyPosibilities.First();

        Pattern = gram.Pattern;
        Probability = (double)Gram.Value / Total;

        Order = Pattern.Length;
    }
}

Gram looks like this:

public class Gram
{
    public string Pattern { get; set; }

    public Dictionary<char, int> Posibilities { get; set; }

    public Gram(List<char> posibilities, int initialValue = 0)
    {
        Posibilities = new Dictionary<char, int>();
        foreach (var posibility in posibilities)
        {
            Posibilities.Add(posibility, initialValue);
        }
    }

    public int Total()
    {
        var keys = Posibilities.Keys;
        var total = 0;
        foreach (var key in keys)
        {
            var value = Posibilities[key];
            total += value;
        }
        return total;
        // return keys.Sum(key => Posibilities[key]);
    }

}

DistancePrediction looks like this:

public class DistancePrediction
{
    public IIRVector3 Velocity { get; set; }
    public float DeltaTime { get; set; }
    public IIRVector3 Position { get; set; }
}

and finally, IIRVector3 looks like this:

public class IIRVector3
{
    public IIRVector3()
    {
        X = 0;
        Y = 0;
        Z = 0;
    }
    public float X { get; set; }
    public float Y { get; set; }
    public float Z { get; set; }
}

I'm trying to define my schema for FlatBuffers:

enum FBPredictionMethod
{
    Distance = 1,
    NGram = 2
}

struct FBIIRVector3
{
    X:float;
    Y:float;
    Z:float;
}

table FBDistancePrediction
{
    Velocity:FBIIRVector3;
    DeltaTime:float;
    Position:FBIIRVector3;
}

table FBGram
{
    Pattern:string;
    Possibilities: ????
}

table FBNGramPrediction
{
   Gram: ????
   Probability:float;
   Pattern:string;
   Total:short;
   Order:short;
}

table FBPrediction
{
    PredictionMethod:FBPredictionMethod;
    NGramPrediction:FBNGramPrediction;
    DistancePrediction:FBDistancePrediction;
    NGramOrder:short;
}

root_type FlatServerToClientMessage;

I think everything looks correct, but I have no idea what to do for the dictionaries...

FBGram.Possibilities should be a Dictionary<char, int> and FBGram should be KeyValuePair<char, int>.

Note: Gram's constructor takes a List<char> and an int as parameters, while the constructor for NGramPrediction takes a Gram as a parameter.

Could someone help me with my schema, please?

pookie
  • 3,796
  • 6
  • 49
  • 105

1 Answers1

3

The KeyValuePair should be easy.. either just store them as two seperate fields, or use a struct KeyValuePair { key:byte; value:int; }

The Dictionary could be stored as Possibilities:[KeyValuePair] (using that same struct). If you wanted to save space if Possibilities can be large, then PossibilityKeys:[byte] and PossibilityValues:[int] will be a little bit more compact, but harder to read/write.

Aardappel
  • 5,559
  • 1
  • 19
  • 22
  • 2
    @Aardapple My friend, we meet again! You helped me on a previous protobuff issue. That is a great idea! I will give it a go. Do you see any issues with Gram? Could I use [byte] for a list of char? – pookie Nov 29 '16 at 17:58
  • Actually, I forgot `char` is unicode in C#, so you may need `ushort` instead of `byte`. – Aardappel Nov 29 '16 at 21:04
  • @Aardapple I have no idea how to deal with the constructors. As you can see, Gram takes a list of char (easy to make, but how to pass to the constructor??) which populates Possibilities, and NGramPrediction takes a Gram as a constructor (not the KeyValuePair). Any way to deal with this? – pookie Nov 30 '16 at 09:40