Merge branch 'mikolaj_branch' of s444417/ProjektAI into master

This commit is contained in:
Mikołaj Krzymiński 2020-04-21 19:15:08 +00:00 committed by Gogs
commit 2ded95f69c
21 changed files with 578 additions and 196 deletions

View File

@ -2,7 +2,7 @@
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="jdk" jdkName="Python 3.7 (WaiterMaster)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">

View File

@ -3,4 +3,5 @@
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (WaiterMaster)" project-jdk-type="Python SDK" />
</project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 706 B

After

Width:  |  Height:  |  Size: 657 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 988 B

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 979 B

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 977 B

After

Width:  |  Height:  |  Size: 832 B

View File

@ -1,21 +1,23 @@
import pygame
from src.components.GridBoard import GridBoard
from src.managers.DrawableCollection import DrawableCollection
from src.managers.MenuManager import MenuManager
from src.components.Waiter import Waiter
from src.components.Table import Table
from src.managers.TaskManager import TaskManager
from kelner.src.components.GridBoard import GridBoard
from kelner.src.components.Waiter import Waiter
from kelner.src.components.Table import Table
from kelner.src.managers.DrawableCollection import DrawableCollection
from kelner.src.managers.MenuManager import MenuManager
from kelner.src.managers.TableManager import TableManager
from kelner.src.managers.WaiterManager import WaiterManager
# create screen consts
CellSize = 100 #pixel size of 1 square cell in the grid
Scale = 2 # scale for all images used within project
CellSize = round(50 * Scale) # pixel size of 1 square cell in the grid
PaintOffset = CellSize # pixel size of paint offset for all drawables
GridCountX = 15 # number of columns in grid
GridCountY = 9 # number of rows in grid
ScreenWidth = CellSize * GridCountX #screen width in pixels
ScreenHeight = CellSize * GridCountY #screen height in pixels
Offset = 50
ScreenWidth = CellSize * GridCountX + 2 * PaintOffset # screen width in pixels
ScreenHeight = CellSize * GridCountY + 2 * PaintOffset # screen height in pixels
# initialize background
gridBoard = GridBoard(ScreenWidth+200, ScreenHeight+200, CellSize)
gridBoard = GridBoard(ScreenWidth, ScreenHeight)
# initialize drawable objects manager
drawableManager = DrawableCollection()
@ -24,31 +26,33 @@ drawableManager = DrawableCollection()
menuManager = MenuManager()
# initialize waiter component
waiter = Waiter(0, 0, 0, GridCountX - 1, 0, GridCountY - 1, CellSize)
waiter = Waiter(0, 0, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
# adds waiter to drawable collection
drawableManager.add(waiter)
# initialize a number of tables given in range
for i in range(1, 20):
table = Table(0, GridCountX - 1, 0, GridCountY - 1, CellSize)
for i in range(1, 45):
table = Table(0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
drawableManager.generatePosition(table)
drawableManager.add(table)
# new thread controlling tables
tableTask = TableManager(drawableManager, menuManager)
tableTask.start()
# new thread controlling waiter
waiterTask = WaiterManager(drawableManager)
waiterTask.start()
# main loop
#object that controlls repainting of changed objects
doRepaint = [True]
#new thread
task = TaskManager(drawableManager, menuManager, doRepaint)
task.start()
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
tableTask.stop()
waiterTask.stop()
running = False
# handles keyboard events
@ -69,13 +73,11 @@ while running:
# checks if new waiter's position down is not occupied by other object
if drawableManager.isPositionAvailable(waiter.getX(), waiter.getY() + 1):
waiter.moveDown()
doRepaint[0] = True
drawableManager.forceRepaint()
# repaints all objects to the screen
# is set only on initial paint or after keyboard event
if doRepaint[0]:
# is set only on initial paint or after keyboard event or call to forceRepaint()
if drawableManager.mustRepaint():
gridBoard.reinitialize()
gridBoard.draw(drawableManager)
gridBoard.udpdate()
doRepaint[0] = False
drawableManager.collectOrders()

View File

@ -0,0 +1,125 @@
from queue import PriorityQueue
from kelner.src.algorithms.AStar.Node import Node
class Finder:
def __init__(self, table):
self._table = table
self._xMin = 0
self._yMin = 0
self._xMax = len(table[0]) - 1
self._yMax = len(table) - 1
self.__isDiagonal = False
def _set(self, x, y, v):
self._table[y][x] = v
def _get(self, x, y):
return self._table[y][x]
# returns right position relative to the node
def __incXnopY(self, node, neighbours):
if node.x < self._xMax and self._get(node.x + 1, node.y) == 0:
neighbours.append(Node(node, node.x + 1, node.y, node.distance + 1))
# returns left position relative to the node
def __decXnopY(self, node, neighbours):
if self._xMin < node.x and self._get(node.x - 1, node.y) == 0:
neighbours.append(Node(node, node.x - 1, node.y, node.distance + 1))
# returns top position relative to the node
def __nopXincY(self, node, neighbours):
if node.y < self._yMax and self._get(node.x, node.y + 1) == 0:
neighbours.append(Node(node, node.x, node.y + 1, node.distance + 1))
# returns bottom position relative to the node
def __nopXdecY(self, node, neighbours):
if self._yMin < node.y and self._get(node.x, node.y - 1) == 0:
neighbours.append(Node(node, node.x, node.y - 1, node.distance + 1))
# returns left top position relative to the node
def __decXdecY(self, node, neighbours):
if (self._xMin < node.x and self._yMin < node.y and
self._get(node.x - 1, node.y - 1) == 0 and
self._get(node.x - 1, node.y) == 0 and
self._get(node.x, node.y - 1) == 0):
neighbours.append(Node(node, node.x - 1, node.y - 1, node.distance + 2))
# returns left bottom position relative to the node
def __decXincY(self, node, neighbours):
if (self._xMin < node.x and node.y < self._yMax and
self._get(node.x - 1, node.y + 1) == 0 and
self._get(node.x - 1, node.y) == 0 and
self._get(node.x, node.y + 1) == 0):
neighbours.append(Node(node, node.x - 1, node.y + 1, node.distance + 2))
# returns right bottom position relative to the node
def __incXincY(self, node, neighbours):
if (node.x < self._xMax and node.y < self._yMax and
self._get(node.x + 1, node.y + 1) == 0 and
self._get(node.x + 1, node.y) == 0 and
self._get(node.x, node.y + 1) == 0):
neighbours.append(Node(node, node.x + 1, node.y + 1, node.distance + 2))
# returns right top position relative to the node
def __incXdecY(self, node, neighbours):
if (node.x < self._xMax and self._yMin < node.y and
self._get(node.x + 1, node.y - 1) == 0 and
self._get(node.x + 1, node.y) == 0 and
self._get(node.x, node.y - 1) == 0):
neighbours.append(Node(node, node.x + 1, node.y - 1, node.distance + 2))
# returns all plausible positions relative to the node
def __getNeighbours(self, node):
neighbours = []
self.__nopXincY(node, neighbours)
self.__incXnopY(node, neighbours)
self.__decXnopY(node, neighbours)
self.__nopXdecY(node, neighbours)
if self.__isDiagonal:
self.__decXdecY(node, neighbours)
self.__decXincY(node, neighbours)
self.__incXincY(node, neighbours)
self.__incXdecY(node, neighbours)
return neighbours
# main algorithm - simplification of well known A*
def __getPath(self, origin, target):
Q = PriorityQueue()
V = set()
Q.put(origin)
while not Q.empty():
head = Q.get()
if head == target:
return head
V.add(head)
for node in self.__getNeighbours(head):
if node not in V:
node.estimated = node.distance + node.getDistanceTo(target)
Q.put(node)
V.add(node)
return None
# returns neighbours for locationXY-tuple as list of tuple(x,y)
def getNeighbours(self, locationXY, isDiagonal):
neighboursXY = []
self.__isDiagonal = isDiagonal
location = Node(None, locationXY[0], locationXY[1], 0)
neighbours = self.__getNeighbours(location)
for neighbour in neighbours:
neighboursXY.append((neighbour.x, neighbour.y))
return neighboursXY
# returns the shortest path as list of tuple(x,y) from originXY-tuple to targetXY-tuple
def getPath(self, originXY, targetXY, isDiagonal):
self.__isDiagonal = isDiagonal
origin = Node(None, originXY[0], originXY[1], 0)
target = Node(None, targetXY[0], targetXY[1], 0)
result = self.__getPath(origin, target)
path = []
while result is not None:
if result.parent is not None:
path.insert(0, (result.x, result.y))
result = result.parent
return path

View File

@ -0,0 +1,60 @@
from random import randint
from kelner.src.algorithms.AStar.Finder import Finder
class FinderTest(Finder):
def __init__(self, table):
super().__init__(table)
def __setValues(self, xys, v):
if xys is not None:
for xy in xys:
self._set(xy[0], xy[1], v)
def print(self, xys):
self.__setValues(xys, 2)
for row in self._table:
for col in row:
v = ' ' if col == 0 else '#' if col == 1 else 'O'
print('|', v, sep='', end='')
print('|')
self.__setValues(xys, 0)
def getRandomTuple(self):
while True:
x = randint(self._xMin, self._xMax)
y = randint(self._yMin, self._yMax)
if self._get(x, y) == 0:
break
return x, y
def getRandomBorderTuple(self):
xSet = [self._xMin, self._xMax]
ySet = [self._yMin, self._yMax]
while True:
x = randint(self._xMin, self._xMax)
y = randint(self._yMin, self._yMax)
if (x in xSet or y in ySet) and self._get(x, y) == 0:
break
return x, y
def fillRandom(self):
for _ in range(120):
while True:
x = randint(self._xMin, self._xMax)
y = randint(self._yMin, self._yMax)
if self._get(x, y) == 0:
break
self._set(x, y, 1)
cols = 20
rows = 20
table = [[0] * cols for i in range(rows)]
finder = FinderTest(table)
finder.fillRandom()
originXY = finder.getRandomBorderTuple()
targetXY = finder.getRandomBorderTuple()
result = finder.getPath(originXY, targetXY, True)
finder.print(result)

View File

@ -0,0 +1,34 @@
from math import sqrt
class Node:
def __init__(self, parent, x, y, distance):
self.parent = parent
self.x = x
self.y = y
self.distance = distance
self.estimated = distance
# returns distance from the object to other node
def getDistanceTo(self, other):
dx = self.x - other.x
dy = self.y - other.y
return sqrt(dx * dx + dy * dy)
# abs(dx) + abs(dy)
# used by str() method to represent the object
def __repr__(self):
return "%s:%s" % (self.x, self.y)
# generates hash key for Set
def __hash__(self):
return hash(str(self))
# operator (==) for Set (determines if the object equals other node)
def __eq__(self, other):
return (self.x == other.x) and (self.y == other.y)
# operator (>) for PriorityQueue comparison (determines the objects order)
def __gt__(self, other):
return self.estimated > other.estimated

View File

@ -5,29 +5,33 @@ class Drawable:
RED = (255, 0, 0)
GREEN = (0, 255, 0)
def __init__(self, x, y, minX, maxX, minY, maxY, ratio):
def __init__(self, x, y, minX, maxX, minY, maxY, cellSize, offset):
self.__minX = minX
self.__maxX = maxX
self.__minY = minY
self.__maxY = maxY
self.setX(x)
self.setY(y)
self.__ratio = ratio #cell size
self.__cellSize = cellSize # cell size in pixels
self.__offset = offset # paint offset in pixels
def setX(self, x):
if (x < self.__minX or self.__maxX < x):
if x < self.__minX or self.__maxX < x:
return False
else:
self.__x = x
return True
def setY(self, y):
if (y < self.__minY or self.__maxY < y):
if y < self.__minY or self.__maxY < y:
return False
else:
self.__y = y
return True
def isPositionCorrect(self, x, y):
return self.__minX <= x <= self.__maxX and self.__minY <= y <= self.__maxY
def getX(self):
return self.__x
@ -46,8 +50,14 @@ class Drawable:
def getMaxY(self):
return self.__maxY
def getRatio(self):
return self.__ratio
def getCellSize(self):
return self.__cellSize
def getOffset(self):
return self.__offset
def draw(self, screen):
pass
def drawAux(self, screen):
pass

View File

@ -1,23 +1,27 @@
import pygame
from kelner.src.managers.ImageCache import ImageCache, Images
class GridBoard:
def __init__(self, width, height, cellSize):
def __init__(self, width, height):
pygame.init() # initialize the pygame
pygame.display.set_caption("Bardzo mądry kelner") # window caption
self.__width = width
self.__height = height
self.__cellSize = cellSize
self.__screen = pygame.display.set_mode((width, height)) # initialize screen
self.Offset = 50
#fills the screen with white and draws grid
# draws the background
def reinitialize(self):
imageBackground = ImageCache.getInstance().getImage(Images.Background, self.__width, self.__height)
self.__screen.blit(imageBackground, (0, 0))
""" # code below fills the screen with white and draws grid
self.__screen.fill((255, 255, 255))
for x in range(0, self.__width, self.__cellSize):
pygame.draw.line(self.__screen, (0,0,0), (x,0), (x,(self.__height - 1)))
for y in range(0, self.__height, self.__cellSize):
pygame.draw.line(self.__screen, (0,0,0), (0,y), ((self.__width - 1),y))
"""
# draws object on screen
def draw(self, component):

View File

@ -1,79 +1,33 @@
import pygame
from enum import Enum
from .Drawable import Drawable
import random
from enum import Enum
from kelner.src.components.Drawable import Drawable
from kelner.src.managers.ImageCache import ImageCache, Images
# status of the table
class Status(Enum):
NotReady = 0
Ready = 1
Waiting = 2
Served = 3
class Table(Drawable):
def __init__(self, minX, maxX, minY, maxY, ratio):
def __init__(self, minX, maxX, minY, maxY, ratio, offset):
# call base class constructor
Drawable.__init__(self, 0, 0, minX, maxX, minY, maxY, ratio)
self.__order = []
super().__init__(0, 0, minX, maxX, minY, maxY, ratio, offset)
self.__status = Status.NotReady
self.ilosc_klientow = random.randint(1,3)
self.guest1 = self.getGuest()
self.guest2 = self.getGuest()
self.guest3 = self.getGuest()
self.ksiazka = self.__loadImg('./images/ksiazka.png')
self.stol = self.__loadImg('./images/stol.png')
self.check = self.__loadImg('./images/check.png')
self.plate = self.__loadImg('./images/plate.png')
self.Offset = 100
#sets table color based on it's status
def getColor(self):
color = None
if self.__status == Status.NotReady:
color = self.__loadImg('./images/stol.png')
elif self.__status == Status.Ready:
color = self.__loadImg('./images/kelner.png')
elif self.__status == Status.Waiting:
color = self.__loadImg('./images/kelner.png')
elif self.__status == Status.Served:
color = self.__loadImg('./images/kelner.png')
return color
def getGuest(self):
guest = None
i = random.randint(1,3)
if i == 1:
guest = self.__loadImg('./images/wiking_blond.png')
elif i == 2:
guest = self.__loadImg('./images/wiking_rudy.png')
elif i == 3:
guest = self.__loadImg('./images/wiking_rudy2.png')
return guest
def __loadImg(self, filePath):
return pygame.transform.scale((pygame.image.load(filePath)),(140,140))
def draw(self, screen):
screen.blit(self.stol, (self.getX() * 100-20+self.Offset, self.getY() * 100-20+self.Offset))
if self.ilosc_klientow == 1:
screen.blit(self.guest1, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 60+self.Offset))
elif self.ilosc_klientow == 2:
screen.blit(self.guest1, (self.getX() * 100 - 62+self.Offset, self.getY() * 100 - 60+self.Offset))
screen.blit(self.guest2, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 60+self.Offset))
elif self.ilosc_klientow == 3:
screen.blit(self.guest1, (self.getX() * 100 - 62+self.Offset, self.getY() * 100 - 60+self.Offset))
screen.blit(self.guest2, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 60+self.Offset))
screen.blit(self.guest3, (self.getX() * 100 + 22+self.Offset, self.getY() * 100 - 60+self.Offset))
if self.__status == Status.NotReady:
screen.blit(self.ksiazka, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 20+self.Offset))
elif self.__status == Status.Ready:
screen.blit(self.check, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 20+self.Offset))
elif self.__status == Status.Waiting:
if self.ilosc_klientow == 1:
screen.blit(self.plate, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 20+self.Offset))
elif self.ilosc_klientow == 2:
screen.blit(self.plate, (self.getX() * 100 - 62+self.Offset, self.getY() * 100 - 20+self.Offset))
screen.blit(self.plate, (self.getX() * 100 - 20+self.Offset, self.getY() * 100 - 20+self.Offset))
elif self.ilosc_klientow == 3:
screen.blit(self.plate, (self.getX() * 100 - 62+self.Offset, self.getY() * 100 - 20+self.Offset))
screen.blit(self.plate, (self.getX() * 100- 20+self.Offset, self.getY() * 100 - 20+self.Offset))
screen.blit(self.plate, (self.getX() * 100+ 22+self.Offset, self.getY() * 100 - 20+self.Offset))
self.__order = []
self.__guests = self.__getRandomGuests()
def __getRandomGuests(self):
possibleGuests = [Images.Guest1, Images.Guest2, Images.Guest3]
guests = []
guestCount = random.randint(1, len(possibleGuests))
for _ in range(guestCount):
guests.insert(0, possibleGuests[random.randint(0, len(possibleGuests) - 1)])
return guests
def setOrder(self, order):
self.__order = order
@ -90,9 +44,57 @@ class Table(Drawable):
def setStatus(self, status):
self.__status = status
#status of the table
class Status(Enum):
NotReady = 0
Ready = 1
Waiting = 2
Served = 3
def __getImage(self, imageKind):
if imageKind in [Images.Guest1, Images.Guest2, Images.Guest3, Images.Plate]:
size = int(self.getCellSize() / 3)
else:
size = int(1.4 * self.getCellSize())
return ImageCache.getInstance().getImage(imageKind, size, size)
# draws only table
def draw(self, screen):
xBase = self.getX() * self.getCellSize() + self.getOffset()
yBase = self.getY() * self.getCellSize() + self.getOffset()
tableXYOffset = int(0.2 * self.getCellSize())
screen.blit(self.__getImage(Images.Table), (xBase - tableXYOffset, yBase - tableXYOffset))
# draws images related to the status of a table
# the method is called in the second turn when all tables are already painted
def drawAux(self, screen):
xBase = self.getX() * self.getCellSize() + self.getOffset()
yBase = self.getY() * self.getCellSize() + self.getOffset()
guest1XOffset = 0
guest2XOffset = int((1 / 3) * self.getCellSize())
guest3XOffset = int((2 / 3) * self.getCellSize())
guest4XOffset = int((1 / 9) * self.getCellSize())
guest5XOffset = int((5 / 9) * self.getCellSize())
guestsYOffset = int(0.1 * self.getCellSize())
tableXYOffset = int(0.2 * self.getCellSize())
if len(self.__guests) == 1:
screen.blit(self.__getImage(self.__guests[0]), (xBase + guest2XOffset, yBase - guestsYOffset))
elif len(self.__guests) == 2:
screen.blit(self.__getImage(self.__guests[0]), (xBase + guest4XOffset, yBase - guestsYOffset))
screen.blit(self.__getImage(self.__guests[1]), (xBase + guest5XOffset, yBase - guestsYOffset))
elif len(self.__guests) == 3:
screen.blit(self.__getImage(self.__guests[0]), (xBase + guest1XOffset, yBase - guestsYOffset))
screen.blit(self.__getImage(self.__guests[1]), (xBase + guest2XOffset, yBase - guestsYOffset))
screen.blit(self.__getImage(self.__guests[2]), (xBase + guest3XOffset, yBase - guestsYOffset))
if self.isStatus(Status.NotReady):
screen.blit(self.__getImage(Images.Menu), (xBase - tableXYOffset, yBase - tableXYOffset))
elif self.isStatus(Status.Ready):
screen.blit(self.__getImage(Images.Check), (xBase - tableXYOffset, yBase - tableXYOffset))
elif self.isStatus(Status.Waiting):
platesYOffset = int(0.3 * self.getCellSize())
imagePlate = self.__getImage(Images.Plate)
if len(self.__guests) == 1:
screen.blit(imagePlate, (xBase + guest2XOffset, yBase + platesYOffset))
elif len(self.__guests) == 2:
screen.blit(imagePlate, (xBase + guest4XOffset, yBase + platesYOffset))
screen.blit(imagePlate, (xBase + guest5XOffset, yBase + platesYOffset))
elif len(self.__guests) == 3:
screen.blit(imagePlate, (xBase + guest1XOffset, yBase + platesYOffset))
screen.blit(imagePlate, (xBase + guest2XOffset, yBase + platesYOffset))
screen.blit(imagePlate, (xBase + guest3XOffset, yBase + platesYOffset))

