from django.shortcuts import render
from django.http import JsonResponse, HttpResponseNotFound
from django.contrib.auth.models import User, Group

from topicyeucau.models import Topic, MyTopic, Rating
from django.db.models import Count, Q

import datetime, numpy as np

# Create your views here.
def index(request):

    year = request.GET.get('year') or datetime.datetime.now().year
    topic_total = [0] * 12
    topic_done = [0] * 12

    query = Topic.objects.filter(start_time__year=year).values('start_time__month').annotate(total=Count('id'))
    for report in query:
        month = report.get('start_time__month')
        count = report.get('total')
        topic_total[month - 1] = count

    query = MyTopic.objects.filter(start_time__year=year).values('start_time__month').annotate(total=Count('id', filter=Q(status="Hoàn thành")))
    for report in query:
        month = report.get('start_time__month')
        count = report.get('total')
        topic_done[month - 1] = count

    return JsonResponse(data={
        'topic_total_set': topic_total,
        'topic_done_set': topic_done,
    })

def employee_ranking(request):

    year = request.GET.get('year') or datetime.datetime.now().year
    query = MyTopic.objects.filter(start_time__year=year).values('employee').annotate(count=Count('id', filter=Q(status="Hoàn thành")))
    ranking = []
    for report in query:
        employee_id = report.get('employee')
        if employee_id is None: continue
        employee_name = User.objects.get(pk=employee_id).userprofile.name
        employee_avatar = User.objects.get(pk=employee_id).userprofile.avatar.url
        count = report.get('count')
        record = dict(
            id=employee_id,
            name=employee_name,
            avatar=employee_avatar,
            count=count,
            rank=0,
        )
        ranking.append(record)

    ranking.sort(key=lambda record: record.get('count'), reverse=True)
    rank = 0
    last_count = None
    for r in ranking:
        if last_count is None or r.get('count') < last_count:
            rank +=1
            last_count = r.get('count')

        r['rank'] = rank

    return JsonResponse(ranking, safe=False)

def get_employee_report(request):

    year = request.GET.get('year') or datetime.datetime.now().year
    emp_id = request.GET.get('emp_id')

    if emp_id is None: return HttpResponseNotFound()
    employee = User.objects.get(pk=emp_id)
    if employee is None or not employee.groups.filter(pk=3).first(): return HttpResponseNotFound()

    query = MyTopic.objects.filter(start_time__year=year, status="Hoàn thành", employee=emp_id).values('start_time__month').annotate(count=Count('id'))
    dataset = [0] * 12

    for report in query:
        month = report.get('start_time__month')
        dataset[month - 1] = report.get('count')

    return JsonResponse(data=dict(
        employee=dict(name=employee.userprofile.name),
        dataset=dataset,
    ))

def get_member_ranking(request):

    year = request.GET.get('year') or datetime.datetime.now().year
    month = request.GET.get('month') or datetime.datetime.now().month

    query = Topic.objects.filter(start_time__year=year, start_time__month=month).values('author').annotate(count=Count('id'))
    ranking = []
    for report in query:
        author_id = report.get('author')
        if author_id is None: continue
        _name = User.objects.get(pk=author_id).userprofile.name
        _avatar = User.objects.get(pk=author_id).userprofile.avatar.url
        count = report.get('count')
        record = dict(
            id=author_id,
            name=_name,
            avatar=_avatar,
            count=count,
            rank=0,
        )
        ranking.append(record)

    ranking.sort(key=lambda record: record.get('count'), reverse=True)
    rank = 0
    last_count = None
    for r in ranking:
        if last_count is None or r.get('count') < last_count:
            rank +=1
            last_count = r.get('count')

        r['rank'] = rank

    return JsonResponse(ranking, safe=False)

def get_rating_on_month(request):

    year = request.GET.get('year') or datetime.datetime.now().year
    month = request.GET.get('month') or datetime.datetime.now().month

    query = Rating.objects.filter(
        topic__start_time__year=year,
        topic__start_time__month=month,
    ).values('score').annotate(count=Count('id'))

    converted = [0] * 6
    for v in query:
        score = int(v.get('score'))
        subcount = v.get('count')
        if score != 0: converted[score] = subcount

    # Chưa đánh giá bao gồm các topic đã hoàn thành nhưng chưa có rating
    total_done_count = MyTopic.objects.filter(
        topic__start_time__year=year,
        topic__start_time__month=month,
        status='Hoàn thành',
    ).count()
    converted[0] = total_done_count - sum(converted)

    data_in_month = converted

    return JsonResponse(data=data_in_month, safe=False)

def get_rating_on_year(request):

    year = request.GET.get('year') or datetime.datetime.now().year

    stars = dict()
    stars[0] = [0] * 12
    stars[1] = [0] * 12
    stars[2] = [0] * 12
    stars[3] = [0] * 12
    stars[4] = [0] * 12
    stars[5] = [0] * 12

    query = Rating.objects.filter(
        topic__start_time__year=year,
    ).values('topic__start_time__month', 'score').annotate(count=Count('id'))
    total = 0
    for v in query:
        score = v.get('score')
        month = v.get('topic__start_time__month')
        subcount = v.get('count')
        if score != 0:
            stars[score][month - 1] = subcount
            total += subcount

    # Chưa đánh giá bao gồm các topic đã hoàn thành nhưng chưa có rating
    query = MyTopic.objects.filter(
        topic__start_time__year=year,
        status='Hoàn thành',
    ).values('topic__start_time__month').annotate(count=Count('id'))
    stars = np.asarray([row for row in stars.values()], dtype=np.int32)
    for v in query:
        month = v.get('topic__start_time__month')
        subcount = v.get('count')
        stars[0, month - 1] = subcount - sum(stars[1:, month - 1])

    return JsonResponse(data=dict(data=stars.tolist(), total=total), safe=False)


import autokeras as ak
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler, RobustScaler
##
# Load and preprocess the data
train_csv = pd.read_csv('d:/study/_data/dacon_diabetes/train.csv', index_col=0)
train_csv = train_csv.dropna()
x = train_csv.drop(['Outcome'], axis=1)
y = train_csv['Outcome']
scaler = MinMaxScaler()
x = scaler.fit_transform(x)
x_train, x_test, y_train, y_test = train_test_split(x, y, shuffle=True, train_size=0.7, random_state=777)
scaler = RobustScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

# Train the model
model = ak.StructuredDataClassifier(overwrite=False, max_trials=2)
model.fit(x_train, y_train, epochs=10, validation_split=0.15)

# Export and save the best model
best_model = model.export_model()
best_model.save('path_to_save_model', save_format='tf')

# Evaluate the model
y_predict = model.predict(x_test)
results = model.evaluate(x_test, y_test)
print('Model results:', results)


import cv2
import numpy as np
import os

# Create the directory structure
paths=["data","data/train","data/test","data/train/okay","data/train/peace","data/train/Clenched_fist","data/train/ILY","data/train/Thumb_up","data/test/okay","data/test/peace","data/test/Clenched_fist","data/test/ILY","data/test/Thumb_up"]

for p in paths:
    if not os.path.exists(p):
        os.makedirs(p)

# Train or test
mode = 'train'
directory = 'data/'+mode+'/'

cap = cv2.VideoCapture(0)

print("Press 1 to save OKAY")
print("Press 2 to save PEACE")
print("Press 3 to save CLENCHED_FIST")
print("Press 4 to save ILY")
print("Press 5 to save for THUMB_UP")

while True:
    _, frame = cap.read()
    # Simulating mirror image
    #frame = cv2.flip(frame, 1)

    # Getting count of existing images
    count = {'okay': len(os.listdir(directory+"/okay")),
             'peace': len(os.listdir(directory+"/peace")),
             'Clenched_fist': len(os.listdir(directory+"/Clenched_fist")),
             'ILY': len(os.listdir(directory+"/ILY")),
             'Thumb_up': len(os.listdir(directory+"/Thumb_up")),
             }

    # Printing the count in each set to the screen
    cv2.putText(frame, "MODE : "+mode, (int(0.5*frame.shape[1])+20, 50), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "IMAGE COUNT", (int(0.5*frame.shape[1])+20, 100), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "OKAY : "+str(count['okay']), (int(0.5*frame.shape[1])+20, 120), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "PEACE : "+str(count['peace']), (int(0.5*frame.shape[1])+20, 140), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "Clenched Fist : "+str(count['Clenched_fist']), (int(0.5*frame.shape[1])+20, 160), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "ILY : "+str(count['ILY']), (int(0.5*frame.shape[1])+20, 180), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)
    cv2.putText(frame, "Thumb Up : "+str(count['Thumb_up']), (int(0.5*frame.shape[1])+20, 200), cv2.FONT_HERSHEY_PLAIN, 1, (0,0,0), 1)

    # Coordinates of the ROI (Region Of Interest)
    x1 = 10
    y1 = 10
    x2 = int(0.5*frame.shape[1])
    y2 = int(0.5*frame.shape[1])
    # Drawing the ROI
    # The increment/decrement by 1 is to compensate for the bounding box
    cv2.rectangle(frame, (x1-1, y1-1), (x2+1, y2+1), (255,0,0) ,1)
    #ROI
    roi = frame[y1:y2, x1:x2]
    roi = cv2.resize(roi, (64, 64))

    cv2.imshow("Frame", frame)

    roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
    _, roi = cv2.threshold(roi, 120, 255, cv2.THRESH_BINARY)
    cv2.imshow("ROI", roi)

    interrupt = cv2.waitKey(10)
    if interrupt & 0xFF == 27: # escape key
        break
    if interrupt & 0xFF == ord('1'):
        cv2.imwrite(directory+'okay/'+str(count['okay'])+'.jpg', roi)
    if interrupt & 0xFF == ord('2'):
        cv2.imwrite(directory+'peace/'+str(count['peace'])+'.jpg', roi)
    if interrupt & 0xFF == ord('3'):
        cv2.imwrite(directory+'Clenched_fist/'+str(count['Clenched_fist'])+'.jpg', roi)
    if interrupt & 0xFF == ord('4'):
        cv2.imwrite(directory+'ILY/'+str(count['ILY'])+'.jpg', roi)
    if interrupt & 0xFF == ord('5'):
        cv2.imwrite(directory+'Thumb_up/'+str(count['Thumb_up'])+'.jpg', roi)

cap.release()
cv2.destroyAllWindows()


import PIL.Image
import argparse, os

ascii_chars = "`^\",:;Il!i~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"

def dir_path(string):
    if os.path.isdir(string):
        return string
    else:
        raise NotADirectoryError(string)

parser = argparse.ArgumentParser(
                    prog='Pic2ASCII',
                    description='Converts the images located in a specified directory to ASCII art',
                    epilog='Text at the bottom of help')

parser = argparse.ArgumentParser()
parser.add_argument('--src_path', type=dir_path, help="Already Existing directory of files to convert")
parser.add_argument('--dest_path', type=dir_path, help="Not-yet existing directory of destination of converted files")

def main():

    parsed_args = parser.parse_args()
    print(parsed_args.src_path)
    # print(len(parsed_args))
    # for arg in parsed_args:
    #     print(arg)
    # print('test')
    # path = input("Enter a pathname to an image:\n")

    # try:
    #     image = Image.open(path)
    # except:
    #     print(path, "is not a valid path.\n")

if __name__ == "__main__":
    main()

from PIL import Image

ascii_characters_by_surface = "`^\",:;Il!i~+_-?][}{1)(|\\/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$"

def main():
    image = Image.open('image.jpg')
    # you can first resize the image if needed
    # image = image.resize((width, height))
    ascii_art = convert_to_ascii_art(image)
    save_as_text(ascii_art)

def convert_to_ascii_art(image):
    ascii_art = []
    (width, height) = image.size
    for y in range(0, height - 1):
        line = ''
        for x in range(0, width - 1):
            px = image.getpixel((x, y))
            line += convert_pixel_to_character(px)
        ascii_art.append(line)
    return ascii_art

