1 2 module markov.json.decoder; 3 4 import markov.chain; 5 import markov.counter; 6 import markov.serialize; 7 import markov.state; 8 9 import std.algorithm; 10 import std.array; 11 import std.conv; 12 import std.json; 13 import std.range; 14 import std.stdio; 15 import std.typecons; 16 17 struct JsonDecoder(T) 18 { 19 MarkovChain!T decode(string input) 20 { 21 return MarkovChain!T(decodeStates(input.parseJSON)); 22 } 23 24 private: 25 State!T[] decodeStates(JSONValue json) 26 { 27 return json.array.map!(state => decodeState(state)).array; 28 } 29 30 State!T decodeState(JSONValue json) 31 { 32 State!T state = State!T(json["size"].str.to!uint); 33 34 foreach(first, counter; json["counters"].object) 35 { 36 state.set(decodeKeys(first), decodeCounter(counter)); 37 } 38 39 return state; 40 } 41 42 Counter!T decodeCounter(JSONValue json) 43 { 44 Counter!T counter; 45 46 foreach(follow, count; json.object) 47 { 48 counter.set(decodeKey(follow), count.str.to!uint); 49 } 50 51 return counter; 52 } 53 54 T[] decodeKeys(string keys) 55 { 56 return keys.to!(string[]).map!(k => decodeKey(k)).array; 57 } 58 59 T decodeKey(string key) 60 { 61 static if(hasDecodeProperty!(T, string)) 62 { 63 return T.decode(key); 64 } 65 else 66 { 67 return key.to!T; 68 } 69 } 70 } 71 72 MarkovChain!T decodeJSON(T)(string encoded) 73 { 74 JsonDecoder!T decoder; 75 return decoder.decode(encoded); 76 } 77 78 MarkovChain!T decodeJSON(T)(File input, size_t chunkSize = 4096) 79 { 80 return input.byChunk(chunkSize).joiner.map!(to!char).text.decodeJSON!T; 81 } 82 83 unittest 84 { 85 auto chain1 = MarkovChain!string(1, 2, 3); 86 chain1.train("a", "b", "c", "e", "b", "a", "b", "a", "c", "e", "d", "c", "b", "a"); 87 88 import markov.json.encoder; 89 auto chain2 = chain1.encodeJSON.decodeJSON!string; 90 91 assert(chain1.sizes.length == chain2.sizes.length); 92 93 foreach(state1, state2; chain1.states.sort!"a.size > b.size".lockstep(chain2.states.sort!"a.size > b.size")) 94 { 95 assert(state1.size == state2.size); 96 assert(state1.keys.length == state2.keys.length); 97 98 foreach(first1, first2; sort(state1.keys).lockstep(sort(state1.keys))) 99 { 100 assert(first1 == first2); 101 auto counters1 = state1.get(first1); 102 auto counters2 = state2.get(first2); 103 104 assert(counters1.total == counters2.total); 105 assert(sort(counters1.keys) == sort(counters2.keys)); 106 107 foreach(follow1, follow2; sort(counters1.keys).lockstep(sort(counters2.keys))) 108 { 109 assert(follow1 == follow2); 110 assert(counters1.get(follow1) == counters2.get(follow2)); 111 } 112 } 113 } 114 }