import numpy as np
import pickle as pkl
import tensorflow as tf
import conv_layer_prediction
import dense_layer_prediction
import dense_layer_poly_mult
import mean_pooling_layer_prediction
import max_pooling_layer
import batch_norm
from write_weights import write_weights, read_weights
# from custom_bfv.bfv import BFV
from custom_bfv.bfv_ntt import BFV
import save_mnist_test
from print_outputs import print_1D_output, print_3D_output
import torch
import torchvision
from residual import residual

def load_pickle(filename):
  with open(f'{filename}', 'rb') as f:
    return pkl.load(f)

def main():
  # model_name = 'miniONN_cifar_model'
  model_name = 'resnet18'
  # single_test = load_pickle('cifar_test.pkl')
  # Xtest = single_test[0]
  # Ytest = single_test[1]
  num = 1 / 256
  Xtest = [[[num]*64] * 64]*3
  Xtest = np.array(Xtest)
  Ytest = [[[num]*64] * 64]
  Ytest = np.array(Ytest)
  Ytest = np.reshape(Ytest, (64, 64, 1))
  tf_test(model_name, Xtest, Ytest)
  Xtest = np.reshape(Xtest, (64, 64, 3))
  custom_test(model_name, Xtest)
  return

P_2_SCALE = 16

def scale_to_int(arr):
  scale = 2**P_2_SCALE
  rescaled = arr * scale
  # rescaled = np.round(rescaled)
  return rescaled.astype(int)

def ReLU(arr):
  ret = arr.copy()

  for i, image in enumerate(ret):
    for j, row in enumerate(image):
      for k, val in enumerate(row):
        if val < 0:
          ret[i][j][k] = 0
  # ret = scale_down(ret, 2**P_2_SCALE)
  return ret

def scale_down(arr, scale):
  ret = arr.copy()

  for i, image in enumerate(ret):
    for j, row in enumerate(image):
      for k, val in enumerate(row):
        ret[i][j][k] = val // scale
  return ret

def wrapper_conv_layer(input_layer, layer_path, pad=0, enc_scheme=None, stride=1, as_ints=False):
  layer = input_layer.copy()
  if pad:
    layer = conv_layer_prediction.pad_images( layer, pad )
  output = conv_layer_prediction.conv_layer_prediction( layer, read_weights(layer_path), stride, enc_scheme )
  output = np.array(output)
  if (as_ints):
    output = scale_down(output, 2**P_2_SCALE)
  layer_name = layer_path.split('/')[-1].split('.')[0]
  print(f'{layer_name} Done')
  return output

