from cx_Freeze import Executable, setup

build_exe_options = {
    "packages": ["win32com", "xlwings"],
    "excludes": [
        "scipy",
        "numpy",
        "email",
        "xml",
        "pandas",
        "Tkinter",
        "Tkconstants",
        "pydoc",
        "tcl",
        "tk",
        "matplotlib",
        "PIL",
        "nose",
        "setuptools",
        "xlrd",
        "xlwt",
        "PyQt4",
        "markdown",
        "IPython",
        "docutils",
    ],
    "optimize": 2,
}

setup(
    name="fibonacci",
    version="0.1.0",
    options={"build_exe": build_exe_options},
    executables=[Executable("fibonacci.py", targetName="fibonacci.exe")],
)


import pickle, sys, string

class OWL:

    def __init__(self, namespace, outfile, propurl):
        self.namespace = str(namespace)
        self.outfile = outfile
        #self.outfile = 'output.owl'
        #self.propurl = 'http://staff.washington.edu/ngopal/prenatal.owl'
        self.propurl = propurl
        self.doc = ''
        self.start()

    def start(self):
#        stub='<?xml version="1.0" encoding="iso-8859-1"?> '+'\n'
        stub=''
        stub+='<rdf:RDF xmlns:dc="http://purl.org/dc/elements/1.1/"'+'\n'
        stub+='\txmlns:owl="http://www.w3.org/2002/07/owl#"'+'\n'
        stub+='\txmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"'+'\n'
        stub+='\txmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" '+'\n'
        stub+='\txmlns:xsd="http://www.w3.org/2001/XMLSchema#"'+'\n'
        stub+='\txml:base="http://www.example.org/'+domain+'"'+'\n'
        stub+='\txmlns="http://www.example.org/'+domain+'#">''\n\n'
#
        stub+='<owl:Ontology rdf:about="">'+'\n'
        stub+='\t<rdfs:comment>Taxonomy for '+domain+'</rdfs:comment>'+'\n'
        stub+='</owl:Ontology>\n'
#        print stub
        self.doc += stub
        return 0

    def addClass(self, classname):
        classname=string.replace(classname,' ','_')
        classname=string.replace(classname,'-','_')
        stub = '\n<owl:Class rdf:ID="'+classname+'">\n'
        stub += '</owl:Class>\n'

#        print stub
        self.doc += stub
        return 0

    def addSubClass(self, classname, superclassname):
        classname=string.replace(classname,' ','_')
        classname=string.replace(classname,'-','_')
        superclassname=string.replace(superclassname,' ','_')
        superclassname=string.replace(superclassname,'-','_')
        stub = '\n<owl:Class rdf:ID="'+classname+'">\n'
        stub += '\t<rdfs:subClassOf rdf:resource="#'+superclassname+'"/>\n'
        stub += '</owl:Class>\n'
#        print stub
        self.doc += stub
        return 0

    def addInstance(self, classname, inst, val):
        classname=string.replace(classname,' ','_')
        inst=string.replace(inst,' ','_')
        stub='\n<'+classname+' rdf:about="#'+str(val)+'">\n'

        stub+='<title rdf:datatype="#string">'+str(inst)+'</title>\n'
        stub+='</'+classname+'>\n'
#        <owl:Class rdf:ID="reviewedarticle">
#            <rdfs:subClassOf rdf:resource="#publication"/>
#        </owl:Class>

    def end(self):
        fileh = open(self.outfile, 'w')
        self.doc += '</rdf:RDF>\n'
        fileh.write(self.doc)
        fileh.close()

def recAdd(o, parent, level):
    p=parent
    if parent=='Product':
        p=''
    try:
        labelMap=pickle.load(open('level'+str(level)+'/'+domain+'_'+p+'_LABEL_MAP.p'))
        labelDict=pickle.load(open('level'+str(level)+'/'+domain+'_'+p+'_LABEL_DICT.p'))
        par=string.replace(parent,'&','and')
        for l in labelMap:
            if labelDict[l]>limit:
                cat=string.replace(labelMap[l],'&','and')

                o.addSubClass(cat,par)
                recAdd(o, labelMap[l], level+1)
    except:
        return

domain=sys.argv[1]
limit=int(sys.argv[2])
namespace=domain
outfile='Data/Tax_'+domain+'.owl'
propUrl='http://www.example.org'
o=OWL(namespace,outfile,propUrl)

labelMap=pickle.load(open('level0/'+domain+'__LABEL_MAP.p'))
labelDict=pickle.load(open('level0/'+domain+'__LABEL_DICT.p'))
cmap={}
isAdded={}

level=0
o.addClass('Product')
recAdd(o,'Product',level)

#for l in labelMap:
#    if labelDict[l]>limit:
#      o.addSubClass(labelMap[l],'Product')
#      recAdd(o,labelMap[l],level+1)

o.end()


# -*- coding: utf-8 -*-
"""
Created on Fri May 17 21:03:14 2019

@author: shane
"""

import gym
import numpy as np

np.set_printoptions(precision=3, linewidth=120)

# Setup GPU TF stability
import tensorflow as tf
gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.8)
sess = tf.Session(config=tf.ConfigProto(
  allow_soft_placement=True, log_device_placement=True))

import gc
gc.enable()

"""
# Create an environment and set random seed
"""
selectedEnvironment = 8
env = 0
envName = 0

# Toy Text - Discrete state and action space
if selectedEnvironment == 0:
    envName = 'Taxi-v2'

# Classic Control - Continuous State and Discrete Action Spaces
elif selectedEnvironment == 1:
    envName = 'MountainCar-v0' # needs Discretized or better
elif selectedEnvironment == 2:
    envName = 'Acrobot-v1'     # needs Discretized, Tile Encoding or better
elif selectedEnvironment == 3:
    envName = 'CartPole-v1'    # needs Deep Q Learning to do well?

# Box 2D - Continuous State, Discrete Actions
elif selectedEnvironment == 4:
    envName = 'LunarLander-v2' # discrete actions, continuous state

# Classic Control - Continuous State and Action Spaces
elif selectedEnvironment == 5:
    envName = 'Pendulum-v0' # continuous only
elif selectedEnvironment == 6:
    envName = 'MountainCarContinuous-v0' # continuous only

# Box 2D - Continuous State and Action Spaces
elif selectedEnvironment == 7:
    envName = 'LunarLanderContinuous-v2' # continuous only
elif selectedEnvironment == 8:
    envName = 'BipedalWalker-v2'  # continuous only

# Box 2D - Image State and Continuous Action Spaces
elif selectedEnvironment == 9:
    envName = 'CarRacing-v0'      #  image input, actions [steer, gas, brake]

# Initialize the environment
env = gym.make(envName)
env.reset()

# Set output file paths based on environment
from visuals import examine_environment, examine_environment_MountainCar_discretized, examine_environment_Acrobat_tiled
#examine_environment(env)

from datetime import datetime
FORMAT = '%Y%m%d%H%M%S'
file_output_train = envName + '_train.txt'       # file name for saved results
file_output_test = envName + '_test.txt'       # file name for saved results
file_output_train = datetime.now().strftime(FORMAT) + file_output_train

print('-----------------------------------------------------------')
print('New Experiment, training output file name: ', file_output_train)

"""
# Create Agent
"""
agent = 0
selectedAgent = 2
if selectedAgent == 0:
    # create the agent discretized state space Q Learning
    state_size = env.observation_space.shape[0]
    action_size = env.action_space.n
    print("env.observation_space.shape[0]", state_size)
    print("env.action_space", action_size)
    from agents import QLearningAgentDiscretized as qlad
    agent = qlad.QLearningAgent(env)
#    examine_environment_MountainCar_discretized(env)

if selectedAgent == 1:
    # create the agent for tiled state space Q Learning
    state_size = env.observation_space.shape[0]
    action_size = env.action_space.n
    print("env.observation_space.shape[0]", state_size)
    print("env.action_space", action_size)
    from agents import QLearningAgentDiscretizedTiles as qlat
    agent = qlat.QLearningAgentDisTiles(env)
#    examine_environment_Acrobat_tiled(env, n_bins)

if selectedAgent == 2:
    # Create DDPG network agent
    obsSpace = env.observation_space.shape
    print("env.observation_space: ", obsSpace)
    from agents.DDPG import DDPG
    agent = DDPG(env, "continousStateAction")  # continousStateAction imageStateContinuousAction

if selectedAgent == 3:
    # Create DDPG network agent
    obsSpace = env.observation_space.shape
    print("env.observation_space: ", obsSpace)
    from agents.DDPG import DDPG
    agent = DDPG(env, "imageStateContinuousAction")  # continousStateAction imageStateContinuousAction

"""
# run the simulation
"""
import interact as sim
num_episodes=500
sim.interact(agent, env, num_episodes, mode='train', file_output=file_output_train, renderSkip=100)

"""
# Plot training scores obtained per episode
"""
from visuals import plot_q_table, plot_score_from_file
plot_score_from_file(file_output_train, -300, 300, 1)
if selectedAgent == 0 or selectedAgent == 1:
    plot_q_table(agent.q_table)

"""
# save model and architecture to single file
# https://machinelearningmastery.com/save-load-keras-deep-learning-models/
"""
if selectedAgent == 2 or selectedAgent == 3:
    import sys
    sys.setrecursionlimit(1000000) # need to be big enough to handle whole weight list
    agent.actor_local.model.save(file_output_train+"actor_local.h5")
    agent.actor_target.model.save(file_output_train+"actor_target.h5")
    agent.critic_local.model.save(file_output_train+"critic_local.h5")
    agent.critic_target.model.save(file_output_train+"critic_target.h5")
    print("Saved model to disk")

"""
# Run in test mode and analyze scores obtained
"""
print("[TEST] Training Done, now running tests...")
test_scores = sim.interact(agent, env, num_episodes=3, mode='test', file_output=file_output_test)
plot_score_from_file(file_output_test, -300, 300, 1)

"""
# Watch Agent
"""
state = env.reset()
score = 0
for t in range(5000):
    # get action from agent
    action = agent.act(state, mode='test')

    # show environment and step it forward
    env.render()
    state, reward, done, _ = env.step(action)
    score += reward
    if done:
        break
print('Final score:', score)

"""
# Exit Environment
"""
#if 0:
env.close()


import json
import socket
import struct
import netifaces
from threading import Thread
from datetime import datetime
from threading import RLock
from json import dumps
from time import sleep
import send_data
import ipaddress
import pygame
from pygame.locals import *
from random import seed
from random import randint

from pygame.locals import (
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
    K_ESCAPE,
    KEYDOWN,
    QUIT,
)

from threading import Thread, RLock
from time import sleep
from json import dumps
import struct
import socket