View File

@ -1,15 +1,14 @@
import pygame
from .Drawable import Drawable
from kelner.src.components.Drawable import Drawable
from kelner.src.managers.ImageCache import ImageCache, Images
class Waiter(Drawable):
def __init__(self, x, y, minX, maxX, minY, maxY, ratio):
def __init__(self, x, y, minX, maxX, minY, maxY, ratio, offset):
# call base class constructor
Drawable.__init__(self, x, y, minX, maxX, minY, maxY, ratio)
self.__image = self.__loadImg('./images/kelner.png')
super().__init__(x, y, minX, maxX, minY, maxY, ratio, offset)
self.__acceptedOrders = []
self.Offset = 100
self.__currentPath = []
def moveUp(self):
if self.getY() > self.getMinY():
@ -43,8 +42,17 @@ class Waiter(Drawable):
def addOrder(self, table):
self.__acceptedOrders += [(table, table.getOrder())]
def __loadImg(self, filePath):
return pygame.transform.scale((pygame.image.load(filePath)),(140,140))
def isPathEmpty(self):
return self.__currentPath == []
def setPath(self, path):
self.__currentPath = path
def popStepFromPath(self):
return self.__currentPath.pop(0)
def draw(self, screen):
screen.blit(self.__image, (self.getX()*100-20+self.Offset, self.getY()*100-20+self.Offset))
imageWaiter = ImageCache.getInstance().getImage(Images.Waiter, self.getCellSize(), self.getCellSize())
xBase = self.getX() * self.getCellSize() + self.getOffset()
yBase = self.getY() * self.getCellSize() + self.getOffset()
screen.blit(imageWaiter, (xBase, yBase))

