import subprocess
import shutil
import os
# from . models import Question, Testcase
from subprocess import STDOUT, check_output
from celery import shared_task

def execute(code, tc, language):
    copy_run_py(language)
    copy_code(code)
    copy_input(tc)
    run = subprocess.run("python code/run.py", shell=True)

    return get_output_files()

def runCode(que, code, language):
    TCs = Testcase.objects.filter(que=que).order_by('pk')
    TC_Status = []
    outputList = []
    for tc in TCs:
        output, err, rc = execute(code, tc, language)
        if rc != 0:
            TC_Status.append("RE")
        elif compare(output, tc):
            TC_Status.append("AC")
        else:
            TC_Status.append("WA")

    return TC_Status

def compare(output, tc):
    try:
        with open(tc.tc_output.path, "r") as correct_output:
            x = correct_output.read().strip()
            return output.strip() == x
    except:
        return False

def create_containers():
    for i in range(6):
        try:
            os.makedirs(f"containers/container_{i}/")
        except:
            pass
    for i in range(6):
        container_path = f"{os.getcwd()}\\containers\\container_{i}"
        subprocess.run(f"docker run --name container_{i} -v {container_path}:src\ python", shell=True)

def copy_run_py(language):
    src = "run.py"
    dst = f"code/run.py"
    shutil.copyfile(src, dst)
    file1 = open(dst, "a")  # append mode
    file1.write(f"\nrun_{language}()")
    file1.close()

def copy_code(code):
    file_path = "code/code.py"
    with open(file_path, 'w+') as file:
        file.write(code)
        file.close()

def copy_input(tc):
    dst = "code/input.txt"
    src = tc.tc_input.path
    shutil.copy(src, dst)

def get_output_files():
    output = open("code/output.txt").read()
    err = open("code/err.txt").read()
    rc = open("code/returnCode.txt").read()
    return output, err, int(rc)

#my
import os,pathlib,subprocess
from django.conf import settings
project_name = "Clash_RC_2"
directory = os.path.join(settings.BASE_DIR,"User_Data")

def make_dir(user):
    print("inside make_dir",directory)
    # project_name = "Clash_RC_2"
    # directory = pathlib.Path(f"./{project_name}/User_Data/{username}")
    # if not directory.exists():
    #     directory.mkdir()
    #     return 1
    user_folder = pathlib.Path(f"{directory}/{user}")  #to check directory is present or not
    #if not it will create it
    if not user_folder.exists():
        user_folder.mkdir()

def make_code_file(language,code,ip_text,user):
    if language == "py":
        code_file = open(f"{directory}/{user}/code.{language}","w")
        code_file.write(code)
        code_file.close()
        text_file = open(f"{directory}/{user}/ip_text_file.txt","w")
        text_file.write(ip_text.replace('\n',""))
        text_file.close()
        return run_code_file(user,language)

def run_code_file(user,language):
    if (language == "py"):
        code_file_path = pathlib.Path(f"{directory}/{user}/code.py")
        text_file = pathlib.Path(f"{directory}/{user}/ip_text_file.txt")
        cmd = f"python {code_file_path} <{text_file}"
        op = subprocess.run(cmd,shell=True,text=True,capture_output=True)
        # print(op)
        # print(op.stdout)
        # print(op.stderr)
        code_op_text_file = open(f"{directory}/{user}/op_text.txt","w")
        if op.returncode !=1:
            code_op_text_file.write(op.stdout)
        else:
            code_op_text_file.write(op.stderr)

        code_op_text_file.close()

        if (compare_answer(user)):
            return True
        else:
            return False

directory_questions = os.path.join(settings.BASE_DIR,"Question_Data")

def compare_answer(user):
    with open(f'{directory_questions}/question_op/Q1_1_op.txt', 'r') as f1, open(f"{directory}/{user}/op_text.txt", 'r') as f2:
    # Read the contents of each file into memory
        file1_contents = f1.readlines()
        file2_contents = f2.readlines()
        print(file1_contents)
        print(file2_contents)

    # Compare the contents of the files
    if file1_contents == file2_contents:
        print("The files are the same")
        return True
    else:
        print("The files are different")
        return False

    # try:
    #     with open(f'{directory_questions}/question_op/Q1_1_op.txt', "r") as correct_output:
    #         x = correct_output.read().strip()
    #         y = f"{directory}/{user}/op_text.txt"
    #         print(x,y)
    #         if y.strip() == x :
    #             print("same file")
    #             return True
    #         else:
    #             print("diff file")
    #             return False
    # except:
    #     return False

#dev

import subprocess,os
import time
codeRunnerPath = os.path.abspath("Code_Runner")
print(codeRunnerPath,"dddddddddddddddddddddkkkkkkkkkkkkkkkkkkkkkkkk")
def run_python():
    code_path = f"{codeRunnerPath}/code.py"
    tc_path = f"{codeRunnerPath}/input.txt"
    # x = open(tc_path,"r")
    # y = open(code_path,"r")
    # print(x.read(),y.read())
    er=open(f'{codeRunnerPath}/error.txt','w+')
    rc=open(f'{codeRunnerPath}/status.txt','w+')
    out=open(f'{codeRunnerPath}/output.txt','w+')
    # run = subprocess.run(f"python {code_path} <{tc_path}", text=True, shell=True, capture_output=True,timeout=1)
    st =time.time()
    try:
        run = subprocess.run(f"python {code_path} <{tc_path}", text=True, shell=True, capture_output=True,timeout=1)
    except subprocess.TimeoutExpired:
        print("enter in exept blockhhhhhhhhhhhhhhhhhhhkkhk")
    et = time.time()
    print("time foe execution  : ",et-st)

    # print(run)
    # print(run.stdout)
    # print(run.stderr)
    # print(run.returncode)

    out.write(run.stdout)
    er.write(run.stderr)
    rc.write(str(run.returncode))
    er.close()
    rc.close()
    out.close()

def run_cpp():
    code_path = f"{codeRunnerPath}/code.cpp"
    tc_path = f"{codeRunnerPath}/input.txt"
    # x = open(tc_path,"r")
    # y = open(code_path,"r")
    # print(x.read(),y.read())
    er=open(f'{codeRunnerPath}/error.txt','w+')
    rc=open(f'{codeRunnerPath}/status.txt','w+')
    out=open(f'{codeRunnerPath}/output.txt','w+')
    # run = subprocess.run(f"python {code_path} <{tc_path}", text=True, shell=True, capture_output=True)
    run = subprocess.run(['g++', '-o', f"{codeRunnerPath}/code", f"{code_path}"], capture_output=True, text=True)
    # print(run)
    if run.returncode != 0:
        rc.write(str(run.returncode))
        rc.close()
        er.write(run.stderr)
        er.close()
        print('Compilation failed. Errors written to errors.txt.')
    else:
        with open(f"{tc_path}", "r") as input_file:
            program_result = subprocess.run([f"{codeRunnerPath}/./code"],stdin=input_file, capture_output=True, text=True)
            out.write(program_result.stdout)
            er.write(program_result.stderr)
            rc.write(str(run.returncode))
            rc.close()
            er.close()
            out.close()

def run_c():
    code_path = f"{codeRunnerPath}/code.c"
    tc_path = f"{codeRunnerPath}/input.txt"
    # x = open(tc_path,"r")
    # y = open(code_path,"r")
    # print(x.read(),y.read())
    er=open(f'{codeRunnerPath}/error.txt','w+')
    rc=open(f'{codeRunnerPath}/status.txt','w+')
    out=open(f'{codeRunnerPath}/output.txt','w+')
    # run = subprocess.run(f"python {code_path} <{tc_path}", text=True, shell=True, capture_output=True)
    run = subprocess.run(['gcc', '-o', f"{codeRunnerPath}/code", f"{code_path}"], capture_output=True, text=True)
    # print(run)
    if run.returncode != 0:
        rc.write(str(run.returncode))
        rc.close()
        er.write(run.stderr)
        er.close()
        print('Compilation failed. Errors written to errors.txt.')
    else:
        with open(f"{tc_path}", "r") as input_file:
            program_result = subprocess.run([f"{codeRunnerPath}/./code "],stdin=input_file, capture_output=True, text=True)
            out.write(program_result.stdout)
            er.write(program_result.stderr)
            rc.write(str(run.returncode))
            rc.close()
            er.close()
            out.close()

#ruuner utils
import subprocess
import shutil
import os
from .models import Question, Testcases
from subprocess import STDOUT, check_output
# from celery import shared_task
codeRunnerPath = os.path.abspath("Code_Runner")
# codeRunnerPath="Clash_RC_2/Code_Runner"
runnerPath = os.path.dirname(__file__)
print(codeRunnerPath,"dddjjjjjjjjjjjjjjjjjjjjjjjjjjjjj")

ErrorCodes={
  "AC": 0,
  "WA": 1,
  "CE": 2,
  "RE": 3,
  "MLE":4,
  "TLE":5,
}

def execute(code, tc, language):
    copy_run_py(language)
    copy_code(code,language)
    copy_input(tc)
    run = subprocess.run(f"python {codeRunnerPath}/code_run.py", shell=True)

    return get_output_files()

def runCode(que_num, code, language,btn_click_status,user_test):             #btn_click_status true = submit and false = run
    TC_Status = []
    # print("fffffffffff",user_test)
    if (btn_click_status==0):
        output, err, rc = execute_run(code, user_test, language)
        print("ge output files",output,"type ",err,rc)

        if int(rc) !=0:
            print("enter in if")
            TC_Status.append(err)
        else:
            print("enter in else")
            TC_Status.append(output)
        print("in run code for run clicke",TC_Status)
        return TC_Status

    TCs = Testcases.objects.filter(q_id=que_num).order_by('t_id')
    # print("TEst casesinside runcode ",TCs)
    outputList = []
    for tc in TCs:

        output, err, rc = execute(code, tc, language)
        # print("op",output,"err",err,"status",rc,"value of compare",compare(output, tc))
        if int(rc) != 0:
            TC_Status.append("RE")
        elif compare(output, tc):
            TC_Status.append("AC")
        else:
            TC_Status.append("WA")
    print("see list of status ",TC_Status)
    return TC_Status

def compare(output, tc):
    try:
        with open(tc.t_op.path, "r") as correct_output:
            x = correct_output.read().strip()
            # print("actual : ",x,"user : ",output)
            return output.strip() == x
    except:
        return False

def copy_run_py(language):
    src = f"{runnerPath}/runner.py"
    dst = f"{codeRunnerPath}/code_run.py"
    print(src,"\n",dst,"\nsdsssssssddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")
    shutil.copyfile(src, dst)
    file1 = open(dst, "a")  # append mode
    file1.write(f"\nrun_{language}()")
    file1.close()

def copy_code(code,language):
    if (language=="python"):
        file_path = f"{codeRunnerPath}/code.py"
    elif (language=="cpp"):
        file_path = f"{codeRunnerPath}/code.cpp"
    elif (language=="c"):
        file_path = f"{codeRunnerPath}/code.c"
    with open(file_path, 'w+') as file:
        file.write(code)
        file.close()

def copy_input(tc):
    dst = f"{codeRunnerPath}/input.txt"
    src = tc.t_ip.path
    shutil.copy(src, dst)

def get_output_files():
    output = open(f"{codeRunnerPath}/output.txt").read()
    err = open(f"{codeRunnerPath}/error.txt").read()
    rc = open(f"{codeRunnerPath}/status.txt").read()
    print("ge output files",output,"type ",err,rc)
    return output, err, rc

