NodesDegree.cs
1 using CodexClient; 2 using CodexPlugin.OverwatchSupport; 3 using OverwatchTranscript; 4 5 namespace TranscriptAnalysis.Receivers 6 { 7 public class NodesDegree : BaseReceiver<OverwatchCodexEvent> 8 { 9 public class Dial 10 { 11 public Dial(Node peer, Node target) 12 { 13 Id = GetLineId(peer.Id, target.Id); 14 InitiatedBy.Add(peer); 15 Peer = peer; 16 Target = target; 17 } 18 19 public string Id { get; } 20 public int RedialCount => InitiatedBy.Count - 1; 21 public List<Node> InitiatedBy { get; } = new List<Node>(); 22 public Node Peer { get; } 23 public Node Target { get; } 24 25 private string GetLineId(string a, string b) 26 { 27 if (string.Compare(a, b) > 0) 28 { 29 return a + b; 30 } 31 return b + a; 32 } 33 } 34 35 public class Node 36 { 37 public Node(string peerId) 38 { 39 Id = peerId; 40 } 41 42 public string Id { get; } 43 public List<Dial> Dials { get; } = new List<Dial>(); 44 public int Degree => Dials.Count; 45 } 46 47 private readonly Dictionary<string, Node> dialingNodes = new Dictionary<string, Node>(); 48 private readonly Dictionary<string, Dial> dials = new Dictionary<string, Dial>(); 49 private long uploadSize; 50 51 public override string Name => "NodesDegree"; 52 53 public override void Receive(ActivateEvent<OverwatchCodexEvent> @event) 54 { 55 if (@event.Payload.DialSuccessful != null) 56 { 57 var peerId = GetPeerId(@event.Payload.NodeIdentity); 58 if (peerId == null) return; 59 AddDial(peerId, @event.Payload.DialSuccessful.TargetPeerId); 60 } 61 if (@event.Payload.FileUploaded != null) 62 { 63 var uploadEvent = @event.Payload.FileUploaded; 64 uploadSize = uploadEvent.ByteSize; 65 } 66 } 67 68 public override void Finish() 69 { 70 var csv = CsvWriter.CreateNew(); 71 72 var numNodes = dialingNodes.Count; 73 var redialOccurances = new OccuranceMap(); 74 foreach (var dial in dials.Values) 75 { 76 redialOccurances.Add(dial.RedialCount); 77 } 78 var degreeOccurances = new OccuranceMap(); 79 foreach (var node in dialingNodes.Values) 80 { 81 degreeOccurances.Add(node.Degree); 82 } 83 84 Log($"Dialing nodes: {numNodes}"); 85 Log("Redials:"); 86 redialOccurances.PrintContinous((i, count) => 87 { 88 Log($"{i} redials = {count}x"); 89 }); 90 91 float tot = numNodes; 92 csv.GetColumn("numNodes", Header.Nodes.Length); 93 csv.GetColumn("filesize", uploadSize.ToString()); 94 var degreeColumn = csv.GetColumn("degree", 0.0f); 95 var occuranceColumn = csv.GetColumn("occurance", 0.0f); 96 degreeOccurances.Print((i, count) => 97 { 98 float n = count; 99 float p = 100.0f * (n / tot); 100 Log($"Degree: {i} = {count}x ({p}%)"); 101 csv.AddRow( 102 new CsvCell(degreeColumn, i), 103 new CsvCell(occuranceColumn, n) 104 ); 105 }); 106 107 CsvWriter.Write(csv, SourceFilename + "_nodeDegrees.csv"); 108 } 109 110 private void AddDial(string peerId, string targetPeerId) 111 { 112 peerId = CodexUtils.ToShortId(peerId); 113 targetPeerId = CodexUtils.ToShortId(targetPeerId); 114 115 var peer = GetNode(peerId); 116 var target = GetNode(targetPeerId); ; 117 118 var dial = new Dial(peer, target); 119 120 if (dials.ContainsKey(dial.Id)) 121 { 122 var d = dials[dial.Id]; 123 d.InitiatedBy.Add(peer); 124 peer.Dials.Add(d); 125 target.Dials.Add(d); 126 } 127 else 128 { 129 dials.Add(dial.Id, dial); 130 peer.Dials.Add(dial); 131 target.Dials.Add(dial); 132 } 133 } 134 135 private Node GetNode(string id) 136 { 137 if (!dialingNodes.ContainsKey(id)) 138 { 139 dialingNodes.Add(id, new Node(id)); 140 } 141 return dialingNodes[id]; 142 } 143 } 144 }