class HelloSender(Thread):
    def __init__(self, lock, hello_interval, localhost, ttl, mcast_group, mcast_port):
        Thread.__init__(self)
        pygame.init()
        self.window_map = {"fishes" : {}, "players" : {}}
        self.lock           = lock
        self.hello_interval = hello_interval
        self.ttl            = ttl
        self.localhost      = localhost
        self.mcast_group    = mcast_group
        self.mcast_port     = mcast_port
        self.window_width = 600
        self.window_height = 400
        self.screen = pygame.display.set_mode((600, 400))
        self.clock = pygame.time.Clock()
        self.font = pygame.font.Font('/home/core/Desktop/SharkBait/core_pys/parte2/Canterbury.ttf', 32)
        self.img_dict = {}
        self.orientation = [10]
        self.sb_x = 10
        self.sb_y = 10
        # Load Background Image
        self.img_dict[0] = pygame.transform.rotozoom(pygame.image.load("/home/core/Desktop/SharkBait/core_pys/parte2/ocean_background.png").convert(), 0, 1).convert_alpha()

        # Load Fish Image
        fish_img_pre = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/fish_model.png')
        fish_img = pygame.transform.rotozoom(fish_img_pre, 0, 0.06)
        self.img_dict[9] = fish_img.convert_alpha()

        # Load Shark Right
        shark_img_pre_r = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_right.png')
        shark_img_r = pygame.transform.rotozoom(shark_img_pre_r, 0, 0.1)
        shark_img_r.convert_alpha()
        self.img_dict[1] = shark_img_r

        # Load Shark Left
        shark_img_pre_l = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_left.png')
        shark_img_l = pygame.transform.rotozoom(shark_img_pre_l, 0, 0.1)
        shark_img_l.convert_alpha()
        self.img_dict[5] = shark_img_l

        # Load Shark Up
        shark_img_pre_u = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_up.png')
        shark_img_u = pygame.transform.rotozoom(shark_img_pre_u, 0, 0.1)
        shark_img_u.convert_alpha()
        self.img_dict[7] = shark_img_u

        # Load Shark Down
        shark_img_pre_d = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_down.png')
        shark_img_d = pygame.transform.rotozoom(shark_img_pre_d, 0, 0.1)
        shark_img_d.convert_alpha()
        self.img_dict[3] = shark_img_d

        # Load Shark Up Right
        shark_img_pre_ur = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_up_right.png')
        shark_img_ur = pygame.transform.rotozoom(shark_img_pre_ur, 0, 0.14)
        shark_img_ur.convert_alpha()
        self.img_dict[8] = shark_img_ur

        # Load Shark Up Left
        shark_img_pre_ul = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_up_left.png')
        shark_img_ul = pygame.transform.rotozoom(shark_img_pre_ul, 0, 0.14)
        shark_img_ul.convert_alpha()
        self.img_dict[6] = shark_img_ul

        # Load Shark Down Right
        shark_img_pre_dr = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_down_right.png')
        shark_img_dr = pygame.transform.rotozoom(shark_img_pre_dr, 0, 0.14)
        shark_img_dr.convert_alpha()
        self.img_dict[2] = shark_img_dr

        # Load Shark Down Left
        shark_img_pre_dl = pygame.image.load('/home/core/Desktop/SharkBait/core_pys/parte2/img_nobg/shark_model_down_left.png')
        shark_img_dl = pygame.transform.rotozoom(shark_img_pre_dl, 0, 0.14)
        shark_img_dl.convert_alpha()
        self.img_dict[4] = shark_img_dl

    def show_scores(self):

        scores = {}

        for key in self.window_map["players"]:
            value = self.window_map["players"][key]
            scores[key] = value[2]

        i = 0
        for key in scores:
            value = scores[key]
            score = self.font.render(f"{key} : {str(value)}", True, (0, 0, 0))
            self.screen.blit(score, (self.sb_x, self.sb_y + i*20))
            i += 1

    def set_title(self, title):
        pygame.display.set_caption(title)

    def draw(self):

        self.screen.blit(self.img_dict[0], [0, 0])

        for key in self.window_map["fishes"]:
            value = self.window_map["fishes"][key]
            self.screen.blit(self.img_dict[9], value)

        print(f'MAPA DE JOGADORES::::{self.window_map}')

        for key in self.window_map["players"]:
            value = self.window_map["players"][key]
            orientation = value[3]
            self.screen.blit(self.img_dict[orientation], [value[0], value[1]])

        self.show_scores()

        pygame.display.flip()
        self.clock.tick(2)

    def set_window_map(self, gs):
        self.window_map = gs

    def create_socket(self):

        try:
            # Criar o socket do client
            client_sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
            client_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_HOPS, self.ttl)
            client_sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, False)

            return client_sock

        except Exception as sock_error:
            print('Failed to create socket: {}'.format(sock_error))

    def hello_sender(self):
        try:
            client_sock = self.create_socket()

                # Messagem a ser enviada
            self.msg = {
                "type": "Request",
                "source": self.localhost,
                "destination" : "2001:0::10",
                "data" : self.orientation
            }

                #print('Sending multicast message to the multicast group ...')
                #print(self.msg)
            client_sock.sendto(dumps(self.msg).encode('utf-8'), (self.mcast_group,self.mcast_port))

        except socket.gaierror as socket_error:
            print('Sending error: {}'.format(socket_error))

        finally:
            client_sock.close()

    def send_request(self):
        self.lock.acquire()
        try:
            self.hello_sender()
            self.window_map = host_movel.get_window_map()

        except Exception as e:
            print('Failed: {}'.format(e.with_traceback()))

        finally:
            self.lock.release()
            print(f'GAME MAP: {self.window_map}')

    def run(self):
        running = True
        while running == True:
            keys = pygame.key.get_pressed()
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

                elif event.type == KEYDOWN:

                    if event.key == K_RIGHT:
                        self.orientation[0] = 1

                    elif event.key == K_LEFT:
                        self.orientation[0] = 5

                    elif event.key == K_UP:
                        self.orientation[0] = 7

                    elif event.key == K_DOWN:
                        self.orientation[0] = 3

                    if event.key == K_UP and keys[K_RIGHT] != False:
                        self.orientation[0] = 8

                    elif event.key == K_UP and keys[K_LEFT] != False:
                        self.orientation[0] = 6

                    elif event.key == K_DOWN and keys[K_RIGHT] != False:
                        self.orientation[0] = 2

                    elif event.key == K_DOWN and keys[K_LEFT] != False:
                        self.orientation[0] = 4

                    elif event.key == K_RIGHT and keys[K_UP] != False:
                        self.orientation[0] = 8

                    elif event.key == K_LEFT and keys[K_UP] != False:
                        self.orientation[0] = 6

                    elif event.key == K_RIGHT and keys[K_DOWN] != False:
                        self.orientation[0] = 2

                    elif event.key == K_LEFT and keys[K_DOWN] != False:
                        self.orientation[0] = 4

                elif event.type == KEYUP:

                    if event.key == K_LEFT and keys[K_UP] != False:
                        self.orientation[0] = 7

                    elif event.key == K_UP and keys[K_LEFT] != False:
                        self.orientation[0] = 5

                    elif event.key == K_UP and keys[K_RIGHT] != False:
                        self.orientation[0] = 1

                    elif event.key == K_RIGHT and keys[K_UP] != False:
                        self.orientation[0] = 7

                    elif event.key == K_DOWN and keys[K_LEFT] != False:
                        self.orientation[0] = 5

                    elif event.key == K_LEFT and keys[K_DOWN] != False:
                        self.orientation[0] = 3

                    elif event.key == K_DOWN and keys[K_RIGHT] != False:
                        self.orientation[0] = 1

                    elif event.key == K_RIGHT and keys[K_DOWN] != False:
                        self.orientation[0] = 3

                else:
                    self.orientation[0] = 10

            if(self.orientation[0] != 10):
                self.send_request()
            self.draw()
#_________________________________________________________

class Host_Movel():

    def __init__(self, localhost, mcast_group, mcast_port, dead_interv, hello_interval):
        Thread.__init__(self)
        self.window_map = {"fishes" : {}, "players" : {}}
        self.mcast_group = mcast_group
        self.mcast_port = mcast_port
        self.dead_interv = dead_interv
        self.hello_interval = hello_interval
        self.lock = RLock()
        self.mcast_ttl = 1
        self.local_ip = localhost
        self.ttl = struct.pack('@i', self.mcast_ttl)
        self.addrinfo = socket.getaddrinfo(self.mcast_group, None, socket.AF_INET6)[0]

    def create_socket(self):
        self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
        self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, False)

    def listen(self):
        # abre porta 6666
        #self.sock.bind(('', self.mcast_port))
        mc_address = ipaddress.IPv6Address('ff02::abcd:1')
        listen_port = 6666
        interface_index = socket.if_nametoindex('eth0')
        self.sock.bind((str(mc_address), listen_port, 0, interface_index))

        # Join Multicast Group
        #member_request = struct.pack("16s15s".encode('utf-8'), socket.inet_pton(socket.AF_INET6, self.mcast_group), (chr(0) * 16).encode('utf-8'))
        self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_MULTICAST_LOOP, False)
        member_request = struct.pack("16sI".encode('utf-8'), socket.inet_pton(socket.AF_INET6, self.mcast_group), socket.INADDR_ANY)
        self.sock.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, member_request)

    def send_data(self,msg):
        send_data.send(msg, self.mcast_group, self.mcast_port)
        print(f'message of type {msg["type"]} sent to ({self.mcast_group},{self.mcast_port})')

    def hello_handler(self,msg):
        test_print = msg['type'] + " from: " + msg['source']
        print(test_print)

    def get_window_map(self):
        return self.window_map

    def receive(self):

        print("my ipv6: " + self.local_ip)

        while True:

            data, addr = self.sock.recvfrom(1024)

            rcv_msg = json.loads(data.decode('utf-8'))

            print(f'Message {rcv_msg} received from {addr[0]}')

            #receive_handler = Receive_Handler(self.lock, rcv_msg, self.local_ip, self.mcast_group, self.mcast_port)

            #receive_handler.start()

            try:
                self.lock.acquire()
                if rcv_msg["type"] == "Request" and rcv_msg["source"] != self.local_ip:
                    self.send_data(rcv_msg)

                elif rcv_msg["type"] == "Reply":
                    if rcv_msg["destination"]!= self.local_ip:
                        self.send_data(rcv_msg)
                        print("recebi do servidor")
                    self.window_map = rcv_msg["data"]

            finally:
                self.lock.release()

    def send(self):

        hello_sender = HelloSender(self.lock, self.hello_interval, self.local_ip, self.mcast_ttl, self.mcast_group, self.mcast_port)

        hello_sender.start()

    def main(self):
        self.create_socket()
        self.listen()
        self.send()
        self.receive()