View File

@ -1,16 +1,18 @@
import random
from src.components.Table import Table, Status
from src.components.Waiter import Waiter
import pygame
from kelner.src.components.Table import Table, Status
from kelner.src.components.Waiter import Waiter
# drawable objects manager
class DrawableCollection:
# const, minimal distance between objects
__MinDistance = 0
__MinDistanceX = 0
__MinDistanceY = 0
def __init__(self):
# collection that holds all drawable objects
self.__mustRepaint = True
self.__drawables = []
self.image = pygame.transform.scale((pygame.image.load('./images/Backgroud.png')),(1700,1100))
# adds drawable objects to the collection
def add(self, drawable):
@ -24,19 +26,13 @@ class DrawableCollection:
y = random.randint(drawable.getMinY() + 1, drawable.getMaxY() - 1)
isPositionUnique = True
for item in self.__drawables:
if abs(item.getX() - x) <= self.__MinDistance and abs(item.getY() - y) <= self.__MinDistance:
if abs(item.getX() - x) <= self.__MinDistanceX and abs(item.getY() - y) <= self.__MinDistanceY:
isPositionUnique = False
break
if isPositionUnique:
drawable.setX(x)
drawable.setY(y)
#draws all objects stored in collection
def draw(self, screen):
screen.blit(self.image, (0, 0))
for item in self.__drawables:
item.draw(screen)
# checks if position (x,y) is not occupied by other object
def isPositionAvailable(self, x, y):
isPositionAvailable = True
@ -50,21 +46,21 @@ class DrawableCollection:
def getTables(self, status):
result = []
for item in self.__drawables:
if isinstance(item, Table) and item.isStatus(status):
if status is None or isinstance(item, Table) and item.isStatus(status):
result += [item]
return result
# gets all waiters from collection
def getWaites(self):
def getWaiters(self):
result = []
for item in self.__drawables:
if isinstance(item, Waiter):
result += [item]
return result
#waiter collects order from the nearest table
# waiter collects orders from all nearest tables
def collectOrders(self):
waiters = self.getWaites()
waiters = self.getWaiters()
for waiter in waiters:
tables = self.getTables(Status.Ready)
for table in tables:
@ -72,3 +68,30 @@ class DrawableCollection:
table.setStatus(Status.Waiting)
waiter.addOrder(table)
table.delOrder()
# returns table: 0 - position is available, 1 - position is occupied
def getReservedPlaces(self, waiter):
cols = waiter.getMaxX() - waiter.getMinX() + 1
rows = waiter.getMaxY() - waiter.getMinY() + 1
reservedPlaces = [[0] * cols for i in range(rows)]
tables = self.getTables(None)
if tables:
for table in tables:
reservedPlaces[table.getY()][table.getX()] = 1
return reservedPlaces
# the method is called externally and forces repainting
def forceRepaint(self):
self.__mustRepaint = True
# returns boolean value: True if objects should be repainted otherwise False
def mustRepaint(self):
return self.__mustRepaint
# draws all objects stored in collection
def draw(self, screen):
for item in self.__drawables:
item.draw(screen)
for item in self.__drawables:
item.drawAux(screen)
self.__mustRepaint = False

