import json
import logging
import random
import time
import copy
from argparse import ArgumentParser
from itertools import chain
from pprint import pformat
import copy
import numpy as np

import torch
import torch.nn.functional as F

from transformers import *
from VideoGPT2 import *
from train import SPECIAL_TOKENS, SPECIAL_TOKENS_DICT
from dataset import get_dataset, build_input_from_segments

def top_filtering(logits, top_k=0, top_p=0.0, threshold=-float('Inf'), filter_value=-float('Inf')):
    """ Filter a distribution of logits using top-k, top-p (nucleus) and/or threshold filtering
        Args:
            logits: logits distribution shape (vocabulary size)
            top_k: <=0: no filtering, >0: keep only top k tokens with highest probability.
            top_p: <=0.0: no filtering, >0.0: keep only a subset S of candidates, where S is the smallest subset
                whose total probability mass is greater than or equal to the threshold top_p.
                In practice, we select the highest probability tokens whose cumulative probability mass exceeds
                the threshold top_p.
            threshold: a minimal threshold to keep logits
    """
    assert logits.dim() == 1  # Only work for batch size 1 for now - could update but it would obfuscate a bit the code
    top_k = min(top_k, logits.size(-1))
    if top_k > 0:
        # Remove all tokens with a probability less than the last token in the top-k tokens
        indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None]
        logits[indices_to_remove] = filter_value

    if top_p > 0.0:
        # Compute cumulative probabilities of sorted tokens
        sorted_logits, sorted_indices = torch.sort(logits, descending=True)
        cumulative_probabilities = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1)

        # Remove tokens with cumulative probability above the threshold
        sorted_indices_to_remove = cumulative_probabilities > top_p
        # Shift the indices to the right to keep also the first token above the threshold
        sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone()
        sorted_indices_to_remove[..., 0] = 0

        # Back to unsorted indices and set them to -infinity
        indices_to_remove = sorted_indices[sorted_indices_to_remove]
        logits[indices_to_remove] = filter_value

    indices_to_remove = logits < threshold
    logits[indices_to_remove] = filter_value

    return logits

def sample_sequence(caption, history, tokenizer, model, args, current_output=None, video=None):
    special_tokens_ids = tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS)
    if current_output is None:
        current_output = []
    for i in range(args.max_length):
        instance, sequence = build_input_from_segments(caption, history, current_output, tokenizer, with_eos=False, drop_caption=False)

        input_ids = torch.tensor(instance["input_ids"], device=args.device).unsqueeze(0)
        token_type_ids = torch.tensor(instance["token_type_ids"], device=args.device).unsqueeze(0)
        input_embs = model.transformer.wte(input_ids)
        if video is not None:
            input_embs = torch.cat([model.video_ff(video), input_embs], dim=1)
            token_type_ids = torch.cat([torch.ones((1, video.size(1))).long().cuda() * tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS[-2]), token_type_ids], dim=1)

        logits = model(input_embs, token_type_ids=token_type_ids)
        if "gpt2" == args.model:
            logits = logits[0]
        logits = logits[0, -1, :] / args.temperature
        logits = top_filtering(logits, top_k=args.top_k, top_p=args.top_p)
        probs = F.softmax(logits, dim=-1)

        prev = torch.topk(probs, 1)[1] if args.no_sample else torch.multinomial(probs, 1)
        if i < args.min_length and prev.item() in special_tokens_ids:
            while prev.item() in special_tokens_ids:
                prev = torch.multinomial(probs, num_samples=1)

        if prev.item() in special_tokens_ids:
            break
        current_output.append(prev.item())

    return current_output

def beam_search(caption, history, tokenizer, model, args, current_output=None, video=None):
    special_tokens_ids = tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS)
    if current_output is None:
        current_output = []
    hyplist = [([], 0., current_output)]
    best_state = None
    comp_hyplist = []

    for i in range(args.max_length):
        new_hyplist = []
        argmin = 0
        for out, lp, st in hyplist:
            instance, sequence = build_input_from_segments(caption, history, st, tokenizer, with_eos=False, drop_caption=False)

            input_ids = torch.tensor(instance["input_ids"], device=args.device).unsqueeze(0)
            token_type_ids = torch.tensor(instance["token_type_ids"], device=args.device).unsqueeze(0)
            input_embs = model.transformer.wte(input_ids)
            if video is not None:
                input_embs = torch.cat([model.video_ff(video), input_embs], dim=1)
                token_type_ids = torch.cat([torch.ones((1, video.size(1))).long().cuda() * tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS[-2]), token_type_ids], dim=1)

            logits = model(input_embs, token_type_ids=token_type_ids)
            if "gpt2" == args.model:
                logits = logits[0]
            logp = F.log_softmax(logits, dim=-1)[:, -1, :]
            lp_vec = logp.cpu().data.numpy() + lp
            lp_vec = np.squeeze(lp_vec)
            if i >= args.min_length:
                new_lp = lp_vec[tokenizer.eos_token_id] + args.penalty * (len(out) + 1)
                comp_hyplist.append((out, new_lp))
                if best_state is None or best_state < new_lp:
                    best_state = new_lp
            count = 1
            for o in np.argsort(lp_vec)[::-1]:
                if o == tokenizer.unk_token_id or o == tokenizer.eos_token_id:
                    continue
                new_lp = lp_vec[o]
                if len(new_hyplist) == args.beam_size:
                    if new_hyplist[argmin][1] < new_lp:
                        new_st = copy.deepcopy(st)
                        new_st.append(int(o))
                        new_hyplist[argmin] = (out + [o], new_lp, new_st)
                        argmin = min(enumerate(new_hyplist), key=lambda h: h[1][1])[0]
                    else:
                        break
                else:
                    new_st = copy.deepcopy(st)
                    new_st.append(int(o))
                    new_hyplist.append((out + [o], new_lp, new_st))
                    if len(new_hyplist) == args.beam_size:
                        argmin = min(enumerate(new_hyplist), key=lambda h: h[1][1])[0]
                count += 1
        hyplist = new_hyplist
    if len(comp_hyplist) > 0:
        maxhyps = sorted(comp_hyplist, key=lambda h: -h[1])[:1]
        return maxhyps
    else:
        return [([], 0)]

def greedy_decode(caption, history, tokenizer, model, args, current_output=None, video=None):
    special_tokens_ids = tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS)
    ys = []

    for i in range(args.max_length):
        instance, sequence = build_input_from_segments(caption, history, ys, tokenizer, with_eos=False, drop_caption=False)

        input_ids = torch.tensor(instance["input_ids"], device=args.device).unsqueeze(0)
        token_type_ids = torch.tensor(instance["token_type_ids"], device=args.device).unsqueeze(0)
        input_embs = model.transformer.wte(input_ids)
        if video is not None:
            input_embs = torch.cat([model.video_ff(video), input_embs], dim=1)
            token_type_ids = torch.cat([torch.ones((1, video.size(1))).long().cuda() * tokenizer.convert_tokens_to_ids(SPECIAL_TOKENS[-2]), token_type_ids], dim=1)

        logits = model(input_embs, token_type_ids=token_type_ids)
        if "gpt2" == args.model:
            logits = logits[0][0]
        logits = logits.cpu().data.numpy()
        next_word = np.argsort(logits[-1])[-1]
        if next_word == special_tokens_ids[1]:
            break
        ys.append(next_word)
    return ys

# Evaluation routine
def generate_response(model, data, dataset, args, ref_data=None):
    result_dialogs = []
    model.eval()
    with torch.no_grad():
        qa_id = 0
        for idx, dialog in enumerate(data['dialogs']):
            vid = dialog['image_id']
            out_dialog = dialog['dialog'][-1:]
            pred_dialog = {'image_id': vid,
                           'dialog': copy.deepcopy(out_dialog)}
            result_dialogs.append(pred_dialog)

            vgg = np.load("data/vggish_testset/"+vid+".npy")
            i3d_flow = np.load("data/i3d_flow_testset/"+vid+".npy")
            i3d_rgb = np.load("data/i3d_rgb_testset/"+vid+".npy")

            sample_i3d_flow = i3d_flow[range(1, i3d_flow.shape[0], 1)]
            sample_i3d_rgb = i3d_rgb[range(1, i3d_rgb.shape[0], 1)]

            vgg = torch.from_numpy(vgg).float().cuda()
            i3d_flow = torch.from_numpy(sample_i3d_flow).float().cuda()
            i3d_rgb = torch.from_numpy(sample_i3d_rgb).float().cuda()
            min_length = min([i3d_flow.size(0), i3d_rgb.size(0), vgg.size(0)])
            i3d = torch.cat([i3d_flow[:min_length], i3d_rgb[:min_length], vgg[:min_length]], dim=1).unsqueeze(0)

            for t, qa in enumerate(out_dialog):
                logging.info('%d %s_%d' % (qa_id, vid, t))
                logging.info('QS: ' + qa['question'])
                # prepare input data
                start_time = time.time()
                qa_id += 1

                if args.beam_search:
                   #hypstr = greedy_decode(dataset[idx]["caption"], dataset[idx]["history"], tokenizer, model, args, video=i3d)
                   hypstr = beam_search(dataset[idx]["caption"], dataset[idx]["history"], tokenizer, model, args, video=i3d)
                   hypstr = hypstr[0][0]
                else:
                   hypstr=sample_sequence(dataset[idx]["caption"], dataset[idx]["history"], tokenizer, model, args, video=i3d)
                hypstr=tokenizer.decode(hypstr, skip_special_tokens=True)
                logging.info('HYP: ' + hypstr)
                pred_dialog['dialog'][t]['answer'] = hypstr
                logging.info('ElapsedTime: %f' % (time.time() - start_time))
                logging.info('-----------------------')

    return {'dialogs': result_dialogs}

##################################
# main
if __name__ =="__main__":
    parser = ArgumentParser()
    parser.add_argument("--model", type=str, default="gpt2", help="Model type (gpt or gpt2)")
    parser.add_argument("--model_checkpoint", type=str, default="log_without_caption_with_valid/", help="Path, url or short name of the model")
    parser.add_argument("--max_history", type=int, default=3, help="Number of previous utterances to keep in history")
    parser.add_argument("--device", type=str, default="cuda" if torch.cuda.is_available() else "cpu", help="Device (cuda or cpu)")

    parser.add_argument("--no_sample", action='store_true', help="Set to use greedy decoding instead of sampling")
    parser.add_argument("--beam_search", action='store_true', help="Set to use beam search instead of sampling")
    parser.add_argument("--beam_size", type=int, default=5, help="Beam size")
    parser.add_argument("--max_length", type=int, default=20, help="Maximum length of the output utterances")
    parser.add_argument("--min_length", type=int, default=1, help="Minimum length of the output utterances")
    parser.add_argument("--penalty", type=float, default=0.3, help="elngth penalty")
    parser.add_argument("--seed", type=int, default=42, help="Seed")
    parser.add_argument("--temperature", type=int, default=0.7, help="Sampling softmax temperature")
    parser.add_argument("--top_k", type=int, default=0, help="Filter top-k tokens before sampling (<=0: no filtering)")
    parser.add_argument("--top_p", type=float, default=0.9, help="Nucleus filtering (top-p) before sampling (<=0.0: no filtering)")
    parser.add_argument("--test_set", type=str, default="data/test_set4DSTC8-AVSD.json")
    parser.add_argument("--lbl_test_set", type=str, default="data/lbl_undisclosedonly_test_set4DSTC7-AVSD.json")
    parser.add_argument("--output", type=str, default="result.json")

    args = parser.parse_args()
    for arg in vars(args):
        print("{}={}".format(arg, getattr(args, arg)))

    logging.basicConfig(level=logging.INFO,
            format='%(asctime)s %(levelname)s: %(message)s')

    logging.info('Loading model params from ' + args.model_checkpoint)

    tokenizer_class = GPT2Tokenizer if "gpt2" == args.model else OpenAIGPTTokenizer
    tokenizer = tokenizer_class.from_pretrained(args.model_checkpoint)
    tokenizer.add_special_tokens(SPECIAL_TOKENS_DICT)
    model_class = VideoGPT2LMHeadModel if "gpt2" == args.model else OpenAIGPTLMHeadModel
    model_config = GPT2Config.from_pretrained(args.model_checkpoint)
    model = model_class.from_pretrained(args.model_checkpoint+"checkpoint_mymodel_4.pth", config=model_config)
    model.to(args.device)
    model.eval()

    logging.info('Loading test data from ' + args.test_set)
    test_data = json.load(open(args.test_set,'r'))
    test_dataset = get_dataset(tokenizer, args.test_set, undisclosed_only=True, n_history=args.max_history)
    # generate sentences
    logging.info('-----------------------generate--------------------------')
    start_time = time.time()
    result = generate_response(model, test_data, test_dataset, args)
    logging.info('----------------')
    logging.info('wall time = %f' % (time.time() - start_time))
    if args.output:
        logging.info('writing results to ' + args.output)
        json.dump(result, open(args.output, 'w'), indent=4)
    logging.info('done')


