diff --git a/.idea/ProjektAI.iml b/.idea/ProjektAI.iml
index d9e6024..d25211e 100644
--- a/.idea/ProjektAI.iml
+++ b/.idea/ProjektAI.iml
@@ -1,8 +1,10 @@
-
-
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a5061af..035315d 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -3,5 +3,5 @@
-
+
\ No newline at end of file
diff --git a/kelner/gui/GAdialog/GADefaults.py b/kelner/gui/GAdialog/GADefaults.py
new file mode 100644
index 0000000..8686454
--- /dev/null
+++ b/kelner/gui/GAdialog/GADefaults.py
@@ -0,0 +1,104 @@
+
+class CrossingOverMethod:
+ FixedQuadrant = 0
+ SingleHorizontalDiv = 1
+ SingleVerticalDiv = 2
+ DoubleHorizontalDiv = 3
+ DoubleVerticalDiv = 4
+ RandomChoice = 5
+
+
+class SelectionMethod:
+ Roulette = 0
+ Tournament = 1
+
+
+class MutationMethod:
+ Flip = 0
+ Swap = 1
+
+
+class GADefaults:
+
+ def __init__(self):
+
+ self.defSelectionMethods = [("ruletka", SelectionMethod.Roulette),
+ ("turniej", SelectionMethod.Tournament)]
+
+ self.defCrossingOverMethods = [("pojedynczy poziomy", CrossingOverMethod.SingleHorizontalDiv),
+ ("pojedynczy pionowy", CrossingOverMethod.SingleVerticalDiv),
+ ("podwójny poziomy", CrossingOverMethod.DoubleHorizontalDiv),
+ ("podwójny pionowy", CrossingOverMethod.DoubleVerticalDiv),
+ ("ćwiartki", CrossingOverMethod.FixedQuadrant),
+ ("losowe", CrossingOverMethod.RandomChoice)]
+
+ self.defMutationMethods = [("inwersja", MutationMethod.Flip),
+ ("wymiana", MutationMethod.Swap)]
+
+ self.windowName = "Algorytm genetyczny - parametry"
+ self.windowGeometry = "400x400"
+
+ self.minTablesCount = 1
+ self.maxTablesCount = 100
+ self.defTablesCount = 20
+ self.runTablesCount = self.defTablesCount
+ self.sliderNameTablesCount = "stoliki"
+
+ self.minPopulationSize = 4
+ self.maxPopulationSize = 30
+ self.defPopulationSize = 5
+ self.runPopulationSize = self.defPopulationSize
+ self.sliderNamePopulationSize = "populacja"
+
+ self.minMutation = 0
+ self.maxMutation = 10
+ self.defMutation = 1
+ self.runMutation = self.defMutation
+ self.sliderNameMutation = "mutacje"
+
+ self.minGenerationsNumber = 1
+ self.maxGenerationsNumber = 1000
+ self.defGenerationsNumber = 20
+ self.runGenerationsNumber = self.defGenerationsNumber
+ self.sliderNameGenerationsNumber = "pokolenia"
+
+ self.defInfoFold = 5
+ self.runInfoFold = self.defInfoFold
+ self.sliderInfoFold = "co ile"
+
+ self.defSelectionMethod = SelectionMethod.Tournament
+ self.runSelectionMethod = self.defSelectionMethod
+ self.radioSelectionMethodName = "metoda selekcji"
+
+ self.defCrossingOverMethod = CrossingOverMethod.SingleHorizontalDiv
+ self.runCrossingOverMethod = self.defCrossingOverMethod
+ self.radioCrossingOverMethodName = "metoda krzyżowania"
+
+ self.defMutationMethod = MutationMethod.Swap
+ self.runMutationMethod = self.defMutationMethod
+ self.radioMutationMethodName = "metoda mutacji"
+
+ self.minElitism = 0
+ self.maxElitism = 50
+ self.defElitism = 0
+ self.runElitism = self.defElitism
+ self.sliderElitismName = "elitarność [%]"
+
+ self.buttonStartName = "generuj"
+ self.buttonDefaultsName = "przywróć"
+
+ self.__forbiddenPlaces = None
+
+ self.waiterPosition = None
+ self.kitchenPosition = None
+
+ def getForbiddenPlaces(self):
+ if self.__forbiddenPlaces is None:
+ self.__forbiddenPlaces = [self.waiterPosition, self.kitchenPosition]
+ return self.__forbiddenPlaces
+
+ def getInfo(self):
+ return "populacja: " + str(self.runPopulationSize) \
+ + ", pokolenia: " + str(self.runGenerationsNumber) \
+ + ", stoliki: " + str(self.runTablesCount) \
+ + ", mutacje: " + str(self.runMutation)
diff --git a/kelner/gui/GAdialog/GADialog.py b/kelner/gui/GAdialog/GADialog.py
new file mode 100644
index 0000000..fd4d6c2
--- /dev/null
+++ b/kelner/gui/GAdialog/GADialog.py
@@ -0,0 +1,82 @@
+import tkinter
+from tkinter import *
+
+from kelner.gui.GAdialog.GADefaults import CrossingOverMethod
+
+
+class GADialog:
+
+ def __init__(self, defaults):
+ self.__defaults = defaults
+ self.window = tkinter.Tk()
+ self.window.attributes('-topmost', 'true')
+ self.window.title(defaults.windowName)
+ self.__sliderTablesCount = self.__getSlider(0, defaults.minTablesCount, defaults.maxTablesCount, defaults.runTablesCount, defaults.sliderNameTablesCount)
+ self.__sliderPopulationSize = self.__getSlider(1, defaults.minPopulationSize, defaults.maxPopulationSize, defaults.runPopulationSize, defaults.sliderNamePopulationSize)
+ self.__sliderMutation = self.__getSlider(2, defaults.minMutation, defaults.maxMutation, defaults.runMutation, defaults.sliderNameMutation)
+ self.__sliderGenerationsNumber = self.__getSlider(3, defaults.minGenerationsNumber, defaults.maxGenerationsNumber, defaults.runGenerationsNumber, defaults.sliderNameGenerationsNumber)
+ self.__sliderInfoFold = self.__getSlider(4, defaults.minGenerationsNumber, defaults.maxGenerationsNumber, defaults.runInfoFold, defaults.sliderInfoFold)
+ self.__sliderElitism = self.__getSlider(5, defaults.minElitism, defaults.maxElitism, defaults.runElitism, defaults.sliderElitismName)
+
+ self.__radioSelectionMethodValue = IntVar()
+ self.__radioSelectionMethodValue.set(self.__defaults.runSelectionMethod)
+ self.__getRadioButton(6, defaults.defSelectionMethods, self.__radioSelectionMethodValue, defaults.radioSelectionMethodName)
+
+ self.__radioCrossingOverMethodValue = IntVar()
+ self.__radioCrossingOverMethodValue.set(self.__defaults.runCrossingOverMethod)
+ self.__getRadioButton(8, defaults.defCrossingOverMethods, self.__radioCrossingOverMethodValue, defaults.radioCrossingOverMethodName)
+
+ self.__radioMutationMethodValue = IntVar()
+ self.__radioMutationMethodValue.set(self.__defaults.runMutationMethod)
+ self.__getRadioButton(12, defaults.defMutationMethods, self.__radioMutationMethodValue, defaults.radioMutationMethodName)
+
+ self.__buttonDefaults = self.__getButton(15, 0, W, defaults.buttonDefaultsName, self.__setDefaults)
+ self.__buttonStart = self.__getButton(15, 1, E, defaults.buttonStartName, self.__getAllValues)
+ self.window.mainloop()
+
+ def __getSlider(self, rowNum, minVal, maxVal, runVal, labText):
+ label = Label(self.window, text = labText)
+ label.grid(row = rowNum, column = 0, sticky = S + W, padx = 5, pady = 5)
+ slider = Scale(self.window, variable = IntVar(), from_ = minVal, to = maxVal, orient=HORIZONTAL, length = 200)
+ slider.grid(row = rowNum, column = 1, sticky = E, padx = 5, pady = 3)
+ slider.set(runVal)
+ return slider
+
+ def __getButton(self, rowNum, colNum, stickPos, btnText, action):
+ button = Button(self.window, text = btnText, command = action)
+ button.grid(row = rowNum, column = colNum, stick = stickPos, columnspan = 2, padx=60, pady=5)
+ return button
+
+ def __getRadioButton(self, rowNum, methods, variable, labText):
+ label = LabelFrame(self.window, text = labText)
+ label.grid(row=rowNum, column=0, columnspan=2, padx=5, pady=5, sticky=W)
+ rowNum += 1
+ iteration = 0
+ for text, mode in methods:
+ radio = Radiobutton(label, text = text, variable = variable, value = mode)
+ radio.grid(row = rowNum, column = iteration % 2, sticky = W, padx = 5, pady = 3)
+ rowNum += iteration % 2
+ iteration += 1
+
+ def __setDefaults(self):
+ self.__sliderTablesCount.set(self.__defaults.defTablesCount)
+ self.__sliderPopulationSize.set(self.__defaults.defPopulationSize)
+ self.__sliderMutation.set(self.__defaults.defMutation)
+ self.__sliderGenerationsNumber.set(self.__defaults.defGenerationsNumber)
+ self.__sliderInfoFold.set(self.__defaults.defInfoFold)
+ self.__sliderElitism.set(self.__defaults.defElitism)
+ self.__radioSelectionMethodValue.set(self.__defaults.defSelectionMethod)
+ self.__radioCrossingOverMethodValue.set(self.__defaults.defCrossingOverMethod)
+ self.__radioMutationMethodValue.set(self.__defaults.defMutationMethod)
+
+ def __getAllValues(self):
+ self.__defaults.runTablesCount = self.__sliderTablesCount.get()
+ self.__defaults.runPopulationSize = self.__sliderPopulationSize.get()
+ self.__defaults.runMutation = self.__sliderMutation.get()
+ self.__defaults.runGenerationsNumber = self.__sliderGenerationsNumber.get()
+ self.__defaults.runInfoFold = self.__sliderInfoFold.get()
+ self.__defaults.runElitism = self.__sliderElitism.get()
+ self.__defaults.runSelectionMethod = self.__radioSelectionMethodValue.get()
+ self.__defaults.runCrossingOverMethod = self.__radioCrossingOverMethodValue.get()
+ self.__defaults.runMutationMethod = self.__radioMutationMethodValue.get()
+ self.window.destroy()
diff --git a/kelner/gui/chart/Plots.py b/kelner/gui/chart/Plots.py
new file mode 100644
index 0000000..4f4934c
--- /dev/null
+++ b/kelner/gui/chart/Plots.py
@@ -0,0 +1,22 @@
+import matplotlib.pyplot as plt
+
+
+class Plots:
+
+ def __init__(self, generationNumber, bestFitnesses, bestTabless, worstFitnesses, worstTables, title):
+ self.__generationsNumber = generationNumber
+ self.__bestFitnesses = bestFitnesses
+ self.__bestTables = bestTabless
+ self.__worstTables = worstTables
+ self.__worstFitnesses = worstFitnesses
+ self.__title = title
+
+ def draw(self):
+ generations = [i for i in range(self.__generationsNumber + 1)]
+ plt.figure(num = self.__title)
+ plt.plot(generations, self.__bestTables, label = "stoliki najlepszego")
+ plt.plot(generations, self.__bestFitnesses, label="fitness najlepszego")
+ plt.plot(generations, self.__worstTables, label = "stoliki najgorszego")
+ plt.plot(generations, self.__worstFitnesses, label = "fitness najgorszego")
+ plt.legend()
+ plt.show()
diff --git a/kelner/images/kitchen.png b/kelner/images/kitchen.png
index f26d55a..5c31f21 100644
Binary files a/kelner/images/kitchen.png and b/kelner/images/kitchen.png differ
diff --git a/kelner/images/kurczak.png b/kelner/images/kurczak.png
index 22af728..dedaf48 100644
Binary files a/kelner/images/kurczak.png and b/kelner/images/kurczak.png differ
diff --git a/kelner/main.py b/kelner/main.py
index 2d731eb..8e5d241 100644
--- a/kelner/main.py
+++ b/kelner/main.py
@@ -1,25 +1,24 @@
import pygame
+
from kelner.src.components.GridBoard import GridBoard
from kelner.src.components.Waiter import Waiter
-from kelner.src.components.Table import Table
from kelner.src.components.Kitchen import Kitchen
from kelner.src.managers.DrawableCollection import DrawableCollection
+
+# create screen consts
from kelner.src.managers.MenuManager import MenuManager
-from kelner.src.managers.TableManager import TableManager
-from kelner.src.managers.WaiterManager import WaiterManager
+from kelner.src.managers.TableGenerator import TableGenerator
from kelner.src.algorithms.DecisionTree import Tree_Builder
from kelner.src.managers.KitchenManager import KitchenManager
from kelner.src.algorithms.CNN.PrepareData import LoadModelThread
import kelner.src.settings as settings
-import time
-# create screen consts
-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 + 2 * PaintOffset # screen width in pixels
+Scale = 1.5 # 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 + 2 * PaintOffset # screen width in pixels
ScreenHeight = CellSize * GridCountY + 2 * PaintOffset # screen height in pixels
running_tasks = {'table': [], 'waiter': []}
@@ -34,8 +33,10 @@ load_model_thread.start()
# joining this thread to main thread. Man thread will be started after this finish
load_model_thread.join()
+kitchenManager = KitchenManager(gridBoard)
+
# initialize drawable objects manager
-drawableManager = DrawableCollection()
+drawableManager = DrawableCollection(kitchenManager)
# initialize menu manager
menuManager = MenuManager()
@@ -75,48 +76,16 @@ else:
print("test4: fail")
# initialize waiter component
-waiter1 = Waiter(0, 0, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
-# waiter2 = Waiter(0, GridCountY - 1, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
-# waiter3 = Waiter(GridCountX - 1, 0, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
-# waiter4 = Waiter(GridCountX - 1, GridCountY - 1, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
-
+waiter1 = Waiter(7, 4, 0, GridCountX - 1, 0, GridCountY - 1, CellSize, PaintOffset)
# adds waiter to drawable collection
drawableManager.add(waiter1)
-# drawableManager.add(waiter2)
-# drawableManager.add(waiter3)
-# drawableManager.add(waiter4)
-
-kitchen = Kitchen(5, GridCountX - 5, 5, GridCountY - 5, CellSize, PaintOffset)
+kitchen = Kitchen(14, 0, 5, GridCountX - 5, 5, GridCountY - 5, CellSize, PaintOffset)
drawableManager.add(kitchen)
-kitchenManager = KitchenManager(drawableManager, gridBoard)
-# My comment
-# initialize a number of tables given in range
-for i in range(0, 40):
- table = Table(1, GridCountX - 2, 1, GridCountY - 2, CellSize, PaintOffset)
- if drawableManager.generatePosition(table):
- drawableManager.add(table)
-
-# new thread controlling tables
-tableTask = TableManager(drawableManager, menuManager)
-tableTask.start()
-running_tasks['table'].append(tableTask)
-
-# new thread controlling waiter
-waiter1Task = WaiterManager(drawableManager, [waiter1], kitchenManager, menuManager, tableTask)
-waiter1Task.start()
-running_tasks['waiter'].append(tableTask)
-
-# waiter2Task = WaiterManager(drawableManager, [waiter2])
-# waiter2Task.start()
-#
-# waiter3Task = WaiterManager(drawableManager, [waiter3])
-# waiter3Task.start()
-#
-# waiter4Task = WaiterManager(drawableManager, [waiter4])
-# waiter4Task.start()
+tableGenerator = TableGenerator(GridCountX, GridCountY, 1, GridCountX - 2, 1, GridCountY - 2, CellSize, PaintOffset, drawableManager)
+tableGenerator.start()
# main loop
running = True
@@ -124,56 +93,12 @@ while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
- tableTask.stop()
- waiter1Task.stop()
- # waiter2Task.stop()
- # waiter3Task.stop()
- # waiter4Task.stop()
+ tableGenerator.stop()
+ drawableManager.stop()
running = False
- # handles keyboard events
- if event.type == pygame.KEYDOWN:
- if event.key == pygame.K_LEFT:
- # checks if new waiter's position to the left is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() - 1, waiter1.getY()):
- waiter1.moveLeft()
- if event.key == pygame.K_RIGHT:
- # checks if new waiter's position to the right is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() + 1, waiter1.getY()):
- waiter1.moveRight()
- if event.key == pygame.K_UP:
- # checks if new waiter's position up is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX(), waiter1.getY() - 1):
- waiter1.moveUp()
- if event.key == pygame.K_DOWN:
- # checks if new waiter's position down is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX(), waiter1.getY() + 1):
- waiter1.moveDown()
-
- if event.key == pygame.K_w:
- # checks if new waiter's position to the left is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() - 1, waiter1.getY() - 1):
- waiter1.moveLeft()
- waiter1.moveUp()
- if event.key == pygame.K_d:
- # checks if new waiter's position to the right is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() + 1, waiter1.getY() - 1):
- waiter1.moveRight()
- waiter1.moveUp()
- if event.key == pygame.K_s:
- # checks if new waiter's position up is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() + 1, waiter1.getY() + 1):
- waiter1.moveDown()
- waiter1.moveRight()
- if event.key == pygame.K_a:
- # checks if new waiter's position down is not occupied by other object
- if drawableManager.isPositionAvailable(waiter1.getX() - 1, waiter1.getY() + 1):
- waiter1.moveDown()
- waiter1.moveLeft()
- drawableManager.forceRepaint()
-
# repaints all objects to the screen
- # is set only on initial paint or after keyboard event or call to forceRepaint()
+ # is set only on initial paint or call to forceRepaint()
if drawableManager.mustRepaint():
if not kitchenManager.is_running():
gridBoard.reinitialize()
diff --git a/kelner/src/algorithms/CNN/PrepareData.py b/kelner/src/algorithms/CNN/PrepareData.py
index 763ed2b..e4b830b 100644
--- a/kelner/src/algorithms/CNN/PrepareData.py
+++ b/kelner/src/algorithms/CNN/PrepareData.py
@@ -8,9 +8,9 @@ from tensorflow.keras.models import load_model
import kelner.src.settings as settings
# currently all images are not stored in repo because of big weight (5 GB)
-data_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101\\images'
-folder_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101'
-foods_sorted = sorted(os.listdir(data_dir))
+#data_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101\\images'
+#folder_dir = 'D:\\Nauka\\Studia\\4_sem\\SztucznaInteligencja\\A_star\\CNN\\foodRecognitionCNN\\food-101'
+#foods_sorted = sorted(os.listdir(data_dir))
food_id = 0
diff --git a/kelner/src/algorithms/GATableGenerator/GATableGenerator.py b/kelner/src/algorithms/GATableGenerator/GATableGenerator.py
new file mode 100644
index 0000000..0694bbf
--- /dev/null
+++ b/kelner/src/algorithms/GATableGenerator/GATableGenerator.py
@@ -0,0 +1,304 @@
+import random
+import math
+from queue import PriorityQueue
+from kelner.src.algorithms.GATableGenerator.Individual import Individual
+from kelner.src.algorithms.AStar.Finder import Finder
+from kelner.gui.GAdialog.GADefaults import GADefaults, CrossingOverMethod, MutationMethod, SelectionMethod
+
+
+class GATableGenerator:
+
+ def __init__(self, gridCols, gridRows, params):
+ self.gridCols = gridCols
+ self.gridRows = gridRows
+ self.params = params
+ self.currentGenerationNumber = 0
+ self.population = None
+ self.bestFitnessScores = []
+ self.worstFitnessScores = []
+ self.bestTables = []
+ self.worstTables = []
+
+ def generateTables(self):
+ table = [[0] * self.gridCols for i in range(self.gridRows)]
+ for _ in range(self.params.runTablesCount):
+ isPositionUnique = False
+ while not isPositionUnique:
+ x = random.randint(0, self.gridCols - 1)
+ y = random.randint(0, self.gridRows - 1)
+ if (x, y) not in self.params.getForbiddenPlaces() and table[y][x] == 0:
+ isPositionUnique = True
+ table[y][x] = 1
+ table[self.params.kitchenPosition[1]][self.params.kitchenPosition[0]] = 1
+ return table
+
+ def getIndividual(self, table):
+ origin = self.params.waiterPosition
+ finder = Finder(table)
+ fitnessScore = 0
+ tablesCount = 0
+ for y in range(self.gridRows):
+ for x in range(self.gridCols):
+ if table[y][x] == 1:
+ tablesCount += 1
+ targets = finder.getNeighbours((x, y), False)
+ for target in targets:
+ if origin == target:
+ fitnessScore += 1
+ break
+ else:
+ path = finder.getPath(origin, target, True)
+ if path:
+ fitnessScore += 1
+ break
+ individual = Individual(table, fitnessScore - (tablesCount - fitnessScore), tablesCount)
+ return individual
+
+ def updateStats(self):
+ bestIndividual = self.getBestIndividual()
+ worstIndividual = self.getWorstIndividual()
+ self.bestFitnessScores.append(bestIndividual.getFitness())
+ self.bestTables.append(bestIndividual.getTablesCount())
+ self.worstFitnessScores.append(worstIndividual.getFitness())
+ self.worstTables.append(worstIndividual.getTablesCount())
+
+ def firstPopulation(self):
+ self.population = PriorityQueue()
+ for _ in range(self.params.runPopulationSize):
+ self.population.put(self.getIndividual(self.generateTables()))
+ self.currentGenerationNumber = 0
+ self.bestFitnessScores = []
+ self.worstFitnessScores = []
+ self.bestTables = []
+ self.worstTables = []
+ self.updateStats()
+
+ def getPopulationQueue(self):
+ queue = PriorityQueue()
+ for item in self.population.queue:
+ queue.put(item)
+ return queue
+
+ def getPopulationSortedArray(self):
+ queue = self.getPopulationQueue()
+ array = []
+ while not queue.empty():
+ array.append(queue.get())
+ return array
+
+ def arrayToQueue(self, array):
+ queue = PriorityQueue()
+ for item in array:
+ queue.put(item)
+ return queue
+
+ def selectParentsByRoulette(self):
+ populationArray = self.getPopulationSortedArray()
+ parents = []
+ delta = populationArray[len(populationArray) - 1].getFitness()
+ if delta > 0:
+ delta = 0
+ else:
+ delta = abs(delta) + 1
+ fitnessSum = 0
+ for individual in populationArray:
+ fitnessSum += individual.getFitness() + delta
+ for _ in range(2):
+ draw = random.uniform(0, 1)
+ accumulated = 0
+ for individual in populationArray:
+ probability = float(individual.getFitness() + delta) / fitnessSum
+ accumulated += probability
+ if draw <= accumulated:
+ parents.append(individual)
+ fitnessSum -= (individual.getFitness() + delta)
+ populationArray.remove(individual)
+ break
+ return parents
+
+ def selectParentsByTournament(self):
+ parents = []
+ competitorsNum = math.ceil(0.25 * self.params.runPopulationSize)
+ if competitorsNum < self.params.minPopulationSize:
+ competitorsNum = self.params.minPopulationSize - 1
+ population = self.getPopulationSortedArray()
+ parent = self.arrayToQueue(random.sample(population, competitorsNum)).get()
+ population.remove(parent)
+ parents.append(parent)
+ parents.append(self.arrayToQueue(random.sample(population, competitorsNum)).get())
+ return parents
+
+ def quadrant(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ if (row <= math.floor((self.gridRows - 1) / 2.0)) and (col <= math.ceil((self.gridCols - 1) / 2.0)) or \
+ (row > math.floor((self.gridRows - 1) / 2.0)) and (col > math.ceil((self.gridCols - 1) / 2.0)):
+ childTables[row][col] = parentL.getTables()[row][col]
+ else:
+ childTables[row][col] = parentR.getTables()[row][col]
+ return childTables
+
+ def singleVerticalDiv(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ divX = random.randint(1, self.gridCols - 2)
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ if col <= divX:
+ childTables[row][col] = parentL.getTables()[row][col]
+ else:
+ childTables[row][col] = parentR.getTables()[row][col]
+ return childTables
+
+ def singleHorizontalDiv(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ divY = random.randint(1, self.gridRows - 2)
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ if row <= divY:
+ childTables[row][col] = parentL.getTables()[row][col]
+ else:
+ childTables[row][col] = parentR.getTables()[row][col]
+ return childTables
+
+ def doubleVerticalDiv(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ divC = math.ceil((self.gridCols - 1) / 2)
+ divX1 = random.randint(1, divC - 1)
+ divX2 = random.randint(divC + 1, self.gridCols - 2)
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ if divX1 <= col < divX2:
+ childTables[row][col] = parentL.getTables()[row][col]
+ else:
+ childTables[row][col] = parentR.getTables()[row][col]
+ return childTables
+
+ def doubleHorizontalDiv(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ divC = math.ceil((self.gridRows - 1) / 2)
+ divY1 = random.randint(1, divC - 1)
+ divY2 = random.randint(divC + 1, self.gridRows - 2)
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ if divY1 <= row < divY2:
+ childTables[row][col] = parentL.getTables()[row][col]
+ else:
+ childTables[row][col] = parentR.getTables()[row][col]
+ return childTables
+
+ def randomChoice(self, parentL, parentR):
+ childTables = [[0] * self.gridCols for i in range(self.gridRows)]
+ parents = [parentL.getTables(), parentR.getTables()]
+ for row in range(self.gridRows):
+ for col in range(self.gridCols):
+ childTables[row][col] = random.choice(parents)[row][col]
+ return childTables
+
+ def procreate(self):
+ if self.params.runSelectionMethod == SelectionMethod.Roulette:
+ parentLeft, parentRight = self.selectParentsByRoulette()
+ elif self.params.runSelectionMethod == SelectionMethod.Tournament:
+ parentLeft, parentRight = self.selectParentsByTournament()
+ child = None
+ if self.params.runCrossingOverMethod == CrossingOverMethod.FixedQuadrant:
+ child = self.quadrant(parentLeft, parentRight)
+ elif self.params.runCrossingOverMethod == CrossingOverMethod.SingleVerticalDiv:
+ child = self.singleVerticalDiv(parentLeft, parentRight)
+ elif self.params.runCrossingOverMethod == CrossingOverMethod.SingleHorizontalDiv:
+ child = self.singleHorizontalDiv(parentLeft, parentRight)
+ elif self.params.runCrossingOverMethod == CrossingOverMethod.DoubleVerticalDiv:
+ child = self.doubleVerticalDiv(parentLeft, parentRight)
+ elif self.params.runCrossingOverMethod == CrossingOverMethod.DoubleHorizontalDiv:
+ child = self.doubleHorizontalDiv(parentLeft, parentRight)
+ elif self.params.runCrossingOverMethod == CrossingOverMethod.RandomChoice:
+ child = self.randomChoice(parentLeft, parentRight)
+ return child
+
+ def getRandTuple(self):
+ isPlaceAvailable = False
+ while not isPlaceAvailable:
+ randX = random.randint(0, self.gridCols - 1)
+ randY = random.randint(0, self.gridRows - 1)
+ isPlaceAvailable = (randX, randY) not in self.params.getForbiddenPlaces()
+ return randX, randY
+
+ def mutateFlip(self, tables):
+ mutatedTables = tables
+ numberOfMutation = random.randint(0, self.params.runMutation)
+ for _ in range(numberOfMutation):
+ randX, randY = self.getRandTuple()
+ if mutatedTables[randY][randX] == 1:
+ mutatedTables[randY][randX] = 0
+ else:
+ mutatedTables[randY][randX] = 1
+ return mutatedTables
+
+ def mutateSwap(self, tables):
+ mutatedTables = tables
+ numberOfMutation = random.randint(0, self.params.runMutation)
+ for _ in range(numberOfMutation):
+ randX1, randY1 = self.getRandTuple()
+ randX2, randY2 = self.getRandTuple()
+ value = mutatedTables[randY1][randX1]
+ mutatedTables[randY1][randX1] = mutatedTables[randY2][randX2]
+ mutatedTables[randY2][randX2] = value
+ return mutatedTables
+
+ def makeNextGeneration(self):
+ tablesArray = []
+ eliteSize = math.ceil((self.params.runPopulationSize * self.params.runElitism) / 100.0)
+ for _ in range(self.params.runPopulationSize - eliteSize):
+ if self.params.runMutationMethod == MutationMethod.Flip:
+ mutated = self.mutateFlip(self.procreate())
+ elif self.params.runMutationMethod == MutationMethod.Swap:
+ mutated = self.mutateSwap(self.procreate())
+ tablesArray.append(mutated)
+ eliteArray = []
+ for _ in range(eliteSize):
+ eliteArray.append(self.population.get())
+ self.population = PriorityQueue()
+ for individual in eliteArray:
+ self.population.put(individual)
+ for table in tablesArray:
+ self.population.put(self.getIndividual(table))
+ self.currentGenerationNumber += 1
+ self.updateStats()
+
+ def canGenerate(self):
+ return self.currentGenerationNumber < self.params.runGenerationsNumber
+
+ def getBestIndividual(self):
+ population = self.getPopulationQueue()
+ return population.get()
+
+ def getWorstIndividual(self):
+ population = self.getPopulationSortedArray()
+ return population[len(population) - 1]
+
+ def printBest(self):
+ populationBest = self.getBestIndividual()
+ populationBest.print(self.currentGenerationNumber)
+
+ def printPopulation(self):
+ queue = self.getPopulationQueue()
+ while not queue.empty():
+ individual = queue.get()
+ individual.print(self.currentGenerationNumber)
+ print('---------------------------------------')
+
+ def makeAllGenerations(self):
+ self.printBest()
+ while self.canGenerate():
+ self.makeNextGeneration()
+ self.printBest()
+
+"""
+params = GADefaults()
+generator = GATableGenerator(15, 9, params)
+generator.firstPopulation()
+generator.printPopulation()
+while generator.canGenerate():
+ generator.makeNextGeneration()
+ generator.printPopulation()
+"""
\ No newline at end of file
diff --git a/kelner/src/algorithms/GATableGenerator/Individual.py b/kelner/src/algorithms/GATableGenerator/Individual.py
new file mode 100644
index 0000000..76cad6f
--- /dev/null
+++ b/kelner/src/algorithms/GATableGenerator/Individual.py
@@ -0,0 +1,33 @@
+class Individual:
+
+ def __init__(self, table, fitnessScore, tablesCount):
+ self.__table = table
+ self.__fitnessScore = fitnessScore
+ self.__tablesCount = tablesCount
+
+ # operator (>) for PriorityQueue comparison (determines the objects order)
+ def __gt__(self, other):
+ return self.__fitnessScore < other.__fitnessScore
+
+ def getTables(self):
+ return self.__table
+
+ def getTablesCount(self):
+ return self.__tablesCount
+
+ def getFitness(self):
+ return self.__fitnessScore
+
+ def getInfo(self, generation):
+ return f"GENERATION: {generation}, FITNESS: {self.__fitnessScore}, TABLES: {self.__tablesCount}"
+
+ def print(self, generation):
+ print(self.getInfo(generation))
+ cols = len(self.__table[0])
+ rows = len(self.__table)
+ for row in range(rows):
+ for col in range(cols):
+ v = self.__table[row][col]
+ v = ' ' if v == 0 else '#' if v == 1 else 'O'
+ print('|', v, sep='', end='')
+ print('|')
\ No newline at end of file
diff --git a/kelner/src/components/Drawable.py b/kelner/src/components/Drawable.py
index dd8fa7e..873d88e 100644
--- a/kelner/src/components/Drawable.py
+++ b/kelner/src/components/Drawable.py
@@ -1,5 +1,3 @@
-from kelner.src.managers.ImageCache import ImageCache, Images
-
class Drawable:
@@ -62,15 +60,3 @@ class Drawable:
def drawAux(self, screen):
pass
-
- def getImage(self, imageKind, img_path=None):
- if imageKind in [Images.Guest1, Images.Guest2, Images.Guest3, Images.Plate]:
- size = int(self.getCellSize() / 3)
- elif imageKind in [Images.Kitchen, Images.Dishes]:
- size = int(self.getCellSize())
- else:
- size = int(1.4 * self.getCellSize())
- if img_path:
- return ImageCache.getInstance().getImage(imageKind, size, size, img_path)
- else:
- return ImageCache.getInstance().getImage(imageKind, size, size)
diff --git a/kelner/src/components/Kitchen.py b/kelner/src/components/Kitchen.py
index 75e9060..01244ce 100644
--- a/kelner/src/components/Kitchen.py
+++ b/kelner/src/components/Kitchen.py
@@ -1,18 +1,15 @@
import random
-from enum import Enum
-from threading import Lock
from kelner.src.components.Drawable import Drawable
from kelner.src.managers.ImageCache import ImageCache, Images
from kelner.src.algorithms.DecisionTree import Tree_Builder
import os
-import copy
-import time
import pygame
+
class Kitchen(Drawable):
- def __init__(self, minX, maxX, minY, maxY, cellSize, offset):
+ def __init__(self, x, y, minX, maxX, minY, maxY, cellSize, offset):
# call base class constructor
- super().__init__(14, 0, minX, maxX, minY, maxY, cellSize, offset)
+ super().__init__(x, y, minX, maxX, minY, maxY, cellSize, offset)
self._preparing_orders = None
self._ready_orders = None
self._photos_path = os.path.join(os.getcwd(), 'foodImages')
@@ -92,7 +89,17 @@ class Kitchen(Drawable):
# print("Image drawing: {}".format(img_path))
return img_paths
-
+ def getImage(self, imageKind, img_path=None):
+ if imageKind in [Images.Guest1, Images.Guest2, Images.Guest3, Images.Plate]:
+ size = int(self.getCellSize() / 3)
+ elif imageKind in [Images.Kitchen, Images.Dishes]:
+ size = int(self.getCellSize())
+ else:
+ size = int(1.4 * self.getCellSize())
+ if img_path:
+ return ImageCache.getInstance().getImage(imageKind, size, size, img_path)
+ else:
+ return ImageCache.getInstance().getImage(imageKind, size, size)
def draw(self, screen):
xBase = self.getX() * self.getCellSize() + self.getOffset()
diff --git a/kelner/src/components/Table.py b/kelner/src/components/Table.py
index 9e12681..2b6ea31 100644
--- a/kelner/src/components/Table.py
+++ b/kelner/src/components/Table.py
@@ -111,7 +111,7 @@ class Table(Drawable):
self.__status = status
def __getImage(self, imageKind):
- if imageKind in [Images.Guest1, Images.Guest2, Images.Guest3, Images.Plate]:
+ if imageKind in [Images.Guest1, Images.Guest2, Images.Guest3, Images.Plate, Images.Chicken]:
size = int(self.getCellSize() / 3)
else:
size = int(1.4 * self.getCellSize())
@@ -164,3 +164,15 @@ class Table(Drawable):
screen.blit(imagePlate, (xBase + guest1XOffset, yBase + platesYOffset))
screen.blit(imagePlate, (xBase + guest2XOffset, yBase + platesYOffset))
screen.blit(imagePlate, (xBase + guest3XOffset, yBase + platesYOffset))
+ elif self.isStatus(Status.Served):
+ platesYOffset = int(0.3 * self.getCellSize())
+ imageChicken = self.__getImage(Images.Chicken)
+ if len(self.__guests) == 1:
+ screen.blit(imageChicken, (xBase + guest2XOffset, yBase + platesYOffset))
+ elif len(self.__guests) == 2:
+ screen.blit(imageChicken, (xBase + guest4XOffset, yBase + platesYOffset))
+ screen.blit(imageChicken, (xBase + guest5XOffset, yBase + platesYOffset))
+ elif len(self.__guests) == 3:
+ screen.blit(imageChicken, (xBase + guest1XOffset, yBase + platesYOffset))
+ screen.blit(imageChicken, (xBase + guest2XOffset, yBase + platesYOffset))
+ screen.blit(imageChicken, (xBase + guest3XOffset, yBase + platesYOffset))
diff --git a/kelner/src/managers/DrawableCollection.py b/kelner/src/managers/DrawableCollection.py
index 7339780..a8f8f06 100644
--- a/kelner/src/managers/DrawableCollection.py
+++ b/kelner/src/managers/DrawableCollection.py
@@ -7,16 +7,43 @@ from kelner.src.components.Kitchen import Kitchen
# drawable objects manager
+from kelner.src.managers.MenuManager import MenuManager
+from kelner.src.managers.TableManager import TableManager
+from kelner.src.managers.WaiterManager import WaiterManager
+
+
class DrawableCollection:
# const, minimal distance between objects
__MinDistanceX = 1
__MinDistanceY = 0
- def __init__(self):
+ def __init__(self, kitchenManager):
# collection that holds all drawable objects
self.__mustRepaint = True
self.__drawables = []
self.__waiterLock = Lock()
+ self.__tasks = []
+ self.__kitchenManager = kitchenManager
+
+ def start(self):
+ # initialize menu manager
+ menuManager = MenuManager()
+ # new thread controlling tables
+ tableTask = TableManager(self, menuManager)
+ self.__tasks.append(tableTask)
+
+ waiters = self.getWaiters()
+ for waiter in waiters:
+ # new thread controlling waiter
+ waiterTask = WaiterManager(self, [waiter], self.__kitchenManager, menuManager, tableTask)
+ self.__tasks.append(waiterTask)
+
+ for task in self.__tasks:
+ task.start()
+
+ def stop(self):
+ for task in self.__tasks:
+ task.stop()
# adds drawable objects to the collection
def add(self, drawable):
@@ -52,6 +79,10 @@ class DrawableCollection:
break
return isPositionAvailable
+ # deletes all tables
+ def delTables(self):
+ self.__drawables = [drawable for drawable in self.__drawables if not isinstance(drawable, Table)]
+
# gets all tables by status from collection
def getTables(self, status):
result = []
@@ -61,11 +92,10 @@ class DrawableCollection:
return result
def get_kitchen(self):
- kitchen = None
for item in self.__drawables:
if isinstance(item, Kitchen):
- kitchen = item
- return kitchen
+ return item
+ return None
def lock(self):
self.__waiterLock.acquire()
@@ -101,8 +131,8 @@ class DrawableCollection:
nearestTables = []
tables = self.getTables(tableStatus)
for table in tables:
- if (table.getX() == waiter.getX() and abs(table.getY() - waiter.getY()) == 1) or \
- (table.getY() == waiter.getY() and abs(table.getX() - waiter.getX()) == 1):
+ if (table.getX() == waiter.getX() and abs(table.getY() - waiter.getY()) == 1) or\
+ (table.getY() == waiter.getY() and abs(table.getX() - waiter.getX()) == 1):
nearestTables.append(table)
return nearestTables
diff --git a/kelner/src/managers/ImageCache.py b/kelner/src/managers/ImageCache.py
index e807e72..5a90c2c 100644
--- a/kelner/src/managers/ImageCache.py
+++ b/kelner/src/managers/ImageCache.py
@@ -23,6 +23,7 @@ class Images(Enum):
ToolTip = 16
Kitchen = 17
Dishes = 18
+ Chicken = 19
class ImageCache:
@@ -60,7 +61,8 @@ class ImageCache:
Images.Guest3: './images/wiking_rudy2.png',
Images.ToolTip: './images/tooltip.png',
Images.Kitchen: './images/kitchen.png',
- Images.Dishes: './images/testDishes/'
+ Images.Dishes: './images/testDishes/',
+ Images.Chicken: './images/kurczak.png'
}
def __getFont(self):
diff --git a/kelner/src/managers/KitchenManager.py b/kelner/src/managers/KitchenManager.py
index 5ad48be..158e2aa 100644
--- a/kelner/src/managers/KitchenManager.py
+++ b/kelner/src/managers/KitchenManager.py
@@ -6,9 +6,8 @@ import sys
# creates new thread
class KitchenManager(threading.Thread):
- def __init__(self, drawable_manager, gridboard):
+ def __init__(self, gridboard):
super().__init__()
- self._drawable_manager = drawable_manager
self._gridboard = gridboard
self.__runThread = False
diff --git a/kelner/src/managers/TableGenerator.py b/kelner/src/managers/TableGenerator.py
new file mode 100644
index 0000000..038c398
--- /dev/null
+++ b/kelner/src/managers/TableGenerator.py
@@ -0,0 +1,120 @@
+import threading
+from tkinter import messagebox, Tk
+from kelner.src.components.Table import Table
+from kelner.src.algorithms.GATableGenerator.GATableGenerator import GATableGenerator
+from kelner.gui.GAdialog.GADialog import GADialog
+from kelner.gui.GAdialog.GADefaults import GADefaults
+from kelner.gui.chart.Plots import Plots
+
+
+# creates new thread
+class TableGenerator (threading.Thread):
+
+ def __init__(self, gridCols, gridRows, minX, maxX, minY, maxY, cellSize, paintOffset, drawableManager):
+ super().__init__()
+ self.__minX = minX
+ self.__maxX = maxX
+ self.__minY = minY
+ self.__maxY = maxY
+ self.__cellSize = cellSize
+ self.__paintOffset = paintOffset
+ self.__drawableManager = drawableManager
+ self.__runThread = True
+ self.__defaults = GADefaults()
+ self.__defaults.waiterPosition = self.__getDefaultWaiterPosition()
+ self.__defaults.kitchenPosition = self.__getDefaultKitchenPosition()
+ self.__gaTableGenerator = GATableGenerator(gridCols, gridRows, self.__defaults)
+
+ def __getDefaultWaiterPosition(self):
+ waiters = self.__drawableManager.getWaiters()
+ if waiters:
+ return waiters[0].getX(), waiters[0].getY()
+ return None
+
+ def __getDefaultKitchenPosition(self):
+ kitchen = self.__drawableManager.get_kitchen()
+ if kitchen is not None:
+ return kitchen.getX(), kitchen.getY()
+ return None
+
+ def __randomTables(self):
+ # initialize a number of tables given in range
+ for i in range(0, 40):
+ table = Table(self.__minX, self.__maxX, self.__minY, self.__maxY, self.__cellSize, self.__paintOffset)
+ if self.__drawableManager.generatePosition(table):
+ self.__drawableManager.add(table)
+
+ def __geneticTables(self):
+ bestIndividual = self.__gaTableGenerator.getBestIndividual()
+ for row in range(self.__gaTableGenerator.gridRows):
+ for col in range(self.__gaTableGenerator.gridCols):
+ if bestIndividual.getTables()[row][col] == 1 and \
+ (row != self.__defaults.kitchenPosition[1] or col != self.__defaults.kitchenPosition[0]):
+ table = Table(0, self.__gaTableGenerator.gridCols - 1, 0, self.__gaTableGenerator.gridRows - 1, self.__cellSize, self.__paintOffset)
+ table.setX(col)
+ table.setY(row)
+ self.__drawableManager.add(table)
+
+ def __askIfGA(self):
+ window = Tk()
+ window.attributes('-topmost', 'true')
+ window.wm_withdraw()
+ result = messagebox.askquestion("Rodzaj algorytmu", "Czy uruchomić algorytm genetyczny?", parent=window)
+ window.destroy()
+ return result == 'yes'
+
+ def __ask(self, info):
+ window = Tk()
+ window.attributes('-topmost', 'true')
+ window.wm_withdraw()
+ result = messagebox.askquestion(info + '\n', "Czy nowa generacja?", parent=window)
+ window.destroy()
+ return result == 'yes'
+
+ def __askIfAgain(self):
+ window = Tk()
+ window.attributes('-topmost', 'true')
+ window.wm_withdraw()
+ result = messagebox.askquestion("Potwierdź", "Czy powtórzyć proces?", parent=window)
+ window.destroy()
+ return result == 'yes'
+
+ def __plot(self):
+ plot = Plots(self.__gaTableGenerator.currentGenerationNumber,
+ self.__gaTableGenerator.bestFitnessScores, self.__gaTableGenerator.bestTables,
+ self.__gaTableGenerator.worstFitnessScores, self.__gaTableGenerator.worstTables,
+ self.__defaults.getInfo())
+ plot.draw()
+
+ def run(self):
+ if self.__askIfGA():
+ while self.__runThread:
+ again = True
+ GADialog(self.__defaults)
+ self.__gaTableGenerator.firstPopulation()
+ while again:
+ self.__drawableManager.delTables()
+ self.__geneticTables()
+ self.__drawableManager.forceRepaint()
+ if self.__gaTableGenerator.canGenerate():
+ if self.__gaTableGenerator.currentGenerationNumber % self.__defaults.runInfoFold != 0 or\
+ self.__ask(self.__gaTableGenerator.getBestIndividual().getInfo(self.__gaTableGenerator.currentGenerationNumber)):
+ self.__gaTableGenerator.makeNextGeneration()
+ else:
+ self.__drawableManager.start()
+ self.stop()
+ again = False
+ self.__plot()
+ else:
+ self.__plot()
+ if not self.__askIfAgain():
+ self.__drawableManager.start()
+ self.stop()
+ again = False
+ else:
+ self.__randomTables()
+ self.__drawableManager.forceRepaint()
+ self.__drawableManager.start()
+
+ def stop(self):
+ self.__runThread = False
diff --git a/kelner/src/managers/WaiterManager.py b/kelner/src/managers/WaiterManager.py
index 9c80ac6..dd6a65e 100644
--- a/kelner/src/managers/WaiterManager.py
+++ b/kelner/src/managers/WaiterManager.py
@@ -1,6 +1,7 @@
import threading
import time
import sys
+from math import sqrt
from kelner.src.components.Table import Status
from kelner.src.algorithms.AStar.Finder import Finder
from kelner.src.algorithms.BFS.BFS import BFS
@@ -20,43 +21,65 @@ class WaiterManager(threading.Thread):
self._menu_manager = menu_manager
self._table_manager = table_manager
- def __getNearestTargetPath(self, waiter, target):
- distance = sys.maxsize
- nearestTargetPath = None
- reservedPlaces = self.__drawableManager.getReservedPlaces(waiter)
+ def __getDistance(self, waiter, tupleXY):
+ dx = waiter.getX() - tupleXY[0]
+ dy = waiter.getY() - tupleXY[1]
+ return sqrt(dx * dx + dy * dy)
+
+ def __sortTargets(self, waiter, targets):
+ return sorted(targets, key=lambda target: self.__getDistance(waiter, (target[0], target[1])))
+
+ def __getTargets(self, waiter, finder):
+ found = []
tables = self.__drawableManager.getTables(Status.Ready)
- finder = Finder(reservedPlaces)
- origin = (waiter.getX(), waiter.getY())
- if target == 'kitchen':
- path = finder.getPath(origin, (14, 1), True)
- path2 = finder.getPath(origin, (13, 0), True)
- path = path2 if len(path) > len(path2) else path
- return path
if tables:
+ origin = (waiter.getX(), waiter.getY())
for table in tables:
if table.hasOrder():
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
+ if target == origin:
+ return []
+ else:
+ found.append(target)
+ return self.__sortTargets(waiter, found)
+
+ def __getNearestTargetPath(self, waiter, targets=None):
+ distance = sys.maxsize
+ nearestTargetPath = None
+ reservedPlaces = self.__drawableManager.getReservedPlaces(waiter)
+ finder = Finder(reservedPlaces)
+ origin = (waiter.getX(), waiter.getY())
+ if targets is None:
+ targets = self.__getTargets(waiter, finder)
+ for target in targets:
+ if distance > self.__getDistance(waiter, target):
+ path = finder.getPath(origin, target, True)
+ if path:
+ result = len(path)
+ if result < distance:
+ distance = result
+ nearestTargetPath = path
return nearestTargetPath
def get_specified_path(self, waiter, table):
+ distance = sys.maxsize
+ nearestTargetPath = None
reserved_places = self.__drawableManager.getReservedPlaces(waiter)
finder = Finder(reserved_places)
origin = (waiter.getX(), waiter.getY())
targets = finder.getNeighbours((table[0], table[1]), False)
for target in targets:
- if target is not None:
+ if distance > self.__getDistance(waiter, target):
path = finder.getPath(origin, target, True)
if path:
- return path
+ result = len(path)
+ if result < distance:
+ distance = result
+ nearestTargetPath = path
+
+ return nearestTargetPath
def __changeWaiterDirection(self, waiter, x, y):
targetDirection = x - waiter.getX(), y - waiter.getY()
@@ -172,13 +195,14 @@ class WaiterManager(threading.Thread):
if len(waiter.getAcceptedOrders()) > 1:
waiter.set_target('kitchen')
- path = self.__getNearestTargetPath(waiter, target=waiter.get_target())
+ path = self.__getNearestTargetPath(waiter, [(14, 1), (13, 0)])
waiter.make_busy()
else:
if waiter.get_target() == 'return_order' and waiter.isPathEmpty():
print("Order returned")
table = self._table_manager.get_table(waiter.get_remaining_positions()[0])
table.setStatus(Status.Served)
+ self.__changeWaiterDirection(waiter, table.getX(), table.getY())
waiter.get_remaining_positions().pop(0)
time.sleep(2)
@@ -187,7 +211,7 @@ class WaiterManager(threading.Thread):
path = self.get_specified_path(waiter, waiter.get_remaining_positions()[0])
else:
waiter.set_target('table')
- path = self.__getNearestTargetPath(waiter, target='table')
+ path = self.__getNearestTargetPath(waiter)
waiter.setPath([] if path is None else path)
@@ -201,6 +225,7 @@ class WaiterManager(threading.Thread):
if waiter.get_target() == 'kitchen':
self._table_manager.pause()
kitchen = self.__drawableManager.get_kitchen()
+ self.__changeWaiterDirection(waiter, kitchen.getX(), kitchen.getY())
waiter_orders = waiter.getAcceptedOrders()
# print("Waiter near kitchen. Collected orders: {}".format(waiter_orders))
kitchen.add_orders(waiter_orders)
diff --git a/Raport - Podprojekt Adam Toppmayer.pdf b/raports/Raport - Podprojekt Adam Toppmayer.pdf
similarity index 100%
rename from Raport - Podprojekt Adam Toppmayer.pdf
rename to raports/Raport - Podprojekt Adam Toppmayer.pdf
diff --git a/Raport - Podprojekt_Adam_Wojdyla.pdf b/raports/Raport - Podprojekt_Adam_Wojdyla.pdf
similarity index 100%
rename from Raport - Podprojekt_Adam_Wojdyla.pdf
rename to raports/Raport - Podprojekt_Adam_Wojdyla.pdf
diff --git a/Raport - _Automatyczny kelner_.pdf b/raports/Raport - _Automatyczny kelner_.pdf
similarity index 100%
rename from Raport - _Automatyczny kelner_.pdf
rename to raports/Raport - _Automatyczny kelner_.pdf
diff --git a/raports/Raport - algorytm genetyczny - generator stolików - Mikołaj Krzymiński.pdf b/raports/Raport - algorytm genetyczny - generator stolików - Mikołaj Krzymiński.pdf
new file mode 100644
index 0000000..1909fe6
Binary files /dev/null and b/raports/Raport - algorytm genetyczny - generator stolików - Mikołaj Krzymiński.pdf differ
diff --git a/Raport 2 - _Automatyczny kelner_.pdf b/raports/Raport 2 - _Automatyczny kelner_.pdf
similarity index 100%
rename from Raport 2 - _Automatyczny kelner_.pdf
rename to raports/Raport 2 - _Automatyczny kelner_.pdf