def convert_pixel_to_character(pixel):
    (r, g, b) = pixel
    pixel_brightness = r + g + b
    max_brightness = 255 * 3
    brightness_weight = len(ascii_characters_by_surface) / max_brightness
    index = int(pixel_brightness * brightness_weight) - 1
    return ascii_characters_by_surface[index]

def save_as_text(ascii_art):
    with open("image.txt", "w") as file:
        for line in ascii_art:
            file.write(line)
            file.write('\n')
        file.close()

if __name__ == '__main__':
    main()


from metaflow import FlowSpec, step, IncludeFile, batch, S3, Parameter, current
import time
import numpy as np
from io import StringIO
from random import choice
from sklearn import linear_model
from sklearn.metrics import r2_score

class RegressionModel(FlowSpec):

    # Include a local file.
    DATA_FILE = IncludeFile(
        'dataset',
        help='Text File With Regression Numbers',
        is_text=True,
        default='dataset.txt')

    # Dummy parameter - can specified via command line 'run': e.g. --dummy_alpha 0.6
    # Parameters can also be defined as JSON for more complex structures.
    DUMMY_ALPHA = Parameter('dummy_alpha',
                    help='dummy paramater, this can be anything!',
                    default=0.01)

    @step
    def start(self):

        print("flow name: %s" % current.flow_name)
        print("run id: %s" % current.run_id)
        print("username: %s" % current.username)
        print("dummy alpha: %s" % self.DUMMY_ALPHA)

        # Data is an array of lines from the text file containing the numbers
        raw_data = StringIO(self.DATA_FILE).readlines()

        # Cast strings to float and prepare for training
        self.dataset = [[float(_) for _ in d.strip().split('\t')] for d in raw_data]

        # store dataset as train and test set
        split_index = int(len(self.dataset) * 0.8)
        self.train_dataset = self.dataset[:split_index]
        self.test_dataset = self.dataset[split_index:]

        # Branch into two nodes, training two versions of the model basedon parameters.
        self.normalise = [True, False]
        self.next(self.train_model, foreach='normalise')

    # @batch(gpu=1, memory=80000)
    @step
    def train_model(self):

        # Get the input fan out parameter
        self.normalise = self.input

        # build the model
        x_train = np.array([[_[0]] for _ in self.train_dataset])
        y_train = np.array([_[1] for _ in self.train_dataset])
        x_test = np.array([[_[0]] for _ in self.test_dataset])
        y_test = np.array([_[1] for _ in self.test_dataset])

        # Create linear regression model
        regr = linear_model.LinearRegression()
        regr.fit(x_train, y_train)

        # Get and store results.
        y_pred = regr.predict(x_test)
        self.r2 = r2_score(y_test, y_pred)
        print("Test set results: {}".format(self.r2))

        # Store model
        self.model = regr

        # finally join with the other runs
        self.next(self.join_runs)

    @step
    def join_runs(self, inputs):

        # merge r2 from runs with different parameters
        self.results_from_runs = {
            input.normalise:{'metrics': input.r2}
            for input in inputs
        }
        print("Current results: {}".format(self.results_from_runs))

        # Pick random model for now (lowest loss in real world)
        self.best_r2 = choice(list(self.results_from_runs.keys()))

        self.next(self.deploy)

    @step
    def deploy(self):
        """
        TODO: Deployment logic
        """
        self.next(self.end)

    @step
    def end(self):
        print('Dag ended!')

if __name__ == '__main__':
    RegressionModel()


import glob
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
from collections import OrderedDict

def get_features(file1,file2):
    # combining the files in first repo
    output_file1 = open("java-output-1.0.0.txt","w")
    for file in glob.glob(file1):
        f = open(file,"r")
        output_file1.write(f.read())
    output_file1.close()

    # combining the files in second repo
    output_file2 = open("java-output-1.0.2.txt","w")
    for file in glob.glob(file2):
        f = open(file,"r")
        output_file2.write(f.read())
    output_file2.close()

    file1 = open("java-output-1.0.0.txt","r")
    file2 = open("java-output-1.0.2.txt","r")

    # removing non-alphabets
    file1 = file1.read().replace('/',' ').replace('#',' ').replace('<',' ').replace('""',' ').replace('_',' ').replace(':',' ').replace('+',' ').translate(str.maketrans('','','0123456789'))
    file2 = file2.read().replace('/',' ').replace('#',' ').replace('<',' ').replace('""',' ').replace('_',' ').replace(':',' ').replace('+',' ').translate(str.maketrans('','','0123456789'))

    vectorizer = CountVectorizer()
    corpus = [file1,file2]
    X = vectorizer.fit_transform(corpus)
    output_features = vectorizer.get_feature_names() # total list of features

    vector1 = np.array(X.toarray()[0])  # vector array for file1
    vector2 = np.array(X.toarray()[1])  # vector array for file2

    difference_vector = np.subtract(vector1,vector2)
    difference_vector = np.absolute(difference_vector)

    # dictionary of features and difference vector
    dictt = dict(zip(output_features,difference_vector))

    # sort in ascending order
    dictt = OrderedDict(sorted(dictt.items(),key=lambda kv:kv[1]))
    bottom25 = {k: dictt[k] for k in list(dictt)[:25]}
    bottom35 = {k: dictt[k] for k in list(dictt)[:35]}

    # sort in descending order
    dictt = OrderedDict(sorted(dictt.items(),key=lambda kv:kv[1],reverse=True))
    top25 = {k: dictt[k] for k in list(dictt)[:25]}
    top35 = {k: dictt[k] for k in list(dictt)[:35]}

    return (top25,bottom25,top35,bottom35)

def main():
    # test with py files
    #file1="repositories/python/nltk-3.2.4/nltk/*.py"
    #file2="repositories/python/nltk-3.4.4/nltk/*.py"

    # test with java files
    file1 = "repositories/java/Fast-Android-Networking-1.0.0/app/src/main/java/com/networking/*.java"
    file2 = "repositories/java/Fast-Android-Networking-1.0.2/app/src/main/java/com/networking/*.java"

    (top25,bottom25,top35,bottom35) = get_features(file1,file2)

    print("Top 25 features",top25)
    print("Bottom 25 features",bottom25)
    print("Top 35 features",top35)
    print("Bottom 35 features",bottom35)

main()

####### sample output for python file
#Top 25 features {'self': 44, 'rule': 33, 'in': 27, 'defaultdict': 24, 'the': 24, 'concordance': 23, 'for': 22, 'grammar': 22, 'if': 22, 'ax': 19, 'return': 19, 'line': 17, 'pylab': 17, 'new': 16, 'print': 16, 'word': 16, 'list': 15, 'seed': 14, 'append': 13, 'def': 13, 'result': 13, 'text': 13, 'len': 12, 'dict': 11, 'param': 11}
#Bottom 25 features {'aaa': 0, 'abbb': 0, 'abbbc': 0, 'abbr': 0, 'abbreviate': 0, 'abc': 0, 'abcmeta': 0, 'able': 0, 'abort': 0, 'aborted': 0, 'aborting': 0, 'about': 0, 'above': 0, 'abs': 0, 'abspath': 0, 'abstract': 0, 'abstractcollocationfinder': 0, 'abstractlazysequence': 0, 'abstractmethod': 0, 'abstractparentedtree': 0, 'ac': 0, 'academic': 0, 'accelerator': 0, 'accents': 0, 'acceptable': 0}
#Top 35 features {'self': 44, 'rule': 33, 'in': 27, 'defaultdict': 24, 'the': 24, 'concordance': 23, 'for': 22, 'grammar': 22, 'if': 22, 'ax': 19, 'return': 19, 'line': 17, 'pylab': 17, 'new': 16, 'print': 16, 'word': 16, 'list': 15, 'seed': 14, 'append': 13, 'def': 13, 'result': 13, 'text': 13, 'len': 12, 'dict': 11, 'param': 11, 'start': 11, 'freqs': 10, 'lines': 10, 'of': 10, 'random': 10, 'resource': 10, 'rhs': 10, 'type': 10, 'context': 9, 'data': 9}
#Bottom 35 features {'aaa': 0, 'abbb': 0, 'abbbc': 0, 'abbr': 0, 'abbreviate': 0, 'abc': 0, 'abcmeta': 0, 'able': 0, 'abort': 0, 'aborted': 0, 'aborting': 0, 'about': 0, 'above': 0, 'abs': 0, 'abspath': 0, 'abstract': 0, 'abstractcollocationfinder': 0, 'abstractlazysequence': 0, 'abstractmethod': 0, 'abstractparentedtree': 0, 'ac': 0, 'academic': 0, 'accelerator': 0, 'accents': 0, 'acceptable': 0, 'accepted': 0, 'access': 0, 'accessed': 0, 'accessor': 0, 'accidentally': 0, 'according': 0, 'account': 0, 'accuracy': 0, 'accurate': 0, 'acl': 0}

# I can see that the distribution first varies a lot between the more different features then starts to decrease (from top 25 features to 35 features,
# there is more distribution between the top 25 rather than from 26th to 35th

####### sample output for java file
#Top 25 features {'response': 8, 'anerror': 6, 'public': 6, 'tag': 6, 'void': 6, 'androidnetworking': 4, 'isrequestrunning': 4, 'log': 4, 'override': 4, 'view': 4, 'file': 3, 'api': 2, 'build': 2, 'cancel': 2, 'checkoptionsrequest': 2, 'com': 2, 'final': 2, 'getasokhttpresponse': 2, 'github': 2, 'headers': 2, 'https': 2, 'issues': 2, 'key': 2, 'logerror': 2, 'new': 2}
#Bottom 25 features {'activity': 0, 'add': 0, 'addbodyparameter': 0, 'addheaders': 0, 'addjsonobjectbody': 0, 'addmultipartfile': 0, 'addpathparameter': 0, 'addqueryparameter': 0, 'agreed': 0, 'amit': 0, 'amitshekhar': 0, 'an': 0, 'analyticslistener': 0, 'and': 0, 'android': 0, 'animageloader': 0, 'animageview': 0, 'anrequest': 0, 'anresponse': 0, 'any': 0, 'apache': 0, 'apiendpoint': 0, 'apitestactivity': 0, 'app': 0, 'appcompatactivity': 0}
#Top 35 features {'response': 8, 'anerror': 6, 'public': 6, 'tag': 6, 'void': 6, 'androidnetworking': 4, 'isrequestrunning': 4, 'log': 4, 'override': 4, 'view': 4, 'file': 3, 'api': 2, 'build': 2, 'cancel': 2, 'checkoptionsrequest': 2, 'com': 2, 'final': 2, 'getasokhttpresponse': 2, 'github': 2, 'headers': 2, 'https': 2, 'issues': 2, 'key': 2, 'logerror': 2, 'new': 2, 'okhttp': 2, 'okhttpresponselistener': 2, 'onerror': 2, 'onresponse': 2, 'options': 2, 'square': 2, 'this': 2, 'tostring': 2, 'utils': 2, 'after': 1}
#Bottom 35 features {'activity': 0, 'add': 0, 'addbodyparameter': 0, 'addheaders': 0, 'addjsonobjectbody': 0, 'addmultipartfile': 0, 'addpathparameter': 0, 'addqueryparameter': 0, 'agreed': 0, 'amit': 0, 'amitshekhar': 0, 'an': 0, 'analyticslistener': 0, 'and': 0, 'android': 0, 'animageloader': 0, 'animageview': 0, 'anrequest': 0, 'anresponse': 0, 'any': 0, 'apache': 0, 'apiendpoint': 0, 'apitestactivity': 0, 'app': 0, 'appcompatactivity': 0, 'append': 0, 'appinstance': 0, 'applicable': 0, 'application': 0, 'argb': 0, 'array': 0, 'as': 0, 'at': 0, 'atbxix': 0, 'base': 0}