def custom_test(model_name, Xtest):

  as_ints = True

  # Load and reshape the test image
  # Xtest = scale_to_int(Xtest)
  image_height, image_width, image_channels = Xtest.shape
  images = np.zeros( (image_channels, image_height, image_width))

  if (as_ints):
    Xtest = scale_to_int(Xtest)
    images = np.zeros( (image_channels, image_height, image_width), dtype=int )
    model_name = 'int_' + model_name

  for wi, w in enumerate(Xtest):
    for hi, h in enumerate(w):
      for ci, c in enumerate(h):
        images[ci][wi][hi] = c
  Xtest = images

  directory = f'./model_weights/{model_name}'

  enc_scheme = BFV(q = 2**38, t = 2**25, n = 2**10)

  OUTPUT_PRINT = lambda output: print(output.reshape( np.prod(output.shape) ).astype(int)[:100])

  def basic_block(inp, layer, first_stride=1, as_ints=False):
    output = wrapper_conv_layer(inp, f'{directory}/layer{layer}.conv1.weight.txt', pad=1, enc_scheme=enc_scheme, stride=first_stride, as_ints=as_ints)
    output = batch_norm.batch_main(output, f'{directory}/layer{layer}.bn1.weight.txt', f'{directory}/layer{layer}.bn1.bias.txt', f'{directory}/layer{layer}.bn1.running_mean.txt', f'{directory}/layer{layer}.bn1.running_var.txt', as_ints=as_ints)
    output = ReLU(output)
    output = wrapper_conv_layer(output, f'{directory}/layer{layer}.conv2.weight.txt', pad=1, enc_scheme=enc_scheme, stride=1, as_ints=as_ints)
    output = batch_norm.batch_main(output, f'{directory}/layer{layer}.bn2.weight.txt', f'{directory}/layer{layer}.bn2.bias.txt', f'{directory}/layer{layer}.bn2.running_mean.txt', f'{directory}/layer{layer}.bn2.running_var.txt', as_ints=as_ints)
    # print(inp.shape, output.shape)
    print(f'inp.shape: {inp.shape}')
    print(f'output.shape: {output.shape}')
    print()
    # output = ReLU(output)
    return output

  def downsample(inp, layer, as_ints=False):
    output = wrapper_conv_layer(inp, f'{directory}/layer{layer}.downsample.0.weight.txt', pad=0, enc_scheme=enc_scheme, stride=2, as_ints=as_ints)
    output = batch_norm.batch_main(output, f'{directory}/layer{layer}.downsample.1.weight.txt', f'{directory}/layer{layer}.downsample.1.bias.txt', f'{directory}/layer{layer}.downsample.1.running_mean.txt', f'{directory}/layer{layer}.downsample.1.running_var.txt', as_ints=as_ints)
    return output

  def _layer(inp, n, _downsample=False, first_stride=1, as_ints=False):
    save_inp = inp.copy()
    if _downsample:
      save_inp = downsample(inp, n, as_ints=as_ints)
    output = basic_block(inp, n, first_stride, as_ints=as_ints)
    output = residual(save_inp, output)
    output = ReLU(output)
    return output

  #test = [[[1]*16]*16]*64
  #test = np.array(test)
  # begin
  output = wrapper_conv_layer(Xtest, f'{directory}/conv1.weight.txt', pad=3, enc_scheme=enc_scheme, stride=2, as_ints=as_ints)
  # OUTPUT_PRINT(output)
  # return
  #print(output.shape)
  output = batch_norm.batch_main(output, f'{directory}/bn1.weight.txt', f'{directory}/bn1.bias.txt', f'{directory}/bn1.running_mean.txt', f'{directory}/bn1.running_var.txt', as_ints=as_ints)
  output = ReLU(output)
  # pad before max pool
  output = conv_layer_prediction.pad_images(output, 1)
  output = max_pooling_layer.max_pooling_layer(output, (3, 3), stride=2)
  # layer 1.0
  output = _layer(output, "1.0", as_ints=as_ints)
  # layer 1.1
  output = _layer(output, "1.1", as_ints=as_ints)
  # layer 2.0
  output = _layer(output, "2.0", _downsample=True, first_stride=2, as_ints=as_ints)
  # layer 2.1
  output = _layer(output, "2.1", as_ints=as_ints)
  # layer 3.0
  output = _layer(output, "3.0", _downsample=True, first_stride=2, as_ints=as_ints)
  # layer 3.1
  output = _layer(output, "3.1", as_ints=as_ints)
  # layer 4.0
  output = _layer(output, "4.0", _downsample=True, first_stride=2, as_ints=as_ints)
  # layer 4.1
  output = _layer(output, "4.1", as_ints=as_ints)
  print()
  # print((output/256))

  # adaptive avg pooling ?
  output = mean_pooling_layer_prediction.adaptive_mean_pooling_layer(output, output_shape=(1, 1))
  # print()
  # print((output/(2**P_2_SCALE))[:50])
  # return output

  filters, width, height = output.shape
  output = output.reshape(width*height*filters)

  dense_kernel = read_weights(f"{directory}/fc.weight.txt")
  dense_bias = read_weights(f"{directory}/fc.bias.txt")
  # output = dense_layer_prediction.dense_layer( output, dense_kernel)
  dense_output = [0] * 1000

  '''
  split = 4000
  for i in range(0, width*height*filters, split):
    temp = dense_layer_prediction.dense_layer( output[i:min(i+split, width*height*filters - i)], dense_kernel[:][i:min(i+split, width*height*filters - i)])
    for j in range(len(temp)):
      dense_output[j] += temp[j]

  for i in range(len(dense_output)):
    dense_output[i] += dense_bias[i]
  '''

  dense_output = dense_layer_prediction.dense_layer( output, dense_kernel, dense_bias)

  if (as_ints):
    dense_output = np.array(dense_output) / 2**P_2_SCALE
    dense_output = np.array(dense_output) / 2**P_2_SCALE
    # dense_output = dense_output.astype(int)
    pass
  output = dense_output

  print(f'Prediction: [', end=' ')
  for pred in output[:100]:
    pred = float(pred)
    print(f'{pred:.7f}', end=' ')
  print(']')
  return output

  max_scale = max(output)
  norm_scale = (2**P_2_SCALE)**2
  for ind, val in enumerate(output):
    output[ind] = val // norm_scale
    pass

  output = dense_layer_prediction.softmax( output )
  print(f'Prediction: [', end=' ')
  for pred in output:
    pred = float(pred)
    print(f'{pred:.7f}', end=' ')
  print(']')
  return output

