# -*- coding: utf8 -*-
import simpy

# Инициализация среды моделирования
env = simpy.Environment()

# Глобальные переменные, для сохранения результатов моделирования
time = []
datax = []
datay = []

class Plot(object):
    '''
    env -- среда моделирования
    xinit, yinit -- начальные значения численности жертвы и хищника соответственно.
    '''

    def __init__(self, env, xinit, yinit):
        self.x = xinit
        self.y = yinit
        self.env = env

    # сохраняем текущие значения численности жертвы и хищника в глобальных 
    # переменных datax, datay, time
    def print_plot(self):
        global datax, datay, time
        # print ('x={0}, y={1}, time={2}'.format(self.x, self.y, self.env.now))
        datax.append(self.x)
        datay.append(self.y)
        time.append(self.env.now)

    # Процесс, ответственный за рождение жертвы
    def bornx(self, alphax):
        while True:
            self.print_plot()
            amount = self.x * alphax
            self.x += amount
            yield self.env.timeout(1)

    # Процесс, ответственный за естественную смерть жертвы
    def deadx(self, betax):
        while True:
            amount = self.x * betax
            self.x -= amount;
            if (self.x <= 1): self.x = 2
            yield self.env.timeout(1)

    # Процесс, ответственный за рождение хищника
    def borny(self, alphay):
        while True:
            amount = self.y * alphay
            self.y += amount
            yield self.env.timeout(1)

    # Процесс, ответственный за естественную смерть хищника
    def deady(self, betay):
        while True:
            amount = self.y * betay
            self.y -= amount;
            if (self.y <= 1): self.y = 2
            yield self.env.timeout(1)

    # Процесс, ответственный за поедание хищником жертвы
    def yeatx(self, gammax, gammay):
        while True:
            amountx = self.y * self.x * gammax
            amounty = self.y * self.x * gammay
            self.x -= amountx;
            if (self.x <= 1): self.x = 2
            self.y += amounty
            yield self.env.timeout(1)


# ------------- Параметры модели -----------------
alphax = 0.3 # рождаемость жертвы
alphay = 0.03  # рождаемость хищника
betax = 0.02  # естественная смертность жертвы
betay = 0.06  # естественная смертность хищника
gammax = 0.025  # 0.03 коэффициент интенсивности поедания жертвы хищником
gammay = 0.0012  # 0.001 коэффициент перехода биомассы жертвы в хищника за счет поедания
# ------------------------------------------------

# Задаем начальные численности жертвы (30) и хищника (8)
# Единицы измерения здесь не важны, но лучше представлять их
# в данной модели как непрерывные показатели биомассы
p = Plot(env, 50, 10)

# Добавление конкурирующих процессов гибели, рождения, поедания
# в модельную среду
env.process(p.bornx(alphax))
env.process(p.borny(alphay))
env.process(p.deadx(betax))
env.process(p.deady(betay))
env.process(p.yeatx(gammax, gammay))

# выполнение имитационного моделирования до определенного
# времени, в данном случае от 0 до 400
# каждый процесс (гибели, рождения, поедания) занимает 1 единицу
# времени (это описывает строка self.env.timeout(1) в каждом
# процессе)  
env.run(until=400)

# ---------- Отрисовка результатов моделирования ----------
# Должен быть установлен пакет matplotlib,
# если нет, то будем рисовать через canvas
try: 
    import matplotlib.pyplot as plt
    plt.rcdefaults()
    fig, ax = plt.subplots()
    # График длины
    ax.plot(time, datax, label='очереди')
    ax.set_title(f' количество еды')
    ax.set_xlabel(u'Время, sec')
    ax.set_ylabel(u'число кроликов')
    fig, bx = plt.subplots()
    # График времени ожидания
    bx.plot(time, datay)
    bx.set_title(f'количество хищников')
    bx.set_xlabel(u'Время, sec')
    bx.set_ylabel(u'число волков')
    plt.show()
except ImportError:
    # if True:
    print('without matplotlib - use tkinter')

    from tkinter import *
    #
    tk = Tk()
    tk.title("Graph plot")
    #
    button = Button(tk)
    button["text"]="Закрыть"
    button["command"]= tk.destroy #tk.quit
    button["font"]="Arial" #"-*-terminus-*-r-*-*-12-*-*-*-*-*-*-*"
    button.pack()
    #
    canva = Canvas(tk)
    canva["height"]=600  #360
    canva["width"]=800  #480
    canva["background"]="#eeeeee"
    canva["borderwidth"]=2
    canva.pack()
    # canva.create_text(790,590,text="800,600")
    # ay=150
    y0=400
    x0=10
    x1=500
    dx=1
    #
    y_axe=[]
    yy=(x0,0);   y_axe.append(yy)
    yy=(x0,y0);  y_axe.append(yy)
    canva.create_line(y_axe,fill="black",width=2,arrow=FIRST)
    for i in range(y0):
       if (i>0) and (i%100==0):
          k = y0 - i
          canva.create_line(x0, k, x0+10, k, width = 0.5,fill = 'black')
          canva.create_text(x0+20, k-10, text = str(i*0.5),fill="purple", font=("Arial", "10"))
    #
    x_axe=[]
    xx=(x0,y0);      x_axe.append(xx)
    xx=(2*x0+x1,y0); x_axe.append(xx)
    canva.create_line(x_axe,fill="black",width=2,arrow=LAST)
    for i in range(x1):
       if (i % 50 == 0):
          k = i
          canva.create_line(x0+i, y0, x0+i, y0+10, width = 0.5,fill='black')
          canva.create_text(x0+i, y0+20, text = str(i),fill="purple",font=("Arial","10"))
    canva.create_text(x0+x1,y0+20,text="время",fill='purple',font=('Arial','10'))
    #
    points=[]
    for n in range(len(datax)):
       pp=(time[n]+10,y0-datax[n]*2)
       points.append(pp)
    #
    canva.create_line(points,fill="blue",smooth=0,tags="pray")
    canva.create_text(x1,y0-300,text=str(int(max(datax))),fill='blue',font=('Arial','14'))
    canva.create_text(x1,y0-320,text="жертва",fill='blue',font=('Arial','14'))
    canva.create_text(x1,y0-280,text=str(int(min(datax))),fill='blue',font=('Arial','14'))
    #
    points=[]
    for n in range(len(datay)):
       pp=(time[n]+10,y0-datay[n]*2)
       points.append(pp)
    #
    canva.create_line(points,fill="red",smooth=0,tags="predator")
    canva.create_text(x1,y0-200,text=str(int(max(datay))),fill='red',font=('Arial','14'))
    canva.create_text(x1,y0-220,text="хищник",fill='red',font=('Arial','14'))
    #
    points=[]
    dy=150; dx=200; sy=5; sx=2
    for n in range(len(datax)):
       pp=(x1-dx+datax[n]*sx,y0+dy-datay[n]*sy)
       points.append(pp)
    canva.create_line(points,fill="green",smooth=0)
    canva.create_oval(x1-dx+datax[0]*sx,y0+dy-datay[0]*sy,x1-dx+datax[0]*sx+3,y0+dy-datay[0]*sy+3,fill='red')
    #
    tk.mainloop()