# Author: Gael Varoquaux <gael dot varoquaux at normalesup dot org>
# License: BSD 3 clause
# mods to use webcam: A.Mazel
# source controlled under electronoos.scripts

import time

# Standard scientific Python imports
import matplotlib.pyplot as plt

# Import datasets, classifiers and performance metrics
from sklearn import datasets, svm, metrics
from sklearn.model_selection import train_test_split
import numpy as np

import cv2 # OpenCV: Open Computer Vision

# The digits dataset
digits = datasets.load_digits()
if 0:
    # affiche des images au hasard

    print("nbr images dans la base: %d" % len(digits.images))
    print(digits.images[0].shape)

    cv2.imshow("une image",cv2.resize(digits.images[0],(640,640)) )
    cv2.imshow("une autre image",cv2.resize(digits.images[100],(640,640)) )
    print("la premiere image: " + str(digits.target[0]))
    print("l'autre image: " + str(digits.target[100]))
    cv2.waitKey(0)
    exit(1)

# The data that we are interested in is made of 8x8 images of digits, let's
# have a look at the first 4 images, stored in the `images` attribute of the
# dataset.  If we were working from image files, we could load them using
# matplotlib.pyplot.imread.  Note that each image must have the same size. For these
# images, we know which digit they represent: it is given in the 'target' of
# the dataset.
_, axes = plt.subplots(2, 4)
images_and_labels = list(zip(digits.images, digits.target))
for ax, (image, label) in zip(axes[0, :], images_and_labels[:4]):
    ax.set_axis_off()
    ax.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    ax.set_title('Training: %i' % label)

# To apply a classifier on this data, we need to flatten the image, to
# turn the data in a (samples, feature) matrix:
n_samples = len(digits.images)
data = digits.images.reshape((n_samples, -1))

# Create a classifier: a support vector classifier
classifier = svm.SVC(gamma=0.001)

# Split data into train and test subsets
X_train, X_test, y_train, y_test = train_test_split(
    data, digits.target, test_size=0.5, shuffle=False)

timeBegin = time.time()
# We learn the digits on the first half of the digits
classifier.fit(X_train, y_train)
print("time: %.3f s" % (time.time()-timeBegin) )

# Now predict the value of the digit on the second half:
predicted = classifier.predict(X_test)