def tf_test(model_name, Xtest, Ytest):
  # model_name = 'small_model'
  # model = tf.keras.models.load_model(f'./models/{model_name}.h5')
  model = torchvision.models.resnet18()
  model.load_state_dict(torch.load('./models/resnet18.pth'))

  Xtest = np.expand_dims(Xtest, 0)
  Xtest = torch.Tensor(Xtest)
  # print(f'Xtest: {Xtest}')
  # print(f'Xtest shape: {Xtest.shape}')
  # print(f'Ytest: {Ytest}')
  # print(f'Ytest shape: {Ytest.shape}')

  # Ypred = model.predict( Xtest )
  model.eval()

  # test = [[[[1]*16]*16]*64]
  # test = torch.Tensor(test)
  # temp = model.conv1(Xtest)
  # temp = model.bn1(temp)
  # temp = model.relu(temp)
  # temp = model.maxpool(temp)
  # temp = model.layer1(temp)
  # temp = model.layer2(temp)
  # temp = model.layer3(temp)
  # temp = model.layer4(temp)
  # temp = model.avgpool(temp)
  # print(temp[0][:50])
  # return temp

  #temp = model.layer2(temp)
  #temp = model.layer3(temp)
  #temp = model.layer4(temp)

  #output = model.avgpool(temp)
  #print(output.shape)
  #print(output[0])
  #return

  #conv_output_image = Ypred.permute(0, 2, 3, 1).detach().numpy()
  # print(conv_output_image)
  # print(output)

  with torch.no_grad():
    Ypred = model(Xtest)
  print(f'Prediction: [', end=' ')
  for pred in Ypred[0][:100]:
    pred = float(pred)
    print(f'{pred:.7f}', end=' ')
  print(']')
  # print(f'Acutal: {Ytest}')
  return Ypred[0]

def test_many_mnist_examples():
  num_tests = 20
  same_pred = 0
  total_diff = 0
  diff_arr = []
  for i in range(num_tests):
    save_mnist_test.main(i)
    print(f'Test {i+1}')
    print('---'*8)
    model_name = '4_layer_mnist_model'
    single_test = load_pickle('single_test.pkl')
    Xtest = single_test[0]
    Ytest = single_test[1]
    tf_output  = tf_test(model_name, Xtest, Ytest)
    our_output = custom_test(model_name, Xtest, Ytest)
    if ( np.argmax(tf_output) == np.argmax(our_output) ):
      same_pred += 1
    diff = sum(map(abs, [t-o for t,o in zip(tf_output, our_output) ]))
    diff_arr.append( diff )
    total_diff += diff
    print(f'diff: {diff}')
    print('\n'*2)
  print(f'total diff:   {total_diff}')
  print(f'average diff: {total_diff / num_tests}')
  print(f'standard dev: {np.std(diff_arr)}')
  print(f'same pred:    {same_pred} / {num_tests}')

if __name__ == '__main__':
  # test_many_mnist_examples()
  main()


from django.http import Http404
from django.shortcuts import render
from tenderapp.models import Tender
from advertise.models import Advertising
from django.contrib.auth.decorators import login_required
from memberships.models import Membership, UserMembership