#when run clicke
def copy_test_input(tc):
    # print("dfddddddddd",tc)
    dst = open(f"{codeRunnerPath}/input.txt","w")
    dst.write(tc)
    dst.close()

def execute_run(code, tc, language):
    copy_run_py(language)
    copy_code(code,language)
    copy_test_input(tc)
    run = subprocess.run(f"python {codeRunnerPath}/code_run.py", shell=True)

    return get_output_files()

#To detect error
# import os
codeRunnerPath = os.path.abspath("testsubprocess")
# codeRunnerPath="Clash_RC_2/Code_Runner"

#It will give current file path
#And our other files are in same folder
FilePath = os.path.dirname(__file__)
print("File Path ",FilePath)

#File in which users code is present
PythonFile = f"{FilePath}/code.py"
CppFile = f"{FilePath}/code.cpp"
CFile = f"{FilePath}/code.c"
#File in which ip testcase is present
ip_file_path = f"{FilePath}/input.txt"
with open(ip_file_path, 'r') as f:
    ip_contents = f.read()

import subprocess
import signal,resource
import psutil,re

ceErrors = [ "SyntaxError:","NameError:","TypeError:","ImportError:","IndentationError:","LogicError:"]
reErrors = ["ZeroDivisionError:","IndexError:","KeyError:","AttributeError:","ValueError:","RuntimeError","StopIteration","RecursionError","OSError"]
#"MemoryError"

#Timeout Signal
TimeoutLimit = 1
def set_time_limit(time_limit):
    def signal_handler(signum, frame):
        raise TimeoutError
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(time_limit)

MemoryLimit = 256 * 1024 * 1024
def set_memory_limit():
    # resource.setrlimit(resource.RLIMIT_CPU, (TimeoutLimit, TimeoutLimit))
    resource.setrlimit(resource.RLIMIT_AS, (MemoryLimit, MemoryLimit))

def execute_user_code(lang):
    try:
        set_time_limit(TimeoutLimit)

        process = RunByLang(lang)

        # # wait for the command to finish and get the stdout and stderr
        stdout, stderr = process.communicate()
        CopyFilesToTxt(stdout,stderr)
        ListOfReturn =stderr.decode().strip().split()
        print(ListOfReturn)
        # signal.alarm(0)

        # check for any errors in stderr
        if process.returncode != 0:
            process.kill()
            if any(error in ListOfReturn for error in ceErrors):
                return "CE"
            elif any(error in ListOfReturn for error in reErrors):
                return "RE"
            elif "MemoryError" in ListOfReturn:
                return "MLE"
            else:
                return "WA"
        else:
            if (process.returncode == 0):
                return "AC"
            else:
                return "WA"
    except TimeoutError:
        # handle timeout error
        process.kill()
        stdout, stderr = process.communicate()
        CopyFilesToTxt(stdout,stderr)

        # stderr = process.stderr.read()
        ListOfReturn =stderr.decode().strip().split()
        # s[s.index("File")] = "ddddd"
        # print("index ",ListOfReturn)
        # print("inside 1timeout ",str(stderr.decode()).split())
        if ("MemoryError" in ListOfReturn):
            print("present MLE")
            return "MLE"

        return "TLE"

def CopyFilesToTxt(stdout,stderr,rCode):
    err=open(f'{FilePath}/error.txt','w+')
    out=open(f'{FilePath}/output.txt','w+')
    # rCode=open(f'{FilePath}/status.txt','w+')

    out.write(stdout.decode().strip())
    err.write(stderr.decode().strip())
    # rCode.write(rCode)

def RunByLang(lang):
    if (lang == "py"):
        process = subprocess.Popen(['python3', f'{PythonFile}'],stdin=ip_contents,stdout=subprocess.PIPE, stderr=subprocess.PIPE,preexec_fn=set_memory_limit)
        return process
    elif (lang == "cpp"):
        process = subprocess.Popen(['g++', '-o', f"{FilePath}/code", f"{CppFile}"],stdout=subprocess.PIPE, stderr=subprocess.PIPE,preexec_fn=set_memory_limit )
        if (process.returncode != 0):
            return process
        process = subprocess.Popen([f"{FilePath}/./code"],stdin=ip_contents,stdout=subprocess.PIPE, stderr=subprocess.PIPE,preexec_fn=set_memory_limit )
        return process

# test the function with a sample command
command = ['python3', f'{PythonFile}']
result = execute_user_code(command)
print("result   ",result)

import subprocess,os
import time

codeRunnerPath = os.path.abspath("Code_Runner")
# codeRunnerPath="Clash_RC_2/Code_Runner"
runnerPath = os.path.dirname(__file__)
print(codeRunnerPath,"sssssssssssss",runnerPath)

def run_with_popen(language):
    # File path for coderunner
    code_path = f"{codeRunnerPath}/code.py"
    # tc_path = f"{codeRunnerPath}/input.txt"

    # Location for ip.txt file
    tc_path = open(f'{codeRunnerPath}/input.txt','r')

    #Locations for error output file
    er=open(f'{codeRunnerPath}/error.txt','w+')
    rc=open(f'{codeRunnerPath}/status.txt','w+')
    out=open(f'{codeRunnerPath}/output.txt','w+')

    st =time.time()
    cmd = f"python3 {code_path}"

    # run = subprocess.Popen(cmd,stdin=tc_path,stderr=subprocess.PIPE,stdout=subprocess.PIPE,shell=True,text=True)
    run = subprocess.Popen(cmd,stdin=tc_path,stderr=er,stdout=out,shell=True,text=True)
    run.wait()

    et = time.time()
    print("time foe execution  : ",et-st)

    # print(run)
    print(run.returncode)
    """ in popen if we piped stdin out then we not need to communicate op will save at specified place
        if not piped then use communicate"""

run_with_popen()


import os, sys
print(sys.version)
import numpy as np
import argparse
import time
import matplotlib.pyplot as plt
from data_io import Data
from preprocess import Preprocess
from optHist import OptHist

# parse input arguments
parser = argparse.ArgumentParser()
parser.add_argument('--data_path', type=str, default='./')
parser.add_argument('--num_points', type=int,default=5000)
parser.add_argument('--range', type=int,default=100)
parser.add_argument('--num_buckets', type=int,default=3)
parser.add_argument('--data_name', type=str, default=None)
parser.add_argument('--toy_example',type=bool,default=False)

config = parser.parse_args()
# run the optimal histogram for inputs or toy example on presentation
if config.toy_example ==False:
    data = Data(config.data_path)
    if config.data_name == None:
        x = data.generate_random_data(config.num_points,config.range,'mixture',4)
    else:
        x = data.load_data(config.data_name)
    print('num points :', x.shape[0])

    proc = Preprocess(x)
    oh = OptHist(proc)

    tic = time.time()
    sse, cut, hist = oh.findBucket(config.num_buckets)
    print('Running time :', time.time()-tic)
    print('Sum Squared Error :',sse)
    print('Optimal Cuts :',cut)
    x_hist, y_hist = oh.visualize_histogram(cut,hist)
    plt.hist(x,400)
    plt.plot(x_hist,y_hist)
    plt.show()
else :
    x = np.array([2,2,2,2,3,3,3,3,3,4,4,5,6,6,6,6,6,6,6,6,6,7,8,8,8,8,9,9,9])
    proc = Preprocess(x)
    print('value\n',proc.value)
    print('freq\n',proc.freq)
    print('P\n',proc.P)
    print('PP\n',proc.PP)
    #print(proc.SSE(1,2))
    oh = OptHist(proc)
    sse, cut, hist = oh.findBucket(3)
    print('cut list\n', cut)
    print('hist')
    print(hist)
    x1,y1 = oh.visualize_histogram(cut,hist)
    plt.hist(x,bins=[1,2,3,4,5,6,7,8,9],range=(1,9))
    plt.plot(x1,y1)
    plt.show()


from django.urls import include, path
from rest_framework.routers import DefaultRouter

from questions.api.views import (QuestionViewSet,
                                 AnswerCreateAPIView,
                                 QuestionAnswerListAPIView,
                                 AnswerRUDAPIView,
                                 AnswerLikeAPIView)

router = DefaultRouter()

router.register(r'questions', QuestionViewSet)
urlpatterns = [
    path('', include(router.urls)),

    path('questions/<slug:slug>/answer/',
         AnswerCreateAPIView.as_view(),
         name='answer-create'),

    path('questions/<slug:slug>/answers/',
         QuestionAnswerListAPIView.as_view(),
         name='list-question-answers'),

    path('answers/<int:pk>/',
         AnswerRUDAPIView.as_view(),
         name='list-question-detail'),

    path('answers/<int:pk>/like/',
         AnswerLikeAPIView.as_view(),
         name='answer-like'),
]


import os
import numpy as np
from astropy.io import fits
from astropy.table import Table
from astropy import units as u
from astropy.coordinates import SkyCoord

def create_sweepfile_dict(listdir = ['/global/project/projectdirs/cosmo/data/legacysurvey/dr9/north/sweep/9.0', '/global/project/projectdirs/cosmo/data/legacysurvey/dr9/south/sweep/9.0']):
    '''Creates dictionary of sweep files containing path, min
    and max ra and dec for the block.

    Parameters
    ----------
    listdir : list of str, optional
        list of directory paths to search for sweep files.
        defaults to dr9 north and south sweeps

    Returns
    -------
    files : dict
        A dictionary w/ filename for keys.
        Every key maps to another dictionary containing
        'min_ra' 'max_ra' 'min_dec' 'max_dec' and 'path'
    '''
    files = {}
    for dir in listdir:
        for dirname, __, filenames in os.walk(dir):

            for filename in filenames:
                block = filename[6:-5]

                if block[6].isdigit():

                    min_ra = int(block[:3])
                    min_dec = int(block[4:7])
                    if block[3] == 'm':
                        min_dec = int('-'+str(min_dec))

                    max_ra = int(block[8:11])
                    max_dec = int(block[12:])
                    if block[-4] == 'm':
                        max_dec = int('-'+str(max_dec))

                    files[filename]={'min_ra':min_ra, 'max_ra':max_ra, 'min_dec': min_dec, 'max_dec':max_dec, 'path':os.path.join(dirname, filename)}
    return files

def find_host_galaxy_file(files,ra, dec):
    '''Matches transient to corresponding host sweep file by
    finding which block it is in.

    Parameters
    ----------
    files : dict
        A dictionary w/ filename for keys.
        Every key maps to another dictionary containing
        'min_ra' 'max_ra' 'min_dec' 'max_dec' and 'path'
    ra : float
        pseudo-host ra for observed transient
    dec : float
        pseudo-host dec for observed transient

    Returns
    -------
    path : str or nan
        full path of the matching sweep file.
        Returns nan if no match is found.
    '''
    for i in files.keys():
         if ra>=files[i]['min_ra'] and ra<=files[i]['max_ra'] and dec>=files[i]['min_dec'] and dec<=files[i]['max_dec']:
            return files[i]['path']
         else: continue

    return float(np.NaN)

def find_ID_RA_DEC_lists_in_brick(brick_path):
    '''Finds lists of OBJID, RA, DEC

    Parameters
    ----------
    sweepfile_path : str
        A sweep file path to extract objects from.

    Returns
    -------
    OBJID_RA_DEC : list of 3 lists
        List of 3 lists corresponding to objid, ra, dec respectiveliy
        of all objects in the brick sweep file.
    '''
    hdus = fits.open(brick_path)
    data = Table(hdus[1].data)
    return [list(data['OBJID']), list(data['RA']), list(data['DEC'])]