def get_ip():
        ipv6 = netifaces.ifaddresses('eth0')

        return ipv6[netifaces.AF_INET6][0]['addr']
        return '::1'

host_movel = Host_Movel(localhost=get_ip(), mcast_group='ff02::abcd:1', mcast_port=6666, hello_interval=2, dead_interv=8)
host_movel.main()


'''
Quora Questions Data ... Download train.csv from: https://www.kaggle.com/c/quora-question-pairs/data
'''
from sys import argv
import gensim
import pandas as pd

filename = argv[1]
output   = argv[2]
df       = pd.read_csv(filename)

def read_questions(row,column_name):
    return gensim.utils.simple_preprocess(str(row[column_name]).encode('utf-8'))

with open(output, 'w') as fp:
    for index, row in df.iterrows():
        question = " ".join(read_questions(row, "question1"))
        fp.write("{}\n".format(question))
        if row["is_duplicate"] == 0:
            question = " ".join(read_questions(row, "question2"))
            fp.write("{}\n".format(question))


import os

import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')

def test_eclipse_config(host):
    cfg_line = host.check_output("grep -r Xmx /opt/eclipse-oxygen-4.7/eclipse/eclipse.ini")
    assert "-Xmx2048m" in cfg_line

def test_hosts_file(host):
    f = host.file('//usr/share/applications/eclipse-oxygen-4.7.desktop')

    assert f.exists
    assert f.user == 'root'
    assert f.group == 'root'


import datetime
import os

from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator
from django.db import models
from django.dispatch import receiver
from django.urls import reverse
from django.utils import timezone
from django.utils.translation import gettext_lazy as _

from lib.functions.custom_functions import truncate
from lib.functions.custom_functions import fiscal_year
from lib.templatetags.custom_filters import nz
from shared_models import models as shared_models
from masterlist import models as ml_models
from sar_search import models as sar_models

class Status(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))
    color = models.CharField(max_length=15, blank=True, null=True)
    old_id = models.IntegerField(blank=True, null=True)
    description_text = models.CharField(max_length=250, blank=True, null=True)

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class Program(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))
    abbrev_eng = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("abbreviation (French)"))
    abbrev_fre = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("abbreviation (French)"))

    def __str__(self):
        # # check to see if a french value is given
        # if getattr(self, str(_("name"))):
        #     return "{}".format(getattr(self, str(_("name"))))
        # # if there is no translated term, just pull from the english field
        # else:
        #     return "{}".format(self.name)
        return "{} ({})".format(self.name, self.abbrev_eng)

    @property
    def full_eng(self):
        return "{} ({})".format(self.name, self.abbrev_eng)

    @property
    def full_fre(self):
        return "{} ({})".format(self.nom, self.abbrev_fre)

    class Meta:
        ordering = [_('name'), ]

class RiskAssessmentScore(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class InitiationType(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class PriorityAreaOrThreat(models.Model):
    # choices for type
    THREAT = 1
    PRIORITY = 2
    SPECIES = 3
    TYPE_CHOICES = (
        (THREAT, _("Threat")),
        (PRIORITY, _("Priority area")),
        (SPECIES, _("Priority species")),
    )
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))
    type = models.IntegerField(blank=True, null=True, choices=TYPE_CHOICES)

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{} ({})".format(
                getattr(self, str(_("name"))),
                self.get_type_display(),
            )
        # if there is no translated term, just pull from the english field
        else:
            return "{} ({})".format(self.name, self.get_type_display())

    class Meta:
        ordering = ['type', _('name'), ]

def draft_ca_file_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/entry_<id>/<filename>
    suffix = filename.split(".")[1]
    return 'spot/{0}/{0}_draft_contribution_agreement.{1}'.format(instance.id, suffix)

class Activity(models.Model):
    #choices for habitat
    FW = 1
    MAR =2
    HABITAT_CHOICES = (
        (FW, _("Freshwater")),
        (MAR, _("Marine")),
    )

    program = models.ForeignKey(Program, on_delete=models.DO_NOTHING, related_name="activities", verbose_name=_("funding program"),
                                blank=True, null=True)
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))
    habitat = models.IntegerField(blank=True, null=True, choices=HABITAT_CHOICES)
    category_eng = models.CharField(max_length=1000, verbose_name=_("category/type (English)"))
    category_fre = models.CharField(max_length=1000, blank=True, null=True, verbose_name=_("category/type (French)"))

    def __str__(self):
        # check to see if a french value is given
        my_str = "{}".format(getattr(self, str(_("category_eng"))))

        if self.habitat:
            my_str += " ({}) - ".format(self.get_habitat_display())
        else:
            my_str += " - "

        my_str +=  "{}".format(getattr(self, str(_("name"))))
        return my_str

    class Meta:
        ordering = ["program", _('category_eng'), _('name'), ]

class DrainageBasin(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class Watershed(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))
    province = models.ForeignKey(shared_models.Province, on_delete=models.DO_NOTHING, related_name="watersheds")
    drainage_basin = models.ForeignKey(DrainageBasin, on_delete=models.DO_NOTHING, related_name="watersheds")
    notes = models.CharField(max_length=1000, blank=True, null=True, verbose_name=_("notes"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}, {} ({})".format(getattr(self, str(_("name"))), self.province.tabbrev, self.drainage_basin)
        # if there is no translated term, just pull from the english field
        else:
            return "{}, {} ({})".format(self.name, self.province.tabbrev, self.drainage_basin)

    class Meta:
        ordering = [_('name'), ]

class Project(models.Model):
    path_number = models.CharField(max_length=50, blank=True, null=True, verbose_name=_("DFO PATH #"))
    program_reference_number = models.CharField(max_length=50, blank=True, null=True)
    organization = models.ForeignKey(ml_models.Organization, on_delete=models.DO_NOTHING, related_name="projects")
    program = models.ForeignKey(Program, on_delete=models.DO_NOTHING, related_name="projects", verbose_name=_("funding program"))
    status = models.ForeignKey(Status, on_delete=models.DO_NOTHING, related_name="projects", default=1, verbose_name=_("project status"))
    regions = models.ManyToManyField(shared_models.Region, default=1, verbose_name=_("DFO regions"))
    start_year = models.ForeignKey(shared_models.FiscalYear, on_delete=models.DO_NOTHING, related_name="gc_projects",
                                   default=fiscal_year(sap_style=True, next=True))
    project_length = models.IntegerField(blank=True, null=True)
    date_completed = models.DateTimeField(blank=True, null=True)
    summary = models.TextField(blank=True, null=True, verbose_name=_("summary"))
    old_id = models.IntegerField(blank=True, null=True)
    eccc_id = models.CharField(max_length=50, blank=True, null=True)

    ## Initiation
    language = models.ForeignKey(shared_models.Language, on_delete=models.DO_NOTHING, related_name="projects",
                                 verbose_name=_("project language"))
    title = models.TextField()
    title_abbrev = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("title abbreviation"))
    initiation_date = models.DateTimeField(blank=True, null=True, default=timezone.now)
    initiation_type = models.ForeignKey(InitiationType, on_delete=models.DO_NOTHING, related_name="projects", blank=True, null=True,
                                        verbose_name=_("type of initiation"))
    priority_area_or_threats = models.ManyToManyField(PriorityAreaOrThreat, related_name="projects", blank=True,
                                                      verbose_name=_("priority areas or threats"))
    initiation_acknowledgement_sent = models.DateTimeField(blank=True, null=True, verbose_name=_("acknowledgement email sent"))
    requested_funding_y1 = models.FloatField(blank=True, null=True, verbose_name=_("requested funding (year 1)"))
    requested_funding_y2 = models.FloatField(blank=True, null=True, verbose_name=_("requested funding (year 2)"))
    requested_funding_y3 = models.FloatField(blank=True, null=True, verbose_name=_("requested funding (year 3)"))
    requested_funding_y4 = models.FloatField(blank=True, null=True, verbose_name=_("requested funding (year 4)"))
    requested_funding_y5 = models.FloatField(blank=True, null=True, verbose_name=_("requested funding (year 5)"))
    overview = models.TextField(blank=True, null=True, verbose_name=_("project overview"))

    ## Regional Review
    regional_score = models.FloatField(blank=True, null=True, verbose_name=_("regional score"))
    rank = models.IntegerField(blank=True, null=True, verbose_name=_("project rank"))
    application_submission_date = models.DateTimeField(blank=True, null=True, verbose_name=_("Date/time of application submission"))
    submission_accepted = models.NullBooleanField(verbose_name=_("was the submission accepted?"))
    notes = models.TextField(blank=True, null=True, verbose_name=_("project notes"))
    recommended_funding_y1 = models.FloatField(blank=True, null=True, verbose_name=_("recommended funding amount - Year 1"))
    recommended_funding_y2 = models.FloatField(blank=True, null=True, verbose_name=_("recommended funding amount - Year 2"))
    recommended_funding_y3 = models.FloatField(blank=True, null=True, verbose_name=_("recommended funding amount - Year 3"))
    recommended_funding_y4 = models.FloatField(blank=True, null=True, verbose_name=_("recommended funding amount - Year 4"))
    recommended_funding_y5 = models.FloatField(blank=True, null=True, verbose_name=_("recommended funding amount - Year 5"))
    recommended_overprogramming = models.FloatField(blank=True, null=True, verbose_name=_("recommended amount for over-programming"))
    regrets_or_op_letter_sent_date = models.DateTimeField(blank=True, null=True,
                                                          verbose_name=_("client notification sent (OP or Regrets only)"))

    ## Negotiations
    risk_assessment_score = models.ForeignKey(RiskAssessmentScore, on_delete=models.DO_NOTHING, related_name="projects", blank=True,
                                              null=True)
    negotiations_workplan_completion_date = models.DateTimeField(blank=True, null=True, verbose_name=_("negotiation workplan complete"))
    negotiations_financials_completion_date = models.DateTimeField(blank=True, null=True, verbose_name=_("negotiation financials complete"))
    negotiation_letter_sent = models.DateTimeField(blank=True, null=True, verbose_name=_("negotiation letter sent to client"))

    ## CA Assembly
    schedule_5_complete = models.DateTimeField(blank=True, null=True, verbose_name=_("schedule 5 is complete"))
    advance_payment = models.BooleanField(default=True, verbose_name=_("will this project receive an advance payment?"))
    draft_ca_sent_to_proponent = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA sent to client"))
    draft_ca_proponent_approved = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA approved by client"))
    draft_ca_ready = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA ready"))
    ## CA Checklist stuff
    draft_ca_sent_to_manager = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA sent to manager"))
    draft_ca_manager_approved = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA approved by manager"))
    draft_ca_sent_to_nhq = models.DateTimeField(blank=True, null=True, verbose_name=_("draft CA sent to NHQ"))
    aip_received = models.DateTimeField(blank=True, null=True, verbose_name=_("approve-in-principal (AIP) received"))
    final_ca_received = models.DateTimeField(blank=True, null=True, verbose_name=_("final CA received from NHQ"))
    final_ca_sent_to_proponent = models.DateTimeField(blank=True, null=True, verbose_name=_("final CA sent to client"))
    final_ca_proponent_signed = models.DateTimeField(blank=True, null=True, verbose_name=_("final CA signed by client"))
    final_ca_sent_to_nhq = models.DateTimeField(blank=True, null=True, verbose_name=_("final CA sent to HNQ"))
    advance_payment_sent_to_nhq = models.DateTimeField(blank=True, null=True, verbose_name=_("advance payment sent to NHQ"))
    final_ca_nhq_signed = models.DateTimeField(blank=True, null=True, verbose_name=_("final CA signed by NHQ"))

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"),
                                         related_name="gc_projects")
    people = models.ManyToManyField(ml_models.Person, through="ProjectPerson", blank=True)
    activities = models.ManyToManyField(Activity, blank=True, verbose_name=_("activities"))
    spp = models.ManyToManyField(sar_models.Species, blank=True, verbose_name=_("species"))
    watersheds = models.ManyToManyField(Watershed, blank=True, verbose_name=_("watersheds"))

    def __str__(self):
        return "{} ({})".format(truncate(self.title, 50), self.organization.abbrev)

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()

        # determine status
        self.status_id = determine_project_status(self)

        # determine length
        self.project_length = determine_project_length(self, self.status_id)

        return super().save(*args, **kwargs)

    class Meta:
        ordering = ["-start_year", "program"]

    @property
    def total_requested_funding(self):
        return sum([
            nz(self.requested_funding_y1, 0),
            nz(self.requested_funding_y2, 0),
            nz(self.requested_funding_y3, 0),
            nz(self.requested_funding_y4, 0),
            nz(self.requested_funding_y5, 0),
        ])

    @property
    def total_recommended_funding(self):
        return sum([
            nz(self.recommended_funding_y1, 0),
            nz(self.recommended_funding_y2, 0),
            nz(self.recommended_funding_y3, 0),
            nz(self.recommended_funding_y4, 0),
            nz(self.recommended_funding_y5, 0),
        ])

    @property
    def total_project_funding(self):
        if self.years:
            return sum([nz(f.annual_funding, 0) for f in self.years.all()])
        else:
            return 0

    @property
    def negotiation_completion_date(self):
        """ this will be the max of negotiations_workplan_completion_date and negotiations_financials_completion_date"""
        return max(self.negotiations_workplan_completion_date, self.negotiations_financials_completion_date)

    @property
    def end_year(self):
        return self.years.order_by("fiscal_year").last().fiscal_year.full

    # PEOPLE
    @property
    def pp(self):
        return self.project_people.get(role=1).person

    @property
    def gc_officer(self):
        return self.project_people.get(role=7).person

    # FILES
    @property
    def application_file(self):
        return File.objects.get(project=self, file_type_id=6)

    @property
    def project_evaluation_file(self):
        return File.objects.get(project=self, file_type_id=8)

    @property
    def risk_assessment_file(self):
        return File.objects.get(project=self, file_type_id=4)

    @property
    def draft_ca_file(self):
        return File.objects.get(project=self, file_type_id=1)

    @property
    def fully_signed_ca_file(self):
        return File.objects.get(project=self, file_type_id=2)