# I notice that in Python there is more distributional similarity between code versions whereas in java is way less.
# The reason could be that Python is higher level programming than Java or C++


import os
import subprocess

CUDA_MPS_PIPE_DIRECTORY = '/tmp/nvidia-mps'
CUDA_MPS_LOG_DIRECTORY = '/tmp/nvidia-log'

os.environ['CUDA_MPS_PIPE_DIRECTORY'] = CUDA_MPS_PIPE_DIRECTORY
os.environ['CUDA_MPS_LOG_DIRECTORY'] = CUDA_MPS_LOG_DIRECTORY

def run_cmd(command, print_output=False):
    # os.system(command)
    output = subprocess.run(command,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.STDOUT,
                            check=True,
                            shell=True)
    if print_output:
        print(output.stdout.decode('utf-8').strip())

def start_server():
    """The nvidia-cuda-mps-server instances are created on-demand
    when client applications connect to the control daemon.
    This function uses cudaMalloc to start the MPS server.
    """
    try: # check if a control daemon is spawned
        get_pid("nvidia-cuda-mps-control")
    except subprocess.CalledProcessError: # control daemon is not yet started
        start_daemon() # start the daemon
    dirname = os.path.dirname(os.path.realpath(__file__))
    cudaMalloc_path = os.path.join(dirname, "cudaMalloc")
    cudaMalloc_source_path = os.path.join(dirname, "cudaMalloc.cu")
    assert(os.path.exists(cudaMalloc_source_path)) # program that invokes cudaMalloc
    if not os.path.exists(cudaMalloc_path): # compile the program on the fly
        run_cmd("nvcc cudaMalloc.cu -Xcompiler -O3 -Xcompiler -Wall -Xptxas -O3 -lcublas -std c++17 -o cudaMalloc")
    # print(f"Running command {cudaMalloc_path}")
    run_cmd(cudaMalloc_path) # run the command to start the MPS server

def start_daemon():
    """Start the MPS control daemon in background process,
    assuming the user has enough privilege (e.g. root).
    """
    run_cmd("nvidia-cuda-mps-control -d")

def quit_everything():
    """Quit the MPS control daemon and any existing MPS servers.
    """
    run_cmd("echo quit | nvidia-cuda-mps-control")

def get_mps_server_pid():
    """Get the pid of the MPS server process.
    If the MPS server is not running, start one.
    Returns:
        int: pid of MPS server process
    """
    try:
        return get_pid("nvidia-cuda-mps-server")
    except subprocess.CalledProcessError: # server is not up
        start_server()
        return get_pid("nvidia-cuda-mps-server")

def get_pid(name):
    """Get the pid of a process by name.
    Args:
        name (str): Name of the process.
    Returns:
        int: pid of process
    """
    output = subprocess.check_output(["pidof", "-s", name])
    return int(output)

def set_active_thread_percentage_of_server(pid, percentage):
    """[summary]
    Args:
        pid (int): process id of the MPS server
        percentage (int): active thread percentage to set to
    """
    run_cmd(
        f"echo set_active_thread_percentage {pid} {percentage} | nvidia-cuda-mps-control")

def set_active_thread_percentage(percentage):
    """[summary]
    Args:
        percentage (int): active thread percentage to set to
    """
    server_pid = get_pid("nvidia-cuda-mps-server")
    set_active_thread_percentage_of_server(server_pid, percentage)

def get_active_thread_percentage_of_server(pid):
    output = subprocess.check_output(f"echo get_active_thread_percentage {pid} | nvidia-cuda-mps-control", shell=True)
    output = output.decode('utf-8').rstrip()
    return int(float(output))

def get_active_thread_percentage():
    server_pid = get_pid("nvidia-cuda-mps-server")
    return get_active_thread_percentage_of_server(server_pid)


from django.urls import path, include
from watchlist_app.api import views
from rest_framework.routers import DefaultRouter

router = DefaultRouter()
router.register('streams', views.streamPlatformVS, basename='streamplatform')

urlpatterns = [
    path('list/', views.WatchListAV.as_view(), name='movie-list'),
    path('<int:pk>/', views.WatchDetailAV.as_view(), name="movie-detail"),
    path('list2/', views.WatchListGV.as_view(), name="watch-list"),

    path("", include(router.urls)),

    path('stream/', views.StreamPlatformAV.as_view(), name='platform-list'),
    # path('stream/<int:pk>', views.StreamPlatformDetailAV.as_view(), name="streamplatform-detail"),

    # path('review/', views.ReviewList.as_view(), name="review-list"),
    # path('review/<int:pk>', views.ReviewDetail.as_view(), name="review-detail")

    path('<int:pk>/review-create/', views.ReviewCreate.as_view(), name="streamplatform-detail"),
    path('<int:pk>/reviews/', views.ReviewList.as_view(), name="review-list"),
    path('review/<int:pk>/', views.ReviewDetail.as_view(), name='review-detail'),

    path('reviews/', views.UserReview.as_view(), name="user-review-detail"),
]


import tensorflow as tf
import json
import keras
from keras.models import Model
from keras.applications import ResNet50
from keras.layers import Input, Dense, Lambda, LeakyReLU, Reshape
#from pix3d_dataset import Pix3DDataset, Pix3DSequence
from loss import batch_cd_loss
from shapenet_dataset import ShapenetDataset
import numpy
import math

config = tf.compat.v1.ConfigProto()
config.gpu_options.allow_growth = True
sesson = tf.compat.v1.Session(config=config)

# Create ResNet-50 Model for 2D feature extraction.
resnet50 = ResNet50(include_top=False, input_shape=(128,128,3), pooling='avg')

# Encode the 2D features extracted by RestNet-50.
def sample(args):
    mean, var = args
    epsilon = keras.backend.random_normal(shape=keras.backend.shape(mean), mean=0.0, stddev=1.0)
    return mean + keras.backend.exp(0.5 * var) * epsilon

encoder_inputs = Input(shape=(100,), name='input')
mean = Dense(100, name='mean')(encoder_inputs)
sigma = Dense(100, name='sigma')(encoder_inputs)
z_prime = Lambda(sample, (100,), name='z_prime')([mean, sigma])

encoder = Model(inputs=encoder_inputs, outputs=z_prime, name='encoder')

# Decode and generate a Point Cloud.
NUM_POINTS = 1024
decoder_inputs = Input(shape=(100,), name='input')
x = Dense(512, name='hidden_layer1')(decoder_inputs)
x = LeakyReLU(alpha=0.5)(x)
x = Dense(1024, name='hidden_layer2')(x)
x = LeakyReLU(alpha=0.5)(x)
x = Dense(NUM_POINTS*3, activation='tanh', name='output')(x)
output = Reshape((NUM_POINTS,3))(x)
point_cloud_generation = Model(inputs=decoder_inputs, outputs=output, name='point_cloud_generation')

reconstnet = keras.Sequential()
reconstnet.add(resnet50)
reconstnet.add(Dense(100))
reconstnet.add(encoder)
reconstnet.add(point_cloud_generation)

# Define optimizer and loss function.
def loss_function(x, y):
    return batch_cd_loss(x,y)

reconstnet.compile(optimizer='adam', loss=loss_function, run_eagerly=True)
#reconstnet.compile(optimizer='adam', loss='mse', run_eagerly=True)

# Open the training/validation data split files.
with open('data/splits/train_models.json', 'r') as f:
    train_models_dict = json.load(f)

with open('data/splits/val_models.json', 'r') as f:
    val_models_dict = json.load(f)

data_dir_imgs = 'data/shapenet/ShapeNetRendering/'
data_dir_pcl = 'data/shapenet/ShapeNet_pointclouds/'

# Create our ShapenetDataset instance, which will help the model iterate over the dataset.
cats = []
cats.append('02691156')
shapenet_dataset = ShapenetDataset(data_dir_imgs, data_dir_pcl, train_models_dict, cats)

# Train the model.
reconstnet.fit(shapenet_dataset)

reconstnet.save('model')


from transformers import AutoTokenizer
from llm_serving.model.wrapper import get_model
from coordinator.coordinator_client import LocalCoordinatorClient
import traceback
from loguru import logger
from time import sleep
import argparse
import time
import math
import torch
import random
import numpy as np
from alpa.device_mesh import set_seed

def get_tokenizer_model(args):
    if args.model_name == 'opt-175b':
        # The 30B version works for all OPT models.
        tokenizer = AutoTokenizer.from_pretrained("facebook/opt-30b")
        tokenizer.add_bos_token = False
        model = get_model(model_name="alpa/opt-175b", path="/root/fm/models/alpa_models/")

    elif args.model_name == 'bloom':
        tokenizer = AutoTokenizer.from_pretrained('bigscience/bloom')
        tokenizer.add_bos_token = False
        model = get_model(model_name="alpa/bloom", path="/root/fm/models/alpa_models/")

    elif args.model_name == 'bloomz':
        tokenizer = AutoTokenizer.from_pretrained('bigscience/bloomz')
        tokenizer.add_bos_token = False
        # llm_serving does not recoginze bloomz, since the model parameter is from bloomz,
        # this should be fine
        model = get_model(model_name="alpa/bloom", path="/root/fm/models/alpa_models/bloomz-np")
    else:
        assert False, f"Not legal name {args.model_name}"

    return tokenizer, model

def post_processing_text(input_text, output_text, query):
    print(f"<post_processing_text> input_text: {input_text}")
    print(f"<post_processing_text> output_text: {output_text}")
    stop_tokens = []
    if query.get('stop', []) is not None:
        for token in query.get('stop', []):
            if token != '':
                stop_tokens.append(token)
    print(f"<post_processing_text> stop_tokens: {stop_tokens}.")

    if query.get('max_tokens') == 0:
        return ""

    if not query.get('echo', False):
        text = output_text[len(input_text):]
    else:
        text = output_text
    end_pos = len(text)
    print(f"<post_processing_text>1 end_pos: {end_pos}.")
    for stop_token in stop_tokens:
        if query.get('echo', False):
            if text[len(input_text):].find(stop_token) != -1:
                end_pos = min(text[len(input_text):].find(stop_token) + len(stop_token), end_pos)
        else:
            if text.find(stop_token) != -1:
                end_pos = min(text.find(stop_token) + len(stop_token), end_pos)
        print(f"<post_processing_text>2 end_pos: {end_pos}.")

    print(f"<post_processing_text> text: {text}, end_pos: {end_pos}")
    post_processed_text = text[:end_pos + 1]
    print(f"<post_processing_text> input: {output_text}")
    print(f"<post_processing_text> output: {post_processed_text}")
    return post_processed_text

def to_result(input_text, output_text, query):
    result = {}
    items = []
    for i in range(len(output_text)):
        item = {'choices': [], }
        print(f"<to_result> output{i}: {len(input_text[i])} / {len(output_text[i])}")
        choice = {
            "text": post_processing_text(input_text[i], output_text[i], query),
            "index": 0,
            "finish_reason": "length"
        }
        item['choices'].append(choice)
        items.append(item)
    result['inference_result'] = items
    return result