def find_redshift(obj_list, path, ra, dec):

    '''Finds Spectroscopic and Photometric redshift and Standard Deviation
       NOTE: - Spectroscopic Redshift will be -99.0 if it does not exist
             - I the associated photo-z file does not exist, returns a tuple
               of type nan

    Parameters
    ----------
    onj_list : list of 3 lists
        List of 3 lists corresponding to objid, ra, dec respectiveliy
        of all objects in the brick sweep file.
    sweepfile_path : str
        A sweep file path associated with the matching brick.
    ra : float
        pseudo-host ra for observed transient
    dec : float
        pseudo-host dec for observed transient

    Returns
    -------
     z_spec, z_photo_mean, z_photo_err: tuple
        A tuple containing spectroscopic redshift, mean of photometric redshift,
        and photometric redshift standard deviation respectively of the matching
        object within the sweep file.
    '''
    c = SkyCoord(ra*u.degree, dec*u.degree)
    catalog = SkyCoord(obj_list[1]*u.degree, obj_list[2]*u.degree)
    idx, d2d, d3d = c.match_to_catalog_3d(catalog)
    obj_id = obj_list[0][idx]

    sweep_pz = path.replace('9.0', '9.0-photo-z').replace('.fits', '-pz.fits')

    if os.path.exists(sweep_pz):
        hdus = fits.open(sweep_pz)
        redshift_data = Table(hdus[1].data)
        try:
            assert redshift_data['OBJID'][idx] == obj_id, 'object ID does not match'
            z_spec, z_photo_mean, z_photo_err = (redshift_data['Z_SPEC'][idx],redshift_data['Z_PHOT_MEAN'][idx], redshift_data['Z_PHOT_STD'][idx])
            return (z_spec, z_photo_mean, z_photo_err)
        except AssertionError as msg:
            print(msg)
    else:
        print(os.path.exists(sweep_pz))
    return (np.NaN, np.NaN, np.NaN)

def do_all(ra, dec):
    files = create_sweepfile_dict()
    path = find_host_galaxy_file(files, ra, dec)
    obj_lists = find_ID_RA_DEC_lists_in_brick(path)
    z_spec, z_photo_mean, z_photo_err = find_redshift(obj_lists, path, ra, dec)
    return {'z_spec': z_spec, 'mean': z_photo_mean,'err': z_photo_err}


from django.forms import (
    CharField,
    ModelChoiceField,
    ModelMultipleChoiceField,
    TextInput,
)
from gbe.models import (
    Event,
)
from gbe_forms_text import (
    scheduling_help_texts,
    scheduling_labels,
)
from gbe.forms.common_queries import (
    visible_personas,
    visible_profiles,
)
from gbe.scheduling.forms import ScheduleBasicForm
from tinymce.widgets import TinyMCE

class ScheduleSelectionForm(ScheduleBasicForm):
    e_title = CharField(
        widget=TextInput(attrs={'size': '79'}),
        label=scheduling_labels['e_title'],
        help_text=scheduling_help_texts['e_title'])

    e_description = CharField(
        widget=TinyMCE(attrs={'cols': 80, 'rows': 20}),
        label=scheduling_labels['e_description'],
        help_text=scheduling_help_texts['e_description'])
    teacher = ModelChoiceField(
        queryset=visible_personas,
        required=False)
    moderator = ModelChoiceField(
        queryset=visible_personas,
        required=False)
    panelists = ModelMultipleChoiceField(
        queryset=visible_personas,
        required=False)
    staff_lead = ModelChoiceField(
        queryset=visible_profiles,
        required=False)

    class Meta:
        model = Event
        fields = ['e_title', 'e_description', 'duration']
        help_texts = scheduling_help_texts
        labels = scheduling_labels


from ursina import *

class Hud(Entity):
    def __init__(self, **kwargs):
        super().__init__(
            parent=camera.ui,
            model=Quad(radius=.015),
            texture='white_cube',
            texture_scale=(4, 1),
            scale=(.4, .1),
            origin=(0, 4.3),
            color=color.color(0, 0, .1, .9),
        )

class Item(Entity):
    def __init__(self,texture):
        super().__init__(
            parent=camera.ui,
            model='quad',
            scale=(0.09, 0.09),
            position=(-.151, 0),
            origin=(0, 4.8),
            texture=texture
        )

class Inventory(Entity):
    def __init__(self, **kwargs):
        super().__init__(
            parent=camera.ui,
            model=Quad(radius=.015),
            texture='white_cube',
            texture_scale=(6, 4),
            scale=(.6, .4),
            origin=(0, 0),
            color=color.color(0, 0, .1, .9)
        )


import datetime as dt

EWMA_ALPHA = 0.05   # make the decay slower or,
FREQUENCY = 2   # update less
NIMPA_URL = 'https://nimpala.me'
NIMPA_CREDENTIALS = ('root', 'root')
SEGMENT_UPDATE_SCHEME = 'dual'

# Affects task_scheduler.py
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
TIMEZONE = 'Asia/Manila'

# MongoDB and MongoEngine
MONGODB_HOST='localhost'
MONGODB_PORT=27017
MONGODB_DB_NAME = 'eta_app'
MONGODB_SEGMENT_COLLECTION = 'segments'
MONGODB_VEHICLE_COLLECTION = 'vehicles'
MONGOENGINE_DB_ALIAS = 'default'

JSON_ROUTE_DATA = 'ikot_route_test.geojson'

# eta_computer
ROUTE_DIRECTION = "increasing"
CONSIDER_DESTINATION_SEGMENT = False
DEFAULT_MAX_NUMBER_OF_PUVS = 3
DEFAULT_ZOMBIE_TIMEDELTA = dt.timedelta(minutes=5)


############# My calculator

import re

#This was my attempt at the calc before watching the video, I didn't know of the eval function
#which was essential really. Also after watching bits of the video, I got to a solid point but
#didn't apply any filters to the calc input, causing errors
def unassissted_calculator():
    boolean_control=1   #These were set globally in his examples
    a=0
    print ('Enter equation:')
    while boolean_control==1:
        if a==0:
            input_equation = input()
        else:
            input_equation = input(str())

        if input_equation == 'Toast':
            boolean_control = 0
        elif input_equation=='Clear':
            a=0
        else:

            input_numbers = re.sub('[^0-9]','',input_equation)
            print(input_numbers)

            a=a+1
    return

def calculator():
    boolean_control = 1  # These were set globally in his examples
    a = 0
    while boolean_control == 1:
        #on the first iteration, get equation prompt
        if a == 0:
            input_equation = input("Enter opalration:")
        #on following iterations, start prompt with the previous answer
        else:
            input_equation = input(str(a))

        if input_equation == 'Toast':
            boolean_control = 0
        elif input_equation == 'Clear':
            a = 0
        else:
            #apply filter to avoid breaking the eval function
            input_filtered=re.sub('[a-zA-Z,.()" "]','',input_equation)
            if a==0:
                a= eval(input_filtered)
            else:
                a=eval(str(a)+input_filtered)

    return

calculator()


#!/usr/bin/env python3

import rclpy

from rclpy.node import Node

from dt_interfaces_cps.msg import WheelsCmdStamped, BoolStamped
from wheels_driver.dagu_wheels_driver import DaguWheelsDriver

class WheelsDriverNode(Node):
    """Node handling the motor velocities communication.
        Subscribes to the requested wheels commands (linear velocities, i.e.
        velocity for the left and the right wheels) and to an
        emergency stop flag.
        When the emergency flag `~emergency_stop` is set to `False` it actuates
        the wheel drive with the velocities received from `~wheels_cmd`.
        Publishes the execution of the commands to `~wheels_cmd_executed`.
        The emergency flag is `False` by default.
        Subscribers:
           ~wheels_cmd (:obj:`WheelsCmdStamped`): The requested wheel command
           ~emergency_stop (:obj:`BoolStamped`): Emergency stop. Can stop
                the actual execution of
                the wheel commands by the motors if set to `True`. Set to
                `False` for nominal operations.
        Publishers:
           ~wheels_cmd_executed (:obj:`WheelsCmdStamped`): Publishes the
                actual commands executed, i.e. when the emergency flag is
                `False` it publishes the requested command, and when it is
                `True`: zero values for both motors.
    """
    def __init__(self, node_name: str):
        super().__init__(node_name)

        self.estop = False

        # Setup the driver
        self.driver = DaguWheelsDriver()

        # Initialize the executed commands message
        self.msg_wheels_cmd = WheelsCmdStamped()

        # Publisher for wheels command wih execution time
        self.pub_wheels_cmd = self.create_publisher(
            WheelsCmdStamped,
            "~/wheels_cmd_executed",
            1)

        # Subscribers
        self.sub_topic = self.create_subscription(
            WheelsCmdStamped,
            "~/wheels_cmd",
            self.wheels_cmd_cb,
            1)
        self.sub_e_stop = self.create_subscription(
            BoolStamped,
            "~/emergency_stop",
            self.estop_cb,
            1)

        self.get_logger().info("Initialised")

    def wheels_cmd_cb(self, msg: WheelsCmdStamped):
        """
        Callback that sets wheels' speeds.
            Creates the wheels' speed message and publishes it. If the
            emergency stop flag is activated, publishes zero command.
            Args:
                msg (WheelsCmdStamped): velocity command
        """
        if self.estop:
            vel_left = 0.0
            vel_right = 0.0
        else:
            vel_left = msg.vel_left
            vel_right = msg.vel_right

        self.driver.set_wheels_speed(left=vel_left, right=vel_right)
        # Put the wheel commands in a message and publish
        self.msg_wheels_cmd.header = msg.header
        # Record the time the command was given to the wheels_driver
        self.msg_wheels_cmd.header.stamp = self.get_clock().now().to_msg()
        self.msg_wheels_cmd.vel_left = vel_left
        self.msg_wheels_cmd.vel_right = vel_right
        self.pub_wheels_cmd.publish(self.msg_wheels_cmd)

    def estop_cb(self, msg: BoolStamped):
        """
        Callback that enables/disables emergency stop
            Args:
                msg (BoolStamped): emergency_stop flag
        """
        self.estop = msg.data
        if self.estop:
            self.get_logger().info("Emergency Stop Activated!!!")
        else:
            self.get_logger().info("Emergency Stop Released!!!")

    def on_shutdown(self):
        """Shutdown procedure.
        Publishes a zero velocity command at shutdown.
        """
        self.driver.set_wheels_speed(left=0.0, right=0.0)

def main(args=None):
    rclpy.init(args=args)
    node = WheelsDriverNode(node_name="wheels_driver_node")
    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        node.on_shutdown()
        node.destroy_node()
        rclpy.shutdown()

if __name__ == "__main__":
    main()


def readUserSession(datafile):
  """
  Reads the user session record from the file's cursor position
  Args:
    datafile: Data file whose cursor points at the beginning of the record

  Returns:
    list of pages in the order clicked by the user
  """
  for line in datafile:
    pages = line.split()
    total = len(pages)
    # Select user sessions with 2 or more pages
    if total < 2:
      continue

    # Exclude outliers by removing extreme long sessions
    if total > 500:
      continue

    return [PAGE_CATEGORIES[int(i) - 1] for i in pages]
  return []


import torch
import torch.nn as nn
import itertools
from util.image_pool import ImagePool
from .base_model import BaseModel
from . import networks
import numpy as np
import cv2
from util import util
from util.saver import save_images
from torch.nn import functional as F
import gc
import random