View File

@ -0,0 +1,50 @@
import pygame
from enum import Enum
# images enum
class Images(Enum):
Background = 0
Waiter = 1
Table = 2
Menu = 3
Check = 4
Plate = 5
Guest1 = 6
Guest2 = 7
Guest3 = 8
class ImageCache:
__instance = None
@staticmethod
def getInstance():
if ImageCache.__instance is None:
ImageCache()
return ImageCache.__instance
def __init__(self):
""" Virtually private constructor. """
if ImageCache.__instance is not None:
raise Exception("This class is a singleton!")
else:
ImageCache.__instance = self
self.__images = {}
self.__paths = {Images.Background: './images/Backgroud.png',
Images.Waiter: './images/kelner.png',
Images.Table: './images/stol.png',
Images.Menu: './images/ksiazka.png',
Images.Check: './images/check.png',
Images.Plate: './images/plate.png',
Images.Guest1: './images/wiking_blond.png',
Images.Guest2: './images/wiking_rudy.png',
Images.Guest3: './images/wiking_rudy2.png'}
def getImage(self, imageKind, width, height):
key = str(imageKind.value) + ':' + str(width) + ':' + str(height)
image = self.__images.get(key, None)
if image is None:
image = pygame.transform.scale((pygame.image.load(self.__paths[imageKind])), (width, height))
self.__images[key] = image
return image