def all(request):
    tender = Tender.objects.order_by('-created_at')[:3]
    advertise = Advertising.objects.order_by('-timestamp')[:3]

    context = {'tender': tender, 'advertise': advertise}
    template = 'tenderonly/all.html'
    return render(request, template, context)

@login_required
def single(request, slug):
    try:
        tender = Tender.objects.get(slug=slug)
        advertise = Advertising.objects.order_by('-timestamp')[:3]
        user_membership = UserMembership.objects.filter(user=request.user).first()
        user_membership_type = user_membership.membership.membership_type
        context = {'tender': tender, 'advertise': advertise, 'user_membership_type':user_membership_type}
        template = 'tenderonly/single.html'
        return render(request, template, context)

    except:
        return render(request, 'loginrequired.html')


# 명확한 프롬프트 작성하기
name = input("Plese enter your name: ")
print("Hello " + name + "!")
"""
input()함수를 사용할 때는 명확하고 따라하기 쉬운 프롬프트(문장)을 써서 사용자가
여러분이 원하는 정보를 정확히 입력할 수 있도록 해야한다 사용자에게 무엇을 입력할지
알리는 문장은 무엇이든 괜찮다
"""

prompt = "IF you tell us who you are we can personalize the messages you see."
prompt += "\nWhat is your first name? "

name = input(prompt)
print("\nHello " + name + "!")


import vocabulary_funcs
import analysis_funcs

import matplotlib.pyplot as plt

def _tfidf_extract(ui_list, Post_list, mrph_path):
    Tfidf = vocabulary_funcs.TfidfClass(f_mrph=mrph_path)
    f_tfidf, else_tfidf = [], []
    for pi in ui_list:
        # print("   pi", pi)
        Tfidf.add_post_words(pi)
        post = Post_list[pi]
        post_tfidf = Tfidf.ref_tfidf_from_pi(pi)

        if not post.reply_to_id:
            else_tfidf.append(post_tfidf)
        elif Post_list[post.reply_to_id].user_id == "facilitator":
            f_tfidf.append(post_tfidf)
        else:
            else_tfidf.append(post_tfidf)

    return f_tfidf, else_tfidf

def _idf_extract(ui_list, Post_list, mrph_path):
    Tfidf = vocabulary_funcs.TfidfClass(f_mrph=mrph_path)
    f_tfidf, else_tfidf = [], []
    for pi in ui_list:
        # print("   pi", pi)
        Tfidf.add_post_words(pi)
        post = Post_list[pi]
        post_idf = Tfidf.ref_idf_per_pi(pi)

        if not post_idf:
            continue

        if not post.reply_to_id:
            else_tfidf.append(max(post_idf.values()))
        elif Post_list[post.reply_to_id].user_id == "facilitator":
            f_tfidf.append(max(post_idf.values()))
        else:
            else_tfidf.append(max(post_idf.values()))

    return f_tfidf, else_tfidf

def graphing_idf(fs, us, save_f):
    # https://stats.biopapyrus.jp/python/barplot.html
    error_bar_set = dict(
        lw=1,
        capthick=1,
        capsize=2
    )

    fig = plt.figure(figsize=(16, 9))
    print(us)
    print(fs)
    u_xs = list(range(len(us[2])))
    print("usr", u_xs)
    plt.bar(u_xs, us[0], yerr=us[1], label="another", color="steelblue", width=0.4, error_kw=error_bar_set)

    f_xs = list(map(lambda x: x + 0.4, fs[2]))  # 標準偏差が見にくいので
    print("fa", f_xs)
    plt.bar(f_xs, fs[0], yerr=fs[1], label="rep to agent", color="orange", width=0.4, error_kw=error_bar_set)

    u_xs = [x + 0.2 for x in u_xs]
    plt.xticks(u_xs, us[2])
    plt.legend(loc="best")
    # plt.show()
    plt.savefig(str(save_f))