class MXResnetModel(BaseModel):
    """
    This class implements the CycleGAN model, for learning image-to-image translation without paired data.

    The model training requires '--dataset_mode unaligned' dataset.
    By default, it uses a '--netG resnet_9blocks' ResNet generator,
    a '--netD basic' discriminator (PatchGAN introduced by pix2pix),
    and a least-square GANs objective ('--gan_mode lsgan').

    CycleGAN paper: https://arxiv.org/pdf/1703.10593.pdf
    """
    @staticmethod
    def modify_commandline_options(parser, is_train=True):
        """Add new dataset-specific options, and rewrite default values for existing options.

        Parameters:
            parser          -- original option parser
            is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.

        Returns:
            the modified parser.

        For CycleGAN, in addition to GAN losses, we introduce lambda_A, lambda_B, and lambda_identity for the following losses.
        A (source domain), B (target domain).
        Generators: G_A: A -> B; G_B: B -> A.
        Discriminators: D_A: G_A(A) vs. B; D_B: G_B(B) vs. A.
        Forward cycle loss:  lambda_A * ||G_B(G_A(A)) - A|| (Eqn. (2) in the paper)
        Backward cycle loss: lambda_B * ||G_A(G_B(B)) - B|| (Eqn. (2) in the paper)
        Identity loss (optional): lambda_identity * (||G_A(B) - B|| * lambda_B + ||G_B(A) - A|| * lambda_A) (Sec 5.2 "Photo generation from paintings" in the paper)
        Dropout is not used in the original CycleGAN paper.
        """
        parser.set_defaults(no_dropout=True)  # default CycleGAN did not use dropout
        if is_train:
        #     parser.add_argument('--lambda_A', type=float, default=10.0, help='weight for cycle loss (A -> B -> A)')
        #     parser.add_argument('--lambda_B', type=float, default=10.0, help='weight for cycle loss (B -> A -> B)')
        #     parser.add_argument('--lambda_identity', type=float, default=0.5, help='use identity mapping. Setting lambda_identity other than 0 has an effect of scaling the weight of the identity mapping loss. For example, if the weight of the identity loss should be 10 times smaller than the weight of the reconstruction loss, please set lambda_identity = 0.1')
            parser.add_argument('--show_cam', type=bool, default=True, help='show cam')
            parser.add_argument('--show_acc', type=bool, default=True, help='show acc for C_A and C_B')
        parser.add_argument('--n_classes', type=int, default=2, help='how many class')
        return parser

    def __init__(self, opt):
        """Initialize the CycleGAN class.

        Parameters:
            opt (Option class)-- stores all the experiment flags; needs to be a subclass of BaseOptions
        """
        BaseModel.__init__(self, opt)
        # specify the training losses you want to print out. The training/test scripts will call <BaseModel.get_current_losses>
        self.loss_names = ['C', 'C_A', 'C_B']
        # specify the images you want to save/display. The training/test scripts will call <BaseModel.get_current_visuals>
        self.opt = opt
        self.only_early_late = 'onlyEarlyLate' in self.opt.name

        visual_names_A = []
        visual_names_B = []
        if self.opt.show_cam:
            visual_names_A.append('cam_A')
            visual_names_B.append('cam_B')

        self.visual_names = visual_names_A + visual_names_B  # combine visualizations for A and B
        # specify the models you want to save to the disk. The training/test scripts will call <BaseModel.save_networks> and <BaseModel.load_networks>.
        self.model_names = []
        self.model_names.append('C')

        # define networks (both Generators and discriminators)
        # The naming is different from those used in the paper.
        # Code (vs. paper): G_A (G), G_B (F), D_A (D_Y), D_B (D_X)
        self.netC = networks.define_C(1, opt.ndf, opt.netC,
                                        opt.n_layers_D, opt.norm, opt.init_type, opt.init_gain, self.gpu_ids,
                                        opt.n_classes)

        if self.isTrain:
            # self.criterionCE = networks.CELoss().to(self.device)
            # self.criterionCE = networks.CELoss(dataset_mode=opt.dataset_mode, n_classes=opt.n_classes,
            #                                    lambda_ce_A=self.opt.lambda_ce_A, lambda_ce_B=self.opt.lambda_ce_B,
            #                                    device=self.device).to(self.device)
            self.criterionCE = networks.CELoss(dataset_mode=opt.dataset_mode, n_classes=opt.n_classes,
                                               lambda_ce_A=self.opt.lambda_ce_A, lambda_ce_B=self.opt.lambda_ce_B,
                                               device=self.device).to(self.device)
            # initialize optimizers; schedulers will be automatically created by function <BaseModel.setup>.
            self.optimizer = torch.optim.Adam(itertools.chain(self.netC.parameters()), lr=opt.lr, betas=(opt.beta1, 0.999))
            self.optimizers.append(self.optimizer)

        if self.opt.netC == 'inception':
            if self.isTrain:
                self.netC.train()
            else:
                self.netC.eval()

        self.features_blobs = []

    def set_input(self, input):
        """Unpack input data from the dataloader and perform necessary pre-processing steps.

        Parameters:
            input (dict): include the data itself and its metadata information.

        The option 'direction' can be used to swap domain A and domain B.
        """
        # for n classes

        AtoB = self.opt.direction == 'AtoB'
        if self.isTrain | self.opt.test_for_traindata:
            bs = len(input['train_A_paths'])
            self.train_A_label = torch.tensor(0).expand(bs).to(self.device)
            self.test_A_label = torch.tensor(0).expand(bs).to(self.device)
            self.train_B_label = torch.tensor(1).expand(bs).to(self.device)
            self.test_B_label = torch.tensor(1).expand(bs).to(self.device)

            self.real_A = input['train_A' if AtoB else 'train_B'].to(self.device)
            self.real_B = input['train_B' if AtoB else 'train_A'].to(self.device)
            if not self.only_early_late:
                self.real1_A = self.real_A[:,0:3,:,:]
                self.real1_B = self.real_B[:,0:3,:,:]
            else:
                self.real2_A = self.real_A[:,0,:,:].unsqueeze(1)
                self.real2_B = self.real_B[:,0,:,:].unsqueeze(1)
                self.real3_A = self.real_A[:,1,:,:].unsqueeze(1)
                self.real3_B = self.real_B[:,1,:,:].unsqueeze(1)

            # self.image_paths = input['A_paths' if AtoB else 'B_paths']
            # by Gloria for test
            self.image_paths_A = input['train_A_paths' if AtoB else 'train_B_paths']
            self.image_paths_B = input['train_B_paths' if AtoB else 'train_A_paths']

            self.test_A = input['test_A' if AtoB else 'test_B'].to(self.device)
            self.test_B = input['test_B' if AtoB else 'test_A'].to(self.device)
            if not self.only_early_late:
                self.test1_A = self.test_A[:,0:3,:,:]
                self.test1_B = self.test_B[:,0:3,:,:]
            else:
                self.test2_A = self.test_A[:,0,:,:].unsqueeze(1)
                self.test2_B = self.test_B[:,0,:,:].unsqueeze(1)
                self.test3_A = self.test_A[:,0,:,:].unsqueeze(1)
                self.test3_B = self.test_B[:,0,:,:].unsqueeze(1)
            # self.image_paths = input['A_paths' if AtoB else 'B_paths']
            # by Gloria for test
            self.test_image_paths_A = input['test_A_paths' if AtoB else 'test_B_paths']
            self.test_image_paths_B = input['test_B_paths' if AtoB else 'test_A_paths']
            # for n classes
            if self.opt.n_classes > 2:
                self.train_B_label = input['train_B_label'].to(self.device)
        else:
            bs = len(input['test_A_paths'])
            self.test_A_label = torch.tensor(0).expand(bs).to(self.device)
            self.test_B_label = torch.tensor(1).expand(bs).to(self.device)

            self.real_A = input['test_A' if AtoB else 'test_B'].to(self.device)
            self.real_B = input['test_B' if AtoB else 'test_A'].to(self.device)
            if not self.only_early_late:
                self.real1_A = self.real_A[:, 0:3, :, :]
                self.real1_B = self.real_B[:, 0:3, :, :]
            else:
                self.real2_A = self.real_A[:,0,:,:].unsqueeze(1)
                self.real2_B = self.real_B[:,0,:,:].unsqueeze(1)
                self.real3_A = self.real_A[:,1,:,:].unsqueeze(1)
                self.real3_B = self.real_B[:,1,:,:].unsqueeze(1)
            # self.image_paths = input['A_paths' if AtoB else 'B_paths']
            # by Gloria for test
            self.image_paths_A = input['test_A_paths' if AtoB else 'test_B_paths']
            self.image_paths_B = input['test_B_paths' if AtoB else 'test_A_paths']
            # for n classes
            if self.opt.n_classes > 2:
                self.test_B_label = input['test_B_label'].to(self.device)

    def forward(self):
        """Run forward pass; called by both functions <optimize_parameters> and <test>."""

    def backward(self):
        """Calculate the loss for generators G_A and G_B"""

        self.loss_C_A = 0
        self.loss_C_B = 0
        self.loss_C = 0
        if self.opt.netC == 'inception':
            self.logit, _ = self.netC(self.real)
        else:
            self.logit1 = self.netC(self.real2_A, self.real3_A)
            self.logit2 = self.netC(self.real2_B, self.real3_B)
            self.loss_C_A += 2 * self.criterionCE(self.logit1, target_label=self.train_A_label)
            self.loss_C_B += 2 * self.criterionCE(self.logit2, target_label=self.train_B_label)

        # self.loss_C = self.criterionCE(self.logit, self.train_label)
        self.loss_C = self.loss_C_A + self.loss_C_B
        self.loss_C.backward()

    def optimize_parameters(self, epoch):
        """Calculate losses, gradients, and update network weights; called in every training iteration"""
        # forward
        self.forward()      # compute fake images and reconstruction images.

        # G_A and G_B
        self.optimizer.zero_grad()  # set G_A and G_B's gradients to zero
        self.backward()  # calculate gradients for G_A and G_B
        self.optimizer.step()  # update G_A and G_B's weights

    def train_acc(self):

        size_A = np.shape(self.logit1)[0]
        size_B = np.shape(self.logit2)[0]
        total = size_A + size_B
        labels = torch.cat((self.train_A_label, self.train_B_label), 0).long()

        # for C_A : logit AB and logit BB
        outputs_A = torch.cat((self.logit1,self.logit2), 0)
        _, predicted = torch.max(outputs_A.data, 1)     # 每一行的最大值，即batch中每个样本的最大值
        correct = predicted.eq(labels.data).sum()
        self.train_C_acc = 100. * correct / total

        self.train_C_A_acc = self.train_C_acc
        self.train_C_B_acc = self.train_C_acc

    def test_acc(self):

        if self.isTrain:
            size_A = np.shape(self.test2_A)[0]
            size_B = np.shape(self.test2_B)[0]

            logit1 = self.netC(self.test2_A, self.test3_A)
            logit2 = self.netC(self.test2_B, self.test3_B)

            total = size_A + size_B
            labels = torch.cat((self.train_A_label, self.train_B_label), 0).long()
        else:
            size_A = np.shape(self.real2_A)[0]
            size_B = np.shape(self.real2_B)[0]

            logit1 = self.netC(self.real2_A, self.real3_A)
            logit2 = self.netC(self.real2_B, self.real3_B)

            total = size_A + size_B
            labels = torch.cat((self.test_A_label, self.test_B_label), 0).long()

        # for C_A : logit AB and logit BB
        outputs_A = torch.cat((logit1, logit2), 0)
        _, predicted_A = torch.max(outputs_A.data, 1)  # 每一行的最大值，即batch中每个样本的最大值
        correct_A = predicted_A.eq(labels.data).sum()
        self.test_C_acc = 100. * correct_A / total

        correct_B = correct_A
        correct = correct_A
        predicted_B = predicted_A
        predicted = predicted_A

        if self.opt.accs_or_logits == 'accs':
            return correct_A, correct_B, correct
        else:
            # return outputs1_A, outputs1_B, outputs1
            if self.opt.n_classes > 2:
                return predicted_A, predicted_B, predicted, labels.data
            else:
                return predicted_A, predicted_B, predicted