View File

@ -1,9 +1,10 @@
import random
# contains all dishes and generates random order for the table
class MenuManager:
#consts, min and max dishes oredered by the people sitting by the same table
# consts, min and max dishes ordered by the people sitting by the same table
__MinDishes = 1
__MaxDishes = 3
@ -24,6 +25,7 @@ class MenuManager:
"EMPTY PLATE",
"BEER",
"CAKE"]
# generator
def generateOrder(self):
count = random.randint(self.__MinDishes, self.__MaxDishes)

View File

@ -0,0 +1,29 @@
import threading
import time
import random
from kelner.src.components.Table import Status
# creates new thread
class TableManager (threading.Thread):
def __init__(self, drawableManager, menuManager):
super().__init__()
self.__drawableManager = drawableManager
self.__menuManager = menuManager
self.__runThread = True
# changes the status of a random table from NotReady to Ready
def run(self):
while self.__runThread:
tables = self.__drawableManager.getTables(Status.NotReady)
if tables:
tableIndex = random.randint(0, len(tables) - 1)
table = tables[tableIndex]
time.sleep(3)
table.setStatus(Status.Ready)
table.setOrder(self.__menuManager.generateOrder())
self.__drawableManager.forceRepaint()
def stop(self):
self.__runThread = False

View File