class Role(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("Name (French)"))
    order = models.IntegerField(blank=True, null=True)

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('order'), ]

class ProjectPerson(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="project_people")
    person = models.ForeignKey(ml_models.Person, on_delete=models.DO_NOTHING, related_name="project_people")
    role = models.ForeignKey(Role, on_delete=models.DO_NOTHING, related_name="project_people")

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

    class Meta:
        unique_together = ['project', 'person', 'role']
        ordering = ['project', 'role', 'person']

class ContributionAgreementChecklist(models.Model):
    project = models.OneToOneField(Project, on_delete=models.CASCADE, related_name="ca_checklist")
    date_assessed = models.DateTimeField(blank=True, null=True, default=timezone.now)
    risk_assessment_complete = models.NullBooleanField(verbose_name=_("The risk assessment has been completed/approved and posted to PATH"))
    correct_clause_selected = models.NullBooleanField(
        verbose_name=_("The clauses selected in the CA reflect the risk level and contribution amount"))
    formatting_correct = models.NullBooleanField(verbose_name=_("There are no hanging/orphan lines/titles"))
    amounts_correct = models.NullBooleanField(verbose_name=_(
        "The annual contribution amount(s) (3.1) match(es) the budget in Schedule 5 and do(es) not exceed the amount(s) approved by the Minister"))
    clear_language = models.NullBooleanField(
        verbose_name=_("Schedule 5: Language is clear, concise and can be generally understood by someone who is not a specialist"))
    acronyms_defined = models.NullBooleanField(verbose_name=_("Schedule 5: Acronyms are defined upon first use"))
    activities_elibigle = models.NullBooleanField(verbose_name=_("Schedule 5: All Activities/tasks are eligible"))
    detail_commensurate_with_budget = models.NullBooleanField(
        verbose_name=_("Schedule 5: The level of detail for each Activity (i.e., task description) is commensurate with its budget"))
    realistic_timeframe = models.NullBooleanField(
        verbose_name=_("Schedule 5: Each Activity can be reasonably expected to be completed within its accorded timeframe"))
    key_tasks_outlined = models.NullBooleanField(
        verbose_name=_("Schedule 5: All key tasks required to be undertaken for each Activity to be achieved are outlined"))
    deliverables = models.NullBooleanField(verbose_name=_(
        "Schedule 5: All Activities/tasks have associated deliverables that will demonstrate that the former were completed as planned and as budgeted"))
    project_budgets_adds_up = models.NullBooleanField(
        verbose_name=_("Schedule 5: The sum of all individual project Activity budgets adds up to the agreement total"))
    sufficient_budget_detail = models.NullBooleanField(
        verbose_name=_("Schedule 5: Sufficient budget details have been provided to confirm that the costs are eligible and reasonable"))
    expenses_eligible = models.NullBooleanField(verbose_name=_("Schedule 5: All expenses are eligible"))
    reasonable_costs = models.NullBooleanField(verbose_name=_("Schedule 5: All costs are reasonable"))
    budget_adds_up = models.NullBooleanField(verbose_name=_("Schedule 5: The budget adds up correctly."))
    maximum_amounts_set = models.NullBooleanField(verbose_name=_(
        "Schedule 5: If applicable, maximum amounts for expense categories have been set (i.e., identified with an asterisk (*))."))
    budget_reflects_activity = models.NullBooleanField(verbose_name=_("Schedule 5: The budget reflects the nature of the Activity(ies)."))
    stacking_limits_respected = models.NullBooleanField(
        verbose_name=_("Schedule 5: The federal and stacking limit have been respected, based on confirmed funding."))
    no_funding_redundancy = models.NullBooleanField(verbose_name=_(
        "Schedule 5: The activities and budget items have been cross-checked against DFO Aboriginal program CAs (e.g., SPI-FHRI, AAROM, AFSAR) to ensure no funding redundancy."))
    stacking_identified = models.NullBooleanField(verbose_name=_(
        "Schedule 5: Funding directly related to the RFCPP project coming from DFO Aboriginal programs has been included in the federal and stacking support."))
    confirmation_letters_2_path = models.NullBooleanField(verbose_name=_(
        "Schedule 5: Confirmation letters for all confirmed cash support have been posted to PATH.  Confirmation letters for large amount/potentially inflated in-kind support have also been posted to PATH."))
    financial_information_2_path = models.NullBooleanField(
        verbose_name=_("Schedule 5: Financial information has been updated/entered in PATH as per Data Entry Procedures"))
    conflict_of_interest_assessed = models.NullBooleanField(verbose_name=_(
        "Schedule 5: If a current or former federal public servant is involved in the project, a conflict of interest assessment has been completed (conflict of interest assessment tool found in CA checklist folder in national shared folder) and conflicts, if any, have been addressed, as appropriate."))
    # Schedule 6
    cashflow_adds_up = models.NullBooleanField(
        verbose_name=_("Schedule 6: The cash flow adds up correctly and reflects the timing of Activities."))
    # Schedule 7
    pre_filled_sched7 = models.NullBooleanField(verbose_name=_("Schedule 7: is pre-filled and mirrors Schedule 5"))
    performance_measures_in_path = models.NullBooleanField(verbose_name=_(
        "Schedule 7: Performance measures are updated in the ‘Planned’ column of the performance tab in PATH as per Data Entry Procedures"))
    # General
    team_leader_reviewed = models.NullBooleanField(verbose_name=_("The Team Leader has reviewed and approves the CA"))
    comment_for_nhq = models.TextField(verbose_name=_("Comments for NHQ"), blank=True, null=True)
    review_completion_date = models.DateTimeField(blank=True, null=True)
    # completed_by = models.ForeignKey(User, on_delete=models.DO_NOTHING)

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"),
                                         related_name="ca_checklist_last_mods")

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

class ExpressionOfInterest(models.Model):
    project = models.OneToOneField(Project, on_delete=models.CASCADE, related_name="eoi")
    date_received = models.DateTimeField(blank=True, null=True, verbose_name=_("date received"))
    description = models.TextField(blank=True, null=True, verbose_name=_("description"))
    coordinator_notified = models.DateTimeField(blank=True, null=True, verbose_name=_("coordinator was notified"))
    project_eligible = models.NullBooleanField(verbose_name=_("is the project eligible?"))
    feedback = models.TextField(blank=True, null=True, verbose_name=_("Feedback to client"))
    feedback_sent = models.DateTimeField(blank=True, null=True, verbose_name=_("feedback sent to client"))

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

    @property
    def file(self):
        return File.objects.get(project=self.project, file_type_id=3)

    @property
    def eoi_evaluation_file(self):
        return File.objects.get(project=self.project, file_type_id=7)

class ProjectYear(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name="years", verbose_name=_("project language"))
    fiscal_year = models.ForeignKey(shared_models.FiscalYear, on_delete=models.DO_NOTHING, related_name="gc_project_years")
    expenditure_initiation_date = models.DateTimeField(blank=True, null=True, default=datetime.datetime(timezone.now().year, 4, 1))
    paye_number = models.CharField(max_length=50, blank=True, null=True)
    annual_funding = models.FloatField(blank=True, null=True)
    forecasting_notes = models.TextField(blank=True, null=True)
    yearend_reminder_sent = models.DateTimeField(blank=True, null=True)
    lapsing_funds = models.NullBooleanField()
    lapsing_funds_nhq_notified = models.DateTimeField(blank=True, null=True)
    funding_recovery_needed = models.NullBooleanField()
    funding_recovery_email_sent = models.DateTimeField(blank=True, null=True)
    funds_recovered = models.NullBooleanField()
    year_complete = models.DateTimeField(blank=True, null=True)

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def __str__(self):
        return "FY {}".format(self.fiscal_year)

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

    class Meta:
        unique_together = ['project', 'fiscal_year']
        ordering = ["project", "fiscal_year"]

    @property
    def payments_issued(self):
        return sum([p.disbursement for p in self.payments.all()])