from functools import reduce
from os import write
from pickle import FALSE
import pronouncing
from nltk.tokenize import word_tokenize
import re
import string
import prosodic
prosodic.config['print_to_screen'] = 0
prosodic.config['en_TTS_ENGINE'] = 1

METER_LIMIT = 5
METER_LINE_LIMIT = 120 # The longer the line the longer it takes to analyze, so let's just skip them for speed

PHONEME_TO_TYPE = dict({(k,v[0]) for (k,v) in pronouncing.cmudict.phones()})

TYPE_TO_PHONEMES = {}
for k in set([i for i in PHONEME_TO_TYPE.values()]):
    TYPE_TO_PHONEMES[k] = [v for v in PHONEME_TO_TYPE if PHONEME_TO_TYPE[v]==k]

def alliterates(phoneme1, phoneme2):
    if(not(phoneme1 and phoneme2)):
        return False
    return phoneme1.split()[0] == phoneme2.split()[0]

def alliteration_and_assonance(tokens, phoneme_list, window_size):
    alliterations = []
    assonances = []
    window_size = min(len(tokens),window_size)-1
    for i in range(1,len(tokens)):
        for j in range(-min(window_size,i), 0):
            (po,pb) = (phoneme_list[i+j], phoneme_list[i])
            t = (tokens[i+j], tokens[i])
            if(any([alliterates(o,b) for o in po for b in pb])):
                alliterations.append(t)
            for o in po:
                for b in pb:
                    (vo, vb) = tuple(map(lambda ps: [p for p in ps.split() if p[:-1] in TYPE_TO_PHONEMES['vowel'] and int(p[-1]) >0],(o,b)))
                    if len(set(vo).intersection(set(vb))):
                        assonances.append(t)

    return (alliterations,assonances)

def estimate_syllables(word):
    approx = int(.6 + len(word)/3.2)
    _range = max(3, int(len(word)/3))
    return [ max(1, (i - int(_range/2)  + approx)) for i in range(_range)]

def is_haiku(tokens, phoneme_list):
    if(len(tokens)>17):
        return False

    all_syllables = []

    for (i,phs) in enumerate(phoneme_list):
        syllables = set([pronouncing.syllable_count(ph) for ph in phs])
        syllables = syllables if len(syllables) > 0 else estimate_syllables(tokens[i])
        syllables = list(set(syllables))
        all_syllables.append(syllables)

    possible_total_syllables = reduce(lambda x,y: [ i+n for i in x for n in y], all_syllables,[0])

    return 17 in set(possible_total_syllables)

def get_stresses(line):
    text = prosodic.Text(line)
    text.parse(meter='default_english')
    parses = text.bestParses()
    stresses = []
    for parse in parses:
        if parse is None:
            continue
        meter = ""
        for pos in parse.positions:
            val = pos.meterVal
            if val == "w":
                meter += "0" # I just prefer this representation
            elif val == "s":
                meter += "1"
        stresses.append(meter)
    return stresses

