Skip to content

Commit

Permalink
Working simulator and visualizer
Browse files Browse the repository at this point in the history
  • Loading branch information
joshtch committed Dec 19, 2016
1 parent e6cfa04 commit 7581ab9
Show file tree
Hide file tree
Showing 12 changed files with 171 additions and 220 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ __pycache__/
*.py[cod]
*$py.class

# ctags tagfile
tags

# C extensions
*.so

Expand Down
87 changes: 21 additions & 66 deletions cloud.py
Original file line number Diff line number Diff line change
@@ -1,81 +1,36 @@
import Queue
if __name__ == "__main__": import packet
from packet import Packet,PacketQueue

# these delays can be seen as the time response time of the server for each game
# being played

MAX_PACKETS_PER_STEP = 350
TRAFFIC_DELAY = { 'high' : 10, 'med' : 5, 'low' : 3 }

class Cloud(object):

def __init__(self, gameTraffic, location, timeout, num_players):

self.requestList = Queue.Queue()

self.timeToProcess = TRAFFIC_DELAY[gameTraffic]

self.num_players = num_players
self.location = location
self.timeout = timeout

def responseAt(self, time):
if time % self.timeToProcess == 0 and not self.requestList.empty() :
headPacket = self.requestList.get();
if (time - headPacket.timestamp) > self.timeout:
return None
else:
responsePackets = []
for i in range(1,self.num_players):
newPacket = headPacket

# update packet
newPacket.sender = 0
newPacket.receiver = i

responsePackets.append(newPacket)
return responsePackets
else:
return None
self.requestList = PacketQueue()
self.time = 0

def step(self):
self.time += 1
responsePackets = []
while not self.requestList.empty() \
and self.requestList.next().isReady(self.time) \
and len(responsePackets) <= MAX_PACKETS_PER_STEP:
headPacket = self.requestList.pop()
#if headPacket.arriveTime() + self.timeout <= self.time:
for i in xrange(1, self.num_players + 1):
newPacket = headPacket.deepcopy()
newPacket.sender = 0
newPacket.receiver = i
responsePackets.append(newPacket)
return responsePackets

def receivePacket(self, packet):
self.requestList.put(packet)


if __name__ == "__main__":
packet1 = packet.Packet(100, 0, 0, 1)
packet2 = packet.Packet( 0, 0, 0, 2)
packet3 = packet.Packet(100, 0, 0, 1)
packet4 = packet.Packet( 100, 0, 0, 2)

cloud = cloud.Cloud(0, 0, 10, 10)

cloud.receivePacket(packet1)
cloud.receivePacket(packet4)
cloud.receivePacket(packet3)
cloud.receivePacket(packet2)

time = 100
print "\ntest 1: should return 3 packets"
for i in range(0,20):
#print time
packetList = cloud.updateTime(time)
if packetList != None:
print packetList[0].packet_id
time = time + 1

cloud.receivePacket(packet1)
cloud.receivePacket(packet2)
cloud.receivePacket(packet3)
cloud.receivePacket(packet4)

time = 100
print "\ntest 2: should return 2 packets"

for i in range(0,20):
#print time
packetList = cloud.updateTime(time)
if packetList != None:
print packetList[0].packet_id
time = time + 1
print "\n"

packet.addLatency(self.timeToProcess)
self.requestList.push(packet)
41 changes: 26 additions & 15 deletions data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,50 @@ class Data(object):
def __init__(self):
self.d = {}

def putSend(self, id, sendTime):
def putSendTime(self, id, sendTime):
if id not in self.d:
self.d[id] = { 'sendTime' : sendTime, 'receiveTime' : None }
self.d[id] = { 'sendTime' : sendTime, 'finalTime' : None }
else:
self.d[id]['sendTime'] = sendTime

def putReceive(self, id, receiveTime):
print "received: " + str(id) + ", " + str(receiveTime)
def putFinalTime(self, id, finalTime):
if id not in self.d:
self.d[id] = { 'sendTime' : None, 'receiveTime' : receiveTime }
self.d[id] = { 'sendTime' : None, 'finalTime' : finalTime }
else:
self.d[id]['receiveTime'] = receiveTime
self.d[id]['finalTime'] = finalTime

def rawData(self):
return self.d

def sendTime(self, id):
return self.d[id]['sendTime']
def getSendTime(self, id):
if id in self.d:
return self.d[id]['sendTime']
else:
return None

def receiveTime(self, id):
return self.d[id]['receiveTime']
def getFinalTime(self, id):
if id in self.d:
return self.d[id]['finalTime']
else:
return None

def latency(self, id):
if self.receiveTime(id) is not None and self.sendTime(id) is not None:
return self.d[id]['receiveTime'] - self.d[id]['sendTime']
if id in self.d and self.getFinalTime(id) is not None \
and self.getSendTime(id) is not None:
return self.getFinalTime(id) - self.getSendTime(id)
else:
return None

def latencyList(self):
return [self.latency(x) for x in self.d.keys() if self.latency(x) is not None]
return [self.latency(x) for x in self.d.keys() \
if self.latency(x) is not None]

def averageLatency(self):
return statistics.median(self.latencyList())
latlist = self.latencyList()
if len(latlist) > 0:
return statistics.median(self.latencyList())
else:
return 0

def numDropped(self):
return len([self.receiveTime(x) for x in self.d if self.receiveTime(x) is None])
return len([self.getFinalTime(x) for x in self.d if self.getFinalTime(x) is None])
48 changes: 24 additions & 24 deletions device.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,55 @@
from random import randint
from data import Data