def main():
    parser = argparse.ArgumentParser(description='Local Inference Runner with coordinator.')
    parser.add_argument('--job-id', type=str, default='-', metavar='S',
                        help='DB ID')
    parser.add_argument('--working-directory', type=str,
                        default='/root/fm/working_dir', metavar='S',
                        help='The IP of coordinator-server.')
    parser.add_argument('--model-name', type=str, default='bloom', metavar='S',
                        help='trained model path')
    parser.add_argument('--batch-size', type=int, default=1, metavar='S',
                        help='batch-size for inference (default:8)')
    parser.add_argument('--fp16', action='store_true',
                        help='Run model in fp16 mode.')
    args = parser.parse_args()
    print(args)

    local_cord_client = LocalCoordinatorClient(
        working_directory=args.working_directory,
        coordinator_url="http://localhost:5000/eth",
    )
    try:
        tokenizer, model = get_tokenizer_model(args)
        local_cord_client.update_status(args.job_id, "running")
    except Exception as e:
        print('Exception in model initialization inference:', e)
        error = traceback.format_exc()
        local_cord_client.update_status(args.job_id, "failed", returned_payload={"message": error})
        print(error)
        raise e

    print(f"{args.model_name} Initialized.")

    try:
        while True:
            job_id = None
            raw_text = None
            try:
                instructions = local_cord_client.fetch_instructions(args.model_name, 0)
                last_instruction = instructions[-1]

                if last_instruction["message"] == "break":
                    logger.info("Received stop instruction.")
                    logger.info("# BREAK ")
                    break
                elif last_instruction["message"] == "continue":
                    logger.info(f"Received keep instruction. <{args.model_name}>")
                    sleep(1)
                elif last_instruction["message"] == "run":
                    fetched_tasks = [x for x in instructions
                                     if x["message"] == "run" and x['payload']['status'] == 'submitted']

                    if len(fetched_tasks) > 0:
                        instruction = fetched_tasks[0]
                        logger.info("Instruction:")
                        logger.info(str(instruction))
                        # TODO: we assume len(payload) is 1, right?
                        query = instruction['payload']['payload'][0]
                        if isinstance(query['prompt'], list):
                            raw_text = query['prompt']
                        elif isinstance(query['prompt'], str):
                            raw_text = [query['prompt']]
                        else:
                            print("wrong prompt format, it can only be str or list of str")
                            print(query['prompt'])

                        job_id = instruction['payload']['id']
                        print(f"Job <{job_id}> has been processed")

                        start_time = time.time()

                        batch_size = 1
                        num_iter = math.ceil(len(raw_text) / batch_size)
                        answers = []
                        seed = query.get('seed', None)
                        if seed is not None:
                            torch.manual_seed(seed)
                            np.random.seed(seed)
                            random.seed(seed)
                            set_seed(seed)

                        for iter_i in range(num_iter):
                            current_raw_text = raw_text[iter_i * batch_size: (iter_i + 1) * batch_size]
                            input_ids = tokenizer(current_raw_text, return_tensors="pt").input_ids
                            if query.get('temperature', 0.9) == 0:
                                output = model.generate(input_ids=input_ids,
                                                        max_new_tokens=query.get('max_tokens', 16),
                                                        temperature=1.0,
                                                        top_k=1,
                                                        top_p=query.get('top_p', 0),
                                                        do_sample=True)
                            else:
                                output = model.generate(input_ids=input_ids,
                                                        max_new_tokens=query.get('max_tokens', 16),
                                                        temperature=query.get('temperature', 0.9),
                                                        top_k=query.get('top_k', 50),
                                                        top_p=query.get('top_p', 0),
                                                        do_sample=True)
                            generated_string = tokenizer.batch_decode(output, skip_special_tokens=True)
                            answers.extend(generated_string)

                        end_time = time.time()
                        print(f"Job-{job_id} {args.model_name} Inference takes {end_time - start_time}s")
                        # print(f"outputs by hf model: {outputs}")
                        result = to_result(raw_text, answers, query)
                        return_payload = {
                            'request': query,
                            'result': result,
                            'raw_compute_time': end_time - start_time
                        }
                        # local_cord_client.update_status(
                        local_cord_client.update_status_global_coordinator(
                            job_id,
                            "finished",
                            returned_payload=return_payload
                        )
                        local_cord_client.update_status(job_id, "finished", returned_payload={})

            except Exception as e:
                error = traceback.format_exc()
                local_cord_client.update_status(
                    job_id,
                    "failed",
                    returned_payload={"message": error}
                )
                print(error)

    except Exception as e:
        print('Exception in latency inference:', e)

if __name__ == "__main__":
    main()


from ._lemma2 import lemma2
from ._lemma3 import lemma3

def case1(self, p, w, d1, k):
    """
     - Case 1: d = 2 and therefore the target set
     - contains w (vk-1) and  children(vk) excluding vk+1.
     - Args:
        - vk - The leftmost child of w.
        - d  - The distance between the previous probe and the target.
    """
    self["trace"] += "Case 1 called for probe " + str(p) + " and d = " + str(d1) + "\n"

    if self["dkPlus"] == []: #If vk has no children, target located at its parent
        return self.located(self["dkMinus"][0])

    elif len(self.tDict[w].children) == 1: #If vk is the unique child of w then lemma 3
        lemma3(self, w, self.tDict[p].parent, self["dkPlus"][0], self["dkPlus"][-1])
        return

    #Otherwise w has more than one child, zk is its rightmost child
    vkMinus2 = self.tDict[w].parent  #vk-2 is w's parent
    vk = self.tDict[w].children[0]   #vk is w's leftmost child
    yk = self.tDict[w].children[1]   #yk is the child to the right of vk
    zk = self.tDict[w].children[-1]  #zk is w's rightmost child
    s  = self.tDict[w].children[-2]  #s is the child to the left of zk

    if len(self.tDict[zk].children) > 1: #zk has > 1 child, then w.parent has <= 1 child, probe zk
        self["trace"] += "zk has more than one child\n"
        d2 = self.probe(zk)

        if d2 == 1:   #If d2 is 1 then the target is at w
            return self.located(w)

        elif d2 == 2: #Target set is w's parent and w's children (minus zk)
            if vkMinus2 is None:  #If w is the root it has no parent, lemma 2 on w's children
                lemma2(self, w, vk, s)
                return

            lemma3(self, vkMinus2, w,  vk,  s)
            return

        elif d2 == 3:   #If d2 is 3 then target is in children(vk) excluding vk + 1, so lemma 2
            lemma2(self, vk, self["dkPlus"][0], self["dkPlus"][-1])
            return

        elif d2 == 4:   #If d2 is 4 then the target is in children(wk+1, xk+1)
            self.lemma4(self["dkPlus"][0], self["dkPlus"][-1], self.tDict[self["dkPlus"][0]].level + 1)
            return

    #Now if zk has at most one child, then we probe w's parent
    elif len(self.tDict[zk].children) <= 1:
        self["trace"] += "zk has at most one child\n"
        d2 = self.probe(vkMinus2)

        if d2 == 1:   #If d2 is 1 then the target is at w
            return self.located(w)

        elif d2 == 2:   #If d2 == 2 then the target is in siblings(vk, zk) so lemma 2
            lemma2(self, w, vk, zk)
            return

        elif d2 == 3:   #If d2 is 3 then target is in children(vk) excluding vk + 1, so lemma 2
            lemma2(self, vk, self["dkPlus"][0], self["dkPlus"][-1])
            return

        elif d2 == 4:   #If d2 is 4 then the target is in children(wk+1, xk+1)
            self.lemma4(self["dkPlus"][0], self["dkPlus"][-1], self.tDict[self["dkPlus"][0]].level + 1)
            return


'''
Edit dialogs for components that contain a group of other components
'''
from PyQt4 import QtGui, QtCore

from . import ComponentEditDialog
from ..componentreorder import ComponentReorderList
from ..inputselector import InputSelector
from ..reorderlist import ReorderWidget
from ..component import updateModel

from ...components import ScanRange, ArgumentList

class ComponentGroupModeDialog( ComponentEditDialog ):
    def __init__( self, parent, component, modes, title ):
        super( ComponentGroupModeDialog, self ).__init__( parent, component, title )

        modeSelector = QtGui.QButtonGroup( self )
        modeSelectorWidget = QtGui.QGroupBox( 'Mode select' )
        modeSelectorWidget.setLayout( QtGui.QHBoxLayout() )

        for name, id, toolTip in modes:
            radio = QtGui.QRadioButton( name )
            radio.setToolTip( toolTip )
            modeSelector.addButton( radio, id )
            modeSelectorWidget.layout().addWidget( radio )

        modeSelector.buttonClicked[int].connect( self.modeSelected )
        modeSelector.buttonClicked[int].connect( self.setToolbar )

        reorderModel = self.reorderModel = ComponentReorderList( component.components )
        reorderModel.addItem = self.addItem
        self.reorderWidget = ReorderWidget( reorderModel )

        self.setToolbar( component.mode )
        modeSelector.button( component.mode ).setChecked( True )

        widget = QtGui.QWidget()
        widget.setLayout( QtGui.QVBoxLayout() )

        widget.layout().addWidget( self.reorderWidget, 1 )
        widget.layout().addWidget( modeSelectorWidget )

        self.tabWidget.insertTab( 0, widget, 'Components' )
        self.tabWidget.setCurrentIndex( 0 )

    @updateModel
    def addItem( self ):
        inputSelector = InputSelector( self )
        inputSelector.inputSelected.connect( self.newInput )
        inputSelector.exec_()
        inputSelector.deleteLater()

    def newInput( self, input ): pass

    def modeSelected( self, id ): pass
    def setToolbar( self, id ): pass

class ArgumentListDialog( ComponentGroupModeDialog ):
    def __init__( self, parent, component ):
        super( ArgumentListDialog, self ).__init__( parent,
                                                    component,
                                                    ( ( 'MONO', ArgumentList.MONO, 'Single input whose value is a collection' ), ( 'POLY', ArgumentList.POLY, 'Collection of inputs' ) ),
                                                    'Argument List' )

    def setToolbar( self, id ):
        rw = self.reorderWidget
        rw.addEnabled = True
        rw.raiseEnabled = rw.lowerEnabled = rw.removeEnabled = False if id is ArgumentList.MONO else True

    @updateModel
    def modeSelected( self, id ):
        rm = self.reorderModel
        nullIndex = QtCore.QModelIndex()
        l = len( rm.pyList )
        newL = 1 if id is ArgumentList.MONO else 0
        if l > newL:
            rm.beginRemoveRows( nullIndex, newL, l - 1 )
            self.component.setMode( id )
            rm.endRemoveRows()
        if l < newL:
            rm.beginInsertRows( nullIndex, l, newL - 1 )
            self.component.setMode( id )
            rm.endInsertRows()
        if l is newL:
            self.component.setMode( id )
        if newL:
            rm.dataChanged.emit( rm.index( 0 ), rm.index( newL - 1 ) )

    @updateModel
    def newInput( self, input ):
        rm = self.reorderModel
        if self.component.mode is ArgumentList.MONO:
            rm.pyList[0] = input
            rm.dataChanged.emit( rm.index( 0 ), rm.index( 0 ) )
        if self.component.mode is ArgumentList.POLY:
            rm.appendObject( input )

class ScanRangeDialog( ComponentGroupModeDialog ):
    def __init__( self, parent, component ):
        super( ScanRangeDialog, self ).__init__( parent,
                                                 component,
                                                 ( ( 'DELTA', ScanRange.DELTA, 'Specify start, end, and the size of the spacings' ),
                                                   ( 'STEPS', ScanRange.STEPS, 'Specify start, end, and number of steps in between' ),
                                                   ( 'COLLECTION', ScanRange.COLLECTION, 'Collection of inputs' ),
                                                   ( 'LIST' , ScanRange.LIST, 'Single input whose value is a collection' ) ),
                                                   'Scan Range' )

    def setToolbar( self, id ):
        rw = self.reorderWidget
        if id is not ScanRange.LIST:
            rw.raiseEnabled = rw.lowerEnabled = rw.removeEnabled = rw.addEnabled = True if id is ScanRange.COLLECTION else False
        else:
            rw.raiseEnabled = rw.lowerEnabled = rw.removeEnabled = False
            rw.addEnabled = True
    @updateModel
    def modeSelected( self, id ):
        rm = self.reorderModel
        nullIndex = QtCore.QModelIndex()
        l = len( rm.pyList )
        if id is ScanRange.COLLECTION:
            newL = 0
        if id is ScanRange.LIST:
            newL = 1
        else:
            newL = 3
        if l < newL:
            rm.beginInsertRows( nullIndex, l, newL - 1 )
            self.component.setMode( id )
            rm.endInsertRows()
        if l > newL:
            rm.beginRemoveRows( nullIndex, newL, l - 1 )
            self.component.setMode( id )
            rm.endRemoveRows()
        if l is newL:
            self.component.setMode( id )
        if newL:
            rm.dataChanged.emit( rm.index( 0, 0 ), rm.index( 0, newL - 1 ) )

    @updateModel
    def newInput( self, input ):
        rm = self.reorderModel
        if self.component.mode is ScanRange.COLLECTION:
            rm.appendObject( input )
        if self.component.mode is ScanRange.LIST:
            rm.pyList[0] = input
            rm.dataChanged.emit( rm.index( 0, 0 ), rm.index( 0, 0 ) )