def stresses_to_meter(stresses):
    meter_table = {
        "01": "Iambic",
        "10": "Trochaic",
        "11": "Spondaic",
        "001": "Anapestic",
        "100": "Dactylic",
        "010": "Amphibrachic",
        "00": "Pyrrhic"
    }
    '''
    This is an ambiguous state machine, let's use the following flags:
    0: No meter found.
    n: End of state, found n copies.
    -n: End of state, go back n, also move pointer back n
    In all cases, simply grab the correct one from the table
    '''
    meter_tree = {
        "0": {
            "0": {
                "0": { # 00, third 0 is second set of 00. This could be done with -1 but let us continue for speed
                    "0": 2,
                    "1": 0 # Found 00 01 which is not a valid consistent meter
                },
                "1": 1 # Must be 001
            },
            "1": {
                "0": { # Ambiguous, need next token
                    "0": -1, # You could expand this state but that's ugly (010 010)
                    "1": 2
                },
                "1": 0
            }
        },
        "1": {
            "0": {
                "0": 1,
                "1": {
                    "0": 2,
                    "1": 0
                }
            },
            "1": {
                "0": 0,
                "1": {
                    "0": 0,
                    "1": 2
                }
            }
        }
    }
    count_table = {
        1: "monometer",
        2: "dimeter",
        3: "trimeter",
        4: "tetrameter",
        5: "pentameter",
        6: "hexameter",
        7: "heptameter",
        8: "octameter"
    }
    pointer = 0
    stack = ""
    counter = 0
    sub_tree = meter_tree
    while pointer < len(stresses) and counter == 0:
        val = stresses[pointer]
        if val == "2":
            val = "1"
        stack += val
        sub_tree = sub_tree[val]
        if not isinstance(sub_tree, dict): # We have found a leaf
            if sub_tree == 0:
                return None
            elif sub_tree < 0:
                pointer += sub_tree
                add = abs(sub_tree)
            else:
                add = sub_tree
                pointer += 1
            counter += add
            stack = stack[:(add//2)+1]
        else:
            pointer += 1
    if counter == 0 or len(stresses) % len(stack) != 0:
        return None
    else: # We have found a pattern, now to see if it repeats
        patt_pointer = 0
        while pointer < len(stresses):
            val = stresses[pointer]
            req = stack[patt_pointer]
            if val != req:
                return None
            pointer += 1
            patt_pointer += 1
            if patt_pointer >= len(stack):
                counter += 1
                patt_pointer = 0
    style = meter_table[stack]
    foot = counter
    if foot in count_table:
        foot = count_table[foot]
    return style + " " + str(foot)

def get_meter(poem):
    meters = []
    lines = poem.splitlines()
    if len(lines) < 2:
        return None
    for line in lines[:METER_LIMIT]:
        if len(line) <= METER_LINE_LIMIT:
            stresses = get_stresses(line)
            line_meters = []
            for stress in stresses:
                meter = stresses_to_meter(stress)
                line_meters.append(meter)
            meters.append(line_meters)
    scores = {}
    for meter in meters:
        for line_meter in meter:
            if line_meter in scores:
                scores[line_meter] += 1
            else:
                scores[line_meter] = 1
    scores = sorted(scores.items(), key=lambda x:x[1], reverse=True)
    return scores

def get_styles(poem, window_size=4):
    poem = re.sub(r"(\w+)-(\w+)",r"\1 \2",poem)
    tokens = [token for token in word_tokenize(poem) if not re.match(r"[^\w]+", token)]
    phonemes_for_tokens = [pronouncing.phones_for_word(t) for t in tokens]

    (alliterations, assonances) = alliteration_and_assonance(tokens, phonemes_for_tokens, window_size)

    meter = get_meter(poem)
    main_meter = None
    if meter:
        main_meter = meter[0][0]
        if main_meter is None and len(meter) > 1: # If it can't analyze most of the lines properly
            main_meter = meter[1][0]

    return {
        "form":{
            "is_haiku": is_haiku(tokens, phonemes_for_tokens),
        },
        "rhyme": {
            "alliteration": len(alliterations)/max(1,len(tokens)),
            "assonance": len(assonances)/max(1,len(tokens))
        },
        "meter": {
            "main": main_meter,
            "all": meter
        }
    }


def edit(self, text, media=None, utc=None, now=None):
    '''
      Edit an existing, individual status update.
    '''

    url = PATHS['EDIT'] % self.id

    post_data = "text=%s&" % text

    if now:
      post_data += "now=%s&" % now

    if utc:
      post_data += "utc=%s&" % utc

    if media:
      media_format = "media[%s]=%s&"

      for media_type, media_item in media.iteritems():
        post_data += media_format % (media_type, media_item)

    response = self.api.post(url=url, data=post_data)

    return Update(api=self.api, raw_response=response['update'])


#!/usr/bin/env python
from collections import Counter
import dis
import sys

import analyse

if __name__ == "__main__":
    if sys.argv[1:] == ["--help"] or len(sys.argv) == 1:
        print(
f"""\
Usage: {sys.argv[0]} [--help] N

Each line from STDIN is a filename to scan for bytecode.

Scan for all bytecode patterns of length N and produce a report on the most
common sequences.\
""")
        exit(0)
    assert len(sys.argv) == 2, "too many arguments"
    N = int(sys.argv[1])
    counter = Counter()
    for bytecode in analyse.find_all():
        for i in range(len(bytecode) - N):
            counter[bytecode[i:i+N]] += 1
    for seq, count in counter.most_common():
        print(count, *(dis.opname[op] for op in seq))


# Uses python3
import re
import sys

def get_optimal_value(capacity, weights, values):

    value = 0
    #write your code here
    lt = list(range(len(values)))
    # Calculate the ratio value weigth
    ratio = [val/wt for val,wt in zip(values,weights)]
    # print(ratio)
    # store the index of each ratio in a list
    lt.sort(key=lambda i : ratio[i],reverse=True)
    #print(lt)
    for i in lt:
        if weights[i]<=capacity:
            value += values[i]
            # print(value)
            capacity -= weights[i]
            # print(capacity)
        else:
            value += values[i]*capacity/weights[i]
            break
    # print(ratio)
    # print(lt)

    # while capacity>0:
    #     pass
    return value

if __name__ == "__main__":
    data = list(map(int, sys.stdin.read().split()))
    # print(data)
    n, capacity = data[0:2]
    # print(n,capacity)
    values = data[2:(2 * n + 2):2]
    # print(values)
    weights = data[3:(2 * n + 2):2]
    # print(weights)
    opt_value = get_optimal_value(capacity, weights, values)
    print("{:.10f}".format(opt_value))


import random
import logging
import numpy as np

from sklearn.model_selection import train_test_split

from npal.data.base_data_loading import BaseDataLoader

class ImbalancedDataLoader(BaseDataLoader):
    def __init__(self, args):
        super().__init__(args)
        self.args = args
        self.data_type = args.data_type

        self.stratify = args.stratify
        self.normalise_features = args.normalise_features
        self.data_split_seed = args.data_split_seed

        self.total_num_points = args.total_num_points
        self.num_test_points = args.num_test_points
        self.num_train_points = args.num_train_points
        self.num_val_points = args.num_val_points
        self.num_reward_points = args.num_reward_points
        self.num_annot_points = args.num_annot_points
        self.num_pool_points = args.num_pool_points

        self.test_fraction = args.test_fraction
        self.val_fraction = args.val_fraction
        self.reward_fraction = args.reward_fraction
        self.pool_fraction = args.pool_fraction

        self.logger = logging.getLogger("ImbalancedDataLoader")

        if args.total_num_points is not None:
            assert (
                args.num_train_points is None
            ), "Cannot specify `num_train_points` and `total_num_points` simultaneously."
            assert args.num_val_points is None, "Cannot specify `num_val_points` and `total_num_points` simultaneously."
            assert (
                args.num_test_points is None
            ), "Cannot specify `num_test_points` and `total_num_points` simultaneously."

        self.imbalancer = Imbalancer(args)

    def __call__(self):
        train_X, train_y, test_X, test_y = self.load_data()  # Implemented by BaseDataLoader
        train_X, train_y, test_X, test_y = self.preprocess_data(train_X, train_y, test_X, test_y)
        train_X, train_y, val_X, val_y, reward_X, reward_y = self.split_train_val_reward(train_X, train_y)
        annot_X, annot_y, pool_X, pool_y = self.split_annot_pool(train_X, train_y)

        num_val_points = len(val_y) if val_y is not None else None
        num_reward_points = len(reward_y) if reward_y is not None else None
        self.logger.info(f"Data shape: {(1, *train_X.shape[1:])}")
        self.logger.info(f"{len(annot_y)} annotated, {len(pool_y)} pool")
        self.logger.info(
            f"{len(train_y)} train, {num_val_points} validation, " f"{len(test_y)} test, {num_reward_points} reward."
        )
        # Logging num datapoints per class
        self.logger.info("Train per class: {}".format(self.get_num_per_class(train_y)))
        self.logger.info("Annot per class: {}".format(self.get_num_per_class(annot_y)))
        self.logger.info("Pool per class: {}".format(self.get_num_per_class(pool_y)))
        return annot_X, annot_y, pool_X, pool_y, train_X, train_y, val_X, val_y, reward_X, reward_y, test_X, test_y

    def preprocess_data(self, train_X, train_y, test_X=None, test_y=None):
        if test_X is None:  # No test data provided yet
            assert test_y is None
            train_X, train_y = self.imbalance_data(train_X, train_y)
            train_X, _, _ = self.normalise_data(train_X)
            train_X, train_y, test_X, test_y = self.split_train_test(train_X, train_y)
        else:  # Train and test data provided
            assert set(train_y) == set(test_y), "Train or test data is missing classes!"
            # First imbalance data, then compute normalisation, to simulate actually only having access to imbalanced
            #  data.
            train_X, train_y = self.imbalance_data(train_X, train_y)
            test_X, test_y = self.imbalance_data(test_X, test_y)
            train_X, mean, std = self.normalise_data(train_X)
            test_X, _, _ = self.normalise_data(test_X, mean, std)
            # Further reduce dataset if we specified some absolute number of points to keep
            train_X, train_y, test_X, test_y = self.split_train_test(train_X, train_y, test_X, test_y)
        return train_X, train_y, test_X, test_y

    def imbalance_data(self, X, y):
        # Imbalance data here, to preserve class ratios between train and test.
        X, y = self.imbalancer(X, y)
        return X, y

    def split_train_test(self, X, y, test_X=None, test_y=None):
        # If test data is given then we don't have to actually split, but we do need to check that we keep the
        #  appropriate number of points if `total_num_points` or `num_test_points` is set.
        if test_X is not None:
            assert test_y is not None
            if self.total_num_points is not None:
                if self.total_num_points > len(y) + len(test_y):
                    raise RuntimeError(
                        f"Requested {self.total_num_points} data points, but data set only contains "
                        f"{len(y) + len(test_y)}; possibly this happens due to imbalancing."
                    )
                num_test_points = int(self.total_num_points * self.test_fraction)
                assert num_test_points <= len(
                    test_y
                ), "Too many test points requested. Reduce `test_fraction` or `total_num_points`."
                num_train_points = self.total_num_points - num_test_points
                assert num_train_points > 0, "Cannot have 0 train points."
                assert num_train_points <= len(
                    y
                ), "Too many train points requested. Increase `test_fraction` or reduce `total_num_points`."

                # Split off num_train_points from provided train data
                labels = y if self.stratify else None
                train_X, _, train_y, _ = train_test_split(
                    X,
                    y,
                    train_size=num_train_points,
                    test_size=None,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
                # Split off num_test_points from provided test data
                labels = test_y if self.stratify else None
                _, test_X, _, test_y = train_test_split(
                    test_X,
                    test_y,
                    train_size=None,
                    test_size=num_test_points,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
            elif self.num_test_points is not None:
                # `total_num_points` not set, so just split off `num_test_points if given`. Train is split off later.
                # Split off num_test_points from provided test data
                labels = test_y if self.stratify else None
                _, test_X, _, test_y = train_test_split(
                    test_X,
                    test_y,
                    train_size=None,
                    test_size=self.num_test_points,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
                train_X, train_y = X, y
            else:
                # No total number of points set and no number of test points set, so just continue with all data.
                train_X, train_y = X, y
        else:
            # Keep args.total_num_points only if set
            if self.total_num_points is not None:
                if self.total_num_points > len(y):
                    raise RuntimeError(
                        f"Requested {self.total_num_points} data points, but data set only contains "
                        f"{len(y)} after imbalancing."
                    )
                labels = y if self.stratify else None
                X, _, y, _ = train_test_split(
                    X,
                    y,
                    train_size=self.total_num_points,
                    test_size=None,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )

                # Now split train, test using fractions
                labels = y if self.stratify else None
                train_X, test_X, train_y, test_y = train_test_split(
                    X,
                    y,
                    train_size=None,
                    test_size=self.test_fraction,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
            else:  # `total_num_points` not set, check if `num_test_points` is set; train is split off later.
                labels = y if self.stratify else None
                if self.num_test_points is not None:
                    train_X, test_X, train_y, test_y = train_test_split(
                        X,
                        y,
                        train_size=None,
                        test_size=self.num_test_points,
                        random_state=self.data_split_seed,
                        stratify=labels,
                    )
                else:  # `num_test_points` not set, so split using `test_fraction`
                    train_X, test_X, train_y, test_y = train_test_split(
                        X,
                        y,
                        train_size=None,
                        test_size=self.test_fraction,
                        random_state=self.data_split_seed,
                        stratify=labels,
                    )

        return train_X, train_y, test_X, test_y

    def split_train_val_reward(self, train_X, train_y):
        val_X, val_y = None, None
        labels = train_y if self.stratify else None
        if self.num_val_points is not None:
            if self.num_val_points > 0:  # Else keep train as is and val as None.
                # Split rest into train, val
                train_X, val_X, train_y, val_y = train_test_split(
                    train_X,
                    train_y,
                    train_size=None,
                    test_size=self.num_val_points,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
        else:
            if self.val_fraction > 0:
                # Split rest into train, val
                train_X, val_X, train_y, val_y = train_test_split(
                    train_X,
                    train_y,
                    train_size=None,
                    test_size=self.val_fraction,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )

        # Split rest into train, reward
        reward_X, reward_y = None, None
        labels = train_y if self.stratify else None
        if self.num_reward_points is not None:
            if self.num_reward_points > 0:  # Else keep train as is and reward as None.
                train_X, reward_X, train_y, reward_y = train_test_split(
                    train_X,
                    train_y,
                    train_size=None,
                    test_size=self.num_reward_points,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
        else:
            reward_fraction = self.reward_fraction / (1 - self.val_fraction)
            if reward_fraction > 0:
                train_X, reward_X, train_y, reward_y = train_test_split(
                    train_X,
                    train_y,
                    train_size=None,
                    test_size=reward_fraction,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )

        # Finally, split of num_train_points if set
        if self.num_train_points is not None:
            assert self.num_train_points > 0, "Cannot use 0 training points."
            labels = train_y if self.stratify else None
            train_X, _, train_y, _ = train_test_split(
                train_X,
                train_y,
                train_size=self.num_train_points,
                test_size=None,
                random_state=self.data_split_seed,
                stratify=labels,
            )

        return train_X, train_y, val_X, val_y, reward_X, reward_y

    def split_annot_pool(self, train_X, train_y):
        # Labeled-unlabeled (annotated-pool) split
        labels = train_y if self.stratify else None
        if self.num_annot_points:  # Set num_annot_points, rest is pool.
            annot_X, pool_X, annot_y, pool_y = train_test_split(
                train_X,
                train_y,
                train_size=self.num_annot_points,
                test_size=None,
                random_state=self.data_split_seed,
                stratify=labels,
            )
            if self.num_pool_points:  # Additionally throw away all points > num_pool_points from pool.
                labels = pool_y if self.stratify else None
                pool_X, _, pool_y, _ = train_test_split(
                    pool_X,
                    pool_y,
                    train_size=self.num_pool_points,
                    test_size=None,
                    random_state=self.data_split_seed,
                    stratify=labels,
                )
        elif self.num_pool_points:  # Set num_pool_points, rest is annot
            annot_X, pool_X, annot_y, pool_y = train_test_split(
                train_X,
                train_y,
                train_size=None,
                test_size=self.num_pool_points,
                random_state=self.data_split_seed,
                stratify=labels,
            )
        else:  # Use pool fraction
            annot_X, pool_X, annot_y, pool_y = train_test_split(
                train_X,
                train_y,
                train_size=None,
                test_size=self.pool_fraction,
                random_state=self.data_split_seed,
                stratify=labels,
            )
        return annot_X, annot_y, pool_X, pool_y

    @staticmethod
    def get_num_per_class(labels):
        return {cl: (labels == cl).sum() for cl in set(labels)}

class Imbalancer:
    def __init__(self, args):
        self.args = args
        self.classes = None
        self.remaining_classes = None
        self.imbalance_factors = np.array(args.imbalance_factors)
        self.ignore_existing_imbalance = args.ignore_existing_imbalance

    def __call__(self, X, y):
        assert len(y.shape) == 1, f"Incorrect label shape: {y.shape}. E.g., labels should not be one-hot here."

        if self.classes and self.classes != set(y):
            raise RuntimeError(
                "Imbalancer called multiple times, but with a different set of target classes! This will lead to "
                "inconsistencies in the number of classes in `imbalance_factors`."
            )
        # NOTE: If we want to use a different set of classes for different data partitions, then we still require
        #  that the below `self.classes` contains all classes in the entire dataset (else score calculations or
        #  training might fail).
        self.classes = set(y)

        if len(self.imbalance_factors) != len(self.classes):
            if len(self.imbalance_factors) == 1 and self.imbalance_factors[0] == 1.0:
                self.imbalance_factors = np.ones(len(self.classes))  # balanced
            else:
                raise RuntimeError(
                    f"`imbalance_factors` should be of length {len(self.classes)}, not {len(self.imbalance_factors)}."
                )

        imbalance_factor_max = np.max(self.imbalance_factors)
        # Imbalance the balanced training data according to imba_fracs.
        # Create dict mapping classes to inds
        indices_per_class = []
        # NOTE: This assumes that the lowest class label corresponds to the first entry of self.imbalance_factors.
        # This is consistent with the way scikit-learn indexes class labels.
        for c in sorted(self.classes):
            indices_per_class.append(np.where(y == c)[0].tolist())

        if self.ignore_existing_imbalance:
            # In case we are ignoring potential existing imbalance we just apply the
            # imbalance factor on top of whatever imbalance is already in the data.
            num_to_keep_per_class = [
                int(len(inds) * self.imbalance_factors[i] / imbalance_factor_max)
                for i, inds in enumerate(indices_per_class)
            ]
        else:
            # Not ignoring existing imbalance: make sure that eventual imbalance matches imbalance_factors, despite
            # existing data imbalance. This may reduce the number of data points available.
            max_num_inds_per_class = np.max([len(inds) for inds in indices_per_class])
            # Ideally, we would use this many points
            num_points_to_try = max_num_inds_per_class * self.imbalance_factors / imbalance_factor_max
            # However, if there is existing imbalance we might not be able to select this number for each class.
            # Determine the fraction we need to reduce this by to make sure every class can be sampled appropriately.
            # zero_fixed_num_points_to_try will be 0 where imbalance_factors is 0.
            nonzero_inds = num_points_to_try != 0
            zero_fixed_num_points_to_try = np.ones_like(num_points_to_try)
            zero_fixed_num_points_to_try[nonzero_inds] = num_points_to_try[nonzero_inds]
            subsample_fractions = np.array([len(inds) for inds in indices_per_class]) / zero_fixed_num_points_to_try
            # Subsample by this fraction
            num_to_keep_per_class = (np.min(subsample_fractions) * num_points_to_try).astype(int).tolist()

        # Get indices of points to keep and remove
        inds = []
        # NOTE: This is the same class order as used above.
        for c in sorted(self.classes):
            # Shuffle not in place
            # NOTE: This changes data order using the python random state.
            # state = random.getstate()
            # random.seed(self.args.data_split_seed)
            class_indices = random.sample(indices_per_class[c], len(indices_per_class[c]))
            # random.setstate(state)

            # Number of indices to select
            class_imba = class_indices[: num_to_keep_per_class[c]]
            inds.extend(class_imba)

        inds = np.array(inds)
        imbalanced_X = X[inds, ...]
        imbalanced_y = y[inds]
        if self.remaining_classes is not None:
            if self.remaining_classes != set(imbalanced_y):
                raise RuntimeError(
                    "`remaining_classes` changed from previous Imbalancer call. Probably called once on train and once "
                    "on test data, and test does not contain the same classes as train?"
                )
        else:
            self.remaining_classes = set(imbalanced_y)
        return imbalanced_X, imbalanced_y


from openerp.osv import osv, fields
from openerp import SUPERUSER_ID

class crm_contact_us(osv.TransientModel):
    """ Create new leads through the "contact us" form """
    _name = 'portal_crm.crm_contact_us'
    _description = 'Contact form for the portal'
    _inherit = 'crm.lead'
    _columns = {
        'company_ids' : fields.many2many('res.company', string='Companies', readonly=True),
    }

    def _get_companies(self, cr, uid, context=None):
        """
        Fetch companies in order to display them in the wizard view

        @return a list of ids of the companies
        """
        r = self.pool.get('res.company').search(cr, uid, [], context=context)
        return r

    def _get_user_name(self, cr, uid, context=None):
        """
        If the user is logged in (i.e. not anonymous), get the user's name to
        pre-fill the partner_name field.
        Same goes for the other _get_user_attr methods.

        @return current user's name if the user isn't "anonymous", None otherwise
        """
        user = self.pool.get('res.users').read(cr, uid, uid, ['login'], context)

        if (user['login'] != 'anonymous'):
            return self.pool.get('res.users').name_get(cr, uid, uid, context)[0][1]
        else:
            return None

    def _get_user_email(self, cr, uid, context=None):
        user = self.pool.get('res.users').read(cr, uid, uid, ['login', 'email'], context)

        if (user['login'] != 'anonymous' and user['email']):
            return user['email']
        else:
            return None

    def _get_user_phone(self, cr, uid, context=None):
        user = self.pool.get('res.users').read(cr, uid, uid, ['login', 'phone'], context)

        if (user['login'] != 'anonymous' and user['phone']):
            return user['phone']
        else:
            return None

    _defaults = {
        'partner_name': _get_user_name,
        'email_from': _get_user_email,
        'phone': _get_user_phone,
        'company_ids': _get_companies,
    }

    def create(self, cr, uid, values, context=None):
        """
        Since they are potentially sensitive, we don't want any user to be able
        to read datas generated through this module.  Therefore we'll write
        these information directly in the crm.lead table and leave blank
        entries in the contact table.
        This is why the create() method is overwritten.
        """
        crm_lead = self.pool.get('crm.lead')

        """
        Because of the complex inheritance of the crm.lead model and the other
        models implied (like mail.thread, among others, that performs a read
        when its create() method is called (in method message_get_subscribers()),
        it is quite complicated to set proper rights for this object.
        Therefore, user SUPERUSER_ID will perform the creation.
        """
        values['contact_name'] = values['partner_name']
        crm_lead.create(cr, SUPERUSER_ID, dict(values, user_id=False), context)

        """
        Create an empty record in the contact table.
        Since the 'name' field is mandatory, give an empty string to avoid an integrity error.
        Pass mail_create_nosubscribe key in context because otherwise the inheritance
        leads to a message_subscribe_user, that triggers access right issues.
        """
        empty_values = dict((k, False) if k != 'name' else (k, '') for k, v in values.iteritems())
        return super(crm_contact_us, self).create(cr, SUPERUSER_ID, empty_values, {'mail_create_nosubscribe': True})

    def submit(self, cr, uid, ids, context=None):
        """ When the form is submitted, redirect the user to a "Thanks" message """
        return {
            'type': 'ir.actions.act_window',
            'view_mode': 'form',
            'view_type': 'form',
            'res_model': self._name,
            'res_id': ids[0],
            'view_id': self.pool.get('ir.model.data').get_object_reference(cr, uid, 'portal_crm', 'wizard_contact_form_view_thanks')[1],
            'target': 'new',
        }

    def _needaction_domain_get(self, cr, uid, context=None):
        """
        This model doesn't need the needactions mechanism inherited from
        crm_lead, so simply override the method to return an empty domain
        and, therefore, 0 needactions.
        """
        return False


from numpy import double
import pandas as pd
path = "C:\\Users\\kausi\\OneDrive\\Desktop\\project\\yolov4-custom-functions\\data\\video\\video.txt"
res_path = path[:path.rfind("\\")]+"\\"+path.split("\\")[-1].split(".")[0]+".csv"
file = open(path, 'r')
Lines = file.readlines()

frames = []
bicyles = []
car = []
person = []
fps = []
# Strips the newline character
for line in Lines:

    if(line.find("FRAME") != -1):
        if(len(fps)!=len(frames)):
            fps.append("0")
        if(len(bicyles)!=len(frames)):
            bicyles.append("0")
        if(len(car)!=len(frames)):
            car.append("0")
        if(len(person)!=len(frames)):
            person.append("0")
        frames.append(int(line.split(":")[1].strip()))
    elif(line.find("persons") != -1):
        person.append(int(line.split(":")[1].strip()))
    elif(line.find("bicycles") != -1):
        bicyles.append(int(line.split(":")[1].strip()))
    elif(line.find("cars") != -1):
        car.append(int(line.split(":")[1].strip()))
    elif(line.find("FPS") != -1):
        fps.append(double(line.split(":")[1].strip()))

df = pd.DataFrame({"Frame Number": frames, "Person": person, "Bicycle": bicyles,"Car": car,"FPS": fps})
df.to_csv(res_path, index = False)


"""
This script contains all necessary functions for the training pipeline.
"""

import pandas as pd
from tqdm import tqdm
import numpy as np
import rasterio
import pickle
import matplotlib.pyplot as plt

# for feature importance:
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import Ridge
from sklearn.linear_model import Lasso
from sklearn.linear_model import ElasticNet
from sklearn.ensemble import GradientBoostingRegressor

def import_data(date_from: str, date_to: str, df_path: str, predict_only: str):
    """
    Imports data and merges into one dataframe.

    Args:
        date_from (format: 'yyyy-mm-dd'): Period starting date (included).

        date_to (format: 'yyyy-mm-dd'): Period end date (included).

        df_path: Path to folder with daily data files.

    Returns:
        pandas.DataFrame: Dataframe with all merged data.
    """

    date_range = pd.date_range(date_from, date_to)  # both ends included
    date_range = [str(day.date()) for day in date_range]
    df = pd.DataFrame()

    for melt_date in tqdm(date_range):
        # print(melt_date)
        try:  # bc some days are empty
            file = pd.read_parquet(df_path + "melt_" + melt_date + "_extended.parquet.gzip")
            file = file.drop(columns=["date"], axis=1)
            if not predict_only:
                # remove masked data, data with no melt and data with little melt (less than 10% of the time)
                file = remove_data(
                    file,
                    removeMaskedClouds=True,
                    removeNoMelt=True,
                    removeLittleMelt=True,
                )
            df = pd.concat([df, file], axis=0)
        except:
            continue

    # df = df.to_pandas()

    return df

def remove_data(df, removeMaskedClouds=True, removeNoMelt=True, removeLittleMelt=True):
    """
    Removes missing/masked mw and opt data from dataframe.
    Used for training and testing, not predicting.

    Args:
        df (pandas.DataFrame): Full train/ test dataframe.

        removeMaskedClouds (bool): True for train and test data, removes masked data from opt data.
                                   False for predicting data, keeps masked opt data.

        removeNoMelt (bool): True for train and test data, removes non-melt areas from mw data.
                             False for predicting data, keeps non-melt areas.

        removeLittleMelt (bool): True for train and test data, removes areas with little melt from mw data.
                                 False for predicting data, keeps areas with little melt.

    Returns:
        pandas.DataFrame: The same dataframe with removed water (and masked data).
    """

    if removeMaskedClouds:
        df = df[df["opt_value"] != -1]

    if removeNoMelt and removeLittleMelt:
        melt_noMelt = pd.read_parquet(r"../AWS_Data/Data/split_indexes/noMelt_indexes.parquet")
        # melt_noMelt = pd.read_parquet(r"/mnt/volume/AWS_Data/Data/split_indexes/noMelt_indexes.parquet")
        melt_littleMelt = pd.read_parquet(r"../AWS_Data/Data/split_indexes/littleMelt_indexes.parquet")
        # melt_littleMelt = pd.read_parquet(r"/mnt/volume/AWS_Data/Data/split_indexes/littleMelt_indexes.parquet")

        df = df.merge(melt_noMelt, how="left", on=["y", "x"])
        df = df.merge(melt_littleMelt, how="left", on=["y", "x"])

        df = df[(df["melt_x"] == 1) & (df["melt_y"] == 1)]
        df.drop(["melt_x", "melt_y"], axis=1, inplace=True)

    elif removeNoMelt:
        # melt = pd.read_parquet(r"/mnt/volume/AWS_Data/Data/split_indexes/noMelt_indexes.parquet")
        melt = pd.read_parquet(r"../AWS_Data/split_indexes/noMelt_indexes.parquet")
        df = df.merge(melt, how="left", on=["y", "x"])
        df = df[df["melt"] == 1]
        df.pop("melt")

    elif removeLittleMelt:
        # melt = pd.read_parquet(r"/mnt/volume/AWS_Data/Data/split_indexes/littleMelt_indexes.parquet")
        melt = pd.read_parquet(r"/../AWS_Data/Data/split_indexes/littleMelt_indexes.parquet")
        df = df.merge(melt, how="left", on=["y", "x"])
        df = df[df["melt"] == 1]
        df.pop("melt")

    return df

def data_normalization(df):
    """
    Normalizes data with min-max (linear) or Z-score normalization depending on feature.

    Args:
        df (pandas.DataFrame): Full train/ test dataframe.

    Returns:
        pandas.DataFrame: The same dataframe with normalized features.
    """
    features = df.columns

    minmax_features = [
        # "col",
        # "row",
        "x",
        "y",
        "mean_3",
        "mean_9",
        "sum_5",
        "mw_value_7_day_average",
        "hours_of_daylight",
        "slope_data",
        "aspect_data",
        "elevation_data",
        "distance_to_margin",
    ]
    log_feature = ["opt_value"]

    for feature in features:
        if feature in minmax_features:
            # if feature == "col":
            #     min, max = 0, 1461
            # elif feature == "row":
            #     min, max = 0, 2662
            if feature == "x":
                min, max = -636500.0, 824500.0
            elif feature == "y":
                min, max = -3324500.0, -662500.0
            elif feature == "mean_3":
                min, max = 0, 1
            elif feature == "mean_9":
                min, max = 0, 1
            elif feature == "sum_5":
                min, max = 0, 25
            elif feature == "mw_value_yesterday":
                min, max = 0, 1
            elif feature == "mw_value_7_day_average":
                min, max = 0, 1
            elif feature == "hours_of_daylight":
                min, max = 0, 24
            elif feature == "slope_data":
                min, max = 0, 90
            elif feature == "aspect_data":
                min, max = -1, 1
            elif feature == "elevation_data":
                min, max = 0, 3694
            else:
                min, max = 1, 500

            df[feature] = (df[feature] - min) / (max - min)

        elif feature in log_feature:
            # add a constant to avoid log(0)
            df[feature] = np.log(1 + df[feature])
        else:
            print(f"Not applicable for feature'{feature}'.")

    return df

def load_object(filename):
    """
    This function loads an object from a pickle file.

    Args:
        filename (str): Name of the file to be loaded, with extension, without path unless a subfolder is desired.

    Returns:
            obj (object): Loaded object.
    """
    filename = r"../Models_v3/" + filename + ".pkl"
    with open(filename, "rb") as inp:
        obj = pickle.load(inp)
    return obj

#############################################
# Model comparisons:
#############################################

def model_comparison_table(model_list):
    """
    This function creates a table with the results of the models in the model_list.

    Args:
        model_list (list): List of models to be compared.

    Returns:
        table (pd.DataFrame): Table with the results of the models in the model_list.
    """
    table = pd.concat([i.get_results() for i in model_list])
    set_index = table.pop("Set")
    multiindex = [[model.name for model in model_list for _ in range(2)], set_index]
    table.index = multiindex
    table.index.names = ["Model", "Set"]
    return table

def model_comparison_plot(model_list, metric="RMSE"):
    """
    Creates a bar plot comparing the train and test metric values for a list of models.

    Args:
        model_list (list): A list of Model objects.

        metric (str): The metric to plot. 'RMSE' or 'R2'.
    """
    table = model_comparison_table(model_list).reset_index()
    model_names = table["Model"].unique()

    # Set the figure size and create a bar plot
    fig, ax = plt.subplots(figsize=(10, 6))
    width = 0.35
    train_color = "steelblue"  # Choose a color for the train set bars
    test_color = "darkorange"  # Choose a color for the test set bars
    for i, model in enumerate(model_names):
        # Get the train and test metric values for the current model
        train_val = table[(table["Model"] == model) & (table["Set"] == "Train")][metric].values[0]
        test_val = table[(table["Model"] == model) & (table["Set"] == "Test")][metric].values[0]
        # Get the train and test metric standard deviation values for the current model
        train_val_std = table[(table["Model"] == model) & (table["Set"] == "Train")][metric + "_std"].values[0]
        test_val_std = table[(table["Model"] == model) & (table["Set"] == "Test")][metric + "_std"].values[0]
        # Create the bar plot
        ax.bar(
            i - width / 2,
            train_val,
            width,
            yerr=train_val_std,
            label=None,
            capsize=10,
            color=train_color,
        )
        ax.bar(
            i + width / 2,
            test_val,
            width,
            yerr=test_val_std,
            label=None,
            capsize=10,
            color=test_color,
        )

    # Add the legend
    ax.legend(["Train", "Test"], loc="upper right")

    # Set the axis labels
    ax.set_xlabel("Model")
    ax.set_ylabel(metric)
    ax.set_xticks(range(len(model_names)))
    ax.set_xticklabels(model_names)

    # Show the plot
    plt.show()

#############################################
# Model predictions:
#############################################

def mean_predict(model, data):
    """
    This function calculates mean predictions, std of predictions and error of predictions.

    Args:
        model (object): model object

        data (dataframe): dataframe with data (should include all columns, both trained on and not).

    Returns:
        df_results (dataframe): dataframe with results (mean predictions, std and error of predictions).
    """
    columns = model.columns
    x_test = data[columns]
    y_test = data["opt_value"]
    all_predictions = []
    for i in range(len(model.cv_model_list)):
        predictions_one_model = model.cv_model_list[i].predict(x_test)
        all_predictions.append(predictions_one_model)

    # transform back from log to normal scale
    all_predictions = np.exp(all_predictions) - 1
    y_test_backtransformed = np.exp(y_test) - 1

    mean_prediction = np.mean(all_predictions, axis=0)
    std_prediction = np.std(all_predictions, axis=0)
    error_prediction = np.abs(mean_prediction - y_test_backtransformed)
    residual_prediction = y_test_backtransformed - mean_prediction
    df_results = pd.DataFrame(
        {
            "row": data["row"],
            "col": data["col"],
            "mean_prediction": mean_prediction,
            "std_prediction": std_prediction,
            "error_prediction": error_prediction,
            "residual_prediction": residual_prediction,
            "opt_value": y_test,
            "opt_value_backtransformed": y_test_backtransformed,
        }
    )

    return df_results

#############################################
# Save to tif:
#############################################

def save_prediction_tif(df_predictions, metric, path_out):
    """
    Function to write predictions to .tif.

    Args:
        df_predictions (dataframe): dataframe with predictions

        metric_to_save (str): metric to save (mean, std or error)

        path_out (str): path to save .tif file, path should include file name and extension
    """
    # original matrix shape:
    nan_matrix = np.full((2663, 1462), np.nan)

    for _, row in tqdm(df_predictions.iterrows(), total=len(df_predictions)):
        row_index = int(row["row"])
        col_index = int(row["col"])
        pred_val = row[metric + "_prediction"]
        nan_matrix[row_index][col_index] = pred_val

    convert_to_tif(nan_matrix, path_out)
    return

def convert_to_tif(data, path_out):
    """
    Function to convert data to tif file.

    Args:
        data (numpy array or xarray): data to convert to tif

        path_out (str): path to save .tif file, path should include file name and extension

    Returns:
        .tif file
    """
    path_file_metadata = r"../Data/microwave-rs/mw_interpolated/2019-07-01_mw.tif"

    with rasterio.open(path_file_metadata) as src:
        kwargs1 = src.meta.copy()

    with rasterio.open(path_out, "w", **kwargs1) as dst:
        dst.write_band(1, data)  # numpy array or xarray
    return

#############################################
# Feature importance:
#############################################

def feature_importance_dict(model, columns):
    """
    Function to plot feature importance.
    """
    # columns = model.columns
    # model = model.cv_model_list[0]

    if isinstance(model, DecisionTreeRegressor):
        feature_importance = model.feature_importances_
    elif isinstance(model, RandomForestRegressor):
        feature_importance = model.feature_importances_
    elif isinstance(model, GradientBoostingRegressor):
        feature_importance = model.feature_importances_
    elif isinstance(model, LinearRegression):
        feature_importance = model.coef_
    elif isinstance(model, Ridge):
        feature_importance = np.abs(model.coef_)
    elif isinstance(model, Lasso):
        feature_importance = np.abs(model.coef_)
    elif isinstance(model, ElasticNet):
        feature_importance = np.abs(model.coef_)
    else:
        print("model not supported")
        assert False
    feature_importance_dict = dict(zip(columns, feature_importance))
    return feature_importance_dict

def plot_feature_importance(model):
    """Plot mean feature importance over 5 cv models with std."""
    feature_importance_df = []
    for mod in model.cv_model_list:
        feature_importance = feature_importance_dict(mod, model.columns)
        if len(feature_importance_df) == 0:
            feature_importance_df = pd.DataFrame(feature_importance, index=[0])
        else:
            feature_importance_df = pd.concat(
                [feature_importance_df, pd.DataFrame([feature_importance])],
                ignore_index=True,
            )

    # sort features by mean importance in descending order by absolute value
    mean_importances = feature_importance_df.mean()
    mean_importances_abs = np.abs(mean_importances)
    sorted_index = mean_importances_abs.sort_values(ascending=False).index
    mean_importances = mean_importances[sorted_index]
    feature_names = mean_importances.index

    """
    # assign colors to positive and negative features
    # #9c3605
    colors = ["firebrick" if imp < 0 else "#fead3a" for imp in mean_importances]

    # plot mean feature importance as bar plot with std
    fig, ax = plt.subplots()
    ax.bar(
        feature_names,
        mean_importances,
        yerr=feature_importance_df[sorted_index].std(),
        capsize=5,
        color=colors,
    )
    ax.set_xlabel("Feature")
    ax.set_ylabel("Mean Importance")
    ax.set_title("Feature Importance")
    ax.tick_params(axis="x", rotation=90)

    plt.show()
    """

    # Assign colors to positive and negative features
    colors = ["firebrick" if imp < 0 else "#fead3a" for imp in mean_importances]

    # Plot mean feature importance as a bar plot with standard deviation
    fig, ax = plt.subplots(figsize=(8, 6))
    ax.bar(
        feature_names,
        mean_importances,
        yerr=feature_importance_df[sorted_index].std(),
        capsize=5,
        color=colors,
    )

    # Set axis labels and title
    ax.set_xlabel("Feature", fontsize=12)
    ax.set_ylabel("Mean Importance", fontsize=12)
    ax.set_title("Feature Importance", fontsize=14)

    # Rotate x-axis labels for better visibility
    ax.tick_params(axis="x", rotation=90)

    # Set grid lines
    ax.grid(axis="y", linestyle="--", linewidth=0.5, alpha=0.7)

    # Customize spines
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["left"].set_linewidth(0.5)
    ax.spines["bottom"].set_linewidth(0.5)

    # Adjust the plot layout
    plt.tight_layout()

    # Show the plot
    plt.show()

    ############
    # to get model params:
    # model.cv_model_list[0].get_params()


# Python - Database - sqlite

import sqlite3

def databaseFunction(db_name):
    conn = sqlite3.connect(db_name)
    print(f" {db_name} database connected")

    tableScript = "create table mytable (name text, age int, mobile int) "

    conn.execute(tableScript)
    print(f"table created")

    insertData = "insert into mytable values('Alex', 28, 652312)"

    conn.execute(insertData)
    print(f"data inserted")

    conn.commit()
    conn.close()

def insertData(tableName):
    conn = sqlite3.connect("sample.db")

    #conn.execute(f"create table {tableName} (name text, age int) ")

    conn.execute(f"insert into mytable values('Tom', 35, 454556)")

    conn.commit()
    conn.close()

choice = input("do you want to create a database? if yes type a name or just press enter  ")

if len(choice) > 1:
    databaseFunction(choice + ".db")

def getData(tableName):
    conn = sqlite3.connect("sample.db")

    selectScript = f"select * from {tableName}"

    cursor = conn.execute(selectScript)

    for rows in cursor:
       print(f"{rows[0]} - {rows[1]} - {rows[2]} ")
       #print(len(rows))

    conn.close()

tableName = "mytable"

#insertData(tableName)

def updateData():
    conn = sqlite3.connect("sample.db")

    conn.execute(f"update mytable set age=32 where name = 'Alex'")

    conn.commit()
    conn.close()

def deleteData():
    conn = sqlite3.connect("sample.db")

    conn.execute(f"delete from mytable where name = 'Alex'")

    conn.commit()
    conn.close()

getData(tableName)

deleteData()

getData(tableName)

#DML - Insert Data, Modify/Update Data, Delete Data
#CRUD - Create/Insert, Read/Select, Update/Modify, Delete