import pygame import random import time import queue import math import joblib from keras.models import load_model, Sequential from keras.preprocessing.image import img_to_array, load_img from keras.layers import Conv2D, MaxPooling2D from keras.layers import Activation, Dropout, Flatten, Dense from keras import backend as K from tkinter import messagebox import tkinter as tk from PIL import Image root = tk.Tk() root.withdraw() #ukrycie okna tworzonego przez tkinter pygame.init() def heuristic(current, goal): dx = abs(current[0] - goal[0]) dy = abs(current[1] - goal[1]) return math.sqrt(dx * dx + dy * dy) class Node(): def __init__(self, parent = None, position = None): self.parent = parent self.position = position self.g = 0 self.h = 0 self.f = 0 def __eq__(self, other): return self.position == other.position def aStar(start, end): if end in cantwalk: print("Wybrano nieodpowiednie pole!") return [] start_node = Node(None, start) start_node.g = start_node.h = start_node.f = 0 end_node = Node(None, end) end_node.g = end_node.h = end_node.f = 0 open_list = [] closed_list = [] open_list.append(start_node) while len(open_list) > 0: current_node = open_list[0] current_index = 0 for index, item in enumerate(open_list): if item.f < current_node.f: current_node = item current_index = index open_list.pop(current_index) closed_list.append(current_node) if current_node == end_node: path = [] current = current_node while current is not None: path.append(current.position) current = current.parent return list(map(lambda t: (t[0], t[1]), path[::-1])) #zwraca odwróconą ściezkę children = [] # można dodać (-1, -1), (-1, 1), (1, -1), (1, 1) dla poruszania się po przekątnej for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]: node_position = (current_node.position[0] + new_position[0], current_node.position[1] + new_position[1]) if node_position[0] >= (rows - 1) or node_position[0] <= 0 or node_position[1] >= (rows - 1) \ or node_position[1] <= 0: #spr. czy w kracie continue if node_position in cantwalk: #spr. czy można przejść continue new_node = Node(current_node, node_position) children.append(new_node) didBreak = False for child in children: didBreak = False for closed_child in closed_list: if child == closed_child: didBreak = True break if didBreak: continue if child.position in cantwalk: child.g = current_node.g + 99999 elif child.position in puddles: child.g = current_node.g + 3 else: child.g = current_node.g + 1 child.h = heuristic(child.position, end_node.position) child.f = child.g + child.h for open_node in open_list: if child == open_node and child.g > open_node.g: didBreak = True break if didBreak: continue open_list.append(child) class Dish(object): def __init__(self, dishName, prepTime, eatTime, price): self.dishName = dishName self.preparationTime = prepTime self.eatingTime = eatTime self.price = int(price) self.fatContent = random.randint(0, 16) self.fiberContent = random.randint(0, 16) self.spicy = random.randint(0, 1) class Plate(object): def __init__(self, dish, img=None): self.dishName = dish.dishName self.isEmpty = False self.preparationTime = dish.preparationTime self.eatingTime = dish.eatingTime self.price = dish.price self.img = img def eat(self): #time.sleep(self.eatingTime) psuje program - nie używajcie self.isEmpty = True #zjadanie dania jest oznaczeniem talerza jako pusty (metoda będzie wywoływana przez klienta) def draw(self): load = Image.open(self.img) load.show() class Kitchen(object): def __init__(self, pos): self.readyDishes = queue.Queue(32) #kolejka o maksymalnej długości 32 self.orders = queue.Queue(32) #wyskakiwał mi tu błąd - poprawiłam na dużą literę i jest ok self.pos = pos def makeDish(self): if not self.orders.empty(): plate = self.orders.get() time.sleep(plate.preparationTime) #kuchnia przygotowuje danie przez określony czas self.readyDishes.put(plate) def giveDish(self): if not self.readyDishes.empty(): plate = self.readyDishes.get() return plate else: return None def draw(self, surface): image1 = pygame.image.load(r'kitchen1.png') image1 = pygame.transform.scale(image1, (sizeBetween - 1, sizeBetween - 1)) surface.blit(image1, (13*sizeBetween+1, 0*sizeBetween+1)) image2 = pygame.image.load(r'kitchen2.png') image2 = pygame.transform.scale(image2, (sizeBetween - 1, sizeBetween - 1)) surface.blit(image2, (14*sizeBetween+1, 0*sizeBetween+1)) image3 = pygame.image.load(r'kitchen3.png') image3 = pygame.transform.scale(image3, (sizeBetween - 1, sizeBetween - 1)) surface.blit(image3, (13*sizeBetween+1, 1*sizeBetween+1)) image4 = pygame.image.load(r'kitchen4.png') image4 = pygame.transform.scale(image4, (sizeBetween - 1, sizeBetween - 1)) surface.blit(image4, (14*sizeBetween+1, 1*sizeBetween+1)) class Client(object): def __init__(self, age, sex, table, budget): self.age = age self.sex = sex self.myPlate = None self.myTable = table #domyślnie klient nie siedzi przy żadnym stole self.budget = budget def takePlateAndEat(self, plate): self.myPlate = plate plate.eat() def takeASeat(self, table): self.myTable = table def returnPlate(self): plate = self.myPlate self.myPlate = None return plate def pay(self, image): load = Image.open(image) load.show() class Table(object): def __init__(self, pos, capacity): self.pos = pos self.capacity = capacity def move(self, newx, newy): #metoda do ustawiania stołów poprzez podanie nowych współrzędnych self.pos[0] = newx self.pos[1] = newy def draw(self, surface): image = pygame.image.load(r'Table-croped.png') image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1)) i = self.pos[0] j = self.pos[1] surface.blit(image, (i*sizeBetween+1, j*sizeBetween+1)) class Waiter(object): def __init__(self, color, pos, direction): self.color = color self.pos = pos #pozycja agenta, zapisana w formie dwuelementowej listy self.posx = pos[0] self.posy = pos[1] self.dirnx = 0 #zmienne dirnx i dirny używane są do ruchu bota i ustalania, w którą stronę jest zwrócony self.dirny = 1 self.plates = [] #lista niesionych przez agenta talerzy, planowo lista par: (talerz, klient) self.direction = direction #kierunek, w ktory jest skierowany bot self.currentRotation = 0 self.rotate = "forward" self.rotationNumber = 0 def resetPosition(self, pos): self.pos = pos def takePlates(self, kitchen): for i in range(2): plate = kitchen.giveDish() if plate == None: break else: self.plates.append(plate) def giveClientPlate(self, client): plate = self.plates.pop(0) client.takePlateAndEat(plate) def rotateRight(self): self.currentRotation += 90 def rotateLeft(self): self.currentRotation -= 90 def goForward(self, movex, movey): self.posx += movex self.posy += movey self.pos = (self.posx, self.posy) def draw(self, surface): image = pygame.image.load(r'waiter_right.png') image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1)) if self.rotate == "right": self.rotateRight() elif self.rotate == "left": self.rotateLeft() elif self.direction == "forward": pass image = pygame.transform.rotate(image, self.currentRotation) i = self.pos[0] j = self.pos[1] surface.blit(image, (i * sizeBetween + 1, j * sizeBetween + 1)) def goByAStar(self, end): positionList = aStar(self.pos, end) print(positionList) if len(positionList) == 0: messagebox.showerror("BŁĄD!", "Wybrano nieosiągalne pole!") pygame.quit() exit() else: lenght = len(positionList) - 1 for i in range(lenght): movex = positionList[i + 1][0] - positionList[i][0] movey = positionList[i + 1][1] - positionList[i][1] prevDirection = self.direction if movex == -1 and movey == 0: self.direction = 1 #"left" elif movex == 1 and movey == 0: self.direction = 3 #"right" elif movey == 1 and movex == 0: self.direction = 4 #"down" else: self.direction = 2 #"up" howToRotate = prevDirection - self.direction #działa! if howToRotate < 0: self.rotate = "left" self.rotationNumber = abs(howToRotate) elif howToRotate > 0: self.rotate = "right" self.rotationNumber = abs(howToRotate) elif howToRotate == 0: self.rotate = "forward" self.rotationNumber = 0 #print(self.rotate) for i in range(self.rotationNumber): redrawWindow(window) time.sleep(0.2) self.rotate = "forward" self.rotationNumber = 0 self.goForward(movex, movey) redrawWindow(window) time.sleep(0.2) def drawGrid(width, rows, surface): x = 0 y = 0 for i in range(rows): x = x + sizeBetween y = y + sizeBetween pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, width)) pygame.draw.line(surface, (255, 255, 255), (0, y), (width, y)) def predictAndShowImg(plate): img_width, img_height = 256, 256 plate.draw() test_image = load_img(plate.img, target_size=(img_width, img_height)) test_image = img_to_array(test_image) test_image = test_image.reshape((1,) + test_image.shape) result = img_classify.predict(test_image) print(result) if (result == [1.]): messagebox.showinfo("Rozpoznanie", "Talerz pełny.") return 1 else: messagebox.showinfo("Rozpoznanie", "Talerz pusty.") return 0 def checkIfEmpty(fullOrEmpty, client): if fullOrEmpty == 1: pass elif fullOrEmpty == 0: client.returnPlate() bot.goByAStar((kitchen.pos[0] - 1, kitchen.pos[1])) def classify(a): if a == 1: dish_1 = Dish("obiad", 40, 20, 15) dish_2 = Dish("deser", 25, 10, 10) dish_3 = Dish("obiad 2", 55, 25, 28) plate_1 = Plate(dish_1, "Sara/data/validation/food/food004.png") plate_2 = Plate(dish_2, "Sara/data/validation/food/food002.png") plate_3 = Plate(dish_1, "Sara/data/validation/dirty/dirty001.png") plate_4 = Plate(dish_3, "Sara/data/validation/dirty/dirty009.png") client_1 = Client(21, 1, 45, 1) client_2 = Client(44, 0, 22, 4) client_3 = Client(27, 1, 15, 5) client_4 = Client(19, 0, 32, 8) client_1.takePlateAndEat(plate_1) client_2.takePlateAndEat(plate_2) client_3.takePlateAndEat(plate_3) client_4.takePlateAndEat(plate_4) ''' TRASA + ROZPOZNAWANIE TALERZY ''' bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1])) fullOrEmpty = predictAndShowImg(plate_1) checkIfEmpty(fullOrEmpty, client_1) bot.goByAStar((tables[4].pos[0] + 1, tables[4].pos[1])) fullOrEmpty = predictAndShowImg(plate_2) checkIfEmpty(fullOrEmpty, client_2) bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1])) fullOrEmpty = predictAndShowImg(plate_3) checkIfEmpty(fullOrEmpty, client_3) bot.goByAStar((tables[8].pos[0] + 1, tables[8].pos[1])) fullOrEmpty = predictAndShowImg(plate_4) checkIfEmpty(fullOrEmpty, client_4) messagebox.showinfo("Informacja końcowa", "Zakończono trasę.") pygame.quit() exit() else: pass def predictDigest(dish, client, model): data = [] data.append(client.age) data.append(dish.fatContent) data.append(dish.fiberContent) data.append(client.sex) data.append(dish.spicy) prediction = model.predict([data]) if prediction == 1: messagebox.showinfo("opinia", "Z tym może być ciężko. " + str(data)) return prediction else: messagebox.showinfo("opinia", "Z tym nie będzie tak źle! " + str(data)) return prediction def evaluate(b): if b == 1: loaded_model = joblib.load('Marta/finalized_model.sav') # load = Image.open('Marta/digest_entropy.png') # load.show() messagebox.showinfo("zaczynamy", "Zaczynamy!") dish_1 = Dish("obiad", 40, 20, 15) dish_2 = Dish("deser", 25, 10, 10) dish_3 = Dish("obiad 2", 55, 25, 28) plate_1 = Plate(dish_1, "Sara/data/validation/food/food004.png") plate_2 = Plate(dish_2, "Sara/data/validation/food/food002.png") plate_4 = Plate(dish_3, "Sara/data/validation/dirty/dirty009.png") client_1 = Client(27, 1, 45, 1) client_2 = Client(44, 0, 22, 4) client_4 = Client(16, 0, 32, 8) client_1.takePlateAndEat(plate_1) client_2.takePlateAndEat(plate_2) client_4.takePlateAndEat(plate_4) bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1])) opinion = predictDigest(dish_1, client_1, loaded_model) bot.goByAStar((tables[3].pos[0] + 1, tables[3].pos[1])) opinion = predictDigest(dish_2, client_2, loaded_model) bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1])) opinion = predictDigest(dish_3, client_4, loaded_model) messagebox.showinfo("Informacja końcowa", "Zakończono trasę.") pygame.quit() exit() else: pass def decide(client, image, dish): img_width, img_height = 256, 256 client.pay(image) test_image = load_img(image, target_size=(img_width, img_height)) test_image = img_to_array(test_image) test_image = test_image.reshape((1,) + test_image.shape) result = pln_model.predict(test_image) print(result) if result.tolist() == [[1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(10 - dish.price) + " zł.") return 0 elif result.tolist() == [[0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(100 - dish.price) + " zł.") return 0 elif result.tolist() == [[0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(20 - dish.price) + " zł.") return 0 elif result.tolist() == [[0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(200 - dish.price) + " zł.") return 0 elif result.tolist() == [[0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(50 - dish.price) + " zł.") return 0 elif result.tolist() == [[0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]]: messagebox.showinfo("Rachunek", "Dziękuję, należy się reszta: " + str(500 - dish.price) + " zł.") return 0 else: messagebox.showinfo("Uwaga", "Niestety, nie przyjmujemy zapłaty kartą.") return 1 def payment(c): if c == 1: dish_1 = Dish("obiad", 40, 20, 150) dish_2 = Dish("deser", 25, 10, 75) dish_3 = Dish("obiad 2", 30, 25, 49) dish_4 = Dish("obiad 2", 15, 25, 14) plate_1 = Plate(dish_1) plate_2 = Plate(dish_2) plate_3 = Plate(dish_3) plate_4 = Plate(dish_4) client_1 = Client(21, 1, 1, 200) client_2 = Client(44, 0, 4, 100) client_3 = Client(27, 1, 5, 50) client_4 = Client(19, 0, 8, 0) #karta client_1.takePlateAndEat(plate_1) client_2.takePlateAndEat(plate_2) client_3.takePlateAndEat(plate_3) client_4.takePlateAndEat(plate_4) bot.goByAStar((tables[1].pos[0] + 1, tables[1].pos[1])) messagebox.showinfo("Rachunek", "Proszę o zapłatę " + str(dish_1.price) + " zł.") client1_payment = ('Kinga/data/examine/200/examine_056.png') decide(client_1, client1_payment, dish_1) bot.goByAStar((tables[4].pos[0] + 1, tables[4].pos[1])) messagebox.showinfo("Rachunek", "Proszę o zapłatę " + str(dish_2.price) + " zł.") client2_payment = ("Kinga/data/examine/100/examine_036.png") decide(client_2, client2_payment, dish_2) bot.goByAStar((tables[5].pos[0] + 1, tables[5].pos[1])) messagebox.showinfo("Rachunek", "Proszę o zapłatę " + str(dish_3.price) + " zł.") client3_payment = ("Kinga/data/examine/50/examine_029.png") decide(client_3, client3_payment, dish_3) bot.goByAStar((tables[8].pos[0] + 1, tables[8].pos[1])) messagebox.showinfo("Rachunek", "Proszę o zapłatę " + str(dish_4.price) + " zł.") client4_payment = ("Kinga/data/examine/cards/card_008.png") decide(client_4, client4_payment, dish_4) messagebox.showinfo("Informacja końcowa", "Zakończono trasę.") pygame.quit() exit() else: pass def text_objects(text, font): textSurface = font.render(text, True, black) return textSurface, textSurface.get_rect() def button(msg, x, y, w, h, ic, ac, action=None): mouse = pygame.mouse.get_pos() click = pygame.mouse.get_pressed() if x+w > mouse[0] > x and y+h > mouse[1] > y: pygame.draw.rect(window, ac, (x, y, w, h)) if click[0] == 1 and action != None: print("pressed") action(1) else: pygame.draw.rect(window, ic, (x, y, w, h)) smallText = pygame.font.Font("freesansbold.ttf", 15) words = [msg.split(' ')] textSurf, textRect = text_objects(words[0][0], smallText) textRect.center = ((x+(w/2)), (y+(h/4))) window.blit(textSurf, textRect) textSurf, textRect = text_objects(words[0][1], smallText) textRect.center = ((x + (w / 2)), (y + (3*h / 4))) window.blit(textSurf, textRect) def redrawWindow(surface): surface.fill(beige) bot.draw(surface) kitchen.draw(surface) for i in range(len(tables)): tables[i].draw(surface) for i in range(len(puddles)): image = pygame.image.load(r'puddle.png') image = pygame.transform.scale(image, (sizeBetween - 1, sizeBetween - 1)) surface.blit(image, (puddles[i][0] * sizeBetween + 1, puddles[i][1] * sizeBetween + 1)) drawGrid(width, rows, surface) button("Rozpoznawanie talerzy", 0, width + 1, 150, 48, light_beige, white) button("Ciężkostrawność dań", 150, width + 1, 150, 48, light_beige, white) button("Rozpoznawanie banknotów", 300, width + 1, 150, 48, light_beige, white) button("Polecanie dań", 450, width + 1, 150, 48, light_beige, white) pygame.display.update() def noWalkable(tables, kitchen): list = [] for i in range(len(tables)): list.append(tables[i].pos) list.append(kitchen.pos) return list def makeImgClassificator(model): img_width, img_height = 256, 256 if K.image_data_format() == 'channels_first': input_shape = (3, img_width, img_height) else: input_shape = (img_width, img_height, 3) model.add(Conv2D(32, (2, 2), input_shape=input_shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(32, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(1)) model.add(Activation('sigmoid')) model.compile(loss='binary_crossentropy', optimizer='rmsprop', metrics=['accuracy']) def recognizeCash(model): img_width, img_height = 256, 256 if K.image_data_format() == 'channels_first': input_shape = (3, img_width, img_height) else: input_shape = (img_width, img_height, 3) model.add(Conv2D(32, (2, 2), input_shape=input_shape)) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(32, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (2, 2))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Activation('relu')) model.add(Dropout(0.5)) model.add(Dense(7)) model.add(Activation('sigmoid')) model.compile(loss='categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) def main(): global width, rows, bot, light_beige, beige, white, black, sizeBetween, tables, kitchen, cantwalk, puddles, window, clock, \ img_classify, pln_model # skróty do kolorów light_beige = (255, 240, 205) beige = (255, 205, 178) white = (255, 255, 255) black = (0, 0, 0) img_classify = Sequential() makeImgClassificator(img_classify) img_classify.load_weights('Sara/model_food_dirty.h5') pln_model = Sequential() recognizeCash(pln_model) pln_model.load_weights('Kinga/model_payment.h5') width = 600 rows = 15 sizeBetween = width // rows #wielkość pojedynczej kratki window = pygame.display.set_mode((width, width + 50)) bot = Waiter((255, 0, 0), (12, 8), 2) tables = [] tables.append(Table((0, 3), 1)) tables.append(Table((0, 6), 1)) tables.append(Table((0, 9), 2)) tables.append(Table((0, 12), 2)) tables.append(Table((4, 4), 2)) tables.append(Table((4, 7), 2)) tables.append(Table((4, 10), 2)) tables.append(Table((4, 13), 2)) tables.append(Table((8, 3), 1)) tables.append(Table((8, 6), 1)) tables.append(Table((8, 9), 2)) tables.append(Table((8, 12), 2)) kitchen = Kitchen((13, 1)) cantwalk = noWalkable(tables, kitchen) # lista pozycji, na ktore bot nie moze wejsc puddles = [] puddles.append((7, 10)) puddles.append((2, 5)) puddles.append((3, 12)) puddles.append((10, 3)) puddles.append((6, 2)) puddles.append((12, 10)) puddles.append((1, 4)) flag = True clock = pygame.time.Clock() while flag: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() quit() button("Rozpoznawanie talerzy", 0, width + 1, 150, 48, light_beige, white, classify) button("Ciężkostrawność dań", 150, width + 1, 150, 48, light_beige, white, evaluate) button("Rozpoznawanie banknotów", 300, width + 1, 150, 48, light_beige, white, payment) button("Polecanie dań", 450, width + 1, 150, 48, light_beige, white) #Natalia tu dopisz swoją funkcję :) redrawWindow(window) pygame.quit() exit() main()