def only_reply_to_facilitator(User_list, Post_list, mrph_path, save_f):
    usrs_idfs = []

    f_ave_list, f_std_list, f_x_list = [], [], []
    u_ave_list, u_std_list = [], []

    usr_name_list = list(User_list.keys())

    usr_name_list.remove("kitkat")
    usr_name_list.remove("faciitator")

    print(usr_name_list, type(usr_name_list))
    for u_idx, u_n in enumerate(usr_name_list):
        print(u_idx, ":", u_n)

    for u_idx, u_n in enumerate(usr_name_list):
        print("[", u_idx, "]", ":", "user name ", u_n)

        f_list, u_list = _idf_extract(User_list[u_n].pi_list, Post_list, mrph_path)

        if len(f_list) != 0:
            print("  ", u_n, "has reply to facilitator!!")
            f_ave, f_std = analysis_funcs.ave_and_var(f_list)
            f_ave_list.append(f_ave)
            f_std_list.append(f_std)
            f_x_list.append(u_idx)
        else:
            print("  ", u_n, "didn't reply to facilitator.")
        # print(u_list)
        u_ave, u_std = analysis_funcs.ave_and_var(u_list)
        u_ave_list.append(u_ave)
        u_std_list.append(u_std)
        # u_name_list[u_idx] = u_n + " (" + str(len(f_list)) + ")"

    graphing_idf([f_ave_list, f_std_list, f_x_list], [u_ave_list, u_std_list, usr_name_list], save_f)


import matplotlib.pyplot as plt
import numpy as np

plt.rcParams["figure.figsize"] = (12,4)

N = 64
n = np.arange(0, N, 1)
L = N / 16
delay = 0
y = 0.5 * np.sin(2 * np.pi / N * L * (n - delay))

plt.figure(1)
plt.subplot(2,2,1)
plt.stem(y)

Y2 = np.fft.fft(y)

plt.subplot(2,2,2)
plt.stem(np.abs(Y2),use_line_collection=True)

plt.subplot(2,2,3)
plt.stem(np.imag(Y2),use_line_collection=True)

plt.show()


#!/usr/bin/env python3

"""Load graphic parts and map on to each other."""

class Graphics():
    """Load, merge and print several asciiart."""

    parts = []
    canvas = []

    def __init__(self, parts):
        """"Setup and load all parts."""
        self.parts = parts
        self.load_and_merge_parts()

    def load_and_merge_parts(self):
        """Load graphics from file and merge into one."""
        for part in self.parts:
            content = self._load_part(part)
            self._merge_part(part, content)

    def _load_part(self, part):
        """Load one graphic from file."""
        path = "graphics/" + part["graphic"]
        with open(path) as f:
            content = f.readlines()
            content = [line.strip("\n") for line in content]
            return content

    def _merge_part(self, part, content):
        """Merge part onto canvas."""
        if not self.canvas:
            self.canvas = content
            return

        p_len = len(content)
        py = part["posY"]
        px = part["posX"]

        for i in range(p_len):
            c_len = len(content[i])
            part_a = self.canvas[i + py][0:px]
            part_b = content[i][:]
            part_c = self.canvas[i + py][px + c_len:]
            self.canvas[i + py] = part_a + part_b + part_c

    def __str__(self):
        """Print a view of the room."""
        str1 = ""
        for row in self.canvas:
            str1 += "".join(row) + "\n"

        return str1

def test():
    print("hej")

    g = Graphics([
        {
            "graphic": "base.txt",
            "posX": 0,
            "posY": 0
        },
        {
            "graphic": "tree.txt",
            "posX": 1,
            "posY": 1
        },
        {
            "graphic": "cat1.txt",
            "posX": 20,
            "posY": 8
        },
        {
            "graphic": "alien.txt",
            "posX": 50,
            "posY": 5
        }
    ])

    print(g)

if __name__ == "__main__":
    test()


from django.shortcuts import render
from ping.models import PingExecution, Ping

def index(request):
    starting_times = PingExecution.objects.values_list("starting_time", flat=True).order_by('-starting_time')
    domain_names = Ping.objects.values_list("domain_name", flat=True).distinct()

    starting_times = [x.strftime("%Y-%m-%d %H:%M:%S.%f") for x in starting_times]

    return render(
        request,
        'pingVisualization.html',
        {"datetimefilters" : list(starting_times),
        "domainnamefilters": list(domain_names)})


import tkinter
import PIL.Image
import PIL.ImageTk
from tkinter import *
from tkinter.font import Font
from tkinter.ttk import *

