import random import time import numpy as np import pygame import pytmx from queue import Queue import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier import json import openpyxl import matplotlib.pyplot as plt import os import cv2 from tqdm import tqdm from keras.models import Sequential from keras.layers import Dense, Dropout, Activation, Flatten from keras.layers import Conv2D, MaxPooling2D import math pygame.init() display = pygame.display.set_mode((640, 640)) clock = pygame.time.Clock() gameMap = pytmx.load_pygame("cafe.tmx") waiterImg = pygame.image.load("waiter.png") waiterImgD = pygame.image.load("waiterD.png") waiterImgL = pygame.image.load("waiterL.png") waiterImgR = pygame.image.load("waiterR.png") tableImg = pygame.image.load('table.png') chairImg = pygame.image.load('chair.png') clientImg = pygame.image.load('client.png') image = pygame.image.load('test/0.jpg') class Waiter: def __init__(self, loc): self.loc = loc def render(self, surface): surface.blit(waiterImg, (self.loc[0], self.loc[1])) def handle_events(self): key = pygame.key.get_pressed() if key[pygame.K_w] or key[pygame.K_UP]: self.loc[1] -= 32 elif key[pygame.K_s] or key[pygame.K_DOWN]: self.loc[1] += 32 elif key[pygame.K_a] or key[pygame.K_LEFT]: self.loc[0] -= 32 elif key[pygame.K_d] or key[pygame.K_RIGHT]: self.loc[0] += 32 def up(self): self.loc[1] -= 32 def down(self): self.loc[1] += 32 def left(self): self.loc[0] -= 32 def right(self): self.loc[0] += 32 class Client: def __init__(self, loc): self.loc = loc def render(self, surface): surface.blit(clientImg, (self.loc[0], self.loc[1])) def generate_client(): loc_for_client = [] for i in chairs: for j in i: loc_for_client.append(j.loc) loc = (random.randint(0, len(loc_for_client))) client_coordinates = (loc_for_client[loc]) return client_coordinates class Table: def __init__(self, loc, num): self.loc = loc self.number = num self.num_of_chairs = np.random.randint(1, 5) def render(self, surface): surface.blit(tableImg, (self.loc[0], self.loc[1])) def get_number(self): return self.number def get_number_of_chairs(self): return self.num_of_chairs def check_collision_with_table(x, y): answer = False for i in tables_coordinates: if i[0] <= x <= i[0] + 32 and i[1] <= y <= i[1] + 32: answer = True else: continue return answer class Chair: def __init__(self, loc): self.loc = loc def render(self, surface): surface.blit(chairImg, (self.loc[0], self.loc[1])) def pos_of_chair(table_cor, k): pos = ((table_cor[0], table_cor[1] - 32), (table_cor[0], table_cor[1] + 32), (table_cor[0] - 32, table_cor[1]), (table_cor[0] + 32, table_cor[1])) return pos[k] def check_collision_with_chair(x, y): answer = False for i in chairs: for j in i: if j.loc[0] <= x <= j.loc[0] + 32 and j.loc[1] <= y <= j.loc[1] + 32: answer = True else: continue return answer class Food: def __init__(self, name, pos_in_card, price, spiciness, vege, size, allergens, ingridients, drink_in): self.name = name self.pos_in_card = pos_in_card self.price = price self.spiciness = spiciness self.vege = vege self.size = size self.allergens = allergens self.ingridients = ingridients self.drink_in = drink_in def get_food(self): return self.name, self.price class Menu: def __init__(self, card={}): self.card = card def get_menu(self): return self.card def add_to_card(self, dish): self.card[str(len(self.card) + 1)] = dish class Order(Table): def __init__(self, status=False, table=0, dishes=[]): self.table = table self.dishes = dishes self.status = status def take_order(self, foods, table): self.dishes.append(foods) self.table = table.number def deliver(self): self.status = True class Graph: def __init__(self, num_of_nodes, directed=True): self.m_num_of_nodes = num_of_nodes self.m_nodes = range(self.m_num_of_nodes) self.m_directed = directed self.m_adj_list = {node: set() for node in self.m_nodes} def add_edge(self, node1, node2, weight=1): self.m_adj_list[node1].add((node2, weight)) if not self.m_directed: self.m_adj_list[node2].add((node1, weight)) def print_adj_list(self): for key in self.m_adj_list.keys(): print("node", key, ": ", self.m_adj_list[key]) def bfs(self, start_node, target_node): visited = set() queue = Queue() queue.put(start_node) visited.add(start_node) parent = dict() parent[start_node] = None path_found = False while not queue.empty(): current_node = queue.get() if current_node == target_node: path_found = True break for (next_node, weight) in self.m_adj_list[current_node]: if next_node not in visited: queue.put(next_node) parent[next_node] = current_node visited.add(next_node) path = [] if path_found: path.append(target_node) while parent[target_node] is not None: path.append(parent[target_node]) target_node = parent[target_node] path.reverse() return path def pathFromTo(start, dest): tab2 = [42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57] tab4 = [41, 58] tab3 = [] tab5 = [] for x in range(16): for num in tab4: tab5.append(num + x * 20) for x in range(16): for num in tab2: tab3.append(num + x * 20) graph = Graph(400, directed=False) for x in tab5: b = x + 1 c = x + 20 d = x - 20 graph.add_edge(x, b) graph.add_edge(x, c) graph.add_edge(x, d) for x in tab3: b = x + 1 c = x + 20 d = x - 1 e = x - 20 graph.add_edge(x, b) graph.add_edge(x, c) graph.add_edge(x, d) graph.add_edge(x, e) graph.add_edge(21, 22) graph.add_edge(21, 41) graph.add_edge(378, 358) graph.add_edge(378, 377) graph.add_edge(38, 37) graph.add_edge(38, 58) graph.add_edge(361, 362) graph.add_edge(361, 341) # graph.print_adj_list() path = [] path = graph.bfs(start, dest) return path def numToX(num): digits = [int(a) for a in str(num)] if num >= 100: if digits[1] % 2 == 0: x = digits[2] else: x = digits[2] + 10 else: if digits[0] % 2 == 0: x = digits[1] else: x = digits[1] + 10 x = x * 32 return x def numToY(num): y = (math.floor(num / 20)) * 32 return y def coordsToNum(coords): num = ((coords[1] // 32) * 20) + (coords[0] // 32) return int(num) def waiterGo(dest): print("Path: ", (pathFromTo(coordsToNum(waiter.loc), dest))) go = [] for numb in range(len(pathFromTo(coordsToNum(waiter.loc), dest)) - 1): go.append(pathFromTo(coordsToNum(waiter.loc), dest)[numb] - pathFromTo(coordsToNum(waiter.loc), dest)[numb + 1]) for x in range(len(go)): if go[x] == -20: waiter.down() display.blit(waiterImgD, (waiter.loc[0], waiter.loc[1])) # waiter.render(display) pygame.display.update() time.sleep(0.2) elif go[x] == 20: waiter.up() display.blit(waiterImg, (waiter.loc[0], waiter.loc[1])) # waiter.render(display) pygame.display.update() time.sleep(0.2) elif go[x] == 1: waiter.left() display.blit(waiterImgL, (waiter.loc[0], waiter.loc[1])) # waiter.render(display) pygame.display.update() time.sleep(0.2) elif go[x] == -1: waiter.right() display.blit(waiterImgR, (waiter.loc[0], waiter.loc[1])) # waiter.render(display) pygame.display.update() time.sleep(0.2) def mouseToNum(): x = pygame.mouse.get_pos()[0] y = pygame.mouse.get_pos()[1] cordTab = [x, y] squareNum = coordsToNum(cordTab) return squareNum class Map: def __init__(self): self.arr = np.zeros((20, 20)) self.arr[1:19, 1:19] = 1 def add_chair(self, loc): self.arr[loc[0] // 32, loc[1] // 32] = 100 def add_table(self, loc): self.arr[loc[0] // 32, loc[1] // 32] = 200 def get_arr(self): return self.arr.transpose() class Tile(): def __init__(self, parent=None, loc=None): self.parent = parent self.position = loc self.g = 0 self.h = 0 self.f = 0 def __eq__(self, other): return self.position == other.position def astar(map, start, end): start_tile = Tile(None, start) start_tile.g = start_tile.h = start_tile.f = 0 end_tile = Tile(None, end) end_tile.g = end_tile.h = end_tile.f = 0 open_list = [] closed_list = [] open_list.append(start_tile) while len(open_list) > 0: current_tile = open_list[0] current_index = 0 for index, item in enumerate(open_list): if item.f <= current_tile.f: current_tile = item current_index = index open_list.pop(current_index) closed_list.append(current_tile) if current_tile == end_tile: path = [] current = current_tile while current is not None: path.append(current.position) current = current.parent return path[::-1] children = [] for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0)]: tile_position = (current_tile.position[0] + new_position[0], current_tile.position[1] + new_position[1]) if map[tile_position[0]][tile_position[1]] == 0: continue new_node = Tile(current_tile, tile_position) children.append(new_node) for child in children: skip = False for closed_child in closed_list: if child == closed_child: skip = True if skip is False: child.g = current_tile.g + map[child.position[0]][child.position[1]] child.h = np.absolute(child.position[0] - end_tile.position[0]) + np.absolute( child.position[1] - end_tile.position[1]) child.f = child.g + child.h for open_node in open_list: if child == open_node and child.g > open_node.g: continue open_list.append(child) def tell_preferences(): possibilities = [[30, 40, 50, None], [True, False, None], [True, False, None], ["high", "low", None], ["tomato", "olives", "feta", None], ["sausage", "pineapple", "mushrooms", "shrimps", "salami", None], [True, False, None]] choices = [] for i in possibilities: choices.append(random.choice(i)) return choices def evaluate_preferences(preferences): data = [] if preferences[0] == 30: data.append(30) elif preferences[0] == 40: data.append(40) elif preferences[0] == 50: data.append(50) else: data.append(random.choice([30, 40, 50])) if preferences[1] is True: data.append(1) elif preferences[1] is False: data.append(0) else: data.append(random.choice([1, 0])) if preferences[2] is True: data.append(1) elif preferences[2] is False: data.append(0) else: data.append(random.choice([1, 0])) if preferences[3] == 'low': data.append(30) elif preferences[3] == 'high': data.append(50) else: data.append(random.choice([30, 50])) if preferences[4] == 'tomato': data.append(1) elif preferences[4] == 'olives': data.append(3) elif preferences[4] == 'feta': data.append(2) else: data.append(0) if preferences[5] == 'salami': data.append(1) elif preferences[5] == 'mushrooms': data.append(2) elif preferences[5] == 'pineapple': data.append(3) elif preferences[5] == 'shrimps': data.append(4) elif preferences[5] == 'sausage': data.append(5) else: data.append(0) if preferences[6] is True: data.append(1) elif preferences[6] is False: data.append(0) else: data.append(random.choice([1, 0])) return data def choose_pizza(prefernce): df = pd.read_excel("restaurant.xlsx") d = {'low': 30, 'high': 50} df['level of hunger'] = df['level of hunger'].map(d) d = {'none': 0, 'tomato': 1, 'feta': 2, 'olives': 3} df['allergy'] = df['allergy'].map(d) d = {'none': 0, 'salami': 1, 'mushrooms': 2, 'pineapple': 3, 'shrimps': 4, 'sausage': 5} df['favorite ingridient'] = df['favorite ingridient'].map(d) d = {'margherita': 0, 'hawajska': 1, 'funghi': 2, 'light': 3, '4 sery': 4, 'pepperoni': 5, 'salami': 6, 'wegetarianska': 7, 'barbecue': 8, 'miesna': 9, 'paprykowa': 10, 'jalapeno': 11, 'barbecue wege': 12, 'kebab': 13, 'grecka': 14, 'piekielna': 15, 'drwala': 16, 'grzybowa': 17, 'staropolska': 18, 'goralska': 19, 'prosciutto': 20, 'broccoli': 21, 'americana': 22, 'farmerska': 23, 'nachos': 24, 'texas': 25, 'kurczak': 26, 'zielona': 27, 'mix': 28} df['pizza'] = df['pizza'].map(d) features = ['budget', 'spiciness', 'vege', 'level of hunger', 'allergy', 'favorite ingridient', 'drink in'] x = df[features] y = df['pizza'] x_train, x_test, y_train, y_test = train_test_split(x, y) clf = DecisionTreeClassifier(random_state=400) clf = clf.fit(x_train, y_train) ans = clf.predict([prefernce]) append_choice(ans, prefernce, d, df) return ans def append_df_to_excel(df, excel_path): df_excel = pd.read_excel(excel_path) result = pd.concat([df_excel, df], ignore_index=True) result.to_excel(excel_path, index=False) def append_choice(ans, pre, d, df): new_row = pre new_row.append(list(d.keys())[list(d.values()).index(int(ans))]) if new_row[3] == 30: new_row[3] = 'low' if new_row[3] == 50: new_row[3] = 'high' if new_row[4] == 0: new_row[4] = 'none' if new_row[4] == 1: new_row[4] = 'tomato' if new_row[4] == 2: new_row[4] = 'feta' if new_row[4] == 3: new_row[4] = 'olives' if new_row[5] == 0: new_row[5] = 'none' if new_row[5] == 1: new_row[5] = 'salami' if new_row[5] == 2: new_row[5] = 'mushrooms' if new_row[5] == 3: new_row[5] = 'pineapple' if new_row[5] == 4: new_row[5] = 'shrimps' if new_row[5] == 5: new_row[5] = 'sausage' data = {"budget": new_row[0], "spiciness": new_row[1], "vege": new_row[2], "level of hunger": new_row[3], "allergy": new_row[4], "favorite ingridient": new_row[5], "drink in": 1, "pizza": new_row[7]} n_df = pd.DataFrame(data, index=[len(df) + 1]) append_df_to_excel(n_df, "restaurant.xlsx") def get_pizza(number): with open("dishes.json") as f: data = json.load(f) for i in data: if i["pos_in_card"] == int(number): food = Food(i['name'], i['pos_in_card'], i['price'], i['spiciness'], i['vege'], i['size'], i['allergens'], i['ingridients'], i['drink_in']) return food def display_img(surface, image): surface.blit(image, (120, 120)) def create_training_data(): DATADIR = "Images" CATEGORIES = ["yes", "no"] IMG_SIZE = 90 training_data = [] for category in CATEGORIES: path = os.path.join(DATADIR, category) class_num = CATEGORIES.index(category) # 0 - pepperoni, 1 - no pepperoni for img in tqdm(os.listdir(path)): try: img_array = cv2.imread(os.path.join(path, img), cv2.IMREAD_GRAYSCALE) new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) training_data.append([new_array, class_num]) except Exception as e: pass X = [] y = [] for features, label in training_data: X.append(features) y.append(label) X = np.array(X).reshape(-1, IMG_SIZE, IMG_SIZE, 1) y = np.array(y) print("Training data created!") return X, y def learn_neural_network(X, y): X = X / 255.0 model = Sequential() model.add(Conv2D(64, (3, 3), input_shape=X.shape[1:])) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Conv2D(64, (3, 3))) model.add(Activation('relu')) model.add(MaxPooling2D(pool_size=(2, 2))) model.add(Flatten()) model.add(Dense(64)) model.add(Dense(1)) model.add(Activation('sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) model.fit(X, y, batch_size=32, epochs=10, validation_batch_size=0.1) return model def prepare_img(filepath): IMG_SIZE = 90 img_array = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE) new_array = cv2.resize(img_array, (IMG_SIZE, IMG_SIZE)) return new_array.reshape(-1, IMG_SIZE, IMG_SIZE, 1) / 255 def predict(model,filepath): return model.predict([prepare_img(filepath)]) def result(prediction): if prediction[0][0] >= 0.5: print(prediction) print(math.ceil(prediction[0][0])) print('No pepperoni') elif prediction[0][0] < 0.5: print(prediction) print(math.floor(prediction[0][0])) print("Pepperoni") map = Map() waiter = Waiter([32, 32]) tables = [] tables_coordinates = ((32 * 3, 32 * 2), (32 * 7, 32 * 2), (32 * 12, 32 * 2), (32 * 16, 32 * 2), (32 * 3, 32 * 6), (32 * 7, 32 * 6), (32 * 12, 32 * 6), (32 * 16, 32 * 6), (32 * 3, 32 * 13), (32 * 7, 32 * 13), (32 * 12, 32 * 13), (32 * 16, 32 * 13), (32 * 3, 32 * 17), (32 * 7, 32 * 17), (32 * 12, 32 * 17), (32 * 16, 32 * 17)) chairs = [] for i in range(16): tables.append(Table(tables_coordinates[i], i)) arr = [] for j in range(0, tables[i].get_number_of_chairs()): arr.append(Chair(pos_of_chair(tables_coordinates[i], j))) map.add_chair(Chair(pos_of_chair(tables_coordinates[i], j)).loc) chairs.append(arr) for table in tables: map.add_table(table.loc) client = Client(generate_client()) neural_prediction_in = False def main(): direction = [] first_time = True number = 0 while True: clock.tick(10) keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == pygame.QUIT: quit() if keys[pygame.K_ESCAPE]: quit() for layer in gameMap.visible_layers: for x, y, gid, in layer: tile = gameMap.get_tile_image_by_gid(gid) if tile is not None: display.blit(tile, (x * gameMap.tilewidth, y * gameMap.tileheight)) waiter.handle_events() for table in tables: table.render(display) for chair_list in chairs: for chair in chair_list: chair.render(display) key = pygame.key.get_pressed() left, middle, right = pygame.mouse.get_pressed() if key[pygame.K_e]: X, y = create_training_data() model = learn_neural_network(X,y) if middle: waiterGo(mouseToNum()) elif right: while True: x = pygame.mouse.get_pos()[1] y = pygame.mouse.get_pos()[0] if y > 608 or y < 32 or x > 608 or x < 32 or check_collision_with_table(y, x) or check_collision_with_chair( y, x): print("I can't go there") break goal = (x // 32, y // 32) route = astar(map.get_arr(), (waiter.loc[1] // 32, waiter.loc[0] // 32), goal) direction = [(x[1] - y[1], x[0] - y[0]) for x, y in zip(route[1:], route)] break elif left: if client.loc[0] in [64, 128, 192, 256, 352, 416, 480, 544]: while True: x = client.loc[1] - 32 y = client.loc[0] goal = (x // 32, y // 32) route = astar(map.get_arr(), (waiter.loc[1] // 32, waiter.loc[0] // 32), goal) direction = [(x[1] - y[1], x[0] - y[0]) for x, y in zip(route[1:], route)] break elif client.loc[0] in [96, 224, 384, 512]: while True: x = client.loc[1] y = client.loc[0] - 32 goal = (x // 32, y // 32) route = astar(map.get_arr(), (waiter.loc[1] // 32, waiter.loc[0] // 32), goal) direction = [(x[1] - y[1], x[0] - y[0]) for x, y in zip(route[1:], route)] break print() print("Hello Sir, tell me yours preferences") print( "Pass: 'budget', 'spiciness', 'vege', 'level_of_hunger', 'allergy', 'favorite_ingridient', 'drink_in'\n") print("Here is my list of preferences") ingridients = tell_preferences() print(ingridients) print() pizza = get_pizza(choose_pizza(evaluate_preferences(ingridients))) print("Our proposition:") print( "Name = {}\nprice = {}\nspiciness = {}\nvege = {}\nsize = {}\nallergens = {}\ningridients = {}\ndrink_in = {}\n" .format(pizza.name, pizza.price, pizza.spiciness, pizza.vege, pizza.size, pizza.allergens, pizza.ingridients, pizza.drink_in)) if len(direction) > 0: d = direction.pop(0) if d[0] == 1: waiter.right() elif d[0] == -1: waiter.left() elif d[1] == 1: waiter.down() elif d[1] == -1: waiter.up() key = pygame.key.get_pressed() if key[pygame.K_p]: pass waiter.render(display) client.render(display) if waiter.loc == [576, 32]: if first_time: number = np.random.randint(20) path = ('test/' + str(number) + '.jpg') image = pygame.image.load(path) first_time = False display_img(display, image) if neural_prediction_in is False: prediction = predict(model, path) result(prediction) neural_prediction_in = True else: first_time = True neural_prediction_in = False pygame.display.update() if __name__ == '__main__': main()