class ReportType(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class Report(models.Model):
    project_year = models.OneToOneField(ProjectYear, on_delete=models.DO_NOTHING, related_name="reports")
    report_type = models.ForeignKey(ReportType, on_delete=models.DO_NOTHING, related_name="reports")
    date_received = models.DateTimeField(blank=True, null=True, default=timezone.now)
    coordinator_notified = models.DateTimeField(blank=True, null=True)
    coordinator_approved = models.DateTimeField(blank=True, null=True)
    gc_officer_approved = models.DateTimeField(blank=True, null=True)
    manager_approved = models.DateTimeField(blank=True, null=True)
    nhq_notified = models.DateTimeField(blank=True, null=True)

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

class ReportChecklist(models.Model):
    report = models.OneToOneField(Report, on_delete=models.DO_NOTHING, related_name="report_checklist")
    recommended_payment_amount = models.FloatField(verbose_name=_("Recommended Payment Amount"))
    # Schedule 7 - General
    sounds_sched7 = models.NullBooleanField(
        verbose_name=_("Schedule 7 matches the one in the signed CA and all sections have been duly filled in."))
    accurate_reporting_period = models.NullBooleanField(verbose_name=_(
        "Reporting period: Where this is the first report submitted by a recipient under the CA, the reporting period commences on the day that RFCPP-funded activities first started taking place."))
    no_missing_period = models.NullBooleanField(verbose_name=_(
        "Reporting period: Where a previous report has been submitted by the recipient under the CA, the reporting period for this report commences the day after the end of the previous reporting period."))

    # Schedule 7 – Section 1
    matching_funds = models.NullBooleanField(verbose_name=_("The “RFCPP funds received year to date” matches the amount in RFCPP records."))
    summed_correctly = models.NullBooleanField(verbose_name=_("Amounts in Table 1.1 are summed correctly."))
    budgeted_amounts_not_exceeded = models.NullBooleanField(
        verbose_name=_("Claimed expenses for expense categories tagged with an asterisk (*) do not exceed the budgeted amount."))
    tab11_no_issues = models.NullBooleanField(verbose_name=_(
        "The amounts reported in Table 1.1 raise no issues and align with the timing of Activities in Schedule 5 and the reporting period."))
    reimbursable_taxes_not_claimed = models.NullBooleanField(
        verbose_name=_("Reimbursable taxes have not been claimed (see application form for percentages reimbursable)."))
    tab12_filled = models.NullBooleanField(verbose_name=_(
        "Table 1.2 has been filled in where budgeted amounts exceed the allowed deviation: a) If the deviation was previously approved by DFO: no action required. b) If the deviation was not previously approved by DFO: review the reason for the deviation and recommend to NHQ (when submitting the report for payment) whether or not the over-expenditure(s) should be reimbursed.  Whether the over-expenditures are reimbursed or not, the recipient must be informed that as per the CA (Sch. 5 s. 6.3) requests for budget reallocations in excess of the set percentage must be submitted to DFO prior to deviating from planned expenditures."))
    confirmation_letters = models.NullBooleanField(verbose_name=_(
        "Confirmation letters for all previously unconfirmed cash support and large in-kind support have been received and posted to PATH (applies to multi-year agreements with supplemental conditions for unconfirmed support)."))
    support_matches = models.NullBooleanField(verbose_name=_(
        "Support received matches what was detailed in the CA. If different, then no effect on federal and stacking limits has been confirmed."))
    actuals_entered = models.NullBooleanField(
        verbose_name=_("All financial information has been entered in the ‘Actual’ section of the financial tab in PATH."))

    # Schedule 7 – Section 2
    deliverables_check_out = models.NullBooleanField(
        verbose_name=_("The status of deliverables matches the claimed expenses and timing of Activities in Schedule 5."))
    invoices_check_out = models.NullBooleanField(verbose_name=_(
        "Where invoices were provided as deliverables, the total(s) of the invoices match what is reported/claimed in Section 1, Table 1.1."))
    sufficient_detail = models.NullBooleanField(verbose_name=_(
        "The quality/level of detail of the deliverables provided is sufficient to recommend payment under s. 34 of the Financial Administration Act (i.e., sufficient information has been provided to justify payment)."))
    tab22_complete = models.NullBooleanField(verbose_name=_(
        "Where Table 2.2 has been filled in: a) Determine whether the explanation may impact the payment amount being requested by the recipient - address with NHQ when submitting the report for payment. b) Determine whether an amendment may be required – address with NHQ when submitting the report for payment (does not apply to final reports). c) Determine whether as a result of cancelled/delayed activities the stacking limit may be exceeded.  If so, the recipient must confirm the actual amounts received from other sources.  If the stacking limit was/will be exceeded, the RFCPP recommended payment must be reduced accordingly to ensure that the staking limit is met."))
    compliant_signage = models.NullBooleanField(verbose_name=_("RFCPP signage follows the RFCPP-FIP Guidelines"))

    # Schedule 7 – Section 3
    tab31_actuals = models.NullBooleanField(verbose_name=_("The “actuals” in Table 3.1 align with the activities and budget table."))
    tab32_complete = models.NullBooleanField(verbose_name=_(
        "All capital acquisitions purchased have been included in Table 3.2 (and align with the costs identified in the budget table)."))
    section3_path_recored = models.NullBooleanField(
        verbose_name=_("All information provided in Section 3 has been recorded in PATH (for final/annual reports only)."))

    # Schedule 7 – Section 4
    section4_signed = models.NullBooleanField(verbose_name=_(
        "Section 4 has been signed by an authorised representative of the Recipient (does not need to be the CA signatory)."))

    # Regional Approval
    sched7_to_path = models.NullBooleanField(
        verbose_name=_("Schedule 7 and all supporting documents (e.g., deliverables) have been posted to PATH."))
    sched6_to_path = models.NullBooleanField(
        verbose_name=_("If a multi-year agreement, Schedule 6 for next year has been received and posted to PATH."))
    site_visit_summary_provided = models.NullBooleanField(
        verbose_name=_("If a site visit was completed for the CA, a summary thereof is provided in the comments section below."))
    team_leader_reviewed = models.NullBooleanField(
        verbose_name=_("The Team Leader has reviewed and approved the recipient report and recommends payment."))

    comments = models.TextField(blank=True, null=True)
    calculations_recommended_payment = models.TextField(blank=True, null=True, verbose_name=_("calculations for recommended payment"))
    review_completion_date = models.DateTimeField(blank=True, null=True)
    completed_by = models.ForeignKey(User, on_delete=models.DO_NOTHING)

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"),
                                         related_name="report_checklist_mods")

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

class RestorationTypeCategory(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class RestorationType(models.Model):
    restoration_type_category = models.ForeignKey(RestorationTypeCategory, on_delete=models.DO_NOTHING, related_name="types")
    name = models.TextField(verbose_name=_("name (English)"))
    nom = models.TextField(blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class SiteType(models.Model):
    name = models.TextField(verbose_name=_("name (English)"))
    nom = models.TextField(blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class Site(models.Model):
    project = models.ForeignKey(Project, on_delete=models.DO_NOTHING, related_name="sites")
    name = models.CharField(max_length=255, verbose_name=_("site name"))
    site_type = models.ForeignKey(SiteType, on_delete=models.DO_NOTHING, related_name="sites", verbose_name=_("site type"))
    lat = models.FloatField(max_length=255, verbose_name=_("latitude (DD.dddddd)"), blank=True, null=True)
    long = models.FloatField(max_length=255, verbose_name=_("longitude (DD.dddddd)"), blank=True, null=True, validators=[MaxValueValidator(0),])
    restoration_type = models.ForeignKey(RestorationType, on_delete=models.DO_NOTHING, related_name="sites", verbose_name=_("restoration type (optional)"), blank=True, null=True)
    width = models.CharField(max_length=255, verbose_name=_("width (optional)"), blank=True, null=True)
    depth = models.CharField(max_length=255, verbose_name=_("depth (optional)"), blank=True, null=True)
    substrate = models.CharField(max_length=255, verbose_name=_("substrate (optional)"), blank=True, null=True)
    comments = models.TextField(verbose_name=_("comments"), blank=True, null=True)

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class SiteVisit(models.Model):
    project_year = models.OneToOneField(ProjectYear, on_delete=models.DO_NOTHING, related_name="site_visits")
    date_of_visit = models.DateTimeField(blank=True, null=True, default=timezone.now)
    personnel_1 = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="site_visits_per1")
    personnel_2 = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name="site_visits_per2")

    # QUARTERLY DOCUMENTED ROUTINE REVIEW (REQUIRED)
    c1 = models.NullBooleanField(verbose_name=_(
        "C.1 Was the work completed as proposed in the CA (activities/tasks, timing and budget)? If not, is an amendment or note-to-file required? Provide details."))
    c1_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.1 comments"))

    c2 = models.NullBooleanField(verbose_name=_(
        "C.2 Are there any challenges affecting delivery of the project (e.g., contractors/personnel issues, required permits, site conditions)? If so, provide details."))
    c2_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.2 comments"))

    c3 = models.NullBooleanField(verbose_name=_("C.3 Was the sign installed?  If not, provide details."))
    c3_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.3 comments"))

    c4 = models.NullBooleanField(verbose_name=_("C.4 Were photos taken? If so, ensure that photos are posted to PATH."))
    c4_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.4 comments"))

    c5 = models.NullBooleanField(verbose_name=_(
        "C.5 Is a follow up site visit (or other follow-up) required? If yes, describe reasons for requiring follow-up, the type of follow-up, and when it is to occur."))
    c5_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.5 comments"))

    # PROGRAM IMPROVEMENT (REQUIRED)
    c6 = models.NullBooleanField(verbose_name=_(
        "C.6 Does the group have any feedback on the Program (positive feedback or suggested improvements)?  Provide details."))
    c6_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.6 comments"))

    # PROJECT EVALUATION (OPTIONAL)
    c7 = models.NullBooleanField(verbose_name=_("C.7 Were the structure(s)/works designed/installed properly?  If not, provide details."))
    c7_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.7 comments"))

    c8 = models.NullBooleanField(
        verbose_name=_("C.8 Did the work address the key issues at the site / is it functioning as intended? If not, provide details."))
    c8_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.8 comments"))

    c9 = models.NullBooleanField(verbose_name=_("C.9 Are recreational fish using the site/have access to the site?"))
    c9_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.9 comments"))

    c10 = models.NullBooleanField(verbose_name=_("C.10 Are there concerns with any aspect of the work? If yes, provide details."))
    c10_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.10 comments"))

    c11 = models.NullBooleanField(verbose_name=_("C.11 Were any suggestions made for future projects? If yes, provide details."))
    c11_comment = models.CharField(max_length=500, blank=True, null=True, verbose_name=_("C.11 comments"))

    # SUMMARY
    summary = models.TextField(blank=True, null=True, verbose_name=_("Summary of Findings and/or Follow-up Actions (if applicable)"))

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

def file_directory_path(instance, filename):
    # file will be uploaded to MEDIA_ROOT/entry_<id>/<filename>
    return 'spot/{0}/{1}'.format(instance.project.id, filename)

class Photo(models.Model):
    caption = models.CharField(max_length=255)
    site_visit = models.ForeignKey(SiteVisit, related_name="photos", on_delete=models.CASCADE)
    file = models.FileField(upload_to=file_directory_path)
    # meta
    date_created = models.DateTimeField(default=timezone.now)
    uploaded_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("uploaded"))

    class Meta:
        ordering = ['-date_created']

    def __str__(self):
        return self.caption

