protected override void Update(GameTime gameTime) { base.Update(gameTime); var dt = (float)gameTime.ElapsedGameTime.TotalSeconds; if (Keyboard.GetState().IsKeyDown(Keys.S)) { dt *= 10; } for (var i = 0; i < agents.Length; i++) { var agent = agents[i]; agent.Position += agent.Velocity * dt; if (agent.Position.X < configuration.AgentRadius) { agent.Velocity.X = Math.Abs(agent.Velocity.X); } if (agent.Position.X > configuration.FieldWidth - configuration.AgentRadius) { agent.Velocity.X = -Math.Abs(agent.Velocity.X); } if (agent.Position.Y < configuration.AgentRadius) { agent.Velocity.Y = Math.Abs(agent.Velocity.Y); } if (agent.Position.Y > configuration.FieldHeight - configuration.AgentRadius) { agent.Velocity.Y = -Math.Abs(agent.Velocity.Y); } agent.BluetoothAdapter.Permit(dt); } int columns = 1 + (configuration.FieldWidth - 1) / SimulationBluetoothConstants.RANGE; int rows = 1 + (configuration.FieldHeight - 1) / SimulationBluetoothConstants.RANGE; var bins = Enumerable.Range(0, columns * rows).Select(i => new List <DeviceAgent>()).ToArray(); foreach (var agent in agents) { var binX = ((int)agent.Position.X) / SimulationBluetoothConstants.RANGE; var binY = ((int)agent.Position.Y) / SimulationBluetoothConstants.RANGE; bins[binX + binY * columns].Add(agent); } var processAgentPair = new Action <DeviceAgent, DeviceAgent>((a, b) => { var distanceSquared = (a.Position - b.Position).LengthSquared(); if (distanceSquared < SimulationBluetoothConstants.RANGE_SQUARED) { if (!a.ActiveConnectionStates.ContainsKey(b)) { var connectionState = new SimulationBluetoothConnectionState(); if (!a.BluetoothAdapter.NeighborsByAdapterId.ContainsKey(b.BluetoothAdapterId)) { var connectionContext = new SimulationBluetoothAdapter.SimulationConnectionContext(a, b); a.BluetoothAdapter.NeighborsByAdapterId[b.BluetoothAdapterId] = new SimulationBluetoothAdapter.SimulationBluetoothNeighbor(a, connectionContext); b.BluetoothAdapter.NeighborsByAdapterId[a.BluetoothAdapterId] = new SimulationBluetoothAdapter.SimulationBluetoothNeighbor(b, connectionContext); connectionContext.Start(); } a.ActiveConnectionStates.AddOrThrow(b, connectionState); b.ActiveConnectionStates.AddOrThrow(a, connectionState); } } }); var processBins = new Action <List <DeviceAgent>, List <DeviceAgent> >((a, b) => { if (a == null || b == null) { return; } if (a == b) { for (var i = 0; i < a.Count - 1; i++) { for (var j = i + 1; j < a.Count; j++) { processAgentPair(a[i], a[j]); } } } else { for (var i = 0; i < a.Count; i++) { for (var j = 0; j < b.Count; j++) { processAgentPair(a[i], b[j]); } } } }); for (var y = 0; y < rows; y++) { for (var x = 0; x < columns; x++) { var a = bins[x + y * columns]; var right = x + 1 < columns ? bins[(x + 1) + y * columns] : null; var bottom = (y + 1 < rows) ? bins[x + (y + 1) * columns] : null; var bottomRight = (x + 1 < columns && y + 1 < rows) ? bins[(x + 1) + (y + 1) * columns] : null; processBins(a, a); processBins(a, right); processBins(a, bottom); processBins(a, bottomRight); processBins(right, bottom); } } var dConnectnessInRangeBase = dt * 5.0f; var dConnectnessOutOfRangeBase = -dt * 50.0f; foreach (var agent in agents) { foreach (var pair in agent.ActiveConnectionStates) { if (agent.BluetoothAdapterId.CompareTo(pair.Key.BluetoothAdapterId) < 0) { continue; } var other = pair.Key; var connectivity = SimulationBluetoothCalculator.ComputeConnectivity(agent, other); var deltaConnectedness = (connectivity.InRange ? connectivity.SignalQuality * dConnectnessInRangeBase : dConnectnessOutOfRangeBase); var connectionState = pair.Value; float nextConnectedness = Math.Max(0.0f, Math.Min(1.0f, connectionState.Connectedness + deltaConnectedness)); connectionState.Quality = connectivity.SignalQuality; connectionState.Connectedness = nextConnectedness; if (nextConnectedness == 0.0f) { agent.ActiveConnectionStates.RemoveOrThrow(other); other.ActiveConnectionStates.RemoveOrThrow(agent); } } } // for (var i = 0; i < agents.Length - 1; i++) { // var a = agents[i]; // var aConnectionStates = a.BluetoothState.ConnectionStates; // for (var j = i + 1; j < agents.Length; j++) { // var b = agents[j]; // var bConnectionStates = b.BluetoothState.ConnectionStates; // } // } if (Keyboard.GetState().IsKeyDown(Keys.A)) { epoch++; epochAgentIndex = (int)(new Random(epochAgentIndex + 5).Next(0, agents.Length)); agents[epochAgentIndex].Client.BroadcastAsync(BitConverter.GetBytes(epoch)).Forget(); } if (Keyboard.GetState().IsKeyDown(Keys.Z)) { while (epoch < 5) { epoch++; epochAgentIndex = (int)(new Random(epochAgentIndex + 5).Next(0, agents.Length)); agents[epochAgentIndex].Client.BroadcastAsync(BitConverter.GetBytes(epoch)).Forget(); } } if (Keyboard.GetState().IsKeyDown(Keys.X)) { while (epoch < 10) { epoch++; epochAgentIndex = (int)(new Random(epochAgentIndex + 5).Next(0, agents.Length)); agents[epochAgentIndex].Client.BroadcastAsync(BitConverter.GetBytes(epoch)).Forget(); } } }
private async Task RunAsync() { var pendingBeginConnect = (BeginConnectEvent)null; while (true) { var adapterEvent = await adapterEventQueueChannel.ReadAsync(CancellationToken.None, x => true).ConfigureAwait(false); switch (adapterEvent.GetType().Name) { case nameof(BeginConnectEvent): var beginConnect = (BeginConnectEvent)adapterEvent; if (pendingBeginConnect == null) { pendingBeginConnect = beginConnect; } else { firstDisconnectChannel.SetIsClosed(false); secondDisconnectChannel.SetIsClosed(false); var pendingBeginConnectCapture = pendingBeginConnect; pendingBeginConnect = null; pendingBeginConnectCapture.ResultBox.SetResult(true); beginConnect.ResultBox.SetResult(true); } break; case nameof(TimeoutConnectEvent): var timeout = (TimeoutConnectEvent)adapterEvent; if (timeout.BeginEvent == pendingBeginConnect) { pendingBeginConnect.ResultBox.SetException(new TimeoutException()); pendingBeginConnect = null; } break; case nameof(SendEvent): var send = (SendEvent)adapterEvent; if (!GetIsConnected(send.Initiator)) { send.CompletionBox.SetException(new NotConnectedException()); break; } var connectivity = SimulationBluetoothCalculator.ComputeConnectivity(firstAgent, secondAgent); if (!connectivity.InRange) { firstDisconnectChannel.SetIsClosed(true); secondDisconnectChannel.SetIsClosed(true); send.CompletionBox.SetException(new NotConnectedException()); break; } var deltaBytesSent = (int)Math.Ceiling(connectivity.SignalQuality * send.Interval.TotalSeconds * SimulationBluetoothConstants.MAX_OUTBOUND_BYTES_PER_SECOND); var bytesSent = send.BytesSent + deltaBytesSent; if (bytesSent >= send.Payload.Length) { await ChannelsExtensions.WriteAsync(GetOtherInboundChannelInternal(send.Initiator), send.Payload).ConfigureAwait(false); send.CompletionBox.SetResult(true); break; } var nextEvent = new SendEvent(DateTime.Now + send.Interval, send.Interval, send.Initiator, send.CompletionBox, send.Payload, bytesSent); await adapterEventQueueChannel.WriteAsync(nextEvent, CancellationToken.None).ConfigureAwait(false); break; } } }