def AusBusiness(window, canvas):
    soleil = Font(family="Soleil", size=26)
    lato = Font(family="Lato", size=18)

    style = Style()
    style.configure("Next.TButton", background='#6558F5', foreground='#020202', font=lato)
    style.configure("Exit.TButton", background='#D3455B', foreground='#020202', font=lato)
    style.configure("Main.TCheckbutton", font=lato, foreground='#020202', background='#EDEDF3')

    def AusBusExitButton():
        window.destroy()

    def AusBusNextButton():
        canvas.delete("all")
        chk1.place(x=-1000, y=-1000)
        chk2.place(x=-1000, y=-1000)
        chk3.place(x=-1000, y=-1000)
        chk4.place(x=-1000, y=-1000)
        chk5.place(x=-1000, y=-1000)
        nextBtn.place(x=-1000, y=-1000)
        x = varTrue()
        if x == True:
            canvas.create_text(640, 100, text="Your business is eligible for a tax-free A$20,000 - A$100,000\ncash boost upon lodgement of an activity statement.\n(Payments will not be made prior to 28 April 2020 but can be lodged).", justify=CENTER, fill='#020202', font=soleil)
        elif x == False:
            canvas.create_text(640, 100, text="Your business is ineligible for any COVID-19 financial aid.", justify=CENTER, fill='#020202', font=soleil)
        canvas.create_text(388, 660, text="Progress: 100%", justify=LEFT, fill='#020202', font=lato)
        canvas.create_rectangle(320, 680, 960, 695, fill='#90929C', outline='#90929C')
        canvas.create_rectangle(320, 680, 960, 695, fill='#6558F5', outline='#6558F5')
        exitBtn.place(x=560, y=575)

    def varTrue():
        if var1.get() == 1 and var2.get() == 1 and var3.get() == 1 and var4.get() == 1 and var5.get() == 1:
            return True
        else:
            return False

    canvas.create_text(640, 100, text="An Australian business? Awesome.\nPlease tick any of the boxes that you meet the criteria for.", justify=CENTER, fill='#020202', font=soleil)

    var1 = IntVar()
    chk1 = Checkbutton(canvas, text='Currently holding an ABN that was active from at latest 12 March 2020.', variable=var1, style='Main.TCheckbutton')
    chk1.place(x=250, y=200)

    var2 = IntVar()
    chk2 = Checkbutton(canvas, text='Small or medium business.', variable=var2, style='Main.TCheckbutton')
    chk2.place(x=250, y=250)

    var3 = IntVar()
    chk3 = Checkbutton(canvas, text='Annual turnover is less than A$50 million.', variable=var3, style='Main.TCheckbutton')
    chk3.place(x=250, y=300)

    var4 = IntVar()
    chk4 = Checkbutton(canvas, text='Made eligible payments that the business is required to withhold.', variable=var4, style='Main.TCheckbutton')
    chk4.place(x=250, y=350)

    var5 = IntVar()
    chk5 = Checkbutton(canvas, text='Lodged 2019 tax return before 12 March 2020 OR:\nMade GST taxable, GST-free or input-taxed sales in a previous tax period.', variable=var5, style='Main.TCheckbutton')
    chk5.place(x=250, y=400)

    nextBtn = Button(canvas, text='FINISH', style='Next.TButton', command=AusBusNextButton)
    nextBtn.place(x=715, y=575);

    exitBtn = Button(canvas, text='EXIT', style='Exit.TButton', command=AusBusExitButton)
    exitBtn.place(x=400, y=575);

    canvas.create_text(388, 660, text="Progress: 40%", justify=LEFT, fill='#020202', font=lato)
    canvas.create_rectangle(320, 680, 960, 695, fill='#90929C', outline='#90929C')
    canvas.create_rectangle(320, 680, 576, 695, fill='#6558F5', outline='#6558F5')


def histogram(string):
    temporary = {}

    for character in string:
        if character not in temporary:
            temporary[character] = 0  # Initialize the count to 0 for a new character
        temporary[character] += 1  # Increment the count for the character

    for character, count in temporary.items():
        print(character, '*' * count)  # Print the character and the '*' character repeated 'count' times