class FileType(models.Model):
    name = models.CharField(max_length=255, verbose_name=_("name (English)"))
    nom = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("name (French)"))

    def __str__(self):
        # check to see if a french value is given
        if getattr(self, str(_("name"))):
            return "{}".format(getattr(self, str(_("name"))))
        # if there is no translated term, just pull from the english field
        else:
            return "{}".format(self.name)

    class Meta:
        ordering = [_('name'), ]

class File(models.Model):
    project = models.ForeignKey(Project, related_name="files", on_delete=models.CASCADE)
    caption = models.CharField(max_length=255, blank=True, null=True, verbose_name=_("file caption (optional)"))
    file_type = models.ForeignKey(FileType, related_name="files", on_delete=models.DO_NOTHING)
    file = models.FileField(upload_to=file_directory_path)
    # meta
    date_modified = models.DateTimeField(default=timezone.now)
    uploaded_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("uploaded by"))

    class Meta:
        ordering = ['file_type']

    def __str__(self):
        my_str = str(self.file_type)
        if self.caption:
            my_str = "{} - {}".format(my_str, self.caption)
        return my_str

    def save(self, *args, **kwargs):
        self.date_modified = timezone.now()
        return super().save(*args, **kwargs)

class Payment(models.Model):
    project_year = models.ForeignKey(ProjectYear, related_name="payments", on_delete=models.CASCADE)
    claim_number = models.IntegerField()
    advance_amount = models.FloatField(default=0)
    reimbursement_amount = models.FloatField(default=0)
    from_period = models.DateTimeField(blank=True, null=True)
    to_period = models.DateTimeField(blank=True, null=True)
    final_payment = models.BooleanField(default=False, verbose_name=_("Is this a final payment (project-year)?"))
    materials_submitted = models.NullBooleanField(verbose_name=_("were all necessary materials submitted?"))
    nhq_notified = models.DateTimeField(blank=True, null=True, verbose_name=_("NHQ notified"))
    payment_confirmed = models.NullBooleanField(verbose_name=_("has the payment been confirmed?"))
    notes = models.TextField(blank=True, null=True)

    # meta
    date_last_modified = models.DateTimeField(blank=True, null=True, default=timezone.now, verbose_name=_("date last modified"))
    last_modified_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, blank=True, null=True, verbose_name=_("last modified by"))

    def save(self, *args, **kwargs):
        self.date_last_modified = timezone.now()
        return super().save(*args, **kwargs)

    class Meta:
        unique_together = ['project_year', 'claim_number']

    @property
    def disbursement(self):
        return self.advance_amount + self.reimbursement_amount

def determine_project_status(project):
    ignore_statuses = [2, 4, 5, 7, 11, 12, 13]
    # first check to see if this function should be escaped
    if project.status_id in ignore_statuses:
        return project.status_id

    # otherwise we assess status
    else:
        # start backwards
        if project.date_completed:
            # means project is over
            return 13
        elif project.final_ca_nhq_signed:
            # means there is a signed agreement inplace. Status should be changed to 'active'
            return 10
        elif nz(project.recommended_overprogramming, 0) > 0:
            # means project is on OP
            return 8
        elif project.total_recommended_funding > 0:
            # means funding has been recommended
            return 9
        elif project.submission_accepted == False:
            # means submission has not been accepted
            return 5
        elif project.submission_accepted == True:
            # means submission was successful
            return 6
        elif ExpressionOfInterest.objects.filter(project=project).count() > 0:
            # means an eoi was submitted
            if project.eoi.project_eligible == False:
                # means project was deemed eligible
                return 2
            elif project.eoi.project_eligible == True:
                # means project was deemed ineligible
                return 3
            else:
                return 1
        else:
            print("returning default status")
            return project.status_id

def determine_project_length(project, status_id):
    # depending on the status, we should set the project length
    my_length = 0

    if status_id == 8:
        # an OP project can only be for 1 year
        my_length = 1
    elif status_id == 9:
        # recommended project will be based on the number of years recommended
        if nz(project.recommended_funding_y1, 0) > 0:
            my_length += 1
        if nz(project.recommended_funding_y2, 0) > 0:
            my_length += 1
        if nz(project.recommended_funding_y3, 0) > 0:
            my_length += 1
        if nz(project.recommended_funding_y4, 0) > 0:
            my_length += 1
        if nz(project.recommended_funding_y5, 0) > 0:
            my_length += 1
    elif status_id == 10:
        # active project will be based on the number of project-years
        my_length = project.years.count()

    else:
        my_length = None

    return my_length

#
# @receiver(models.signals.post_delete, sender=Project)
# def auto_delete_draft_ca_on_delete(sender, instance, **kwargs):
#     """
#     Deletes file from filesystem
#     when corresponding `MediaFile` object is deleted.
#     """
#     # for draft ca
#     if instance.draft_ca:
#         if os.path.isfile(instance.draft_ca.path):
#             os.remove(instance.draft_ca.path)
#
#
# @receiver(models.signals.pre_save, sender=Project)
# def auto_delete_draft_ca_on_change(sender, instance, **kwargs):
#     """
#     Deletes old file from filesystem
#     when corresponding `MediaFile` object is updated
#     with new file.
#     """
#     if not instance.pk:
#         return False
#
#     # for draft ca
#     try:
#         old_file = Project.objects.get(pk=instance.pk).draft_ca
#     except Project.DoesNotExist:
#         return False
#
#     if old_file:
#         new_file = instance.draft_ca
#         if not old_file == new_file:
#             if os.path.isfile(old_file.path):
#                 os.remove(old_file.path)

@receiver(models.signals.post_delete, sender=Photo)
def auto_delete_photo_on_delete(sender, instance, **kwargs):
    """
    Deletes file from filesystem
    when corresponding `MediaFile` object is deleted.
    """
    if instance.file:
        if os.path.isfile(instance.file.path):
            os.remove(instance.file.path)

@receiver(models.signals.pre_save, sender=Photo)
def auto_delete_photo_on_change(sender, instance, **kwargs):
    """
    Deletes old file from filesystem
    when corresponding `MediaFile` object is updated
    with new file.
    """
    if not instance.pk:
        return False

    try:
        old_file = Photo.objects.get(pk=instance.pk).file
    except Photo.DoesNotExist:
        return False

    if old_file:
        new_file = instance.file
        if not old_file == new_file:
            if os.path.isfile(old_file.path):
                os.remove(old_file.path)

@receiver(models.signals.post_delete, sender=File)
def auto_delete_file_on_delete(sender, instance, **kwargs):
    """
    Deletes file from filesystem
    when corresponding `MediaFile` object is deleted.
    """
    if instance.file:
        if os.path.isfile(instance.file.path):
            os.remove(instance.file.path)

@receiver(models.signals.pre_save, sender=File)
def auto_delete_file_on_change(sender, instance, **kwargs):
    """
    Deletes old file from filesystem
    when corresponding `MediaFile` object is updated
    with new file.
    """
    if not instance.pk:
        return False

    try:
        old_file = File.objects.get(pk=instance.pk).file
    except File.DoesNotExist:
        return False

    if old_file:
        new_file = instance.file
        if not old_file == new_file:
            if os.path.isfile(old_file.path):
                os.remove(old_file.path)


#coding=utf-8

import tensorflow as tf
import os

FLAGS = tf.app.flags.FLAGS
tf.app.flags.DEFINE_float('gpu_memory_fraction', 0.02, 'gpu占用内存比例')
tf.app.flags.DEFINE_integer('batch_size', 10, 'batch_size大小')
tf.app.flags.DEFINE_integer('reload_model', 0, '是否reload之前训练好的模型')
tf.app.flags.DEFINE_string('model_dir', "./model/", '保存模型的文件夹')
tf.app.flags.DEFINE_string('event_dir', "./event/", '保存event数据的文件夹,给tensorboard展示用')

def weight_init(shape, name):
    '''
    获取某个shape大小的参数
    '''
    return tf.get_variable(name, shape, initializer=tf.random_normal_initializer(mean=0.0, stddev=0.1))

def bias_init(shape, name):
    return tf.get_variable(name, shape, initializer=tf.constant_initializer(0.0))

def conv2d(x,conv_w):
    return tf.nn.conv2d(x, conv_w, strides=[1, 1, 1, 1], padding='VALID')

def max_pool(x, size):
    return tf.nn.max_pool(x, ksize=[1,size,size,1], strides = [1,size,size,1], padding='VALID')

def read_and_decode(filename_queue):
  reader = tf.TFRecordReader()
  _, serialized_example = reader.read(filename_queue)
  features = tf.parse_single_example(
      serialized_example,
      features={
          'height': tf.FixedLenFeature([], tf.int64),
          'width': tf.FixedLenFeature([], tf.int64),
          'channels': tf.FixedLenFeature([], tf.int64),
          'image_data': tf.FixedLenFeature([], tf.string),
          'label': tf.FixedLenFeature([], tf.int64),
      })

  image = tf.decode_raw(features['image_data'], tf.uint8)
  image = tf.reshape(image, [100, 100, 3])

  image = tf.cast(image, tf.float32) * (1. / 255) - 0.5
  #image = tf.cast(image, tf.float32)

  label = tf.cast(features['label'], tf.int32)

  return image, label