if 0:
    images_and_predictions = list(zip(digits.images[n_samples // 2:], predicted))
    for ax, (image, prediction) in zip(axes[1, :], images_and_predictions[:4]):
        ax.set_axis_off()
        ax.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
        ax.set_title('Prediction: %i' % prediction)
    print(digits.target[n_samples // 2:][:4])

    print("Classification report for classifier %s:\n%s\n"
          % (classifier, metrics.classification_report(y_test, predicted)))
    disp = metrics.plot_confusion_matrix(classifier, X_test, y_test)
    disp.figure_.suptitle("Confusion Matrix")
    print("Confusion matrix:\n%s" % disp.confusion_matrix)

    plt.show()

if 0:
    # get image from camera
    cap = cv2.VideoCapture(1)
    cap.set(cv2.CAP_PROP_FRAME_WIDTH,640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT,480)

    while 1:
        ret, frame = cap.read()

        cv2.imshow("webcam", frame)
        if ( cv2.waitKey(1) & 255 ) == ord('q'):
            break

    cv2.imwrite("/tmp10/sample.png", frame )

if 1:
    frame = cv2.imread("../datas/sample4c.png")
    cv2.imshow("sample", frame)

    frame_grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    frame_grey = ~ frame_grey
    print(frame_grey.shape)

    frame_grey = frame_grey[60:-60,:] #remove black border
    cv2.imshow("sample_grey", frame_grey)

    frame_grey = frame_grey[40:-10,40:-70]

    low_lim = 100
    low_lim = 0
    #~ ret,frame_grey = cv2.threshold(frame_grey,low_lim,255,cv2.THRESH_TOZERO)
    ret,frame_grey = cv2.threshold(frame_grey,127,255,cv2.THRESH_BINARY)

    frame_grey_h = frame_grey.copy()
    #~ frame_grey_h = cv2.equalizeHist(frame_grey)

    cv2.imshow("sample_grey_reduced_histo", frame_grey_h )

    sgr = cv2.resize(frame_grey_h,(8,8))
    #~ sgr = digits.images[100]

    print( sgr.dtype )

    # convert sgr to match same style of data than digits
    sgr = sgr.astype(dtype=np.float64)

    sgr /= 16.
    print( "sgr:" + str(sgr.dtype) )
    print( sgr )
    print( "digits...:" + str(digits.images[100].dtype) )
    print( digits.images[100] )

    cv2.imshow("sample_grey_reduced", cv2.resize(sgr,(320,320),interpolation=cv2.INTER_NEAREST ) )
    cv2.imshow("sample as ref", cv2.resize(digits.images[100],(320,320),interpolation=cv2.INTER_NEAREST ) )

    cv2.waitKey(0)

    #~ predicted = classifier.predict(sgr.ravel()) #.ravel().reshape(1, -1)
    predicted = classifier.predict(sgr.ravel().reshape(1, -1))
    print("predicted: %s" % str(predicted) )
    # see confidence
    decision = classifier.decision_function(sgr.ravel().reshape(1, -1))
    decision = np.around(decision,decimals=2)
    decision = list(zip(range(10),decision[0]))
    print("decision: %s" % str(sorted(decision,key=lambda d: d[1], reverse=True) ) )


class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashMap = {}

        for index , value in  enumerate(nums):
            num_needed = target - value
            if num_needed in hashMap:
                return [hashMap[num_needed], index]
            hashMap [value] = index
        return


from threading import *
import time
import cv2
import socket
import io
import pickle
import struct

global connection
global address
cam=cv2.VideoCapture(0)
#stream = io.BytesIO()
client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
client_socket.connect(('192.168.1.5', 9000))#192.168.43.205

cam.set(3, 640);
cam.set(4, 480);

img_counter = 0
print('sending')

while True:
	ret, frame = cam.read()
	data = pickle.dumps(frame, 0)
	size = len(data)

	print("frames:","{}: {}".format(img_counter, size))
	len1=str(size)

	#sending frame size
	client_socket.send(len1.encode())

	#receiving acknowledgement
	ack=client_socket.recv(2)

	#sending frame
	client_socket.send(data)

	buy=client_socket.recv(2)
	print("ack for vinnu: ",buy)

	img_counter += 1
	if cv2.waitKey(1) & 0xFF == ord('q'):
		break

	time.sleep(0.03)

cam.release()


'''class Student(object):#类名开头通常大写
    pass
bart = Student()
bart.name ='Green'
print(bart.name)'''

'''class Student (object):
    def __init__(self,name,score):
        self.name = name
        self.score = score
bart = Student('Green',100)
print(bart.name,bart.score)
def print_score(std):
    print('%s:%s' %(std.name,std.score))
print_score(bart)'''

class Student (object):
    def __init__(self,name,score):
        self.name = name
        self.score = score
    def print_score(self):
        print('%s:%s'%(self.name,self.score))
    def get_grade(self):
        if self.score>90:
            return 'A'
        elif self.score>=60:
            return 'B'
        else:
            return 'C'
bart = Student('Green',18)
bart.print_score()
a = bart.get_grade()
print(a)


__author__ = "maggie.sun@intel.com, ryan.lei@intel.com"

from shutil import copyfile
import fileinput
import os
import re
from Utils import GetShortContentName, ExecuteCmd
from Config import BinPath, LogCmdOnly, LoggerName, HDRTool
import logging

subloggername = "HDRToolsRun"
loggername = LoggerName + '.' + '%s' % subloggername
logger = logging.getLogger(loggername)

HDRToolsConfigFileTemplate = os.path.join(BinPath, 'HDRMetricsYUV420_template.cfg')
HDRToolsMetricsFullList = ['PSNR_Y', 'PSNR_U', 'PSNR_V', 'MS-SSIM_Y', 'MS-SSIM_U',
                           'MS-SSIM_V', 'SSIM_Y', 'SSIM_U', 'SSIM_V']

def GenerateCfgFile(orig_file, rec_file, num, w, h, configpath):
    filename = GetShortContentName(rec_file, False) + '_hdrtools.cfg'
    cfgfile = os.path.join(configpath, filename)
    copyfile(HDRToolsConfigFileTemplate, cfgfile)
    fp = fileinput.input(cfgfile, inplace=1)
    for line in fp:
        if 'Input0File=' in line:
            line = 'Input0File="%s"\n' % orig_file
        if 'Input1File=' in line:
            line = 'Input1File="%s"\n' % rec_file
        if 'NumberOfFrames=' in line:
            line = 'NumberOfFrames=%d\n' % num
        if 'Input0Width=' in line:
            line = 'Input0Width=%d\n' % w
        if 'Input1Width=' in line:
            line = 'Input1Width=%d\n' % w
        if 'Input0Height=' in line:
            line = 'Input0Height=%d\n' % h
        if 'Input1Height=' in line:
            line = 'Input1Height=%d\n' % h
        print(line, end='')
    fp.close()
    return cfgfile

def ParseHDRToolLogFile(logfile):
    flog = open(logfile, 'r')
    pattern = re.compile(r'\d+\.?\d*')
    floats = len(HDRToolsMetricsFullList) * [0.0]
    for line in flog:
        if 'D_Avg' in line:
            floats = [float(i) for i in pattern.findall(line)]
            break

    print_str = "HDRTools qty metrics: "
    for metrics, idx in zip(HDRToolsMetricsFullList,
                            range(len(HDRToolsMetricsFullList))):
        print_str += "%s = %2.5f, " % (metrics, floats[idx])
    logger.info(print_str)
    return floats[0:len(HDRToolsMetricsFullList)]

def GetHDRLogFile(recfile, path):
    filename = GetShortContentName(recfile, False) + '_hdrtools.log'
    file = os.path.join(path, filename)
    return file

################################################################################
##################### Exposed Functions ########################################
def HDRTool_CalQualityMetrics(origfile, recfile, num, w, h, logfilepath,
                              cfgfilepath):
    cfgFile = GenerateCfgFile(origfile, recfile, num, w, h, cfgfilepath)
    logfile = GetHDRLogFile(recfile, logfilepath)
    args = " -f %s > %s" % (cfgFile, logfile)
    cmd = HDRTool + args
    ExecuteCmd(cmd, LogCmdOnly)

def HDRTool_GatherQualityMetrics(recfile, logfilepath):
    logfile = GetHDRLogFile(recfile, logfilepath)
    results = ParseHDRToolLogFile(logfile)
    return results


# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution:

    def __init__(self):
        self.res = list()

    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if not root:
            return 0
        else:
            l=1+self.maxDepth(root.left)
            r=1+self.maxDepth(root.right)
            return max(l,r)

if __name__ == '__main__':
    root1 = TreeNode(3)
    n1 = TreeNode(9)
    root1.left = n1
    n2 = TreeNode(20)
    root1.right = n2
    n2.left = TreeNode(15)
    n2.right = TreeNode(7)

    s = Solution()
    print(s.maxDepth(root1))


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
from clime import Command
from clime.util import *

class TestClime(unittest.TestCase):

    def test_util_autotype(self):
        cases   = ('string', '100', '100.0', None)
        answers = ('string',  100 ,  100.0 , None)
        for case, answer in zip(cases, answers):
            self.assertEqual(autotype(case), answer)

    def test_util_getargspec(self):

        docs = [
            None,
            '',
            'abcd',
            'f1()',
            'f2(x)',
            'f3(x, y)',
            'f4(x[, a])',
            'f5(x, y[, a])',
            'f6(x, y[, a[, b]])',
            'f7([a])',
            'f8([a[, b]])',
        ]

        answers = [
            ([], 0),
            ([], 0),
            ([], 0),
            ([], 0),
            (['x'], 0),
            (['x', 'y'], 0),
            (['x', 'a'], 1),
            (['x', 'y', 'a'], 1),
            (['x', 'y', 'a', 'b'], 2),
            (['a'], 1),
            (['a', 'b'], 2),
        ]

        f = type('Dummy', tuple(), {'__doc__': None})()
        trans = lambda x: (x[0], len(x[-1] or []))

        for doc, answer in zip(docs, answers):
            f.__doc__ = doc
            self.assertEqual(trans(getargspec(f)), answer)

    def test_command_arg_re(self):

        cases = [
            '--key meta',
            '--key=meta',
        ]

        for case in cases:
            self.assertEqual(Command.arg_re.match(case).group('key', 'meta'), ('key', 'meta'))

        cases = [
            '-k meta',
            '-k=meta',
            '-kmeta',
        ]

        for case in cases:
            self.assertEqual(Command.arg_re.match(case).group('key', 'meta'), ('k', 'meta'))

if __name__ == '__main__':
    unittest.main()


import torch
from tqdm import tqdm
from transformers import AutoModelForCausalLM, AutoTokenizer, logging as tf_logging

from model_utils import predict
from utils import (
    HitsMetric,
    adjust_top_k,
    get_args,
    get_filename,
    load_data,
    prepare_input,
    update_history,
    update_metric,
    write_results,
)

tf_logging.set_verbosity_error()

if __name__ == "__main__":
    args = get_args()

    test_data, head_search_space, tail_search_space = load_data(args)

    adjust_top_k(test_data, args)

    tokenizer = AutoTokenizer.from_pretrained(args.model, revision=args.tokenizer_revision)
    tokenizer.pad_token_id = tokenizer.eos_token_id
    model = AutoModelForCausalLM.from_pretrained(
        args.model,
        torch_dtype=torch.float16 if args.fp16 else torch.float32,
        device_map="auto",
    )
    model.eval()
    print(f"model is loaded on device {model.device.type}")

    metric = HitsMetric()
    filename = get_filename(args)
    with torch.no_grad(), open(filename, "w", encoding="utf-8") as writer, tqdm(test_data) as pbar:
        for i, (x, direction) in enumerate(pbar):
            if i % args.world_size != args.rank:
                continue

            if direction == "tail":
                search_space = head_search_space
            elif direction == "head":
                search_space = tail_search_space
            else:
                raise ValueError

            model_input, candidates = prepare_input(x, search_space, args, return_prompt=True)

            predictions = predict(tokenizer, model, model_input, args)

            update_history(x, search_space, predictions, candidates, args)

            example = write_results(x, predictions, candidates, direction, writer, args)

            update_metric(example, metric, args)
            pbar.set_postfix(metric.dump())


#!/usr/bin/python3
# -*-coding:utf-8 -*-

from handler import *

from v1 import *

"""AdminHandler(관리자) """

class AdminHandler:
    def __init__(self):
        pass

    def get_score(self, data):
        """경기일 점수정보"""
        if not data:
            return jsonify({"data": {"games": []}})

        scores = adm.get_scores(data["playdate"])

        return jsonify({"data": {"games": scores}})

    def get_day_games(self, data):
        """경기리스트"""
        if not data:
            return jsonify({"data": {"games": []}})

        scores = adm.get_day_games(data["playdate"])

        return jsonify({"data": {"games": scores}})

    def put_score(self, data):
        """경기스코어 갱신"""
        if not data:
            return jsonify({"data": {"status": 0}})

        dbid = data["id"]
        awayscore = data["awayScore"]
        homescore = data["homeScore"]

        score = adm.put_score(
            {
                "dbid": dbid,
                "awayscore": awayscore,
                "homescore": homescore,
            }
        )

        return jsonify({"data": {"status": score["id"]}})

    def post_new_game(self, data):
        """경기등록"""
        if not data:
            return jsonify({"data": {"status": 0}})

        game = adm.post_new_game(data)

        return jsonify({"data": {"status": game["id"]}})

    def get_users(self, data, args):
        """사용자전체리스트"""
        if not data:
            return jsonify({"users": []})

        users_db = adm.get_users(data, args)

        users = []
        for user in users_db:
            users.append(
                {
                    "id": user["id"],
                    "fcmToken": user["fcmtoken"],
                    "email": user["email"],
                    "regDate": user["regdate"],
                    "team": user["team"],
                    "pagingKey": self.make_paging_keys(user["email"], user["id"]),
                }
            )

        return jsonify({"users": users})

    def make_paging_keys(self, email, user_id):
        email_arr = email.split("@")
        firstKey = email_arr[0][0:2]
        lastKey = email_arr[1][0:2]

        return firstKey + lastKey + str(user_id)

    def get_user_records(self, data):
        """사용자기록리스트"""
        if not data:
            return False

        user_id = data["id"]
        records = adm.get_user_records({"user_id": user_id})

        return jsonify({"res": records})


import pandas as pd
from sklearn.model_selection import train_test_split, cross_val_predict
from sklearn.metrics import classification_report, accuracy_score
from sklearn.utils.validation import column_or_1d
from sklearn.metrics import roc_auc_score, roc_curve
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt

datasets = ["a_affirmative", "a_conditional", "a_doubt_question", "a_emphasis", "a_negative", "a_relative", "a_topics", "a_wh_question", "a_yn_question",
             "b_affirmative", "b_conditional", "b_doubt_question", "b_emphasis", "b_negative", "b_relative", "b_topics", "b_wh_question", "b_yn_question"]

bestsParams = {}

maxd= [20,10,30,30,10,50,10,None,20,20,20,None,None,20,50,20,30,30]
maxf= [4,18,'log2','log2','auto','auto','auto','auto','auto','log2','sqrt',8,4,'log2',None,'log2',14,8]
mins= [12,12,20,20,12,20,20,12,20,20,20,20,12,20,20,20,20,20]
c= ["gini", "entropy","entropy","entropy","gini","gini","gini","entropy","gini","entropy","gini","entropy","gini","entropy","entropy","entropy","gini","gini"]
estimators=[10,20,50,100,200]

# writer= open("ForestPREPROCESSADO/forestparams.txt", "w+")

scorelist = []
combinations = range(0, 5)  # N de combinacoes

plt.title("ROC AUC Score Combinations for Random Forest")
for cnt, d in enumerate(datasets):

    X_train = pd.read_csv("../SplitPreprocessedData/{}_X_train.csv".format(d))
    X_test = pd.read_csv("../SplitPreprocessedData/{}_X_test.csv".format(d))
    y_train = pd.read_csv("../SplitPreprocessedData/{}_y_train.csv".format(d))
    y_train = column_or_1d(y_train, warn=True)
    y_test = pd.read_csv("../SplitPreprocessedData/{}_y_test.csv".format(d))
    y_test = column_or_1d(y_test, warn=True)
    # max_score=0
    # scorelist.clear()
    roc = []
    for e in estimators:

        clf = RandomForestClassifier(n_estimators=e, criterion=c[cnt],min_samples_split=mins[cnt],max_features=maxf[cnt],max_depth=maxd[cnt])
        y_train_proba = cross_val_predict(clf, X_train, y_train, cv=10, method="predict_proba")
        y_scores = y_train_proba[:, 1]
        score = roc_auc_score(y_train, y_scores)
        roc.append(score)
        # if (score > max_score):
        #     bestsParams[d]={
        #             "n_estimators":e,
        #             "ROC":score
        #             }
        #     max_score = score
    plt.plot(combinations, roc, label=d)
    # with open("ForestPREPROCESSADO/{}.txt".format(d), "w+") as wp:
    #     for x in scorelist:
    #         wp.write(str(x))
    #         wp.write('\n')

    # print(d)
    # print('\n')
    # print(str(bestsParams[d]))
    # print('\n')

# for i in bestsParams:
#     writer.write(str(i))
#     writer.write('\n')
#     writer.write(str(bestsParams[i]))
#     writer.write('\n')

# writer.close()

plt.legend()
plt.ylabel("ROC AUC")
plt.xlabel("Combination")
plt.xticks(list(combinations))
plt.legend()

plt.show()


# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def minDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if root == None:
            return 0
        if root.left == None and root.right == None:
            return 1
        nodes = [[root]]
        nextlevel = []
        count = 0
        flag = 0
        while len(nodes[0]) != 0:
            for i in xrange(len(nodes[0])):
                if nodes[0][i].left == None and nodes[0][i].right == None:
                    count += 1
                    flag = 1
                    break
                else:
                    if nodes[0][i].left != None:
                        nextlevel.append(nodes[0][i].left)
                    if nodes[0][i].right != None:
                        nextlevel.append(nodes[0][i].right)
            nodes.append(nextlevel)
            nextlevel = []
            nodes.pop(0)
            if flag == 1:
                return count
                break
            count += 1
        return count

Breadth-first Search/111 - Minimum Depth of Binary Tree.py


import os
import logging
import ycm_core
from collections import defaultdict
from ycmd.completers.general_completer import GeneralCompleter
from ycmd import identifier_utils
from ycmd import utils
from ycmd.utils import ToUtf8IfNeeded
from ycmd import responses

SYNTAX_FILENAME = 'YCM_PLACEHOLDER_FOR_SYNTAX'

class IdentifierCompleter( GeneralCompleter ):
  def __init__( self, user_options ):
    super( IdentifierCompleter, self ).__init__( user_options )
    self._completer = ycm_core.IdentifierCompleter()
    self._tags_file_last_mtime = defaultdict( int )
    self._logger = logging.getLogger( __name__ )
    self._max_candidates = user_options[ 'max_num_identifier_candidates' ]

  def ShouldUseNow( self, request_data ):
    return self.QueryLengthAboveMinThreshold( request_data )

  def ComputeCandidates( self, request_data ):
    if not self.ShouldUseNow( request_data ):
      return []

    completions = self._completer.CandidatesForQueryAndType(
      ToUtf8IfNeeded( utils.SanitizeQuery( request_data[ 'query' ] ) ),
      ToUtf8IfNeeded( request_data[ 'filetypes' ][ 0 ] ) )

    completions = completions[ : self._max_candidates ]
    completions = _RemoveSmallCandidates(
      completions, self.user_options[ 'min_num_identifier_candidate_chars' ] )

    def ConvertCompletionData( x ):
        return responses.BuildCompletionData(
                insertion_text = x,
                extra_menu_info='[ID]' )

    return [ ConvertCompletionData( x ) for x in completions ]

  def AddIdentifier( self, identifier, request_data ):
    try:
      filetype = request_data[ 'filetypes' ][ 0 ]
    except KeyError:
      filetype = None
    filepath = request_data[ 'filepath' ]

    if not filetype or not filepath or not identifier:
      return

    vector = ycm_core.StringVector()
    vector.append( ToUtf8IfNeeded( identifier ) )
    self._logger.info( 'Adding ONE buffer identifier for file: %s', filepath )
    self._completer.AddIdentifiersToDatabase( vector,
                                              ToUtf8IfNeeded( filetype ),
                                              ToUtf8IfNeeded( filepath ) )

  def AddPreviousIdentifier( self, request_data ):
    self.AddIdentifier(
      _PreviousIdentifier(
        self.user_options[ 'min_num_of_chars_for_completion' ],
        request_data ),
      request_data )

  def AddIdentifierUnderCursor( self, request_data ):
    cursor_identifier = _GetCursorIdentifier( request_data )
    if not cursor_identifier:
      return

    self.AddIdentifier( cursor_identifier, request_data )

  def AddBufferIdentifiers( self, request_data ):
    try:
      filetype = request_data[ 'filetypes' ][ 0 ]
    except KeyError:
      filetype = None
    filepath = request_data[ 'filepath' ]
    collect_from_comments_and_strings = bool( self.user_options[
      'collect_identifiers_from_comments_and_strings' ] )

    if not filetype or not filepath:
      return

    text = request_data[ 'file_data' ][ filepath ][ 'contents' ]
    self._logger.info( 'Adding buffer identifiers for file: %s', filepath )
    self._completer.ClearForFileAndAddIdentifiersToDatabase(
        _IdentifiersFromBuffer( text,
                                filetype,
                                collect_from_comments_and_strings ),
        ToUtf8IfNeeded( filetype ),
        ToUtf8IfNeeded( filepath ) )

  def AddIdentifiersFromTagFiles( self, tag_files ):
    absolute_paths_to_tag_files = ycm_core.StringVector()
    for tag_file in tag_files:
      try:
        current_mtime = os.path.getmtime( tag_file )
      except:
        continue
      last_mtime = self._tags_file_last_mtime[ tag_file ]

      # We don't want to repeatedly process the same file over and over; we only
      # process if it's changed since the last time we looked at it
      if current_mtime <= last_mtime:
        continue

      self._tags_file_last_mtime[ tag_file ] = current_mtime
      absolute_paths_to_tag_files.append( ToUtf8IfNeeded( tag_file ) )

    if not absolute_paths_to_tag_files:
      return

    self._completer.AddIdentifiersToDatabaseFromTagFiles(
      absolute_paths_to_tag_files )

  def AddIdentifiersFromSyntax( self, keyword_list, filetypes ):
    keyword_vector = ycm_core.StringVector()
    for keyword in keyword_list:
      keyword_vector.append( ToUtf8IfNeeded( keyword ) )

    filepath = SYNTAX_FILENAME + filetypes[ 0 ]
    self._completer.AddIdentifiersToDatabase( keyword_vector,
                                              ToUtf8IfNeeded( filetypes[ 0 ] ),
                                              ToUtf8IfNeeded( filepath ) )

  def OnFileReadyToParse( self, request_data ):
    self.AddBufferIdentifiers( request_data )
    if 'tag_files' in request_data:
      self.AddIdentifiersFromTagFiles( request_data[ 'tag_files' ] )
    if 'syntax_keywords' in request_data:
      self.AddIdentifiersFromSyntax( request_data[ 'syntax_keywords' ],
                                     request_data[ 'filetypes' ] )

  def OnInsertLeave( self, request_data ):
    self.AddIdentifierUnderCursor( request_data )

  def OnCurrentIdentifierFinished( self, request_data ):
    self.AddPreviousIdentifier( request_data )

# This looks for the previous identifier and returns it; this might mean looking
# at last identifier on the previous line if a new line has just been created.
def _PreviousIdentifier( min_num_candidate_size_chars, request_data ):
  def PreviousIdentifierOnLine( line, column ):
    nearest_ident = ''
    for match in identifier_utils.IdentifierRegexForFiletype(
        filetype ).finditer( line ):
      if match.end() <= column:
        nearest_ident = match.group()
    return nearest_ident

  line_num = request_data[ 'line_num' ] - 1
  column_num = request_data[ 'column_num' ] - 1
  filepath = request_data[ 'filepath' ]
  try:
    filetype = request_data[ 'filetypes' ][ 0 ]
  except KeyError:
    filetype = None

  contents_per_line = (
    request_data[ 'file_data' ][ filepath ][ 'contents' ].split( '\n' ) )

  ident = PreviousIdentifierOnLine( contents_per_line[ line_num ], column_num )
  if ident:
    if len( ident ) < min_num_candidate_size_chars:
      return ''
    return ident

  prev_line = contents_per_line[ line_num - 1 ]
  ident = PreviousIdentifierOnLine( prev_line, len( prev_line ) )
  if len( ident ) < min_num_candidate_size_chars:
    return ''
  return ident

def _RemoveSmallCandidates( candidates, min_num_candidate_size_chars ):
  if min_num_candidate_size_chars == 0:
    return candidates

  return [ x for x in candidates if len( x ) >= min_num_candidate_size_chars ]

def _GetCursorIdentifier( request_data ):
  try:
    filetype = request_data[ 'filetypes' ][ 0 ]
  except KeyError:
    filetype = None
  return identifier_utils.IdentifierAtIndex( request_data[ 'line_value' ],
                                             request_data[ 'column_num' ] - 1,
                                             filetype )

def _IdentifiersFromBuffer( text,
                            filetype,
                            collect_from_comments_and_strings ):
  if not collect_from_comments_and_strings:
    text = identifier_utils.RemoveIdentifierFreeText( text )
  idents = identifier_utils.ExtractIdentifiersFromText( text, filetype )
  vector = ycm_core.StringVector()
  for ident in idents:
    vector.append( ToUtf8IfNeeded( ident ) )
  return vector


from decimal import Decimal
from math import floor
from itertools import chain
import json
from datetime import datetime, timedelta

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, render
from django.utils import timezone
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseServerError
from django.core.urlresolvers import reverse
from django.core.paginator import Paginator, EmptyPage
from django.db.models import Q

from brutils.decorators import access_required
from brutils.generic.views import JSONUpdateView, JSONDeleteView, JSONCreateView, LoginAndSalePrivelege, LoginAndAdminPrivelege, BRListView, StoreLevelObjectMixin
from pos.models import *
from pos.forms import *
from lib.jsonStringify.sales import saleFromJson, jsonFromSale
from lib.jsonStringify.utility import decodeReceivedText
from lib.search import filterGenericSearchQuery, getGenericCrudURLS
from lib.queries import get_query

# Create your views here.
@access_required('sale')
@login_required()
def home(request):
    terminal = Terminal.objects.get_or_create(store=request.store, name=1)
    terminals = Terminal.objects.filter(store=request.store)
    spanSize = int(floor(12/len(terminals))) #for span div
    context = {'terminals': terminals,
               'spanSize': spanSize}
    return render(request, 'pos/dashboard.html', context)

@access_required('sale')
@login_required()
def newSale(request, terminal_id=0):
    Terminal.objects.get_or_create(store=request.store, name=1)
    if terminal_id == 0: #if no terminal_id was passed get the first one
        terminal = Terminal.objects.filter(store=request.store)[0]
    else:
        terminal = get_object_or_404(Terminal, id=terminal_id)
    paymentMethods = PaymentMethod.objects.all().filterReadAll(request.store)
    customerForm = CustomerForm(store=request.store)

    context = {
        'terminal' : terminal,
        'customerForm' : customerForm,
        'paymentMethods': paymentMethods,
    }

    return render(request, 'pos/sales/new.html', context)

@access_required('sale')
@login_required()
def newSaleFromCustomer(request, customer_id, terminal_id=0):
    Terminal.objects.get_or_create(store=request.store, name=1)
    if terminal_id ==0: #if no terminal_id was passed get the first one
        terminal = Terminal.objects.filter(store=request.store)[0]
    else:
        terminal = get_object_or_404(Terminal, id=terminal_id)
    paymentMethods = PaymentMethod.objects.all().filterReadAll(request.store)
    customerForm = CustomerForm(store=request.store)
    customer = get_object_or_404(Customer, id=customer_id)
    sale = Sale(customer=customer)
    salesData = jsonFromSale(sale)

    context = {
        'terminal' : terminal,
        'customerForm' : customerForm,
        'paymentMethods': paymentMethods,
        'salesData': json.dumps(salesData),
    }

    return render(request, 'pos/sales/new.html', context)

@access_required('sale')
@login_required()
def openSale(request, terminal_id, sale_id):
    #base sale items.
    terminal = get_object_or_404(Terminal, id=terminal_id)
    paymentMethods = PaymentMethod.objects.all().filterReadAll(request.store)
    customerForm = CustomerForm(store=request.store)
    #saved sale specific
    sale = get_object_or_404(Sale, id=sale_id)
    printing = range(1, sale.getMostRecentGroupedBy()+1)#iterable for previous invoices
    salesData = jsonFromSale(sale)

    context = {
        'terminal': terminal,
        'customerForm': customerForm,
        'paymentMethods': paymentMethods,
        'walkInCustomerID': 4,
        #loadsale specific
        'sale': sale,
        'salesData': json.dumps(salesData),
        'printing': printing,
        #end
    }

    if sale.status == "COMPLETED":
        return render(request, 'pos/sales/completed.html', context)
    elif sale.status == "QUOTE":
        return render(request, 'pos/sales/new.html', context)
    else: #PENDING
        return render(request, 'pos/sales/pending.html', context)

@access_required('sale')
@login_required()
def saveSale(request, terminal_id):
    staffMember = get_object_or_404(Staff, pk=request.session['staff_id'])
    terminal = get_object_or_404(Terminal, id=terminal_id)
    groupedBy = 0
    if request.method == 'POST':
        if ('salesData' in request.POST) and request.POST['salesData'].strip():
            salesData = json.loads(request.POST['salesData'],encoding="utf-8")
            try:
                prevSale = Sale.objects.get(pk=salesData['id'])
            except Sale.DoesNotExist:
                prevSale = None
            #savesale
            sale = saleFromJson(salesData, terminal, staffMember)
            #create terminal Activity
            term = TerminalActivity.objects.get_or_create(sale=sale, terminal=terminal)[0]
            term.save()
            returnUrls = {
                "storePrint" : reverse('pos:printPaymentReceipt', args=[sale.id, groupedBy]),
                "openSale" : reverse('pos:openSale', args=[terminal.id, sale.id]),
            }
            jsonResponse = json.dumps(returnUrls)
            return HttpResponse(jsonResponse)

@access_required('sale')
@login_required()
def printSummaryReceipt(request, sale_id):
    '''
        0 is a summary of the invoices, anything above 0 will be
        the x payment they made to the sale.
    '''
    sale = Sale.objects.get(pk=sale_id)
    saleLines = SalesLine.objects.filter(sale=sale)
    context = {
        "sale": sale,
        "saleLines": saleLines,
        "payments": sale.getPayments(),
        "servedBy": sale.salesPerson.name
    }
    return render(request, 'pos/sales/print/storeSummary.html', context)

@access_required('sale')
@login_required()
def printPaymentReceipt(request, sale_id, payment_grouping):
    sale = Sale.objects.get(pk=sale_id)
    saleLines = SalesLine.objects.filter(sale=sale)
    groupedBy = int(payment_grouping)
    context = {
        "sale": sale,
        "saleLines": saleLines,
        "payments": sale.getGroupedPayments(groupedBy),
        "paidBefore": sale.getSalePaymentsTill(groupedBy),
        "balanceAfter": sale.getSaleBalanceAfter(groupedBy+1),
        "groupedBy": groupedBy,
        "servedBy": sale.getPaymentServedBy(groupedBy)
    }
    return render(request, 'pos/sales/print/customerReceipt.html', context)

@access_required('sale')
@login_required()
def printLedgerPaymentReceipt(request, customer_id, payment_grouping):
    customer = get_object_or_404(Customer, pk=customer_id)
    account = customer.account
    groupedBy = int(payment_grouping)
    payments = LedgerAccountPayment.objects.all().filter(groupedBy=groupedBy, account=account)
    snapshot = LedgerAccountPaymentSnapshot.objects.get(paymentGrouping=groupedBy)
    context = {
        "snapshot": snapshot,
        "customer": customer,
        "payments": payments,
    }
    return render(request, 'pos/customers/print/accountReceipt.html', context)

@access_required('sale')
@login_required()
def printLedgerAccountSummary(request, customer_id):
    customer = get_object_or_404(Customer, pk=customer_id)
    account = customer.account
    lines = account.getCurrentEntries().exclude(balance=0)
    context = {
        "snapshot": account,
        "customer": customer,
        "lines": lines,
    }
    return render(request, 'pos/customers/print/accountSummary.html', context)

@access_required('sale')
@login_required()
def adjustCreditLimit(request, customer_id):
    customer = get_object_or_404(Customer, pk=customer_id)
    account = customer.account
    if request.POST:
        if 'limit' in request.POST:
            account.creditLimit = Decimal(request.POST['limit'])
            account.save()
            return HttpResponseRedirect(reverse('pos:viewCustomer', args=[customer.id]))

@access_required('sale')
@login_required()
def printProformaInvoice(request, sale_id):
    sale = Sale.objects.get(pk=sale_id)
    saleLines = SalesLine.objects.filter(sale=sale)
    context = {
        "sale": sale,
        "saleLines": saleLines,
    }
    return render(request, 'pos/sales/print/proformaInvoice.html', context)

@access_required('sale')
@login_required()
def printDeliveryDocket(request, sale_id):
    sale = Sale.objects.get(pk=sale_id)
    saleLines = SalesLine.objects.filter(sale=sale)
    context = {
        "sale": sale,
        "saleLines": saleLines,
    }
    return render(request, 'pos/sales/print/deliveryDocket.html', context)

@access_required('sale')
@login_required()
def printTaxInvoice(request, invoice_id):
    invoice = SaleInvoice.objects.get(pk=invoice_id)
    invoiceLines = SaleInvoiceLine.objects.filter(invoice=invoice)
    context = {
        "sale": invoice.sale,
        "saleInvoice": invoice,
        "invoiceLines": invoiceLines
    }
    return render(request, 'pos/sales/print/taxInvoice.html', context)

@access_required('sale')
@login_required()
def deleteSale(request, sale_id):
    sale = get_object_or_404(Sale,pk=sale_id)
    if sale.status == "QUOTE":
        SalesLine.objects.filter(sale=sale).delete()
        sale.delete()
    return HttpResponseRedirect(reverse('pos:home'))

@access_required('sale')
@login_required()
def searchSales(request, sale_type):
    sales = Sale.objects.all().filter(terminal__store=request.store) #filter stores sales.

    if sale_type =="PENDING":
        sales = sales.filter(status="PENDING")
    else:
        sales = sales.filter(status=sale_type)

    context = filterGenericSearchQuery(sales, ['code', 'note', 'customer__firstName', 'customer__lastName', 'salesline__item__model'], request.GET)

    context.update({
        'salesFilter' : sale_type,
        'entityName' : "Sale"
    })

    return render(request, 'pos/sales/search.html', context)

@access_required('sale')
@login_required()
def customerPayment(request, customer_id):
    staffMember = get_object_or_404(Staff, pk=request.session['staff_id'])
    customer = get_object_or_404(Customer, pk=customer_id)
    account = customer.account
    now = timezone.now()
    groupedBy = account.getMostRecentGroupedBy() + 1
    if 'accountPayments' in request.POST:
        accountsPayments = json.loads(request.POST['accountPayments'])
        payments = accountsPayments['paymentLines']
        ledgerEntries = accountsPayments['ledgerEntries']
        for payment in payments:
            paymentMethod = PaymentMethod.objects.get(pk=payment['method_id'])
            ledgerPayment = LedgerAccountPayment(
                account=account,
                amount=payment['amount'],
                date=now,
                receivedBy=staffMember,
                paymentMethod=paymentMethod,
                groupedBy=groupedBy,
            )
            if paymentMethod.id == settings.CREDIT_ID:
                note = CreditNote.objects.get(pk=payment['note_id'])
                note.active = False
                note.save()
                ledgerPayment.notes = payment['note']
            ledgerPayment.save()
        snapshot = LedgerAccountPaymentSnapshot(
            account=account,
            accountTotal=account.getAccountTotal(),
            paidToDate=account.getPaidToDate(),
            balanceDue=account.getAccountBalance(),
            paymentGrouping=groupedBy
        )
        for ledgerEntry in ledgerEntries:
            dbLedgerEntry = LedgerAccountEntry(
                account=account,
                status=ledgerEntry['status'],
                referenceID=ledgerEntry['referenceID'] if ledgerEntry['referenceType'] != 'invoice' else groupedBy,
                referenceNum=ledgerEntry['referenceNum'],
                referenceType=ledgerEntry['referenceType'],
                total=ledgerEntry['total'],
                balance=ledgerEntry['balance'],
                comment=ledgerEntry['comment']
            )
            dbLedgerEntry.save()
            if ledgerEntry['referenceType'] == 'entry':
                relatedTo = LedgerAccountEntry.objects.get(pk=ledgerEntry['referenceID'])
                relatedTo.balance = relatedTo.balance + Decimal(ledgerEntry['total']) #correct the balance of the original entry
                if relatedTo.balance == Decimal('0.00') and ledgerEntry['status'] == 'FINALISED':
                    relatedTo.status = 'FINALISED'
                    for entry in relatedTo.getReferenceEntries(): #change all payments towards this balance to finalised.
                        entry.status = 'FINALISED'
                        entry.save()
                relatedTo.save()
        snapshot.balanceCarried = account.getAccountBalance()
        snapshot.save()
    return HttpResponse(json.dumps({'success': True}))

@access_required('sale')
@login_required()
def newEOD(request, terminal_id):
    terminal = get_object_or_404(Terminal, pk=terminal_id)
    try: #last terminal closure
        lastTerminalClosure = TerminalClosure.objects.filter(terminal=terminal).order_by('-endDate')[:1].get()
        firstDate = lastTerminalClosure.endDate
    except TerminalClosure.DoesNotExist: #first Payment
        try:
            lastPayment = SalesPayment.objects.filter(sale__terminal=terminal).order_by('date')[:1].get()
            firstDate = lastPayment.date
        except SalesPayment.DoesNotExist:
            return HttpResponseServerError()
    endDate = timezone.now()

    excludeMethods = [settings.ACCOUNTS_ID, settings.CREDIT_ID]
    salesPayments = SalesPayment.objects.filter(sale__terminal=terminal, date__range=(firstDate, endDate)).exclude(sale__status="QUOTE")
    readableCustomers = Customer.objects.all().filterReadAll(request.store)
    ledgerAccountPayments = LedgerAccountPayment.objects.filter(date__range=(firstDate, endDate), account__customer__in=readableCustomers)

    allTerminalPaymentsToday = list(chain(salesPayments, ledgerAccountPayments))

    salesPayments = salesPayments.filter(~Q(paymentMethod__in=excludeMethods) & ~Q(paymentMethod__parentMethod__in=excludeMethods))
    ledgerAccountPayments = ledgerAccountPayments.filter(~Q(paymentMethod__in=excludeMethods) & ~Q(paymentMethod__parentMethod__in=excludeMethods))
    NonAccountCreditTerminalPaymentsToday = list(chain(salesPayments, ledgerAccountPayments))

    terminalCounts = []
    paymentLogs = []
    completeTotal = Decimal('0.00')

    for paymentMethod in PaymentMethod.objects.all().filterReadAll(request.store).filter(~Q(id__in=excludeMethods) & ~Q(parentMethod__in=excludeMethods)).exclude(id=settings.CARD_ID):
        filteredPayments = filter(lambda x: x.paymentMethod.id == paymentMethod.id, NonAccountCreditTerminalPaymentsToday)
        if len(filteredPayments) > 1:
            total = reduce(lambda x, y: x.amount + y.amount if hasattr(x, 'amount') else x + y.amount, filteredPayments)
        elif len(filteredPayments) == 1:
            total = filteredPayments[0].amount
        else:
            total = None
        if total is None: total = Decimal('0.00')
        terminalCount = {
            "name": paymentMethod.name,
            "total": total,
            "id": paymentMethod.id,
        }
        completeTotal += total
        terminalCounts.append(terminalCount)

    for payment in allTerminalPaymentsToday:
        paymentLog = {
            "ReceivedBy" : payment.receivedBy.name,
            "PaymentAmount" : payment.amount,
            "PaymentMethod" : payment.paymentMethod.name,
            "DateTime" : payment.date,
        }
        if hasattr(payment, 'sale'):
            paymentLog["InvoiceNum"] = payment.sale.code
        paymentLogs.append(paymentLog)

    context = {
        "endDate" : endDate,
        "startDate" : firstDate,
        "totals" : terminalCounts,
        "completeTotal" : completeTotal,
        "paymentLogs" : paymentLogs,
        "terminal" : terminal,
    }

    return render(request, 'pos/eod/new.html', context)

@access_required('sale')
@login_required()
def saveEOD(request, terminal_id):
    terminal = get_object_or_404(Terminal, pk=terminal_id)
    staffMember = get_object_or_404(Staff, pk=request.session['staff_id'])
    if request.method == "POST":
        if ('EODData' in request.POST) and request.POST['EODData'].strip():
            EODData = json.loads(request.POST['EODData'],encoding="utf-8")
            neweod = TerminalClosure()
            neweod.comment = decodeReceivedText(EODData['comment'])
            neweod.count = EODData['count']
            neweod.difference = EODData['difference']
            neweod.endDate = datetime.now()
            neweod.startDate = EODData['startDate']
            neweod.terminal = terminal
            neweod.status = EODData['status']
            neweod.total = EODData['total']
            neweod.closedBy = staffMember
            neweod.save()
            for count in EODData['TerminalCounts']:
                paymentMethod = get_object_or_404(PaymentMethod,pk=count['id'])
                dbcount = TerminalCount(paymentMethod=paymentMethod)
                dbcount.count = count['count']
                dbcount.difference = count['difference']
                dbcount.eod = neweod
                dbcount.total = count['total']
                dbcount.save()
            term = TerminalActivity.objects.get_or_create(closure=neweod, terminal=terminal)[0]
            term.save()
    returnUrls = {
        "openEOD" : reverse('pos:openEOD', args=[neweod.id]),
    }
    jsonResponse = json.dumps(returnUrls)
    return HttpResponse(jsonResponse)

@access_required('sale')
@login_required()
def openEOD(request, EOD_id):
    eod = get_object_or_404(TerminalClosure, pk=EOD_id)
    terminal = eod.terminal
    terminalPaymentsRange= SalesPayment.objects.filter(sale__terminal=terminal, date__range=(eod.startDate, eod.endDate))
    terminalCounts = []
    paymentLogs = []

    for count in TerminalCount.objects.all().filter(eod=eod):
        terminalCount = {
            "name" : count.paymentMethod.name,
            "total" : count.total,
            "count" : count.count,
            "difference" : count.difference,
            "id" : count.paymentMethod.id,
            }
        terminalCounts.append(terminalCount)

    for payment in terminalPaymentsRange:
        paymentLog = {
            "InvoiceNum" : payment.sale.code,
            "ReceivedBy" : payment.receivedBy.name,
            "PaymentAmount" : payment.amount,
            "PaymentMethod" : payment.paymentMethod.name,
            "DateTime" : payment.date,
            }
        paymentLogs.append(paymentLog)

    context = {
        "endDate" : eod.endDate,
        "startDate" : eod.startDate,
        "comment" : eod.comment,
        "totals" : terminalCounts,
        "completeTotal" : eod.total,
        "paymentLogs" : paymentLogs,
        "terminal" : terminal,
        }

    return render(request, 'pos/eod/load.html', context)

@access_required('sale')
@login_required()
def searchEOD(request):
    storeTerminals = Terminal.objects.filter(store=request.store)
    closures = TerminalClosure.objects.filter(terminal__in=storeTerminals) #filter stores sales.
    startDate = datetime.today() - timedelta(days=120)
    endDate = datetime.today() + timedelta(days=1)
    p = 1

    if ('startDate' in request.POST) and (len(request.POST['startDate'].strip())>0):
        startDate = datetime.strptime(request.POST['startDate'],"%m/%d/%Y")
        endDate = datetime.strptime(request.POST['endDate'],"%m/%d/%Y")
        if startDate > endDate:
            endDate = startDate

    closures = closures.filter(endDate__lte=endDate, endDate__gte=startDate).order_by('-endDate')[:300]

    paginator = Paginator(closures, 30)
    if ('page' in request.POST)  and (len(request.POST['page'].strip())>0):
        p = int(request.POST['page'])
    try:
        closures = paginator.page(p)
    except EmptyPage:
        closures = paginator.page(paginator.num_pages)

    context = {
        'entities': closures,
        'startDate': startDate,
        'endDate': endDate,
        'entityName': "Closure",
        'page': p,
    }

    return render(request, 'pos/eod/search.html', context)

#Payment Methods CRUD
class PaymentMethodCreateView(LoginAndAdminPrivelege, StoreLevelObjectMixin, JSONCreateView):
    model = PaymentMethod
    form_class = PaymentMethodForm

    def form_valid(self, form):
        method = super(PaymentMethodCreateView, self).storeLevelFormSanitize(form)
        method.save()
        return HttpResponse(json.dumps({'success': True, }))

class PaymentMethodUpdateView(LoginAndAdminPrivelege, StoreLevelObjectMixin, JSONUpdateView):
    model = PaymentMethod
    form_class = PaymentMethodForm
    template_name = 'pos/paymentmethod/update.html'

class PaymentMethodDeleteView(LoginAndAdminPrivelege, JSONDeleteView):
    model = PaymentMethod

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        method = self.object
        if SalesPayment.objects.filter(paymentMethod=method).count() or LedgerAccountPayment.objects.filter(paymentMethod=method).count():
            return HttpResponse(json.dumps({'error': 'Payment method has been used in 1 or more Sales - Action Not Completed', }))
        else:
            method.delete()
            return HttpResponse(json.dumps({'success': True, }))
#end of payment methods CRUD

#Customer Crud

class CustomerCreateView(LoginAndSalePrivelege, StoreLevelObjectMixin, JSONCreateView):
    model = Customer
    form_class = CustomerForm

    def form_valid(self, form):
        customer = super(CustomerCreateView, self).storeLevelFormSanitize(form)
        customer.save()
        returnData = {
            "firstContactPoint" : customer.firstContactPoint(),
            "fullName" : customer.firstName + " " + customer.lastName,
            "creditLimit": 0,
            "formattedAddress" : customer.htmlFormattedAddress(),
            "id" : customer.id,
        }
        return HttpResponse(json.dumps(returnData))

class CustomerUpdateView(LoginAndSalePrivelege, StoreLevelObjectMixin, JSONUpdateView):
    model = Customer
    form_class = CustomerForm
    template_name = 'pos/customers/update.html'
    context_object_name = 'customer'

class CustomerDeleteView(LoginAndSalePrivelege, JSONDeleteView):
    model = Customer

    def delete(self, request, *args, **kwargs):
        self.object = self.get_object()
        customer = self.object
        if Sale.objects.filter(customer=customer).count():
            return HttpResponse(json.dumps({'error': 'Customer is attached to one or more Sales - Action Not Completed', }))
        else:
            customer.delete()
            return HttpResponse(json.dumps({'success': True, }))

@access_required('sale')
@login_required()
def viewCustomer(request, customer_id):
    customer = get_object_or_404(Customer, pk=customer_id)
    staffMember = get_object_or_404(Staff, pk=request.session['staff_id'])
    completedSales = Sale.objects.filter(customer=customer, status="COMPLETED")
    allSalesHistory = Sale.objects.filter(customer=customer)
    quotes = allSalesHistory.filter(status="QUOTE")
    openSales = allSalesHistory.filter(status="PENDING")
    creditNotes = CreditNote.objects.filter(customer=customer, active=True) #get only the notes that have not been used.
    paymentMethods = PaymentMethod.objects.all().filterReadAll(request.store)
    form = CustomerForm(instance=customer, store=request.store)
    ledgerAccount = customer.account
    accountPayments = LedgerAccountPayment.objects.filter(account=ledgerAccount).order_by('-date')
    context = {
        'customer': customer,
        'staff': staffMember,
        'ledgerAcc': ledgerAccount,
        'accountPayments': accountPayments,
        'completedSales': completedSales,
        'openSales': openSales,
        'quotes': quotes,
        'paymentMethods': paymentMethods,
        'creditNotes': creditNotes,
        'form': form,
    }
    return render(request, 'pos/customers/view.html', context)

class CustomerSearchView(LoginAndSalePrivelege, BRListView):
    model = Customer
    template_name = 'pos/customers/search.html'
    paginate_by = 30
    context_object_name = 'entities'

    def get_queryset(self):
        #dynamic filter based on request.POST or request.GET
        customers = Customer.objects.all().filterReadAll(self.request.store)
        #search by simple query
        q = self.request.GET.get('q') or self.request.POST.get('q') or ''
        self.context_append['q'] = q
        if len(q.strip()):
            customers = customers.filter(get_query(q, ['firstName', 'lastName', 'address', 'email', 'homePhone', 'workPhone', 'mobile', 'VCN']))
        return customers.order_by('lastName')[:300]

    def get_context_data(self, **kwargs):
        context = super(CustomerSearchView, self).get_context_data(**kwargs)
        context.update(getGenericCrudURLS("Customer", c=True, u=True, d=True, prepend="pos:"))
        context['form'] = CustomerForm(store=self.request.store)
        return context

class CustomerAjaxSearchView(CustomerSearchView):
    template_name = 'pos/customers/search-ajax-main.html'
    context_object_name = 'customer_list'

    def get_context_data(self, **kwargs):
        context = super(CustomerAjaxSearchView, self).get_context_data(**kwargs)
        format = self.request.GET.get('format') or self.request.POST.get('format') or ''
        context['format'] = format
        return context
#end of customer CRUD


import boto3
import numpy as np
from tempfile import  NamedTemporaryFile
from librosa.feature import melspectrogram
import librosa

boto_session = boto3.session.Session(region_name='eu-west-3')
s3 = boto_session.resource('s3')
sukikana_bucket = 'sukikana'

def get_logmels(song_id):
    with NamedTemporaryFile('wb+') as download_file:
        s3.Object(sukikana_bucket, song_id).download_fileobj(download_file)
        download_file.seek(0)
        offset = 0  # np.random.randint(26 * 1000) / 1000.0
        duration = 3.0
        y, sr = librosa.load(download_file.name, offset=offset, duration=duration)
        return np.log10(melspectrogram(y=y, sr=sr, n_fft=1024, hop_length=512, power=2))

if __name__ == '__main__':
    song_id = 'SOAAAKE12A8C1397E9'
    feature_sequence = get_logmels(song_id)


from . import DataProduct
class CTDAS(DataProduct):
  """
  CTDAS CH4 data
  """

  # List of all possible fields we expect from the data
  # (original_name, standard_name, units)
  field_list = (
    ('bio_flux_opt',  'CH4_natural_flux', 'Tg(CH4) year-1'),
    ('anth_flux_opt', 'CH4_fossil_flux',  'Tg(CH4) year-1'),
    ('fire_flux_imp', 'CH4_bioburn_flux', 'Tg(CH4) year-1'),
    ('term_flux_imp', 'CH4_agwaste_flux', 'Tg(CH4) year-1'),
    ('ocn_flux_imp',  'CH4_ocean_flux',   'Tg(CH4) year-1'),
    ('total_flux_opt','CH4_flux',         'Tg(CH4) year-1'),
    ('tempm', 'air_temperature', 'K'),
    ('presm', 'surface_pressure', 'Pa'),
    ('ch4', 'CH4', 'mol mol(semidry_air)-1'),
  )
  # Helper methods

  # Method to open a single file
  @staticmethod
  def open_file (filename):
    from pygeode.formats import netcdf as nc, hdf4
    from os.path import basename, splitext
    from pygeode.timeaxis import StandardTime
    from pygeode.axis import Lat, Lon, ZAxis
    from pygeode.var import Var
    import numpy as np
    # Case 1: netCDF flux file
    if filename.endswith('.nc'):
      f = nc.open(filename)
      # Use the date from the filename.
      yyyymm = splitext(basename(filename))[0].split('_')[-2]
      year = int(yyyymm[:4])
      month = int(yyyymm[4:])
      taxis = StandardTime(year=[year], month=[month], units='days', startdate=dict(year=2000,month=1))
      # Create the time axis.
      f = f.extend(0,taxis)
    # Case 2: HDF4 concentration file
    elif filename.endswith('.hdf'):
      f = hdf4.open(filename)
      # Use the date from the filename.
      yyyymmddhh = splitext(basename(filename))[0].split('_')[-2]
      year = int(yyyymmddhh[:4])
      month = int(yyyymmddhh[4:6])
      day = int(yyyymmddhh[6:8])
      hour = int(yyyymmddhh[8:])
      taxis = StandardTime(year=[year], month=[month], day=[day], hour=[hour], units='days', startdate=dict(year=2000,month=1))
      # Create the time axis.
      f = f.extend(0,taxis)
      # Store the hybrid a/b information for later use.
      at = f.atts['at']
      a = (at[:-1] + at[1:]) / 2
      a = Var(axes=[f.HYBRID], name='a', values=a)
      bt = f.atts['bt']
      b = (bt[:-1] + bt[1:]) / 2
      b = Var(axes=[f.HYBRID], name='b', values=b)
      f = f + a + b
      # Partial decoding of zaxis.
      # Can't create a full Hybrid axis here, because the diagnostic machinery
      # gets confused about the extra A/B auxiliary array.
      f = f.replace_axes(HYBRID=ZAxis)
      # Attach lat/lon  coordinates (for concentration files.)
      # Have to do it here in the opener, because the data_scanner can't handle
      # the default "dummy" lat/lon axes in the file.
      latbounds = np.linspace(-90,90,46)
      lat = (latbounds[:-1] + latbounds[1:]) / 2
      lat = Lat(lat)
      lonbounds = np.linspace(-180,180,61)
      lon = (lonbounds[:-1] + lonbounds[1:]) / 2
      lon = Lon(lon)
      f = f.replace_axes(LATglb600x400=lat, LONglb600x400=lon)

    # Remove idate attribute (causes problems with the data_scanner).
    for var in f:
      var.atts.pop('idate',None)
    return f

  # Method to decode an opened dataset (standardize variable names, and add any
  # extra info needed (pressure values, cell area, etc.)
  @classmethod
  def decode (cls, data):

    from ..common import ndays_in_year, compute_pressure
    from pygeode.axis import Hybrid

    # Apply fieldname conversions
    data = DataProduct.decode.__func__(cls,data)

    # Convert to a dictionary (for referencing by variable name)
    data = dict((var.name,var) for var in data)

    # Add species name for all products (to assist in things like unit conversion)
    for varname in data:
      if varname.startswith('CH4'):
        data[varname].atts['specie'] = 'CH4'
      # Convert units from mass/year to mass/day
      if 'units' in data[varname].atts:
        if data[varname].atts['units'] == 'Tg(CH4) year-1':
          data[varname] = data[varname] / ndays_in_year(data[varname].time)
          data[varname].atts['units'] = 'Tg(CH4) day-1'
          data[varname].atts['specie'] = 'CH4'
      # Add default units to unprocessed data
      else:
        data[varname].atts['units'] = ''

    # Finish defining level coordinates (for concentration files.)
    hybrid = None
    for varname in data:
      if data[varname].hasaxis('HYBRID'):
        if hybrid is None:
          hybrid = Hybrid(data[varname].HYBRID.values, name='hybrid', A=data['a'].get(), B=data['b'].get())
        data[varname] = data[varname].replace_axes(HYBRID=hybrid)
    # Remove a,b variables.
    data.pop('a',None)
    data.pop('b',None)

    # Add pressure field (if not explicitly provided).
    if 'surface_pressure' in data and hybrid is not None:
      #try:
        air_pressure = compute_pressure(hybrid, data['surface_pressure'])
        air_pressure.name = 'air_pressure'
        data['air_pressure'] = air_pressure
      #except (TypeError, ValueError, AttributeError): pass

    # Make sure the variables have the appropriate names
    for name, var in data.iteritems():  var.name = name

    # Add extra fields that will be useful for the diagnostics.
    data = cls._add_extra_fields(data)

    return data

  # Method to find all files in the given directory, which can be accessed
  # through this interface.
  @staticmethod
  def find_files (dirname):
    from glob import glob
    return glob(dirname+"/monthly_CH4_??????_1x1.nc") + glob(dirname+"mmix_??????????_??????????_glb600x400.hdf")

  # Method to find a unique identifying string for this dataset, from the
  # given directory name.
  @staticmethod
  def get_dataname (dirname):
    # No versioning information in directory name, just use interface name.
    return 'CTDAS-CH4'

# Add this interface to the table.
from . import table
table['ctdas-ch4'] = CTDAS


import re
import docutils.core
import docutils.io

import markdown
import textwrap
from rst2html5 import HTML5Writer

import wiki

#===============================================================================
# MARKUP BASE
#===============================================================================

class Markup(object):
    """ Base markup class."""
    NAME = 'Text'
    META_LINE = '%s: %s\n'
    EXTENSION = '.txt'
    HOWTO = """ """

    def __init__(self, raw_content):
        self.raw_content = raw_content

    @classmethod
    def render_meta(cls, key, value):
        return cls.META_LINE % (key, value)

    def process(self):
        """
        return (html, body, meta) where HTML is the rendered output
        body is the the editable content (text), and meta is
        a dictionary with at least ['title', 'tags'] keys
        """
        raise NotImplementedError("override in a subclass")

    @classmethod
    def howto(cls):
        return cls(textwrap.dedent(cls.HOWTO)).process()[0]

#===============================================================================
# MARKDOWN
#===============================================================================

class Markdown(Markup):
    NAME = 'markdown'
    META_LINE = '%s: %s\n'
    EXTENSION = '.md'
    HOWTO = """
        This editor is [markdown][] featured.

            * I am
            * a
            * list

        Turns into:

        * I am
        * a
        * list

        `**bold** and *italics*` turn into **bold** and *italics*. Very easy!

        Create links with `[Wiki](http://github.com/alexex/wiki)`.
        They turn into [Wiki][http://github.com/alexex/wiki].

        Headers are as follows:

            # Level 1
            ## Level 2
            ### Level 3

        [markdown]: http://daringfireball.net/projects/markdown/
        """

    def process(self):
        # Processes Markdown text to HTML, returns original markdown text,
        # and adds meta
        md = markdown.Markdown(['codehilite', 'fenced_code', 'meta'])
        html = md.convert(self.raw_content)
        meta_lines, body = self.raw_content.split('\n\n', 1)
        meta = md.Meta
        return html, body, meta

#===============================================================================
# RESTRUCTURED TEXT
#===============================================================================

class RestructuredText(Markup):
    NAME = 'restructuredtext'
    META_LINE = '.. %s: %s\n'
    IMAGE_LINE = '.. image:: %(url)s'
    LINK_LINE = '`%(filename)s <%(url)s>`_'

    EXTENSION = '.rst'
    HOWTO = """
        This editor is `reStructuredText`_ featured::

            * I am
            * a
            * list

        Turns into:

        *  I am
        *  a
        *  list

        ``**bold** and *italics*`` turn into **bold** and *italics*. Very easy!

        Create links with ```Wiki <http://github.com/alexex/wiki>`_``.
        They turn into `Wiki <https://github.com/alexex/wiki>`_.

        Headers are just any underline (and, optionally, overline).
        For example::

            Level 1
            *******

            Level 2
            -------

            Level 3
            +++++++

        .. _reStructuredText: http://docutils.sourceforge.net/rst.html
        """

    def process(self):
        settings = {'initial_header_level': 2,
                    'record_dependencies': True,
                    'stylesheet_path': None,
                    'link_stylesheet': True,
                    'syntax_highlight': 'short',
                    }

        html = self._rst2html(self.raw_content,
                              settings_overrides=settings)

        # Convert unknow links to internal wiki links.
        # Examples:
        #   Something_ will link to '/something'
        #  `something great`_  to '/something_great'
        #  `another thing <thing>`_  '/thing'
        refs = re.findall(r'Unknown target name: "(.*)"', html)
        if refs:
            content = self.raw_content + self.get_autolinks(refs)
            html = self._rst2html(content, settings_overrides=settings)
        meta_lines, body = self.raw_content.split('\n\n', 1)
        meta = self._parse_meta(meta_lines.split('\n'))
        return html, body, meta

    def get_autolinks(self, refs):
        autolinks = '\n'.join(['.. _%s: /%s' % (ref, wiki.urlify(ref, False))
                               for ref in refs])
        return '\n\n' + autolinks

    def _rst2html(self, source, source_path=None,
                  source_class=docutils.io.StringInput,
                  destination_path=None, reader=None, reader_name='standalone',
                  parser=None, parser_name='restructuredtext', writer=None,
                  writer_name=None, settings=None, settings_spec=None,
                  settings_overrides=None, config_section=None,
                  enable_exit_status=None):

        if not writer:
            writer = HTML5Writer()

        # Taken from Nikola
        # http://bit.ly/14CmQyh
        output, pub = docutils.core.publish_programmatically(
            source=source, source_path=source_path, source_class=source_class,
            destination_class=docutils.io.StringOutput,
            destination=None, destination_path=destination_path,
            reader=reader, reader_name=reader_name,
            parser=parser, parser_name=parser_name,
            writer=writer, writer_name=writer_name,
            settings=settings, settings_spec=settings_spec,
            settings_overrides=settings_overrides,
            config_section=config_section,
            enable_exit_status=enable_exit_status)
        return pub.writer.parts['body']

    def _parse_meta(self, lines):
        """ Parse Meta-Data. Taken from Python-Markdown"""
        META_RE = re.compile(r'^\.\.\s(?P<key>.*?): (?P<value>.*)')
        meta = {}
        key = None
        for line in lines:
            if line.strip() == '':
                continue
            m1 = META_RE.match(line)
            if m1:
                key = m1.group('key').lower().strip()
                value = m1.group('value').strip()
                try:
                    meta[key].append(value)
                except KeyError:
                    meta[key] = [value]
        return meta

#===============================================================================
# MAIN
#===============================================================================

if __name__ == "__main__":
    print(__doc__)


#!/usr/bin/env python
# coding: utf-8

# # Introduction

#

#
#
# **What?** self and __init__
#
#
#

# # Create a class

#

#
#
# - So in python everything is an object, but classess and objects are not exactly the same thing. You can create an object instantiating a class though.
# - Classes can be thought as **blueprint** for creating object. In other words, I've created a sort of instruction manual for constructing a customer object.
#
#
#

# In[2]:

class Customer(object):
    """A customer of ABC bank with a checking. account.

    Customer have the following propperties:

    Atributes:
        name: a string representing the custome name
        balance: a float. tracking the current balance of the customer's account
    """

    def __init__(self, name, balance = 0.0):
        """Object initialisation.

        Returns a customers objkect whose name is name and stating
        balance is balance.
        """

        self.name = name
        self.balance = balance

    def withdraw(self, amount):
        """Withdraw.

        Returns the balance remaininga fter withdrawing ana mount.
        """

        if amount > self.balance:
            raise RuntimeError("Amount requested is greater than the current balance")
        self.balance -= amount

        return self.balance

    def deposit(self, amount):
        """Deposit.

        Returns the balance remaining after depositing some monies.
        """

        self.balance += amount

        return sel.balance

#

#
#
# - The class `Customer(object)` does not create a new customer, as we have created a blueprint only.
# - How do we create a real customer then? We;ll have to call the special class method `__init__` to create one.
# - This method is call automtically when we. instantiate the obejct with (for instance) `Customer("Charlier", 100)`. This is saying "hey create a customer named Charlie with 100GBP in his account!.
#
#
#

# In[26]:

custormerA = Customer("Charlier", 100)
custormerB = Customer("Maria", 200)
customerNull = Customer("Null")

# In[27]:

custormerA.__dict__

# In[28]:

custormerB.__dict__

# In[29]:

customerNull.__dict__

# # What is self?

#

#
#
# - `self` is the instance itself!
# - When we say `withdraw(self, amount)`, we're saying: "here's how you  withdraw money from a Customer object (called `self`) and a money figure (called amount)."
# - Put in another way `customerA.withdraw(10)` is totally equivalent to `Customer.withdraw(customerA, 10)`.
# - But how can pass `customerA` is there is not `customerA` as yet? This is where `__init__` comes in.
#
#
#

# # What is _ _init_ _ ?

#

#
#
# - Python allows us to extend the `self` pattern also to objects that are being constructed.
# - **This is the reason why** when we call `__init__` we initialise object by saying `self.name = name`.
#
#
#

# # References

#

#
#
# - Jeff Knupp, Everything I know about Python, old blog post no longer available online?
#
#
#

# In[ ]:


import xml.etree.ElementTree as ET
from subprocess import check_output

import logging
logger = logging.getLogger(__name__)

class AEMetric(object):
    # command to run official eval.jar to get f1 score
    commands = {
        "rest": "./java -cp reviewlab/eval/A.jar absa16.Do Eval -prd data/ft/ae/16/rest/rest_pred.xml -gld data/ft/ae/16/rest/EN_REST_SB1_TEST.xml.gold -evs 2 -phs A -sbt SB1",
        "laptop": "./java -cp reviewlab/eval/eval.jar Main.Aspects data/ft/ae/14/laptop/laptop_pred.xml data/ft/ae/14/laptop/Laptops_Test_Gold.xml"

    }

    templates = {
        "rest": "data/ft/ae/16/rest/EN_REST_SB1_TEST.xml.A",
        "laptop": "data/ft/ae/14/laptop/Laptops_Test_Data_PhaseA.xml"
    }

    @classmethod
    def metric_name(cls, index):
        if index == 0:
            return "f1"
        else:
            raise Exception("unknown index")

    @classmethod
    def append_helper(cls, ix, tag_on, domain, sent, start, opins):
        end = ix
        tag_on = False
        if domain == 'rest':
            opin = ET.Element("Opinion")
            opin.attrib['target'] = sent.find('text').text[start:end]
        elif domain == 'laptop':
            opin = ET.Element("aspectTerm")
            opin.attrib['term'] = sent.find('text').text[start:end]
        opin.attrib['from'] = str(start)
        opin.attrib['to'] = str(end)
        opins.append(opin)
        return end, tag_on, opins

    @classmethod
    def label_xml(cls, fn, output_fn, corpus, label, domain):
        dom = ET.parse(fn)
        root = dom.getroot()
        pred_y = []
        for zx, sent in enumerate(root.iter("sentence")):
            tokens = corpus[zx]
            lb = label[zx]
            if domain == 'rest':
                opins = ET.Element("Opinions")
            elif domain == 'laptop':
                opins = ET.Element("aspectTerms")
            token_idx, pt, tag_on = 0, 0, False
            start, end = -1, -1
            for ix, c in enumerate(sent.find('text').text):
                if token_idx < len(tokens) and pt >= len(tokens[token_idx]):
                    pt = 0
                    token_idx += 1

                case_1 = token_idx < len(tokens) and lb[token_idx] == 1 and pt == 0 and c != ' '
                case_2 = token_idx < len(tokens) and lb[token_idx] == 2 and pt == 0 and c != ' ' and not tag_on
                case_3 = token_idx < len(tokens) and (lb[token_idx] == 0 or lb[token_idx] == 1) and tag_on and pt == 0
                case_4 = token_idx >= len(tokens) and tag_on

                if (case_1 and tag_on) or case_3 or case_4:
                    end, tag_on, opins = AEMetric.append_helper(ix, tag_on, domain, sent, start, opins)

                if case_1 or case_2:
                    start = ix
                    tag_on = True

                quote_marks = ['``', "''"]
                if c == ' ':
                    pass
                elif tokens[token_idx][pt:pt + 2] in quote_marks:
                    pt += 2
                else:
                    pt += 1
            if tag_on:
                end, tag_on, opins = AEMetric.append_helper(len(sent.find('text').text), tag_on, domain, sent, start, opins)
            sent.append(opins)
        dom.write(output_fn)

    @classmethod
    def evaluate(cls, config, pred_json):
        y_pred = [[pred_json["labels"].index(pred) for pred in preds] for preds in pred_json["preds_list"]]

        command = AEMetric.commands[config.domain].split()
        if config.domain == "rest":
            AEMetric.label_xml(AEMetric.templates[config.domain], command[6], pred_json["sentence"], y_pred, config.domain)
            result = check_output(command).split()
            logger.info("**** java output ****")
            logger.info("%s", result)
            return [float(result[9][10:])]
        elif config.domain == "laptop":
            AEMetric.label_xml(AEMetric.templates[config.domain], command[4], pred_json["sentence"], y_pred, config.domain)
            result = check_output(command).split()
            logger.info("**** java output ****")
            logger.info("%s", result)
            return [float(result[15])]
        else:
            raise ValueError("unknown domain %s.", config.domain)


import discord
import logging
import asyncio

import settings as stg
import db_handler
from module_registry import get_default_registry
from unz_modules import UnzBaseModule, EventHandlerStatus

logging.basicConfig(
    level=stg.LOG_LEVEL,
    format=stg.LOG_FORMAT,
    datefmt=stg.LOG_DATEFMT,
    handlers=[
        logging.FileHandler(
            stg.LOG_FILENAME,
            mode=stg.LOG_FILEMODE
        ),
        logging.StreamHandler()
    ]
)

client = discord.Client()
with open("SECRET") as f:
    SECRET = f.readline().strip()

registry = get_default_registry()
database = db_handler.load_or_create()
UnzBaseModule.global_data = database.get("unz_global", {})
loaded_modules = []
for modname in stg.LOADED_MODULES:
    config = stg.MODULE_CONFIG.get(modname, {})
    loaded_modules.append(registry.get_module(modname)(database, config))

@client.event
async def on_ready():
    app_info = await client.application_info()
    logging.info(f"Client logged in as {app_info.name}")

    for module in loaded_modules:
        status = await module.event_on_ready(client)
        if status is not None and status == EventHandlerStatus.BLOCK:
            break

@client.event
async def on_message(message):
    if message.author == client.user or not message.content:
        return
    if type(message.channel) == discord.TextChannel:
        log_msg = f"Message :: {message.channel.name} ({message.channel.id}) :: {message.author} ({message.author.id}) :: {message.content}"
    else:
        log_msg = f"Message :: {message.channel.id} :: {message.author} ({message.author.id}) :: {message.content}"
    logging.info(log_msg)
    for module in loaded_modules:
        status = await module.event_on_message(message, client)
        if status is not None and status == EventHandlerStatus.BLOCK:
            break

@client.event
async def on_disconnect():
    db_handler.save(database, loaded_modules)

async def db_saver():
    await client.wait_until_ready()
    while not client.is_closed():
        db_handler.save(database, loaded_modules)
        await asyncio.sleep(stg.DB_AUTOSAVE_INTERVAL)

async def secondary_loop():
    await client.wait_until_ready()
    time = 0
    seconds_to_wait = 1000
    while not client.is_closed():
        for module in loaded_modules:
            interval = module.secondary_interval
            if interval == 0:
                continue

            if time % interval == 0:
                await module.loop_function(client)

            next_rep = (int(time / interval) + 1) * interval
            seconds_to_wait = min((seconds_to_wait, next_rep-time))

        await asyncio.sleep(seconds_to_wait)
        seconds_to_wait = 1000

if __name__ == "__main__":
    client.loop.create_task(db_saver())
    client.loop.create_task(secondary_loop())
    client.run(SECRET)


from __future__ import annotations

import logging
from pathlib import Path
from typing import TYPE_CHECKING

import pytest

from pyk.kcfg.show import KCFGShow
from pyk.proof import APRProof, APRProver, ProofStatus
from pyk.proof.show import APRProofNodePrinter
from pyk.testing import KCFGExploreTest, KProveTest
from pyk.utils import single

from ..utils import K_FILES

if TYPE_CHECKING:
    from collections.abc import Iterable
    from typing import Final, Union

    from pytest import TempPathFactory

    from pyk.kcfg import KCFGExplore
    from pyk.ktool.kprove import KProve

    STATE = Union[tuple[str, str], tuple[str, str, str]]

_LOGGER: Final = logging.getLogger(__name__)

APR_PROVE_TEST_DATA: Iterable[tuple[str, Path, str, str, int | None, int | None, Iterable[str], ProofStatus, int]] = (
    (
        'ensures-constraint-simplification',
        K_FILES / 'mini-kevm-spec.k',
        'MINI-KEVM-SPEC',
        'ensures-constraint',
        2,
        1,
        [],
        ProofStatus.PASSED,
        1,
    ),
)

def leaf_number(proof: APRProof) -> int:
    non_target_leaves = [nd for nd in proof.kcfg.leaves if not proof.is_target(nd.id)]
    return len(non_target_leaves) + len(proof.kcfg.predecessors(proof.target))

class TestMiniKEVM(KCFGExploreTest, KProveTest):
    KOMPILE_MAIN_FILE = K_FILES / 'mini-kevm.k'

    @pytest.mark.parametrize(
        'test_id,spec_file,spec_module,claim_id,max_iterations,max_depth,cut_rules,proof_status,expected_leaf_number',
        APR_PROVE_TEST_DATA,
        ids=[test_id for test_id, *_ in APR_PROVE_TEST_DATA],
    )
    def test_all_path_reachability_prove(
        self,
        kprove: KProve,
        kcfg_explore: KCFGExplore,
        test_id: str,
        spec_file: str,
        spec_module: str,
        claim_id: str,
        max_iterations: int | None,
        max_depth: int | None,
        cut_rules: Iterable[str],
        proof_status: ProofStatus,
        expected_leaf_number: int,
        tmp_path_factory: TempPathFactory,
    ) -> None:
        with tmp_path_factory.mktemp('apr_tmp_proofs') as proof_dir:
            claim = single(
                kprove.get_claims(
                    Path(spec_file), spec_module_name=spec_module, claim_labels=[f'{spec_module}.{claim_id}']
                )
            )
            proof = APRProof.from_claim(
                kprove.definition,
                claim,
                subproof_ids=[],
                logs={},
                proof_dir=proof_dir,
            )

            new_init_cterm = kcfg_explore.cterm_assume_defined(proof.kcfg.node(proof.init).cterm)
            proof.kcfg.replace_node(proof.init, new_init_cterm)
            kcfg_explore.simplify(proof.kcfg, {})

            prover = APRProver(
                proof,
                kcfg_explore=kcfg_explore,
            )
            prover.advance_proof(max_iterations=max_iterations, execute_depth=max_depth, cut_point_rules=cut_rules)

            kcfg_show = KCFGShow(
                kcfg_explore.kprint,
                node_printer=APRProofNodePrinter(proof, kcfg_explore.kprint, full_printer=True, minimize=False),
            )
            cfg_lines = kcfg_show.show(proof.kcfg)
            _LOGGER.info('\n'.join(cfg_lines))

            assert proof.status == proof_status
            assert leaf_number(proof) == expected_leaf_number


from rest_framework import viewsets
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import IsAuthenticated

from api.permissions import OnlyAuthorChangeContent
from api.serializers import PostSerializer, GroupSerializer, CommentSerializer
from posts.models import Post, Group

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [OnlyAuthorChangeContent, IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

class GroupReadOnlyViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

class CommentViewSet(viewsets.ModelViewSet):
    serializer_class = CommentSerializer
    permission_classes = [OnlyAuthorChangeContent, IsAuthenticated]

    def post_obj(self):
        queryset = get_object_or_404(Post, id=self.kwargs.get('post_id'))
        return queryset

    def get_queryset(self):
        queryset = self.post_obj().comments.all()
        return queryset

    def perform_create(self, serializer):
        serializer.save(author=self.request.user, post=self.post_obj())


import unittest
import random

class Mean:
    def __init__(self, message):
        self.message = message

    def __enter__(self):
        return self

    def __exit__(self, a, b, c):
        print("exit a=" + str(a) + ", b=" + str(b) + ", c=" + str(c) )
        self.message = None

    def getString(self):
        if(random.random() > 0.5):
            return self.message
        else:
            raise ArithmeticError("Mean error")

def piDigits():
    str = "3.14159265359"[2:]
    for char in str:
        yield char

class Contacts():

    names = ["Alan", "Benjamin", "Charlotte"]

    def __init__(self):
        print("init")

    def __iter__(self):
        return ContactsIterator()

class ContactsIterator():

    def __init__(self):
        self.i = 0;

    def __next__(self):

        if(self.i == len(Contacts.names)):
            raise StopIteration

        name = Contacts.names[self.i]
        self.i = self.i+1
        return name

class TestIdioms( unittest.TestCase ):

    def test_tuples(self):
        ita = tuple( ["Italy", 60E6, "+39", "EU"] )
        fra = tuple( ["France", 70E6, "+34", "EU"] )
        txs = tuple( ["Texas", 8E6, "+1", "US"] )
        self.assertEqual( ita[3], "EU" )
        self.assertEqual( ita[3], fra[3] )

    def test_mean_object(self):
        try:
            with Mean("I'm mean") as mean:
                print(mean.getString())
        except:
            pass

    def test_pi_generator(self):
        digits = []
        for d in piDigits():
            digits.append( d )

        self.assertEqual( '1', digits[0] )
        self.assertEqual( '4', digits[1] )
        self.assertEqual( '1', digits[2] )
        self.assertEqual( '5', digits[3] )

    def test_is(self):

        numberA = 5
        numberB = 5

        self.assertIs(numberA, numberB)
        self.assertEqual(numberA, numberB)

        stringA = "hello"
        stringB = "hello"

        self.assertIs(stringA, stringB)
        self.assertEqual(stringA, stringB)

        listA = [stringA, numberA]
        listB = [stringB, numberB]

        self.assertIsNot(listA, listB)
        self.assertEqual(listA, listB)

    def test_contacts_as_iterable(self):
        contacts = Contacts();

        expected = []
        for contact in contacts:
            expected.append(contact)

        self.assertEqual( "Alan", expected[0] )
        self.assertEqual( "Benjamin", expected[1] )
        self.assertEqual( "Charlotte", expected[2] )

if __name__ == '__main__':
    unittest.main()


import sys
import random

while True:
    line = input()

    n = int(line.split()[0])

    for i in range(n):
        line = input()

    m = int(input())

    for i in range(m):
        line = input()

    # use file=sys.stderr to print for debugging
    print("debug code", file=sys.stderr, flush=True)

    # this will choose one of random actions
    print("100 100 200 200", flush=True)