TICKS_PER_EVENT = 20
TICKS_PER_EVENT = 500

class Device(object):
cloud_id = 0
rendering_time = 5 #ms

def __init__(self, deviceID, fps, ticksPerEvent, location):
self.deviceID = deviceID
def __init__(self, fps, ticksPerEvent, location):
self.fps = fps
self.ticksPerEvent = ticksPerEvent
self.firstEventOffset = randint(0, ticksPerEvent - 1)
self.location = location
self.data = Data()
self.time = 0

def responseAt(self, time):
if (time + self.firstEventOffset) % self.ticksPerEvent == 0:
packet = Packet(time, 0, self.deviceID)
def step(self):
self.time += 1
if self.time % self.ticksPerEvent == self.firstEventOffset:
packet = Packet(self.time, Device.cloud_id, self.id)
id = packet.packet_id
self.data.putSend(id, time)
print 'Device: %d. Location: %s. Packet sent: %s. Timestamp: %s' % (self.deviceID, self.location, packet.packet_id, packet.timestamp)
self.data.putSendTime(id, self.time)
return [packet]
else:
return []

def receivePacket(self, packet):
id = packet.packet_id
arrival = packet.arriveTime()
self.data.putReceive(id, arrival)
print 'Device: %d. Location: %s. Packet received: %s. Timestamp: %s' % (self.deviceID, self.location, packet.packet_id, packet.timestamp)

finalTime = packet.arriveTime() + Device.rendering_time
self.data.putFinalTime(id, finalTime)

class OculusRift(Device):
def __init__(self, deviceID, location):
super(OculusRift, self).__init__(deviceID, 90, TICKS_PER_EVENT, location)
def __init__(self, location):
super(OculusRift, self).__init__(90, TICKS_PER_EVENT, location)

class HTCVive(Device):
def __init__(self, deviceID, location):
super(HTCVive, self).__init__(deviceID, 90, TICKS_PER_EVENT, location)
def __init__(self, location):
super(HTCVive, self).__init__(90, TICKS_PER_EVENT, location)

class PlayStationVR(Device):
def __init__(self, deviceID, location):
super(PlayStationVR, self).__init__(deviceID, 120, TICKS_PER_EVENT, location)
def __init__(self, location):
super(PlayStationVR, self).__init__(120, TICKS_PER_EVENT, location)

class LG360VR(Device):
def __init__(self, deviceID, location):
super(LG360VR, self).__init__(deviceID, 120, TICKS_PER_EVENT, location)
def __init__(self, location):
super(LG360VR, self).__init__(120, TICKS_PER_EVENT, location)

class GearVR(Device):
def __init__(self, deviceID, location):
super(GearVR, self).__init__(deviceID, 60, TICKS_PER_EVENT, location)
def __init__(self, location):
super(GearVR, self).__init__(60, TICKS_PER_EVENT, location)

class VisusVR(Device):
def __init__(self, deviceID, location):
super(VisusVR, self).__init__(deviceID, 60, TICKS_PER_EVENT, location)
def __init__(self, location):
super(VisusVR, self).__init__(60, TICKS_PER_EVENT, location)
6 changes: 0 additions & 6 deletions location.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,3 @@ def createPropagationMatrix(self):
self.addPropagation("San Francsico", "Washington", 41)

self.addPropagation("Seattle", "Washington", 68)

if __name__ == "__main__":
loc1 = Location("Washington")
loc2 = Location("Chicago")
print "Delay from " + loc1.city + " to " + loc2.city + " is" \
+ str(loc1.propagationDelayFrom(loc2)) + " ms"
12 changes: 0 additions & 12 deletions network.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,3 @@ def networkDelay(self, loc1, loc2):
return propDelay + self.HEADER_PROCESSING
else:
return None

if __name__ == "__main__":

loc1 = Location("Washington")
loc2 = Location("Chicago")

# Timeout test
network = Network(2) # 2 percent chance to drop packet
attempts = 0
while network.networkDelay(loc1, loc2) != None:
attempts += 1
print "Network dropped packet after " + str(attempts + 1) + " packets sent"
33 changes: 26 additions & 7 deletions packet.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,43 @@
import uuid
import heapq

class Packet(object):

def __init__(self, timestamp, receiver, sender):
self._init_packet_id()
def __init__(self, timestamp, receiver, sender, packet_id = None):
self.packet_id = packet_id if packet_id is not None else uuid.uuid4()
self.timestamp = timestamp
self.receiver = receiver
self.sender = sender
self.elapsedTime = 0
self.phase = 'network->cloud'

def _init_packet_id(self):
self.packet_id = uuid.uuid4() # generate a random UUID

def addLatency(self, elapsedTime):
self.elapsedTime += elapsedTime

def isReady(self, time):
return self.timestamp + self.elapsedTime >= time
return self.arriveTime() >= time

def arriveTime(self):
return self.timestamp + self.elapsedTime

def deepcopy(self):
return Packet(self.timestamp, self.receiver, self.sender, self.packet_id)

# Packet priority queue, with packets ordered by arrival time
class PacketQueue(object):

def __init__(self):
self._packets = []

def push(self, packet):
toAdd = (packet.arriveTime(), packet)
heapq.heappush(self._packets, toAdd)

def pop(self):
return (heapq.heappop(self._packets))[1]

def next(self):
return self._packets[0][1]

def empty(self):
return len(self._packets) == 0

Loading

0 comments on commit 7581ab9

Please sign in to comment.