def inputs(filename, batch_size):
  with tf.name_scope('input'):
    filename_queue = tf.train.string_input_producer(
        [filename], num_epochs=2000)

    image, label = read_and_decode(filename_queue)

    images, labels = tf.train.shuffle_batch(
        [image, label], batch_size=batch_size, num_threads=1,
        capacity=4,
        min_after_dequeue=2)

    return images, labels

def inference(input_data):
  '''
  定义网络结构、向前计算过程
  '''
  with tf.name_scope('conv1'):
    w_conv1 = weight_init([10,10,3,16], 'conv1_w')
    b_conv1 = bias_init([16], 'conv1_b')

    #卷积之后图片大小变成100-10+1 = 91
    h_conv1 = tf.nn.relu(conv2d(input_data, w_conv1) + b_conv1)
    #池化之后图片大小变成45
    h_pool1 = max_pool(h_conv1, 2) #140

  with tf.name_scope('conv2'):
    w_conv2 = weight_init([5,5,16,16], 'conv2_w')
    b_conv2 = bias_init([16], 'conv2_b')

    #卷积之后图片大小变成 45 -5+1 = 41
    h_conv2 = tf.nn.relu(conv2d(h_pool1, w_conv2) + b_conv2)
    #池化之后图片大小变成20
    h_pool2 = max_pool(h_conv2, 2) #68

  with tf.name_scope('conv3'):
    w_conv3 = weight_init([5,5,16,16], 'conv3_w')
    b_conv3 = bias_init([16], 'conv3_b')

    #卷积之后图片大小变成 20 -5+1 = 16
    h_conv3 = tf.nn.relu(conv2d(h_pool2, w_conv3) + b_conv3)
    #池化之后图片大小变成8
    h_pool3 = max_pool(h_conv3, 2) # 32

  with tf.name_scope('fc1'):
    w_fc1 = weight_init([8*8*16, 128], 'fc1_w')
    b_fc1 = bias_init([128], 'fc1_b')

    h_fc = tf.nn.relu(tf.matmul(tf.reshape(h_pool3,[-1,8*8*16]), w_fc1)  + b_fc1)

  #keep_prob = 0.8
  #h_fc_drop = tf.nn.dropout(h_fc,keep_prob)
  with tf.name_scope('fc2'):
    w_fc2 = weight_init([128, 2], 'fc2_w')
    b_fc2 = bias_init([2], 'fc2_b')

    h_fc2 = tf.matmul(h_fc, w_fc2) + b_fc2

  return h_fc2

def train():
  '''
  训练过程
  '''
  global_step = tf.get_variable('global_step', [],
                                initializer=tf.constant_initializer(0),
                                trainable=False, dtype=tf.int32)

  batch_size = FLAGS.batch_size
  train_images, train_labels = inputs("./tfrecord_data/train.tfrecord", batch_size )
  test_images, test_labels = inputs("./tfrecord_data/train.tfrecord", batch_size )

  train_labels_one_hot = tf.one_hot(train_labels, 2, on_value=1.0, off_value=0.0)
  test_labels_one_hot = tf.one_hot(test_labels, 2, on_value=1.0, off_value=0.0)

  #因为任务比较简单，故意把学习率调小了，以拉长训练过程。
  learning_rate = 0.000001

  with tf.variable_scope("inference") as scope:
    train_y_conv = inference(train_images)
    scope.reuse_variables()
    test_y_conv = inference(test_images)

  cross_entropy = tf.reduce_mean(
      tf.nn.softmax_cross_entropy_with_logits(labels=train_labels_one_hot, logits=train_y_conv))
  optimizer = tf.train.GradientDescentOptimizer(learning_rate)
  train_op = optimizer.minimize(cross_entropy, global_step=global_step)

  train_correct_prediction = tf.equal(tf.argmax(train_y_conv, 1), tf.argmax(train_labels_one_hot, 1))
  train_accuracy = tf.reduce_mean(tf.cast(train_correct_prediction, tf.float32))

  test_correct_prediction = tf.equal(tf.argmax(test_y_conv, 1), tf.argmax(test_labels_one_hot, 1))
  test_accuracy = tf.reduce_mean(tf.cast(test_correct_prediction, tf.float32))

  init_op = tf.global_variables_initializer()
  local_init_op = tf.local_variables_initializer()

  saver = tf.train.Saver()
  tf.summary.scalar('cross_entropy_loss', cross_entropy)
  tf.summary.scalar('train_acc', train_accuracy)
  summary_op = tf.summary.merge_all()

  gpu_options = tf.GPUOptions(
    per_process_gpu_memory_fraction=FLAGS.gpu_memory_fraction)
  config = tf.ConfigProto(gpu_options=gpu_options)

  with tf.Session(config=config) as sess:
    if FLAGS.reload_model == 1:
      ckpt = tf.train.get_checkpoint_state(FLAGS.model_dir)
      saver.restore(sess, ckpt.model_checkpoint_path)
      save_step = int(ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1])
      print("reload model from %s, save_step = %d" % (ckpt.model_checkpoint_path, save_step))
    else:
      print("Create model with fresh paramters.")
      sess.run(init_op)
      sess.run(local_init_op)

    summary_writer = tf.summary.FileWriter(FLAGS.event_dir, sess.graph)

    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)
    try:
      while not coord.should_stop():
        _, g_step = sess.run([train_op, global_step])
        if g_step % 2 == 0:
          summary_str = sess.run(summary_op)
          summary_writer.add_summary(summary_str, g_step)

        if g_step % 100 == 0:
          train_accuracy_value, loss = sess.run([train_accuracy, cross_entropy])
          print("step %d training_acc is %.2f, loss is %.4f" % (g_step, train_accuracy_value, loss))
        if g_step % 1000 == 0:
          test_accuracy_value = sess.run(test_accuracy)
          print("step %d test_acc is %.2f" % (g_step, test_accuracy_value))

        if g_step % 2000 == 0:
          #保存一次模型
          print("save model to %s" % FLAGS.model_dir  + "model.ckpt." + str(g_step) )
          saver.save(sess, FLAGS.model_dir + "model.ckpt", global_step=global_step)

    except tf.errors.OutOfRangeError:
      pass
    finally:
      coord.request_stop()

    coord.join(threads)

if __name__ == "__main__":
  if not os.path.exists("./tfrecord_data/train.tfrecord") or \
    not os.path.exists("./tfrecord_data/test.tfrecord"):
    gen_tfrecord_data("./data/train", "./data/test/")

  os.environ["CUDA_VISIBLE_DEVICES"] = "0"
  #test()
  if not os.path.exists(FLAGS.model_dir):
    os.makedirs(FLAGS.model_dir)
  train()


from django.urls import path

from . import views

app_name = 'trigger3'

urlpatterns = [
    path('createpesanansumberdaya', views.createPesananSD, name='CreatePesananSumberDaya'),
    path('readpesanansumberdaya', views.readPesanan, name='ReadPesananSumberDaya'),
    path('readpesanansumberdaya/detail/<int:idPesanan>', views.detailPesanan, name='DetailPesanan'),
    path('readpesanansumberdaya/riwayatstatus/<int:idPesanan>',views.riwayatStatus,name='RiwayatStatus'),
    path('readpesanansumberdaya/updatepesanan/<int:idPesanan>', views.updatePesanan, name='UpdatePesanan'),
    path('SupplierReadPesanan',views.SupplierReadPesanan,name='SupplierReadPesanan'),
    path('SupplierReadPesanan/detail/<int:idPesanan>',views.detailPesananSupplier,name='DetailPesananSupplier'),
    path('SupplierReadPesanan/riwayatstatus/<int:idPesanan>',views.riwayatStatusSupplier,name='RiwayatStatusSupplier'),
    path('createstockfaskes',views.createStockFaskes, name='CreateStockFaskes'),
    path('liststockfaskes',views.listStockFaskes, name='ListStockFaskes'),
    path('liststockfaskes/updatestock/<str:kodeFaskes>/<str:namaFaskes>/<str:namaItem>', views.updateStockFaskes, name='UpdateStockFaskes'),
    path('liststockfaskespetugas',views.ListStockFaskesPetugas,name='ListStockFaskesPetugas')
]


import bitstring as bs
from bitstring import BitArray
from math import log
import sys
import argparse
import pandas as pd
class cache:
    def __init__(self,block_size=16,num_blocks=16,associativity = 1):
        #2d cache data structure with all rows init to 0's
        #rowlen - index_bits
        #contains ending index of index
        self.index_bits = 0
        #contains ending index of valid bit
        self.valid_bit = 1
        #contains ending index of tag bits
        self.tag_bits = 0
        self.num_sets = 0
        self.offset = 0
        self.address_size = 32
        self.hits = 0
        self.misses = 0
        self.num_reads = 0
        self.block_size = block_size
        self.num_blocks = num_blocks
        self._addr_structure(self.block_size,self.num_blocks,associativity)
        self.cache = self._create_cache(num_blocks,32)
        self.size = num_blocks * block_size
        self._check_validity(associativity,num_blocks,self.num_sets)

    def _addr_structure(self,block_size,num_blocks,associativity=1):
        valid_bits = 1
        #addr_size = log(num_blocks,2)
        addr_size =32
        self.offset = int(log(block_size,2))
        if associativity == 1:
            self.num_sets = num_blocks
        elif associativity == 2:
            self.num_sets = num_blocks/2

        #[]
        self.index_bits = int(log(self.num_sets,2))
        self.tag_bits = addr_size - self.index_bits - self.offset - valid_bits
        #row_len = block_size + self.tag_bits + self.index_bits + valid_bits

    def _create_cache(self,num_blocks,row_len):
        #2d cache data structure with all rows init to 0's
        return [BitArray(row_len) for i in range(num_blocks)]

    def _check_validity(self,asc,nb,ns):
        if asc*ns != nb:
            print("invalid number of blocks")
            exit()

    def _block_addr(self,address):
        return address/self.block_size

    def _index(self,block_addr):
        return block_addr%self.num_sets

    def _check_valid_bit(self,idx):
        vb = self.cache[idx][0]

        if vb:
            return True
        else:
            self.misses += 1
            self.cache[idx][0] = 1
            return False

    def _check_tag(self,idx,tag):
        act_tag = self.cache[idx][1:self.tag_bits+1]

        if tag == act_tag:
            self.hits += 1
        else:
            self.misses += 1
            self.cache[idx][1:self.tag_bits+1] = tag

    def _find_tag(self,address):
        return address/(self.num_sets*self.block_size)

    def cache_read(self,address):
        #find address
        block_addr = int(self._block_addr(address))
        #go to line number
        index = int(self._index(block_addr))
        tag = int(self._find_tag(address))
        #check valid bit
        vb = self._check_valid_bit(index)
        #if 0, cache miss
        #set valid bit to 1
        #set tag
        if vb:
            self._check_tag(index,tag)

    def read_all(self,addr_list):
        for addr in addr_list:
            self.cache_read(int(addr,base=16))

        cache_reads = len(addr_list)
        self.results(cache_reads)

    def results(self,cache_reads):
        hit_ratio = self.hits/cache_reads
        miss_ratio = 1 - hit_ratio

        print(f"Reads: {cache_reads}")
        print(f"Hits: {self.hits}")
        print(f"Hits: {self.misses}")
        print(f"Hit rate: {(hit_ratio*100):.2f}%")
        print(f"Miss rate: {(miss_ratio*100):.2f}%")