@ -1,25 +0,0 @@
import threading
import time
import random
from src.components.Table import Status
#creates new threads
class TaskManager (threading.Thread):
def __init__(self, drawableManager, menuManager, doRepaintObject):
threading.Thread.__init__(self)
self.__drawableManager = drawableManager
self.__menuManager = menuManager
self.__doRepaintObject = doRepaintObject
#changes the status of a random table from NotReady to Ready
def run(self):
while True:
time.sleep(3)
tables = self.__drawableManager.getTables(Status.NotReady)
if tables != []:
tableIndex = random.randint(0, len(tables) - 1)
table = tables[tableIndex]
table.setStatus(Status.Ready)
table.setOrder(self.__menuManager.generateOrder())
self.__doRepaintObject[0] = True

View File

@ -0,0 +1,57 @@
import threading
import time
import sys
from kelner.src.components.Table import Status
from kelner.src.algorithms.AStar.Finder import Finder
# creates new thread
class WaiterManager (threading.Thread):
def __init__(self, drawableManager):
super().__init__()
self.__drawableManager = drawableManager
self.__runThread = True
def __getNearestTargetPath(self, waiter):
distance = sys.maxsize
nearestTargetPath = None
tables = self.__drawableManager.getTables(Status.Ready)
if tables:
reservedPlaces = self.__drawableManager.getReservedPlaces(waiter)
finder = Finder(reservedPlaces)
origin = (waiter.getX(), waiter.getY())
for table in tables:
targets = finder.getNeighbours((table.getX(), table.getY()), False)
for target in targets:
if target is not None:
path = finder.getPath(origin, target, True)
if path:
result = len(path)
if result < distance:
distance = result
nearestTargetPath = path
return nearestTargetPath
# changes the status of a random table from NotReady to Ready
def run(self):
while self.__runThread:
waiters = self.__drawableManager.getWaiters()
if waiters:
for waiter in waiters:
path = self.__getNearestTargetPath(waiter)
if path is not None:
waiter.setPath(path)
if not waiter.isPathEmpty():
step = waiter.popStepFromPath()
time.sleep(0.4)
waiter.setX(step[0])
waiter.setY(step[1])
self.__drawableManager.forceRepaint()
if waiter.isPathEmpty():
time.sleep(2)
self.__drawableManager.collectOrders()
self.__drawableManager.forceRepaint()
def stop(self):
self.__runThread = False