# checkerboard

from tkinter import *

root = Tk()

canvas_width = 400
canvas_height = 400
size = canvas_height // 8
canvas = Canvas(root, width = canvas_width, height = canvas_height)

canvas.pack()

for i in range(8):
    for j in range(8):
        x = i * size
        y = j * size
        color = 'white'
        if (i + j) % 2 == 0:
            color = 'black'
        canvas.create_rectangle(x, y, x + size, y + size, fill = color)

root.mainloop()


from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem
from PyQt5.QtCore import QSize, pyqtSignal
from PyQt5.QtGui import QIcon, QBrush, QColor, QFont
from domestic.core import ReaderDb, Settings
from domestic.widgets.treeitem import FolderItem, FeedItem

class TreeWidget(QTreeWidget):
    def __init__(self, parent=None):
        super(QTreeWidget, self).__init__(parent)
        self.parent = parent
        self.setAlternatingRowColors(True)
        self.setIconSize(QSize(18, 18))
        font = QFont()
        font.setBold(True)
        self.setFont(font)
        self.setAnimated(True)
        self.header().setVisible(False)
        self.headerItem().setText(0,"Feed")
        self.itemExpanded.connect(self.expandSignal)
        self.itemCollapsed.connect(self.collapseSignal)

        self.widgetInitial()

        self.itemClicked.connect(self.folderClick)
        self.categorySorting(treeitem=self)
        self.unreadFolderInit()
        self.deletedFolderInit()
        self.storeFolderInit()

        self.parent.syncSignal.connect(self.unreadFolderClick)
        self.parent.syncSignal.connect(self.deletedFolderClick)
        self.parent.syncSignal.connect(self.storeFolderClick)
        self.parent.syncSignal.connect(self.titleSignal)

    def titleSignal(self):
        if not self.currentItem() is None:
            self.treeWidgetTitleSignal.emit(self.currentItem().text(0))

    def collapseSignal(self, item):
        key = "TreeWidget/{}".format(item.title.replace(" ", "-"))
        Settings.setValue(key, 0)
        Settings.sync()

    def expandSignal(self, item):
        key = "TreeWidget/{}".format(item.title.replace(" ", "-"))
        Settings.setValue(key, 1)
        Settings.sync()

    def widgetInitial(self):
        self.unreadFolder = QTreeWidgetItem(self)
        self.unreadFolder.type = "static"
        self.unreadFolder.setIcon(0, QIcon(":/images/icons/folder_home.png"))
        self.unreadFolder.setText(0, self.tr("Unread"))
        self.storeFolder = QTreeWidgetItem(self)
        self.storeFolder.type = "static"
        self.storeFolder.setIcon(0, QIcon(":/images/icons/folder_tar.png"))
        self.storeFolder.setText(0, self.tr("Stored"))
        self.deletedFolder = QTreeWidgetItem(self)
        self.deletedFolder.type = "static"
        self.deletedFolder.setIcon(0, QIcon(":/images/icons/trash_empty.png"))
        self.deletedFolder.setText(0, self.tr("Deleted"))

    categoryList = []
    def categorySorting(self, id=0, treeitem=None):
        db = ReaderDb()
        db.execute("select * from folders where parent=?",(id,))
        folders = db.cursor.fetchall()
        for folder in folders:
            if folder["type"] == "folder":
                item = FolderItem(treeitem)
                item.addOptions(folder)
                self.parent.syncSignal.connect(item.folderClick)
                key = "TreeWidget/{}".format(item.title.replace(" ", "-"))
                if Settings.value(key) != None:
                    item.setExpanded(int(Settings.value(key)))
                self.categoryList.append(item)
                self.categorySorting(folder["id"], item)

            elif folder["type"] == "feed":
                item = FeedItem(treeitem)
                item.addOptions(folder)
                self.parent.syncSignal.connect(item.feedClick)
                self.categoryList.append(item)
                self.categorySorting(folder["id"], item)

    treeWidgetTitleSignal = pyqtSignal(str)
    folderClicked = pyqtSignal(list)
    def folderClick(self, widget, row):
        self.parent.toolBox.widget(0).treeWidget.clear()
        self.parent.toolBox.setCurrentIndex(0)
        if widget == self.unreadFolder:
            self.folderClicked.emit(self.unreadFolderInit())
            self.unreadFolderClick()
        elif widget == self.deletedFolder:
            self.folderClicked.emit(self.deletedFolderInit())
            self.deletedFolderClick()
        elif widget == self.storeFolder:
            self.folderClicked.emit(self.storeFolderInit())
            self.storeFolderClick()
        elif widget.type == "feed":
            self.folderClicked.emit(widget.feedInit())
            widget.feedClick()
        elif widget.type == "folder":
            self.folderClicked.emit(widget.folderInit())
            widget.folderClick()
        self.parent.syncSignal.emit()
        self.treeWidgetTitleSignal.emit(widget.text(0))

    def unreadFolderInit(self):
        db = ReaderDb()
        data = db.execute("select * from store where iscache=1")
        feedList = data.fetchall()
        db.close()
        self.unreadFolder.setForeground(0,QBrush(QColor(0,0,0,255)))
        if len(feedList) > 0:
            self.unreadFolder.setText(0, self.tr("({}) Unread").format(len(feedList)))
            self.unreadFolder.setForeground(0,QBrush(QColor(0,0,255)))
        return feedList

    def unreadFolderClick(self):
        feedList = self.unreadFolderInit()
        if len(feedList) > 0:
            self.unreadFolder.setText(0, self.tr("({}) Unread").format(len(feedList)))
        else: self.unreadFolder.setText(0, self.tr("Unread"))

    def deletedFolderInit(self):
        db = ReaderDb()
        data = db.execute("select * from store where istrash=1")
        feedList = data.fetchall()
        db.close()
        self.deletedFolder.setForeground(0,QBrush(QColor(0,0,0,255)))
        if len(feedList) > 0:
            self.deletedFolder.setText(0, self.tr("({}) Deleted").format(len(feedList)))
            self.deletedFolder.setForeground(0,QBrush(QColor(0,0,255)))
            self.deletedFolder.setIcon(0, QIcon(":/images/icons/trash_full.png"))
        return feedList

    def deletedFolderClick(self):
        feedList = self.deletedFolderInit()
        if len(feedList) > 0:
            self.deletedFolder.setText(0, self.tr("({}) Deleted").format(len(feedList)))
        else: self.deletedFolder.setText(0, self.tr("Deleted"))

    def storeFolderInit(self):
        db = ReaderDb()
        data = db.execute("select * from store where isstore=1")
        feedList = data.fetchall()
        db.close()
        self.storeFolder.setForeground(0,QBrush(QColor(0,0,0,255)))
        if len(feedList) > 0:
            self.storeFolder.setText(0, self.tr("({}) Stored").format(len(feedList)))
            self.storeFolder.setForeground(0,QBrush(QColor(0,0,255)))
        self.treeWidgetTitleSignal.emit(self.storeFolder.text(0))
        return feedList

    def storeFolderClick(self):
        feedList = self.storeFolderInit()
        if len(feedList) > 0:
            self.storeFolder.setText(0, self.tr("({}) Stored").format(len(feedList)))
        else: self.storeFolder.setText(0, self.tr("Stored"))


import os
import configparser
from irods.meta import iRODSMeta, AVUOperation
from git import Repo

def configReader():
    """
    ConfigParser function
    Reads configuration variables inside a file and returns a reader object.
    Returns
    -------
    config : object
    """

    config_file = os.path.expandvars('$HOME/.config/gitirods.conf')
    config = config = configparser.ConfigParser()
    config.read(config_file)
    return config

def getRepo(repository_path=None):
    """
    Object function:
    It instantiate the Repo object and returns it together with
    the repository path.
    Parameters
    ----------
    repository_path : None
    Returns
    -------
    repo : object
    repository_path : str
    """

    if repository_path is None:
        repository_path = os.getcwd()
    repo = Repo(repository_path)
    return repo, repository_path

def addAtomicMetadata(
        obj, keys, values,
        external_repos=None, func=None):
    """
    Metadata add function:
    It adds metadata (keys and values) atomically - transactionally in a single call - on
    an irods object
    Parameters
    ----------
    obj : an iRODS object (col=session.collections.get('path/to/collection'))
    keys : python list of attributes
    values : python list of values for attributes
    external_repos : python string for .repos path (default is None)
    func : python function that will return metedata keys and values
    from external repositories - defineExternalReposMetadata(path) (default is None)
    """

    if external_repos is None:
        avus = list(zip(keys, values))
        obj.metadata.apply_atomic_operations(*[AVUOperation(operation='add', \
                                             avu=iRODSMeta(meta[0], meta[1])) for meta in avus])
    else:
        if os.path.exists(external_repos):
            try:
                repository_path = os.path.dirname(external_repos)
                metadata = func(repository_path)
                external_attrs = list(metadata.keys())
                external_vals = list(metadata.values())
                all_attrs = keys + external_attrs
                all_values = values + external_vals
                avus = list(zip(all_attrs, all_values))
                obj.metadata.apply_atomic_operations(*[AVUOperation(operation='add', \
                                                     avu=iRODSMeta(meta[0], meta[1])) for meta in avus])
            except Exception as error:
                print(error)
        else:
            avus = list(zip(keys, values))
            obj.metadata.apply_atomic_operations(*[AVUOperation(operation='add', \
                                             avu=iRODSMeta(meta[0], meta[1])) for meta in avus])

def projectExists(object):
    """
    Check function:
    Based on a specific commit message it will determine whether
    the project in question exists or not.
    Parameters
    ----------
    object : instantiation of Repo
    Returns
    -------
    True : shows this is a nonempty repository
    """

    project_message = 'iRODS:Trigger project workflow'
    commits_list = list(object.iter_commits())
    commit_messages_list = []
    for item in range(len(commits_list)):
        commit = commits_list[item]
        commit_message = commit.message.strip()
        commit_messages_list.append(commit_message)
    del commit_messages_list[0]
    if project_message not in commit_messages_list:
        return True

def resetCommit(obj):
    """
    Reset function:
    It removes the last commit softly. An equivalant of 'git reset --soft HEAD~1'
    If working_tree=True; removes hardly.
    Parameters
    ----------
    object : instantiation of Repo
    """

    obj.head.reset('HEAD~1', index=False, working_tree=False)

def ignoreKeystrokes(callSession):
    """
    Flush function:
    It calls iRODS session renewal function and
    while waiting for it to finish, ignores any keystrokes.
    Parameters
    ----------
    callSession : function - renewIrodsSession()
    """

    while (1):
        import sys
        from termios import tcflush, TCIOFLUSH
        callSession()
        sys.stdout.flush()
        tcflush(sys.stdin, TCIOFLUSH)
        break


"""Main file"""
import importlib

import click
import pyspark.pandas as ps
from hamilton import driver
from hamilton.experimental import h_spark