def read_addr_file(file):
    addr = pd.read_csv(file, delimiter=' ', header=None)
    return addr[0].values.tolist()

def main(argv):
    parser = argparse.ArgumentParser()
    parser.add_argument("-i","--input_file")
    parser.add_argument("-b","--block_size")
    parser.add_argument("-n","--num_blocks")
    parser.add_argument("-a", "--associativity")
    parser.add_argument("-t","--hit_time")
    parser.add_argument("-m","--miss_time")
    parser.add_argument("-l","--lru")
    args = parser.parse_args()
    address_data = read_addr_file(args.input_file)
    block_size = args.block_size
    num_block = args.num_blocks
    associativity = args.associativity
    hit_time = args.hit_time
    miss_time = args.miss_time
    lru = args.lru
    cche = cache(block_size=int(block_size),num_blocks=int(num_block),associativity=1)
    cche.read_all(address_data)

if __name__ == "__main__":
    main(sys.argv[1:])


idades = []
alturas = []
alturas_inv = []
idades_inv = []

for i in range(5):
  idades.append(int(input("Digite sua idade: ")))
  alturas.append(float(input("Digite sua altura: ")))

alturas_inv = alturas[::-1]
idades_inv = idades[::-1]

print(idades)
print(alturas)
print(idades_inv)
print(alturas_inv)


from django.urls import path
from django.conf.urls import url
from .views import Check, PlacedOrder, ReviewOrder, ListOrder

app_name = 'order'

urlpatterns = [
    path('', Check.as_view(), name='check'),
    path('placed/', PlacedOrder.as_view(), name='placed_order'),
    url(r'review/(?P<cod_ordine>[0-9]+)/$', ReviewOrder.as_view(), name='review_order'),
    url(r'list/(?P<cod_locale>[0-9]+)/$', ListOrder.as_view(), name='list_order')
]


import tensorflow as tf
import numpy as np
import time
import math
import os
from MultiParticle import MPFormular as mpf, MPTrainModel as mpt
from MultiParticle import MPSaveDataSet as sd
import matplotlib
matplotlib.use('TkAgg')
from matplotlib import pyplot as plt

# Parameters for training spectrum
r_min = 20/mpf.scale_R              #Real R = scale_R*R*1e-9
r_max = 100/mpf.scale_R             #Real R = scale_R*R*1e-9
fr_min = 40/mpf.scale_FR            #Real fr = scale_FR*fr*1e-3
fr_max = 400/mpf.scale_FR           #Real fr = scale_FR*fr*1e-3
k0_min = 4/mpf.scale_K0             #Real k0 = scale_K0*k0*1e+6
k0_max = 40/mpf.scale_K0            #Real k0 = scale_K0*k0*1e+6
k1_min = 0.8/mpf.scale_K1           #Real k1 = scale_K1*k1*1e+6
k1_max = 200/mpf.scale_K1           #Real k1 = scale_K1*k1*1e+6
kx_min = 0.0                        #Real kx = scale_KX*kX
kx_max = 1.0*math.pi/mpf.scale_KX   #Real kx = scale_KX*kX

train_ep = 1.59**2
train_em = 1.0
train_ec = 1.45**2
train_vc = 1.47e-16
train_startFreq = -10.0
train_stopFreq = 10.0

#Set numpy array display precision
np.set_printoptions(precision=3)

# Figure Path
figurePath = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) \
           + '/Share/' \
           + 'TestMPSensing.png'

# Generate testing batches
def generateTestBatches():
    #Using generated dataset
    data_spectrum, correct_label = sd.loadDataSet()

    TensorX = tf.convert_to_tensor(data_spectrum, dtype=tf.float32)
    TensorY = tf.convert_to_tensor(correct_label, dtype=tf.float32)

    return [TensorX, TensorY]

def generateSingleBatch():

    data_spectrum, correct_label = sd.generateTrainBatches(batch_size=1)

    TensorX = tf.convert_to_tensor(data_spectrum, dtype=tf.float32)
    TensorY = tf.convert_to_tensor(correct_label, dtype=tf.float32)

    return [TensorX, TensorY]

# Load the multi nano-particle sensing model
def loadMPModel():
    # Construct model
    trainNet = mpt.MPTrainNet()
    trainNet.__init__()

    # create a saver
    saver = tf.train.Saver()

    # Model Name
    modelName = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) \
                + '/MPModel/' \
                + 'MPModel' \
                + '.ckpt'

    sess = tf.Session()

    try:
        # Initialize variables
        sess.run(tf.global_variables_initializer())
        # Try to restore the trained session
        saver.restore(sess, modelName)

    except:
        print("Load model fail!")

    return [sess, trainNet]

def closeMPModel():
    tf.reset_default_graph()

# Just test one frame
def testSingleMPModel(sess, trainNet):
    TensorX, TensorY = generateSingleBatch()
    predict, error, loss = trainNet.evaluate(TensorX, TensorY)

    # Radius prediction
    predictR1 = tf.cast(predict[:1, 0], tf.float32)
    Predict_R1 = mpf.scale_R * predictR1.eval(session=sess)
    Label_R1 = mpf.scale_R * TensorY[:1, 0].eval(session=sess)
    Error_R1 = np.abs(Predict_R1-Label_R1)
    Precision_R1 = np.subtract(1, Error_R1/Label_R1)*100

    predictR2 = tf.cast(predict[:1, 1], tf.float32)
    Predict_R2 = mpf.scale_R * predictR2.eval(session=sess)
    Label_R2 = mpf.scale_R * TensorY[:1, 1].eval(session=sess)
    Error_R2 = np.abs(Predict_R2-Label_R2)
    Precision_R2 = np.subtract(1, Error_R2/Label_R2)*100

    # Edit message send to iPhone
    message = 'MPSensing:\n' \
              + "Label_R1  = %6.2fnm  " % Label_R1 \
              + "Predict_R1  = %6.2fnm  " % Predict_R1 \
              + "Error_R1 = %6.2fnm  " % Error_R1 \
              + "Precision = %4.1f%%\n" % Precision_R1 \
              + "Label_R2  = %6.2fnm  " % Label_R2 \
              + "Predict_R2  = %6.2fnm  " % Predict_R2 \
              + "Error_R2 = %6.2fnm  " % Error_R2 \
              + "Precision = %4.1f%%\n" % Precision_R2 \
              + "StartFreq = %6.2e\n" % train_startFreq \
              + "StopFreq = %6.2e\n" % train_stopFreq \
              + "Number = %6.0e\n" % int(mpt.n_input/2) \
              + "Spectrum = %s\n" % TensorX.eval(session=sess)[0] \
              + "SpectrumEnd"\

    return  message.encode()

# Test one batch
def testBatchMPModel(sess, trainNet, batch_size = 200):

    TensorX, TensorY = generateTestBatches()
    predict, error, loss = trainNet.evaluate(TensorX, TensorY)

    # Plot R1 prediction
    plt.figure()

    plt.subplot(2,1,1)
    plt.plot(mpf.scale_R * TensorY[:batch_size, 0].eval(session=sess), mpf.scale_R* sess.run(predict)[:, 0], '.',
             color='red', label='R1')
    plt.xlabel('Assume Radius(nm)')
    plt.ylabel('Predict Radius(nm)')
    plt.legend()

    plt.subplot(2,1,2)
    plt.plot(mpf.scale_R * TensorY[:batch_size, 1].eval(session=sess), mpf.scale_R* sess.run(predict)[:, 1], '.',
             color='red', label='R2')
    plt.xlabel('Assume Radius(nm)')
    plt.ylabel('Predict Radius(nm)')
    plt.legend()

    plt.tight_layout()

    # Save the figure
    plt.savefig(figurePath, bbox_inches='tight')
    plt.close()

    message = b'BatchMultiParticleSensing:'

    return message

if __name__ == '__main__':

    sess, trainNet = loadMPModel()
    # testSingleMPModel(sess=sess, trainNet=trainNet)
    testBatchMPModel(sess=sess, trainNet=trainNet, batch_size=sd.size)


'''
follow_curve.py
Michael Clavan

Description:
	- This script creates a curve that is attached to ether end to selected objects.
	- Mainly its snapping both ends and then appling a cluster.  These clusters
	are then point constraint to their respected selected object.
	- The script creates a group to store the curve and clusters the script generates.
	- The group can be parented under the master control icon for the rig.

'''
import pymel.core as pm

def create_follow_curve_selected():
	selected = pm.ls(selection=True)
	target_1 = selected[0]
	target_2 = selected[1]
	create_follow_curve(target_1, target_2)

def create_follow_curve(target_1, target_2):
	target_2_pieces = target_2.split('_')
	target_2_pieces[-1] = 'follow'
	point_line_name = '_'.join(target_2_pieces)

	point_line = pm.curve(d=1, name=point_line_name, p=((-1, 0, 0), (1, 0, 0)), k=(0, 1))
	cv_1 = point_line.cv[0]
	cv_2 = point_line.cv[1]

	target_2_pieces[-1] = 'clst1'
	cv_cluster_1_name = '_'.join(target_2_pieces)
	target_2_pieces[-1] = 'clst2'
	cv_cluster_2_name = '_'.join(target_2_pieces)

	cv_cluster_1 = pm.cluster(cv_1, relative=True, name=cv_cluster_1_name)
	cv_cluster_2 = pm.cluster(cv_2, relative=True, name=cv_cluster_2_name)
	pm.pointConstraint(target_1, cv_cluster_1)
	pm.pointConstraint(target_2, cv_cluster_2)

	target_2_pieces[-1] = 'folGrp'
	point_line_grp_name = '_'.join(target_2_pieces)
	point_line_grp = pm.group(cv_cluster_1, cv_cluster_2, point_line, world=True, name=point_line_grp_name)
	cv_cluster_1[1].attr('v').set(0)
	cv_cluster_2[1].attr('v').set(0)

	# Red
	icon_color = 13
	pm.setAttr('{0}.overrideEnabled'.format(point_line), 1)
	pm.setAttr('{0}.overrideColor'.format(point_line), icon_color)
	# While reference is turned on the color will NOT display.
	pm.setAttr('{0}.overrideDisplayType'.format(point_line), 2)