Automatyczny_kelner/main.py

497 lines
16 KiB
Python
Raw Normal View History

2024-03-13 18:05:38 +01:00
import pygame
import random
import time
import pandas as pd
import math
import matplotlib.pyplot as plt
2024-03-13 18:05:38 +01:00
2024-04-11 23:21:53 +02:00
kuchnia_xy = 0
pozycja_startowa = 0
losuj_uklad = False # Gdy True, losuje uklad stolikow oraz przeszkod
2024-04-11 23:21:53 +02:00
# ------------Ustawienia siatki
2024-04-11 23:21:53 +02:00
blockSize = 60
rows = 14
columns = 24
# -----------------------------Inicjacja klas
class Kelner:
def __init__(self, x, y):
self.x = x
self.y = y
self.speed = 80 # od 0 do 100, preferowane 80
self.stanPrzestrzeni = [0, 0, 0]
self.stan = "stoi" # Stan kelnera: stoi, odbiera lub wraca
self.stolik_docelowy = None # Stolik, do którego idzie kelner
2024-04-11 23:21:53 +02:00
self.chodzi = True
self.cel_x = x
self.cel_y = y
self.kierunek = 0 # 0 - północ, 1 - wschód, 2 - południe, 3 - zachód
2024-04-24 21:18:09 +02:00
self.indexRuchu = 0
def wklej(self):
2024-04-17 21:22:50 +02:00
kelnerRotated = pygame.transform.rotate(kelnerImg, -90 * kelner.kierunek)
screen.blit(kelnerRotated, (self.x * blockSize, self.y * blockSize))
2024-04-24 21:18:09 +02:00
# def idz_do_stolika(self):
# self.cel_x, self.cel_y = self.stolik_docelowy.x, self.stolik_docelowy.y
# kelner.stan = "odbiera"
def idz_do_kuchni(self):
2024-04-11 23:21:53 +02:00
self.cel_x, self.cel_y = kuchnia_xy, kuchnia_xy
self.stolik_docelowy = None
kelner.stan = "wraca"
2024-04-17 21:22:50 +02:00
def obrot_w_lewo(self):
2024-04-24 21:18:09 +02:00
self.kierunek = (self.kierunek - 1) % 4
self.stanPrzestrzeni[2] = (self.stanPrzestrzeni[2] - 1) % 4
2024-04-17 21:22:50 +02:00
def obrot_w_prawo(self):
2024-04-24 21:18:09 +02:00
self.kierunek = (self.kierunek + 1) % 4
self.stanPrzestrzeni[2] = (self.stanPrzestrzeni[2] + 1) % 4
2024-04-17 21:22:50 +02:00
def idz_do_przodu(self):
if self.kierunek == 0:
self.y -= 1
2024-04-24 21:18:09 +02:00
self.stanPrzestrzeni[1] -= 1
2024-04-17 21:22:50 +02:00
elif self.kierunek == 1:
self.x += 1
2024-04-24 21:18:09 +02:00
self.stanPrzestrzeni[0] += 1
2024-04-17 21:22:50 +02:00
elif self.kierunek == 2:
self.y += 1
2024-04-24 21:18:09 +02:00
self.stanPrzestrzeni[1] += 1
2024-04-17 21:22:50 +02:00
elif self.kierunek == 3:
self.x -= 1
2024-04-24 21:18:09 +02:00
self.stanPrzestrzeni[0] -= 1
def wykonajAkcje(self, ruchy):
if self.indexRuchu < len(ruchy):
akcja = ruchy[self.indexRuchu]
if akcja == 'F':
self.idz_do_przodu()
elif akcja == 'L':
self.obrot_w_lewo()
elif akcja == 'R':
self.obrot_w_prawo()
self.indexRuchu += 1
if self.indexRuchu >= len(ruchy): # Reset po zakończeniu wszystkich ruchów
self.indexRuchu = 0
2024-04-17 21:22:50 +02:00
class Stolik:
def __init__(self, x, y):
self.x = x
self.y = y
self.zamowione = False
def wklej(self):
2024-04-11 23:21:53 +02:00
screen.blit(stolikImg, (self.x * blockSize, self.y * blockSize))
2024-03-13 18:05:38 +01:00
class Przeszkoda:
def __init__(self, x, y, typ):
self.x = x
self.y = y
self.typ = typ
# ocena kosztu przeszkody
if self.typ == "sliska podloga":
self.cena = 2
elif self.typ == "dywan":
self.cena = 4
def wklej(self):
if self.typ == "sliska podloga":
screen.blit(sliskaPodlogaImg, (self.x * blockSize, self.y * blockSize))
elif self.typ == "dywan":
screen.blit(dywanImg, (self.x * blockSize, self.y * blockSize))
# -----------------Przeszukiwanie przestrzeni stanów
2024-04-24 21:18:09 +02:00
import heapq
2024-04-24 21:18:09 +02:00
def a_star(start, cel, stoliki, przeszkody):
queue = [] # Kolejka priorytetowa
heapq.heappush(queue, (0, start)) # (koszt, stan)
2024-04-24 21:18:09 +02:00
odwiedzone = set([start])
poprzednicy = {start: (None, None, 0)} # (poprzedni stan, ruch, koszt do tej pory)
2024-04-24 21:18:09 +02:00
while queue:
obecny_koszt, obecny = heapq.heappop(queue) # pobranie stanu z najniższym kosztem
2024-04-24 21:18:09 +02:00
if obecny[:2] == cel:
return odtworz_ruchy(poprzednicy, obecny)
for nastepnik, ruch, koszt_ruchu in generuj_nastepniki_i_ruchy(obecny, stoliki, przeszkody):
nowy_koszt = poprzednicy[obecny][2] + koszt_ruchu # Obliczanie nowego kosztu dojscia do nastepnika
# nastepnik nie był odwiedzony lub znaleziono tansza sciezke do niego
if nastepnik not in odwiedzone or nowy_koszt < poprzednicy.get(nastepnik, (None, None, float('inf')))[2]:
heapq.heappush(queue, (nowy_koszt + heurystyka(nastepnik, cel), nastepnik))
poprzednicy[nastepnik] = (obecny, ruch, nowy_koszt)
odwiedzone.add(nastepnik)
return []
2024-04-24 21:18:09 +02:00
def heurystyka(nastepnik, cel):
# Oszacowanie sumy odleglosci w pionie i w poziomie
return abs(nastepnik[0] - cel[0]) + abs(nastepnik[1] - cel[1])
2024-04-24 21:18:09 +02:00
# ----------Funkcja generowania następników dla poszczególnych stanów
def generuj_nastepniki_i_ruchy(stan, stoliki, przeszkody):
2024-04-24 21:18:09 +02:00
x, y, kierunek = stan
ruchy = []
# Obrot w lewo
nowy_kierunek = (kierunek - 1) % 4
ruchy.append(((x, y, nowy_kierunek), 'L', 1))
2024-04-24 21:18:09 +02:00
# Obrot w prawo
nowy_kierunek = (kierunek + 1) % 4
ruchy.append(((x, y, nowy_kierunek), 'R', 1))
2024-04-24 21:18:09 +02:00
# Krok do przodu
if kierunek == 0:
nowy_x, nowy_y = x, y - 1
elif kierunek == 1:
nowy_x, nowy_y = x + 1, y
elif kierunek == 2:
nowy_x, nowy_y = x, y + 1
elif kierunek == 3:
nowy_x, nowy_y = x - 1, y
# sprawdzamy, czy następny stan jest w granicach planszy
2024-04-24 21:18:09 +02:00
if 0 <= nowy_x < columns and 0 <= nowy_y < rows:
# sprawdzamy, czy następny stan nie wchodzi w stolik
if not any(stolik.x == nowy_x and stolik.y == nowy_y for stolik in stoliki):
koszt = next(
(przeszkoda.cena for przeszkoda in przeszkody if przeszkoda.x == nowy_x and przeszkoda.y == nowy_y), 1)
ruchy.append(((nowy_x, nowy_y, kierunek), 'F', koszt))
2024-04-24 21:18:09 +02:00
return ruchy
# -----Funkcja tworząca listę kroków potrzebnych do uzyskania celu
2024-04-24 21:18:09 +02:00
def odtworz_ruchy(poprzednicy, cel):
ruchy = []
krok = cel
while krok and poprzednicy[krok][0] is not None:
2024-04-24 21:18:09 +02:00
ruchy.append(poprzednicy[krok][1])
krok = poprzednicy[krok][0]
ruchy.reverse()
return ruchy
def licz_entropie(data, target_column):
total_rows = len(data)
target_values = data[target_column].unique()
entropy = 0
for value in target_values:
value_count = len(data[data[target_column] == value])
proportion = value_count / total_rows
entropy -= proportion * math.log2(proportion)
return entropy
def licz_zysk(atrybut,korzen,data):
entropia_wazona = 0
unique_values = data[atrybut].unique()
for value in unique_values:
subset = data[data[atrybut] == value]
proportion = len(subset) / len(data)
entropia_wazona += proportion * licz_entropie(subset, data.columns[-1])
zysk = korzen - entropia_wazona
return zysk
def szukaj_split(z, atrybuty):
max = 0
max_atr = "None"
for atrybut in atrybuty:
if z[atrybut]>max:
max = z[atrybut]
max_atr = atrybut
return max_atr
def GenerujDane(ques):
k = [0,0,0,0,0,0,0,0]
for n in range(8):
k[n] = random.choice([0,1])
print(ques[n] + str(k[n]))
return k
def id3(data,mode,klient):
zysk = {}
korzen = licz_entropie(data,data.columns[-1])
lista = data.columns
for atrybut in lista[:-1]:
zysk[atrybut] = licz_zysk(atrybut,korzen,data)
split = szukaj_split(zysk, data.head(0).columns[:-1])
if split == "None":
wynik = data.iloc[0, -1]
if wynik == 1 and mode == "klient":
print("Klient zadowolony!")
elif wynik == 0 and mode == "klient":
print("Klient niezadowolony!")
print("---------------------------------------------------------------------------------------")
else:
#print("Split: " + str(split))
subset0 = data[data[split] == 0]
subset0 = subset0.drop([split], axis=1)
subset1 = data[data[split] == 1]
subset1 = subset1.drop([split], axis=1)
#print("Klient: " + str(klient))
if len(subset0) < len(data) and len(subset1) < len(data):
if mode == "klient":
if klient[split] == 0:
frames.append(subset0)
else:
frames.append(subset1)
elif mode == "full":
frames.append(subset0)
frames.append(subset1)
if len(frames) > 0:
newData = frames.pop()
id3(newData,mode, klient)
2024-04-24 21:18:09 +02:00
start = (0, 0, 0) # Początkowy stan
cel = (0, 0) # Docelowe współrzędne
# --------------Inicjacja obiektów
kelner = Kelner(pozycja_startowa, pozycja_startowa)
2024-04-24 21:18:09 +02:00
# -----------wspolrzedne stolikow
coords = ["8 4", "16 4", "0 7", "23 7", "12 9", "8 10", "16 10", "4 12", "12 12", "20 12"]
# -----------wspolrzedne sliskich podlog
coords2 = ["0 2", "0 3", "0 4", "0 5", "4 8", "4 9", "12 2", "12 3", "15 8", "16 8", "19 4", "20 4", "21 4"]
# -----------wspolrzedne dywanow
coords3 = ["6 0", "6 1", "2 2", "3 2", "4 2", "5 2", "1 5", "6 2", "8 6", "8 7", "20 2", "20 3", "19 9", "20 9", "21 9"]
2024-04-24 21:18:09 +02:00
# Tworzenie listy stolikow i przeszkod
stoliki = []
przeszkody = []
if not losuj_uklad:
for coord in coords:
x, y = map(int, coord.split())
stoliki.append(Stolik(x, y))
for coord in coords2:
x, y = map(int, coord.split())
przeszkody.append(Przeszkoda(x, y, "sliska podloga"))
for coord in coords3:
x, y = map(int, coord.split())
przeszkody.append(Przeszkoda(x, y, "dywan"))
else:
juzbyly = []
for j in range(1, rows):
for i in range(columns):
if (random.randrange(7) == 0) and ((i, j - 1) not in juzbyly) and (
((i - 1, j - 1) not in juzbyly) or ((i + 1, j - 1) not in juzbyly)):
stoliki.append(Stolik(i, j))
juzbyly.append((i, j))
elif random.randrange(9) == 0:
przeszkody.append(Przeszkoda(i, j, "sliska podloga"))
elif random.randrange(12) == 0:
przeszkody.append(Przeszkoda(i, j, "dywan"))
# stoliki = []
# for i in range(rows)
pygame.init()
2024-03-13 18:05:38 +01:00
pygame.display.set_caption("Automatyczny kelner")
# ----------------wymiary okna
2024-04-11 23:21:53 +02:00
width = columns * blockSize
height = rows * blockSize
2024-03-13 18:05:38 +01:00
screen = pygame.display.set_mode((width, height))
kelnerImg = pygame.image.load("kelner.png")
2024-04-11 23:21:53 +02:00
kelnerImg = pygame.transform.scale(kelnerImg, (blockSize, blockSize))
2024-03-13 18:05:38 +01:00
stolikImg = pygame.image.load("stolik.png")
2024-04-11 23:21:53 +02:00
stolikImg = pygame.transform.scale(stolikImg, (blockSize, blockSize))
menuImg = pygame.image.load("menu.png")
2024-04-11 23:21:53 +02:00
menuImg = pygame.transform.scale(menuImg, (blockSize / 2, blockSize / 2))
kitchenImg = pygame.image.load("kitchen.png")
2024-04-11 23:21:53 +02:00
kitchenImg = pygame.transform.scale(kitchenImg, (blockSize * 2, blockSize * 2))
sliskaPodlogaImg = pygame.image.load("plama.png")
sliskaPodlogaImg = pygame.transform.scale(sliskaPodlogaImg, (blockSize, blockSize))
dywanImg = pygame.image.load("dywan.png")
dywanImg = pygame.transform.scale(dywanImg, (blockSize, blockSize))
def kuchnia(x, y):
2024-04-11 23:21:53 +02:00
screen.blit(kitchenImg, (x * blockSize, y * blockSize))
2024-03-13 18:05:38 +01:00
def menu(x, y):
2024-04-11 23:21:53 +02:00
screen.blit(menuImg, (x * blockSize, y * blockSize))
def wypiszOkno():
screen.fill((0, 0, 0))
for x in range(0, width, blockSize):
for y in range(0, height, blockSize):
rect = pygame.Rect(x, y, blockSize, blockSize)
pygame.draw.rect(screen, (200, 200, 200), rect, 1) # -------------Wypisz kratę -TA
# pygame.draw.rect(screen, (0, 0, 0), rect, 1) #-------------Wypisz kratę -TA
def czyZadowolony():
data = pd.read_csv('zbior_uczacy.csv')
frames = []
frames.append(data)
ques = ["Czy klient sie usmiecha? ", "Czy zostawil napiwek? ", "Czy zachowywal sie grzecznie? ",
"Czy zjadl cala porcje? ", "Czy zlozyl dodatkowe zamowienia? ",
"Czy wyrazil zainteresowanie karta stalego klienta? ", "Czy zarezerwowal stolik na przyszlosc? ",
"Czy zabral wizytowke? "]
k = GenerujDane(ques)
atrybuty = []
for column in data.columns[:-1]:
atrybuty.append(column)
klient = {}
i = 0
for atr in atrybuty:
klient[atr] = k[i]
i = i + 1
while len(frames) > 0:
data = frames.pop()
id3(data, "klient", klient)
2024-03-13 18:05:38 +01:00
run = True
2024-04-11 23:21:53 +02:00
# czcionka = pygame.font.SysFont('Arial',50)
2024-04-11 23:21:53 +02:00
licznik = 0
2024-04-24 21:18:09 +02:00
ruchy = []
cel2 = []
klient = {}
frames = []
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import plot_tree, DecisionTreeClassifier
data = pd.read_csv('zbior_uczacy.csv')
data.head()
#print(heart_data)
data_x = data.drop('Zadowolony', axis=1)
data_y = data['Zadowolony']
data_x_encoded = pd.get_dummies(data_x, drop_first = True)
data_x_encoded.head()
best_acc = 0
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score
X_train, X_test, y_train, y_test = train_test_split(data_x_encoded, data_y, test_size=0.3)
dtree = DecisionTreeClassifier(max_depth=100)
dtree.fit(X_train, y_train)
fig = plt.figure(figsize=((25,20)))
plot_tree(dtree,
feature_names=data_x_encoded.columns,
class_names=['niezadowolony', 'zadowolony'],
impurity=False,
proportion=False,
filled=True)
fig.savefig('tree.png')
2024-03-13 18:05:38 +01:00
while run:
2024-04-24 21:18:09 +02:00
cel2 = list(cel)
# print(f"{kelner.stanPrzestrzeni}, {cel2}, {kelner.indexRuchu} {kelner.stan}")
wypiszOkno()
kuchnia(kuchnia_xy, kuchnia_xy)
for stolik in stoliki:
stolik.wklej()
for przeszkoda in przeszkody:
przeszkoda.wklej()
kelner.wklej()
if kelner.stan == "wraca":
menu(kelner.x, kelner.y)
2024-04-11 23:21:53 +02:00
licznik += 1
# ------------weź zamowienie
for stolik in stoliki:
if stolik.zamowione == True:
menu(stolik.x, stolik.y)
if kelner.stan == "stoi":
kelner.stolik_docelowy = stolik
2024-04-24 21:18:09 +02:00
kelner.cel_x, kelner.cel_y = kelner.stolik_docelowy.x, kelner.stolik_docelowy.y - 1
cel = (kelner.cel_x, kelner.cel_y)
print("Szukam ścieżki do stolika...")
ruchy = a_star(tuple(kelner.stanPrzestrzeni), cel, stoliki, przeszkody)
2024-04-24 21:18:09 +02:00
kelner.stan = "odbiera"
2024-04-24 21:18:09 +02:00
if ruchy:
print("Znaleziono ścieżkę ruchów: ", ruchy)
czyZadowolony()
2024-04-24 21:18:09 +02:00
else:
print("Nie znaleziono ścieżki do celu.")
# ----------Losuje stoliki, które dokonają zamówienia
if kelner.stan == "stoi":
for stolik in stoliki:
if stolik.zamowione == True:
break
2024-04-11 23:21:53 +02:00
for i in range(len(stoliki)):
if random.randrange(2) == 1:
stoliki[i].zamowione = True
# print(kelner.stan)--------------------------Wypisuje stan kelnera
# print(f"{kelner.x} {kelner.y}")-------------Wypisuje wspolrzedne kelnera
2024-04-24 21:18:09 +02:00
# ----------------Zmiana pozycji kelnera
if kelner.chodzi == True and licznik % (101 - kelner.speed) == 0 and kelner.stanPrzestrzeni[
:2] != cel2: # ograniczenie prędkości
2024-04-24 21:18:09 +02:00
kelner.wykonajAkcje(ruchy)
if kelner.stanPrzestrzeni[:2] == cel2:
if kelner.stan == "odbiera" and kelner.x == kelner.stolik_docelowy.x and kelner.y == kelner.stolik_docelowy.y - 1:
kelner.stolik_docelowy.zamowione = False
kelner.idz_do_kuchni()
2024-04-24 21:18:09 +02:00
cel = (kelner.cel_x, kelner.cel_y)
print("Szukam ścieżki do kuchni...")
ruchy = a_star(tuple(kelner.stanPrzestrzeni), cel, stoliki, przeszkody)
2024-04-24 21:18:09 +02:00
if ruchy:
print("Znaleziono ścieżkę ruchów: ", ruchy)
else:
print("Nie znaleziono ścieżki do celu.")
elif kelner.stan == "wraca" and kelner.x == kuchnia_xy and kelner.y == kuchnia_xy:
kelner.stan = "stoi"
2024-03-13 18:05:38 +01:00
time.sleep(0.001)
key = pygame.key.get_pressed()
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
#------------------------------------------------------------------------------------------------------------------
'''
frames.clear()
frames.append(data)
while len(frames) > 0:
data = frames.pop()
id3(data,"full")
'''
2024-03-13 18:05:38 +01:00
pygame.quit()