from utils.constants import (CLINICAL_TRIALS_MAPPING, DRUG_TITLE_COL,
                             DRUGS_MAPPING, OUTPUT_DF_COLS, P_DATE_COL,
                             PUBMED_MAPPING, PUBMED_TITLE_COL, PUBMED_WORD_COL,
                             SPARK_CONF, T_DATE_COL, TRIALS_TITLE_COL,
                             TRIALS_WORD_COL)
from utils.spark import SparkProvider

@click.command()
@click.option('-s', '--source-paths', type=(str, str, str))
@click.option('-o', '--output-path', type=str)
def main(source_paths: (str, str, str), output_path: str):
    # Reading parameters
    clinical_trials_path, drugs_path, pubmed_path = source_paths
    # Initialising spark
    spark = SparkProvider("MedTest", conf=SPARK_CONF).spark
    ps.set_option('compute.ops_on_diff_frames', True)

    skga = h_spark.SparkKoalasGraphAdapter(
        spark_session=spark,
        result_builder=h_spark.base.DictResult(),
        # KoalasDataFrameResult(),
        spine_column=None,
    )
    module_names = [
        "jobs.data_loader",
        "jobs.drugs_mentions"
    ]
    initial_config = {
        'clinical_trials_path': clinical_trials_path,
        'drugs_path': drugs_path,
        'pubmed_path': pubmed_path,
        'drugs_mapping': DRUGS_MAPPING,
        'clinical_trials_mapping': CLINICAL_TRIALS_MAPPING,
        'pubmed_mapping': PUBMED_MAPPING,
        'drug_title_col': DRUG_TITLE_COL,
        'trials_title_col': TRIALS_TITLE_COL,
        'trials_word_col': TRIALS_WORD_COL,
        'pubmed_title_col': PUBMED_TITLE_COL,
        'pubmed_word_col': PUBMED_WORD_COL,
        'output_df_cols': OUTPUT_DF_COLS,
        'p_date_col': P_DATE_COL,
        't_date_col': T_DATE_COL
    }
    modules = [importlib.import_module(m) for m in module_names]

    dr = driver.Driver(initial_config, *modules, adapter=skga)
    outputs = ['df_stats_cleaned_df']
    df = dr.execute(outputs)
    dr.display_all_functions('./output/graph.dot')
    df["df_stats_cleaned_df"].to_spark().write.format('json').mode("overwrite")\
        .save(output_path)
    SparkProvider.tear_down_spark(spark)

if __name__ == "__main__":
    main()


import datetime
from contextlib import contextmanager
from logging import getLogger

LOG = getLogger(__name__)

class RecordDetail(object):

    def __init__(self, name):
        self.name = name
        self.status = None
        self.start_time = datetime.datetime.now()
        self.stop_time = None
        self.number_of_records = None
        self.other_details = None
        LOG.info('___INIT__')

    def save(self,):
        # Do stuff to write to database
        LOG.info('saving %s ', self)

    def __str__(self):
        return ('name: %s start: %s stop : %s' % (self.name, self.start_time, self.stop_time))

    def stop(self, status):
        LOG.info('stopping')
        self.status = status
        self.stop_time = datetime.datetime.now()
        self.save()

    def __enter__(self,):
        LOG.info('__ENTER__')
        self.save()
        # Return value is used if you with ... as VAR
        return self

    def __exit__(self, etype, evalue, etrace):
        self.stop(0)
        # rethrow any exception (set to True to swallow it ...)
        return False

@contextmanager
def record_detail(name):
    detail = RecordDetail(name)
    detail.save()
    yield detail
    detail.stop(0)


# 42884 (단속카메라)
# 시간 복잡도: O(n log n)

def solution(routes):
    routes.sort(key=lambda x: x[1]) # routes를 차량이 나간 지점(진출)을 기준으로 정렬
    camera = -30001 # 문제의 제한사항에서 진입 지점이 -30000 이상부터라 명시했으니 -30001부터 카메라 위치를 찾는다.
    answer = 0

    for i in routes:
        if i[0] > camera:   # 기준(카메라)보다 진입지점이 뒤에 있으면
            answer += 1     # 단속이 안되기에 카메라 개수 + 1
            camera = i[1]   # 새로운 기준은 해당 경로의 진출지점이 된다.

    return answer

# 문제 제한사항을 고려해야 해서 초반에 좀 틀렸던 것 같다.


import os
from datetime import datetime, timedelta

import requests
from src.applications.boe_app import BOEApplication, PermissionsEnum, query_table_dao, GenderEnum, TransactionMethodEnum

INFRASTRUCTURE_FACTORY = "eventsourcing.sqlite:Factory";
SQLITE_DBNAME = "_db/prod_db"

os.environ['INFRASTRUCTURE_FACTORY'] = INFRASTRUCTURE_FACTORY
os.environ['SQLITE_DBNAME'] = SQLITE_DBNAME

headers = {
    "content_type": "application/json"
}

def main():
    app = BOEApplication()
    #
    role_id, child_id = app.setup()
    parent_id = app.create_parent(
        first_name='minh',
        last_name='baxter',
        email='minh.baxter@gmail.com',

    )
    #
    child_id = app.create_child(
        first_name='john',
        last_name='baxter',
        email='joe.baxter@gmail.com',
        gender=GenderEnum.MALE,
        age=8,
        grade=3
    )

    #

    # items = query_table_dao.query_child(query={"email": "joe.baxter@gmail.com"})
    # items = query_table_dao.query_role(query={"name": "AdminRole"})
    items = query_table_dao.scan_adult_aggregates()

    app.append_permisson_to_role(role_id=role_id, permission=PermissionsEnum.AccountChangeBalance)
    app.append_role_to_account(account_id=parent_id, role_id=role_id)
    print(items)
    #
    # print(account_id)
    # app.create_task(
    #     name="Clean Your Room",
    #     description="I want your room clean",
    #     value=200,
    #     due_date=datetime.datetime.now()
    # )

    account_id = app.create_account(
        owner_id=child_id,
        adimin_id=parent_id,
        overdraft_protection=True

    )
    app.change_account_balance(account_id=account_id, val=70, transaction_method=TransactionMethodEnum.ADD)
    app.change_account_balance(account_id=account_id, val=50, transaction_method=TransactionMethodEnum.ADD)
    app.change_account_balance(account_id=account_id, val=20, transaction_method=TransactionMethodEnum.SUBTRACT)

def api_create_child():
    payload = {
        "first_name": "liam",
        "last_name": "Baxter",
        "email": "liam@gmail.com",
        "gender": 1,
        "age": 5,
        "grade": 8,
    }
    response = requests.post(
        url="http://127.0.0.1:5000/api/v1/users/child",
        json=payload,
    )
    print(response.json())
    if response.status_code in [200, 417]:
        response_data = response.json()
        return response_data['id']

def api_get_child():
    child_id = '1b417d26-e413-5407-8f7f-b632c4afb1e4'
    response = requests.get(f"http://127.0.0.1:5000/api/v1/users/child/{child_id}")
    print(response.json())

def api_get_get_account():
    account_id = "fd3c2347680955f28788f54323336eff"
    response = requests.get(f"http://127.0.0.1:5000/api/v1/account/{account_id}")
    print(response)

def api_create_account():
    admin_id = "1b417d26-e413-5407-8f7f-b632c4afb1e4"
    child_id = "d95effc8-ca27-591a-8655-33603fe3c022"

    payload = {
        "admin_id": admin_id,
        "owner_id": child_id,
        "overdraft_protection": True

    }

    response = requests.post(
        url="http://127.0.0.1:5000/api/v1/account",
        json=payload,
        headers=headers
    )
    print(response.json())
    if response.status_code in [200, 417]:
        response_data = response.json()
        if response_data.get("id"):
            return response_data['id']

def api_create_adult():
    payload = {
        "first_name": "Courtney",
        "last_name": "Baxter",
        "email": "cbaxtertech@gmail.com"
    }
    response = requests.post(
        url="http://127.0.0.1:5000/api/v1/users/adult",
        json=payload,
    )

    if response.status_code in [200, 417]:
        response_data = response.json()
        return response_data['id']

def api_change_account_balace_add():
    account_id = "40a4f1cdf9e05af38d95f3b585c13f81"

    payload = {
        "account_id": account_id,
        "val": 50,
        "method": 1
    }

    response = requests.put(
        url="http://127.0.0.1:5000/api/v1/account/balance",
        json=payload,
        headers=headers
    )
    print(response.json())

def api_change_account_balace_subtract():
    account_id = "40a4f1cdf9e05af38d95f3b585c13f81"

    payload = {
        "account_id": account_id,
        "val": 50,
        "method": 2
    }

    response = requests.put(
        url="http://127.0.0.1:5000/api/v1/account/balance",
        json=payload,
        headers=headers
    )
    print(response.json())

def api_create_task():
    due_date_dt = datetime.now() + timedelta(days=5)
    payload = {
        "name": "Clean Your Room",
        "description": "Cleaning MY Room",
        "due_date": due_date_dt.timestamp(),
        "value": 50,
        "child_id": "d95effc8-ca27-591a-8655-33603fe3c022",
    }

    response = requests.post(
        url="http://127.0.0.1:5000/api/v1/task",
        json=payload,
    )
    print(response.json())

if __name__ == "__main__":
    # child_id = api_create_child()
    # adult_id = api_create_adult()
    # account_id = api_create_account()
    api_change_account_balace_add()
    # api_create_task()


from outil.models import ParametreZE
#from outil.models import Epci
from outil.models import Commune
from .params import PACK
from .params import FICHIER_ZE
from .charger_ze import ZonesEmploi
from .charger_data import FichierPack
from outil.calcul.calculs_ze import CalculZE

def init_bdd():
    '''
    Reinitialise la table de paramètrage de la base de données
    '''
    ParametreZE.objects.all().delete()

    ze = ZonesEmploi()
    ze.charger(FICHIER_ZE)
    # Récupération des codes zone issus du Pack B1
    codes_zone = FichierPack(PACK).codes_zones
    for code in codes_zone:
        param_ze = ParametreZE(code_ze=code, nom_ze=ze.nom(code))
        param_ze.save()

    # Correction des paramètres Omphale pour les ZE n'ayant pas de scénarios Omphale
    calcul = CalculZE()
    parametres = ParametreZE.objects.all()
    scenarii = [(nom_court, nom_long) for nom_court, nom_long in ParametreZE.SCENARIOS_OMPHALE.items()]
    for parametre in parametres:
        resultat = calcul.resultat(parametre.code_ze)
        evolution_menage = resultat.evolution_menage
        valeurs_scenario = [(valeurs[0], valeurs[1], resultat.evolution_omphale(valeurs[0])) for valeurs in scenarii]
        # modification des paramètrage des ZE n'ayant pas de scénario Omphale
        if parametre.b2_choix_omphale and valeurs_scenario[0][2] == 0:
            param = ParametreZE.objects.get(code_ze = parametre.code_ze)
            param.b2_choix_omphale = False
            param.autre_source_b21 = evolution_menage
            param.save()

    #Commune.objects.all().delete()
    if len(Commune.objects.all()) == 0:
        Commune.objects.integrer_communes()

def init_classe_communes():
    '''
    Reinitialise les classes des communes
    '''
    Commune.objects.reinitiliser_classe()

def init_communes():
    '''
    Remets à jour les communes avec les EPCI associés à l'aide du fichier de désagrégation des communes
    '''
    Commune.objects.integrer_communes()


# 브루트 포스법으로 풀이

lst = [7,1,5,3,6,4]
def maxinterest(s:list):
  presult=[]
  result=[]
  for i in range(len(s)-1):
    for j in range(i,len(s)):
      presult.append(s[j]-s[i])
    result.append(max(presult))
  return max(result)

maxinterest(lst)

7장/주식을 사고팔기 가장 좋은 시점.py

주식을 사고팔기 가장 좋은 시점.py


import jax.numpy as jnp
from jax import device_put
from bench.core.executer import Executer

