from casioplot import *
from math import *

def f(x):
  p=False
  try:
    r=exp(x)# <- Function expression
    p=True
  except:
    p=False
  if p and (type(r)==float or type(r)==int):
    return r
  else:
    return False

def f2(x,y,p):
  r=False
  try:
    if abs(tan(x**2+y**2))<p:# <- Function expression
      r=True
  except:
    r=False
  return r

#x:0-383 y:0-191
dp_mx=383
dp_my=191
start_menu=False
a_col=(0,0,0) # axis coloor
g_col=(0,0,255) # graph color
d_col=(0,210,50) # derivative color
i_col=(180,60,0) # integral color

def axis(xmin,xmax,ymin,ymax):
  if ymin<=0<=ymax:
    dp_y=int(dp_my*(1-ymin/(ymin-ymax)))
    for dp_x in range(dp_mx+1):
      for i in range(3):
        set_pixel(dp_x, dp_y+i-1, a_col)
  if xmin<=0<=xmax:
    dp_x=int(dp_mx*xmin/(xmin-xmax))
    for dp_y in range(dp_my+1):
      for i in range(3):
        set_pixel(dp_x+i-1, dp_y, a_col)
          
def coord(xmin,xmax,ymin,ymax,sx,sy,grid):
  x0=int(dp_mx*xmin/(xmin-xmax))
  y0=int(dp_my*(1-ymin/(ymin-ymax)))
  kx=(xmax-xmin)/sx
  ky=(ymax-ymin)/sy
  xstep=dp_mx/kx
  ystep=dp_my/ky
  x=xstep
  y=ystep
  while x<=dp_mx:
    for i in range(9):
      set_pixel(x0+int(x), y0-4+i, a_col)
      set_pixel(x0-int(x), y0-4+i, a_col)
    if grid:
      for i in range(0, dp_my+1, 2):
        set_pixel(x0+int(x), i)
        set_pixel(x0-int(x), i)
    x+=xstep
  while y<=dp_my:
    for i in range(9):
      set_pixel(x0-4+i, y0+int(y), a_col)
      set_pixel(x0-4+i, y0-int(y), a_col)
    if grid:
      for i in range(0, dp_mx+1, 2):
        set_pixel(i, y0+int(y))
        set_pixel(i, y0-int(y))
    y+=ystep
  draw_string(300,0,"Scale:",(255,0,0))
  draw_string(300,15,"x:"+"{:.3f}".format((xmax-xmin)/kx),(255,0,0))
  draw_string(300,30,"y:"+"{:.3f}".format((ymax-ymin)/ky),(255,0,0))
  
def graph(xmin=-10,xmax=10,ymin=-5,ymax=5,width=2,sx=1,sy=1,grid=True,d=False,integral=False,acc=4):
  clear_screen()
  axis(xmin,xmax,ymin,ymax)
  step=(xmax-xmin)/(dp_mx*acc)
  x=xmin
  d_a=None
  i_a=0
  for dp_x in range(dp_mx*acc+1):
    dp_x=dp_x//acc
    r=f(x)
    if r!=False:
      if d:  
        if d_a==None:
          d_a=r
        else:
          d_b=r
          der=(d_b-d_a)/step
          dp_y=int(dp_my*(1-(der-ymin)/(ymax-ymin)))
          for i in range(-width//2,width//2+1):
            for j in range(-width//2,width//2+1):
              set_pixel(dp_x+i, dp_y+j, d_col)
          d_a=d_b
      if integral:
        i_b=i_a+step*r
        dp_y=int(dp_my*(1-(i_b-ymin)/(ymax-ymin)))
        for i in range(-width//2,width//2+1):
          for j in range(-width//2,width//2+1):
            set_pixel(dp_x+i, dp_y+j, i_col)
        i_a=i_b
      dp_y=int(dp_my*(1-(r-ymin)/(ymax-ymin)))
      for i in range(-width//2,width//2+1):
        for j in range(-width//2,width//2+1):
          set_pixel(dp_x+i, dp_y+j, g_col)
    x+=step
  coord(xmin,xmax,ymin,ymax,sx,sy,grid)
  show_screen()
  draw_string(300,145,"- f",g_col)
  k=0
  if d:
    draw_string(300,160,"- df/dx",d_col)
    k+=15
  if integral:
    draw_string(300,160+k,"- F",i_col)

def config():  
  p=False
  xmin=float(input("xmin: "))
  while not p:
    xmax=float(input("xmax: "))
    if xmax>xmin:
      p=True
    else:
      print("Please make sure that\nxmax>xmin")
  p=False
  ymin=float(input("ymin: "))
  while not p:
    ymax=float(input("ymax: "))
    if ymax>ymin:
      p=True
    else:
      print("Please make sure that\nymax>ymin")
  width=int(input("line width: "))
  sx=float(input("x graduation\nscale: "))
  sy=float(input("y graduation\nscale: "))
  grid=int(input("Show grid?\n1: Yes\n2: No\n"))
  if grid==1:
    grid=True
  else:
    grid=False
  d=int(input("Show derivative?\n1: Yes\n2: No\n"))
  if d==1:
    d=True
  else:
    d=False
  integral=int(input("Show integral?\n1: Yes\n2: No\n"))
  if integral==1:
    integral=True
  else:
    integral=False
  acc=int(input("Accuracy\n(calculation per pixel)\n1-5 recommended\n"))
  graph(xmin,xmax,ymin,ymax,width,sx,sy,grid,d,integral,acc)
  
def menu():  
  p=False
  ans=None
  while ans!=0 and ans!=1: 
    ans=float(input("0: Default config\n1: Custom config\n2: Help\n"))
    if ans==0:
      graph()
    if ans==1:
      config()
    if ans==2:
      t=str(input("Change the function\nequations at line 7/19.\nChange the colors by\nediting lines 29-32.\nEnter anything to\ncontinue. "))

if start_menu:
  menu()  

def graph2(xmin=-10,xmax=10,ymin=-5,ymax=5,width=2,sx=1,sy=1,grid=True,acc=1,p=2.5):
  clear_screen()
  p=(ymax-ymin)/(10**p)
  axis(xmin,xmax,ymin,ymax)
  xstep=(xmax-xmin)/(dp_mx*acc)
  ystep=(ymax-ymin)/(dp_my*acc)
  x=xmin
  y=ymax
  for dp_x in range(dp_mx*acc+1):
    dp_x=dp_x//acc
    y=ymax
    for dp_y in range(dp_my*acc+1):  
      dp_y=dp_y//acc
      r=f2(x,y,p)
      if r:
        for i in range(-width//2,width//2+1):
          for j in range(-width//2,width//2+1):
            set_pixel(dp_x+i, dp_y+j, g_col)
      y-=ystep
    x+=xstep
  coord(xmin,xmax,ymin,ymax,sx,sy,grid)
  show_screen()
  draw_string(300,145,"- f",g_col)