-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TODO: Test for bugs TODO: Decide which tests to run
- Loading branch information
Showing
10 changed files
with
300 additions
and
109 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import statistics | ||
class Data(object): | ||
|
||
def __init__(self): | ||
self.d = {} | ||
|
||
def putSend(self, id, sendTime): | ||
if id not in self.d: | ||
self.d[id] = { 'sendTime' : sendTime, 'receiveTime' : -1 } | ||
else: | ||
self.d[id]['sendTime'] = sendTime | ||
|
||
def putReceive(self, id, receiveTime): | ||
if id not in self.d: | ||
self.d[id] = { 'sendTime' : -1, 'receiveTime' : receiveTime } | ||
else: | ||
self.d[id]['receiveTime'] = receiveTime | ||
|
||
def rawData(self): | ||
return self.d | ||
|
||
def sendTime(self, id): | ||
return self.d[id]['sendTime'] | ||
|
||
def receiveTime(self, id): | ||
return self.d[id]['receiveTime'] | ||
|
||
def latency(self, id): | ||
if self.receiveTime(id) != -1: | ||
return self.d[id]['receiveTime'] - self.d[id]['sendTime'] | ||
else: | ||
return None | ||
|
||
def latencyList(self): | ||
return [self.latency(x) for x in self.d if self.latency(x) is not None] | ||
|
||
def averageLatency(self): | ||
return statistics.median(self.latencyList) | ||
|
||
def numDropped(self): | ||
return len([self.receiveTime(x) for x in self.d if self.receiveTime(x) is None]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,88 @@ | ||
import cloud, device, game, network | ||
import cloud, device, network, packet, data | ||
import heapq | ||
|
||
CLOUD = 0 | ||
MAX_PACKETS_PER_STEP = 350 # https://blog.cloudflare.com/how-to-receive-a-million-packets/ | ||
|
||
class Simulator(object): | ||
|
||
def __init__ (cloud, network, device, game): | ||
self.cloud = cloud | ||
def __init__(self, cloud, network, devices, simTime): | ||
self.endpoints = [cloud] + devices | ||
self.network = network | ||
self.device = device | ||
self.game = game | ||
self.time = 0 | ||
self.endTime = simTime | ||
|
||
# Priority queue of tuples (timestamp+elapsedtime, packet) | ||
self.activePackets = [] | ||
|
||
def run(self): | ||
for timeStep in xrange(self.endTime): | ||
self.runStep(timeStep) | ||
|
||
def getResults(self): | ||
results = [] | ||
for deviceID in xrange(1, self.numEndpoints()): | ||
results.append(self.endpoints[deviceID].data) | ||
return results | ||
|
||
def numEndpoints(self): | ||
return len(self.endpoints) | ||
|
||
def runStep(self, step): | ||
self.deliverReadyPackets(step) | ||
self.updateActivePackets(step) | ||
|
||
def sendThruNetwork(self, packet): | ||
senderLocation = self.locationOf(packet.sender) | ||
receiverLocation = self.locationOf(packet.receiver) | ||
response = self.network.networkDelay(senderLocation, receiverLocation) | ||
if notDropped(reponse): | ||
delay = response | ||
packet.addLatency(delay) | ||
return packet | ||
else: | ||
return None | ||
|
||
def addActivePacket(self, packet): | ||
toAdd = (packet.arriveTime(), packet) | ||
heapq.heappush(self.activePackets, toAdd) | ||
|
||
def nextActivePacket(self): | ||
return self.activePackets[0][1] | ||
|
||
def hasActivePackets(self): | ||
return len(self.activePackets) > 0 | ||
|
||
def popActivePacket(self): | ||
return heapq.heappop(self.activePackets) | ||
|
||
def deliverReadyPackets(self, step): | ||
self.resetDeliveryCounts() | ||
if self.hasActivePackets() and self.nextActivePacket().isReady(step): | ||
self.deliverPacket(self.popActivePacket()) | ||
|
||
def deliverPacket(self, packet): | ||
dest = packet.receiver | ||
if self.deliveryCounts[dest] <= MAX_PACKETS_PER_STEP: | ||
self.endpoints[dest].receivePacket(packetToDeliver) | ||
self.incrementDeliveryCountFor(dest) | ||
|
||
def incrementDeliveryCountFor(self, deviceID): | ||
self.deliveryCounts[deviceID] += 1 | ||
|
||
def updateActivePackets(self, step): | ||
for endpoint in self.endpoints: | ||
response = endpoint.responseAt(step) | ||
for packet in response: | ||
self.queuePacket(packet) | ||
|
||
def queuePacket(packet): | ||
networkResponse = self.sendThruNetwork(packet) | ||
if isinstance(networkResponse, Packet): | ||
self.addActivePacket(networkResponse) | ||
|
||
def resetDeliveryCounts(self): | ||
self.deliveryCounts = [0] * len(self.endpoints) | ||
|
||
def run(): | ||
# TODO: Use the 4 classes to produce meaningful data | ||
pass | ||
def locationOf(self, deviceID): | ||
return self.endpoints[deviceID].location |
Oops, something went wrong.