def yolo_encode(bboxes, gt_bboxes, stride, eps=1e-6):
    x_center_gt = (gt_bboxes[..., 0] + gt_bboxes[..., 2]) * 0.5
    y_center_gt = (gt_bboxes[..., 1] + gt_bboxes[..., 3]) * 0.5
    w_gt = gt_bboxes[..., 2] - gt_bboxes[..., 0]
    h_gt = gt_bboxes[..., 3] - gt_bboxes[..., 1]
    x_center = (bboxes[..., 0] + bboxes[..., 2]) * 0.5
    y_center = (bboxes[..., 1] + bboxes[..., 3]) * 0.5
    w = bboxes[..., 2] - bboxes[..., 0]
    h = bboxes[..., 3] - bboxes[..., 1]
    w_target = jnp.log(w_gt / w)
    w_target = jnp.clip(eps, w_target)
    h_target = jnp.log(h_gt / h)
    h_target = jnp.clip(eps, h_target)
    x_center_target = ((x_center_gt - x_center) / stride + 0.5)
    y_center_target = ((y_center_gt - y_center) / stride + 0.5)
    x_center_target = jnp.clip(x_center_target, eps, 1 - eps)
    y_center_target = jnp.clip(y_center_target, eps, 1 - eps)
    encoded_bboxes = jnp.stack(
        [x_center_target, y_center_target, w_target, h_target], axis=-1)
    return encoded_bboxes

def args_adaptor(np_args):
    bboxes = device_put(np_args[0])
    gt_bboxes = device_put(np_args[1])
    stride = device_put(np_args[2])
    eps = 1e-6

    return [bboxes, gt_bboxes, stride, eps]

def executer_creator():
    return Executer(yolo_encode, args_adaptor)


from django.urls import path
from Paytm import PaymentViews, views

urlpatterns = [
    # Payments urls

    # Creating Order
    path('create-order/',views.CreateOrder,name='create-order'),

    # First Step
    path('ReactNativeCustomPayment/',views.ReactNativeCustomPayment,name='ReactNativeCustomPayment'),

    # Second Step When ReactNativeCustomPayment Form Will Be Submited.
    path('pay/', PaymentViews.start_payment, name="start_payment"),

    # If Second Step Succed It Will Push To THis URL Which Will Send To Paytm Payment GateWay.
    path('handlepayment/', PaymentViews.handlepayment, name="handlepayment"),

]


def solution(research, n, k):
    search_alpha = set()
    _dict = dict()
    for r in research:
        for c in r:
            search_alpha.add(c)

    search_alpha = list(search_alpha)
    search_alpha.sort()

    for alpha in search_alpha:
        _dict[alpha] = []
        for r in research:
            _dict[alpha].append(r.count(alpha))

    length = len(research)

    _answer = dict()

    for i in range(length - n + 1):
        for key in _dict.keys():
            temp = _dict[key]
            if sum(temp[i:i + n]) < 2 * n * k:
                continue

            v = True
            for j in range(i, i + n):
                if temp[j] < k:
                    v = False
                    break

            if v:
                if key in _answer.keys():
                    _answer[key] += 1
                else:
                    _answer[key] = 1

    listAnswer = []

    for key in _answer.keys():
        listAnswer.append([key, _answer[key]])

    listAnswer.sort(key=lambda x: (int(-x[1]), x[0]))

    if listAnswer:
        return listAnswer[0][0]
    else:
        return "None"

if __name__ == '__main__':
    arr_research = [["abaaaa", "aaa", "abaaaaaa", "fzfffffffa"], ["yxxy", "xxyyy"], ["yxxy", "xxyyy", "yz"],
                    ["xy", "xy"]]
    arr_n = [2, 2, 2, 1]
    arr_k = [2, 1, 1, 1]
    arr_result = ["a", "x", "y", "None"]

    for research, n, k, result in zip(arr_research, arr_n, arr_k, arr_result):
        print(solution(research, n, k), result)


#!/usr/bin/env python3
"""
This module contains functions that interpolate between two low-symmetry
structures relative to a high-symmetry structure.
"""
from isodistortfile import isodistort
from convert2cell import cif2cell
import os
import time
import numpy as np
import numpy.linalg as la
from copy import deepcopy

class StructureInterp:
    """
    Class for the interpolation between two low-symmetry structures with
    different order parameters relative to a high-symmetry structure.

    Parameters
    ----------
    self.HS, self.LS1, self.LS2: str
        Names of the .cif files of the high-symmetry (HS) and two low-symmetry
        (LS) structures, subgroups of the high-symmetty phase, between which
        the interpolation is to be done.

    self.LS1_sub, self.LS2_sub: str
        Names of the .cif files of the LS structures reduced to a common
        subgroup.

    self.subgroup: int
        Space group number of subgroup.

    self.modeValues: list of two dicts
        List of two dictionaries mapping the distortion mode to the mode vector
        for the LS1 and LS2 structures relative to the HS structure.

    """

    def __init__(self, HSfile, LS1file, LS2file, subgroup, silent=True,
                 verbose=False):
        self.HS = HSfile
        self.LS1 = LS1file
        self.LS2 = LS2file
        self.subgroup = subgroup
        self.silent = silent
        self.modeValues = None
        self.interpList = {}
        self.verbose = verbose

    def reduce_common_subgroup(self):
        """
        This function reduces the two low-symmetry files to a common subgroup
        with common lattice parameters.

        Parameters:
        ----------
        subgroup: int
            The number corresponding to the space group of the common subgroup
            to both low-symmetry structures.

        cellparams: int
            The lattice parameters to use for the common reduction of both
            low-symmetry structures. 0: high-symmetry file, 1: low-symmetry
            file 1, 2: low-symmetry file 2.

        Returns:
        --------
        LS#file_"subgroup".cif: file
            Two CIF files in the same directory for the two reduced structures
        """

        for sfile in [self.LS1, self.LS2]:
            # Initialise ISODISTORT and get reduced structure
            iso = isodistort(sfile, silent=self.silent)
            iso.choose_by_spacegroup(self.subgroup)
            iso.select_space_group()

            # Save CIF file and get new name
            sfile = sfile.replace('.cif', '_{}.cif'.format(self.subgroup))
            iso.save_cif(fname=sfile, close=True)
            count = 0
            while sfile not in os.listdir("."):
                time.sleep(1)
                assert count < 10, "Printing CIF file took too long."

        return None

    def get_extremal_mode_vectors(self, save2file=True):
        """
        This function gets the values of the displacements of the irreducible
        sites of the structures between which we are interpolating.
        """
        if self.modeValues is not None:
            print("Extremal modes have already been extracted.")
            return None

        if 'modevals_dict.npy' in os.listdir("."):
            if self.verbose:
                print("Reading end-member mode values from .npy file.")

            self.modeValues = list(np.load('modevals_dict.npy', allow_pickle=
                                           "TRUE"))
        else:
            # Initialise Isodistort instance with HTT
            iso = isodistort(self.HS, silent=self.silent)
            self.modeValues = []

            for lsFile in [self.LS1, self.LS2]:
                iso.load_lowsym_structure(lsFile)
                iso.get_mode_labels()
                self.modeValues.append(iso.modevalues)

            iso.close()

            if self.verbose:
                return self.modeValues
            elif save2file:
                #Save to binary file if requested
                np.save('modevals_dict.npy', self.modeValues)

    def interp_mode_vector(self, mode, rho, theta):

        # Define the vectors
        v1 = np.array(self.modeValues[0][mode])
        v2 = np.array(self.modeValues[1][mode])

        return list(rho * ((v1 / la.norm(v1)) * np.cos(2 * theta) +
                    (v2 / la.norm(v2)) * np.sin(2 * theta)))

    def get_interp_modevalues(self, mode, step=0.1, pc=50,
                              starting_structure=0, point_bounds=None,
                              add_original=True):
        """
        This function gets interpolated mode values by first creating a 2D grid
        of xy-points homogeneously sampling an eigth of the plane (0-45 degrees)
        where x and y run from 0 to the maximum magnitude of the mode vectors
        corresponding to LTT and LTO.

        x_max = max(rho_lto, rho_ltt)

        Each pair (x,y) is converted into a pair (|M|, θ) via the equations:
            ρ = sqrt(x² + y²)
            |M| = ρ*sqrt(1 + α sin(4θ))
            α = M_LTO.dot(M_LTT)
            θ = atan(y/x)
        Conversely, we have:
            x = ρ cos(θ)
            y = ρ sin(θ)

        For each value pair (ρ, θ), a mode vector is generated for GM1+ via the
        formula:
            mode(ρ, θ) = ρ(mode_lto * cos(2θ) + mode_ltt * sin(2θ))
        """
        # Ensure the mode vectors of the low-symmetry structures are generated
        self.get_extremal_mode_vectors()

        # Get data for LTT and LTO structures
        v_lto = np.array(self.modeValues[0][mode])
        v_ltt = np.array(self.modeValues[1][mode])

        # Define the scalar product between the LTO and LTO mode vectors
        self.alpha = np.dot(v_lto, v_ltt)

        # Define the norm of the LTO and LTT structures
        rho_lto = la.norm(v_lto)
        rho_ltt = la.norm(v_ltt)
        x_lto, y_lto = rho_lto, 0.0
        x_ltt, y_ltt = rho_ltt / np.sqrt(2), rho_ltt / np.sqrt(2)

        # Define maximum magnitude to sample (relative)
        rho_max = max(rho_lto, rho_ltt) * (1 + pc / 100)

        # Define grid to sample 2D energy landscape
        if point_bounds is None:
            points = np.arange(0, rho_max, step)
            xy = [(round(xval, 3), round(yval, 3)) for yval in points for xval
                  in points if (yval <= xval)]
        else:
            xmin, xmax, ymin, ymax = point_bounds
            xy = [(xval, yval) for yval in np.arange(ymin, ymax + 1e-5, step)
                  for xval in np.arange(xmin, xmax + 1e-5, step) if
                  (yval <= xval)]

        # Add the LTT and LTO relaxed structures to the list
        if add_original:
            xy.append((x_lto, y_lto))
            xy.append((x_ltt, y_ltt))

        # Convert grid to polar coordinates
        # The polar coordinates are (|M|, θ) since the basis is not orthogonal
        # |M| = sqrt((x² + y²)*(1 + α sin(4θ)))
        # Getting ρ: ρ = sqrt((x² + y²) / (1 + α.sin(4θ)))
        self.cart2polar = {
                xy_vals: (
                    np.sqrt((xy_vals[0]**2 + xy_vals[1]**2) /
                            (1 + self.alpha * np.sin(4 *
                             np.arctan(xy_vals[1] / xy_vals[0])))),
                    np.arctan(xy_vals[1] / xy_vals[0]))
                if (xy_vals[0] != 0) else
                (np.sqrt(xy_vals[0]**2 + xy_vals[1]**2), 0.0)
                for xy_vals in xy
                }

        # Initialise list of mode vectors
        self.interpList = {}
        for key, values in self.cart2polar.items():
            (rho, theta) = values
            self.interpList[key] = deepcopy(self.modeValues[starting_structure]
                                            )
            self.interpList[key][mode] = self.interp_mode_vector(mode, rho,
                                                                 theta)
        return None

    def print_interp_cif(self, extent='all'):
        # Launch ISODISTORT class instance
        # Load HS and starting-point LS structures
        itp = isodistort(self.HS, silent=self.silent)
        itp.load_lowsym_structure(self.LS1)
        itp.get_mode_labels()

        if extent == 'all':
            for key in self.interpList:
                if self.verbose:
                    print(key)
                # Define filename
                fname = "La2MgO4_interpolated_{:.3f}_{:.3f}.cif".\
                        format(key[0], key[1])

                # Pass if filename already in directory
                if fname in os.listdir('.'):
                    continue

                assert 'subgroup_cif(1).txt' not in os.listdir('.'),\
                    "New structure 'subgroup_cif.txt' downloaded " + \
                    "before previous one was converted."

                # Set the mode values for this interpolation
                # Iterate over interpolation entries
                itp.modevalues = self.interpList[key]
                itp.set_amplitudes()
                itp.save_cif(fname=fname)

        elif extent in self.interpList:
            key = extent
            if self.verbose:
                print(key)

            # Set the mode values for this interpolation
            # Iterate over interpolation entries
            itp.modevalues = self.interpList[key]
            itp.set_amplitudes()
            fname = "La2MgO4_interpolated_{:1.3f}_{:1.3f}.cif".\
                    format(key[0], key[1])
            itp.save_cif(fname=fname)

        # Close ISODISTORT page instance.
        time.sleep(2)
        itp.close()
        return None

    def check_mode_vector(self, filename, mode):
        """
        This function checks whether the mode amplitude of the generated file
        has the expected angle and magnitude.

        Parameters:
        -----------
        filename: str
            CIF file given as interpolated_rho_theta.cif

        Returns:
        """
        seed = filename.strip("interpolated_").strip(".cif")
        (rho, theta) = (float(seed.split("_")[0]), float(seed.split("_")[1]))

        isocheck = isodistort(self.HS, silent=self.silent)
        isocheck.load_lowsym_structure(filename)
        isocheck.get_mode_labels()

        modevalues = isocheck.modevalues[mode]
        isocheck.close()
        N = len(modevalues)
        norm = round(la.norm(modevalues),3)
        try:
            thetas = (180 / np.pi)*np.array([np.arctan(modevalues[i]/\
                modevalues[i+1]) for i in range(0, N, 2)])
        except ZeroDivisionError:
            thetas = np.array([0.0, 0.0, 0.0])
        #assert abs(rho - norm) < 1e-3, "The magnitudes of the modes are not"+\
        #        "the same as what is expected. The expected norm is" + str(rho) + \
         #       " and the calculated norm is " + str(norm)

        #assert abs(thetas[0] - theta) > 1e-3, "The angles are not the same "+\
                #"The expected angle is {.1f} and the calculated angle is {.1f}." % \
                #(theta, thetas[0])
        return modevalues, rho, theta, norm, thetas


# -*- coding: utf-8 -*-
from django import forms
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone

from common.shortcuts import reorder_form_fields
from profiles.models import Membership
from .models import Meeting
from committees.models import Committee
from permissions import PERMISSIONS
from permissions.shortcuts import has_role_permission

class MeetingFilter(forms.Form):
    # order_by = forms.ChoiceField([('asc', _('Nearest first')), ('desc', _('Latest first'))],
    #                              required=False,
    #                              widget=forms.Select(attrs={'class': 'default selectize-it'}))
    order_by = forms.ChoiceField([('asc', _('oldest to newest')),
                                  ('desc', _('newest to oldest')),
                                  ('near', _('nearest first'))],
                                 required=False,
                                 widget=forms.Select(attrs={'class': 'default selectize-it'}))

    def __init__(self, membership, *args, **kwargs):
        super(MeetingFilter, self).__init__(*args, **kwargs)
        committee_options = ([('__all__', _('Any committee')),
                              ('__full__', _('All Board Members'))]
                             + [(c.id, c.name) for c in Committee.objects.for_membership(membership)])

        self.fields['committee'] = forms.ChoiceField(committee_options,
                                                     required=False,
                                                     widget=forms.Select(attrs={'class': 'default selectize-it committee-select'}))

def meeting_action_choices(meeting, membership, allow_update=True):
    """
    That's kind of magic selection in which situation what is possible. At first it was just select all the times.
    Then it was replaced with hidden field (for Publish button) and dynamic hidden in update.
    """
    if meeting.pk:
        if not meeting.is_published:
            actions = []
            if allow_update:
                # Note: this is correct, update at this stage is without emails sending
                actions.append(('update', _('Update')))
                actions.append(('update-no-email', _('Update without email')))
            else:
                actions.append(('publish', _('Publish')))
        else:
            actions = []
            if allow_update:
                actions.append(('update', _('Update')))
                if membership.is_admin or (meeting.creator and membership.id == meeting.creator.id)\
                        or membership.role == membership.ROLES.assistant:
                    actions.append(('update-no-email', _('Update without notification')))

        return actions
    else:
        return [('update-no-email', _('Save as draft')),
                # Note: this is correct, update is essentially don't change anything
                ('publish', _('Publish'))]

class MeetingPublishForm(forms.Form):
    def __init__(self, meeting, membership, *args, **kwargs):
        super(MeetingPublishForm, self).__init__(*args, **kwargs)
        self.fields['action'] = forms.ChoiceField(meeting_action_choices(meeting, membership, allow_update=False))

class LocationWidget(forms.TextInput):

    xattrs = {'id': 'edit-location-box',
              'list': 'select-location-box',
              'autocomplete': 'on',
              'placeholder': 'Enter or select location',
              'title': 'Enter or select location', }

    def __init__(self, data_list, name="location", *args, **kwargs):
        super(LocationWidget, self).__init__(*args, **kwargs)
        self._name = name
        self._list = data_list

    def render(self, name, value, attrs=None, renderer=None):

        attrs.update(self.xattrs)
        text_html = super(LocationWidget, self).render(name, value, attrs=attrs)

        data_list = '<select id="select-location-box">'
        for item in self._list:
            data_list += '<option value="%s">%s</option>' % (item, item)
        data_list += '</select>'

        return '
' + text_html + data_list + '
'

class MeetingAddForm(forms.ModelForm):
    action = forms.ChoiceField()
    repeat_end_type = forms.CharField(widget=forms.RadioSelect(choices=Meeting.REPEAT_END_TYPES))

    def __init__(self, *args, **kwargs):
        is_event = kwargs.pop('is_event')

        super(MeetingAddForm, self).__init__(*args, **kwargs)
        self.fields['committee'].label = _('Attendees')
        self.fields['committee'].empty_label = _('All Board Members')
        self.fields['name'].widget.attrs['placeholder'] = \
            _('Untitled Event') if is_event else _('Untitled Meeting')
        self.fields['description'].widget.attrs['placeholder'] = \
            _('Event Description') if is_event else _('Meeting Description')

        membership = self.initial.get('membership')
        account = self.initial.get('account')
        meeting = self.instance
        assert isinstance(meeting, Meeting)

        top_locations = self.get_locations()

        if account.default_meetings_location and len(account.default_meetings_location) > 0:
            init_location = account.default_meetings_location
        elif top_locations and len(top_locations) > 0:
            init_location = top_locations[0]
        else:
            init_location = ""

        self.fields['location'] = \
            forms.CharField(label=_('Location'),
                            widget=LocationWidget(data_list=top_locations),
                            initial=init_location,
                            max_length=250,
                            required=True)

        queryset = Committee.objects.filter(account=account)
        if has_role_permission(membership, Committee, PERMISSIONS.add):
            # can add meeting for any committee
            self.fields['committee'].queryset = queryset
        else:
            # can add meeting only if chairman
            self.fields['committee'].queryset = \
                queryset.filter(Q(chairman=membership) | Q(chairman__in=membership.get_bosses()))

        self.fields['repeat_end_date'] = \
            forms.DateField(label=_('Repeat end date'),
                            input_formats=['%b. %d, %Y'],
                            widget=forms.DateInput(attrs={'placeholder': '{:%b. %d, %Y}'.format(timezone.now())}),
                            required=False)
        self.fields['date'] = \
            forms.DateField(label=_('Date'),
                            input_formats=['%b. %d, %Y'],
                            widget=forms.DateInput(attrs={'placeholder': '{:%b. %d, %Y}'.format(timezone.now())}),
                            required=True)
        self.fields['time_start'] = forms.TimeField(label=_('From'), input_formats=['%I:%M %p'],
                                                    widget=forms.TimeInput(attrs={'class': 'from'}), required=True)
        self.fields['time_end'] = forms.TimeField(label=_('To'), input_formats=['%I:%M %p'],
                                                  widget=forms.TimeInput(attrs={'class': 'to'}), required=True)
        self.fields['action'] = forms.ChoiceField(meeting_action_choices(meeting, membership))

        members = Membership.objects.filter(account=account,
                                            user__is_active=True, is_active=True).select_related('user')
        self.fields['extra_members'] = \
            forms.ModelMultipleChoiceField(members, label=_('Additional Attendees'), required=False,
                                           widget=forms.SelectMultiple(attrs={'class': 'default'}))

        key_order = ['name', 'description', 'committee', 'extra_members', 'date', 'time_start', 'time_end', 'location', 'action',
                     'repeat_type', 'repeat_interval', 'repeat_max_count', 'repeat_end_date', 'repeat_week_days', 'repeat_end_type']
        self.fields = reorder_form_fields(self.fields, key_order)

        if not is_event:
            self.fields['board_book'] = forms.FileField(label=_('Add Board Book'), required=False)
            self.fields['agenda'] = forms.FileField(label=_('Add Agenda'), required=False)
            self.fields['minutes'] = forms.FileField(label=_('Add Minutes'), required=False)

        self.fields['other'] = forms.FileField(label=_('Add Other Documents'), required=False)
        self.fields['uploaded'] = forms.CharField(widget=forms.HiddenInput(), required=False)
        self.fields['repeat_end_type'].initial = meeting.repeat_end_type

        if meeting.pk:
            start = timezone.localtime(meeting.start)
            end = timezone.localtime(meeting.end)
            self.fields['date'].initial = start.strftime("%b. %d, %Y")
            self.initial['repeat_end_date'] = \
                meeting.repeat_end_date.strftime("%b. %d, %Y") if meeting.repeat_end_date else None
            self.fields['time_start'].initial = start.strftime("%I:%M %p")
            self.fields['time_end'].initial = end.strftime("%I:%M %p")

    def get_locations(self):

        # qs = Meeting.objects.filter(account=self.initial.get('account'))\
        #     .values_list('location', flat=True).distinct()
        # return list(qs)  # unsorted list

        # sorted by created date, but with location duplicates
        qs = Meeting.objects.filter(status=Meeting.STATUSES.published,
                                    account=self.initial.get('account'))\
            .order_by('-created_at').values_list('location', flat=True)

        locs = []
        for q in qs:
            if q not in locs:
                locs.append(q)
        return locs

    def clean(self):
        cleaned_data = super(MeetingAddForm, self).clean()

        repeat_end_type = cleaned_data.get('repeat_end_type', Meeting.REPEAT_END_TYPES.never)

        if repeat_end_type == Meeting.REPEAT_END_TYPES.max_count:
            cleaned_data['repeat_end_date'] = None
        elif repeat_end_type == Meeting.REPEAT_END_TYPES.end_date:
            cleaned_data['repeat_max_count'] = None
        else:
            cleaned_data['repeat_max_count'] = None
            cleaned_data['repeat_end_date'] = None

        return cleaned_data

    class Meta:
        model = Meeting
        exclude = ['account', 'start', 'end', 'status']
        widgets = {
            'name': forms.TextInput(attrs={'class': 'txt title', 'placeholder': _('Untitled Meeting')}),
            'description': forms.Textarea(attrs={'class': 'txt textarea', 'placeholder': _('Untitled Meeting'), 'rows': 3}),
            'location': forms.TextInput(attrs={'class': 'txt location', 'placeholder': _('Add location details')}),
        }


from pathlib import Path

import pytest

from src.utils import LineReader

def test_LineReader_lines_ok():
    """
    Tests if correct lines are returned, empty lines are skipped and StopIteration is reached
    :return: None
    """

    line_reader = LineReader(Path("tests/test_fiels_text.txt"))
    line_generator = line_reader.next_line_generator()
    line1 = next(line_generator)
    line2 = next(line_generator)

    assert line1 == "this is a test line1"
    assert line2 == "this is a test line2"

    with pytest.raises(StopIteration) as ex_info:
        next(line_generator)
    assert ex_info.type is StopIteration