import uuid
from typing import Callable
import pandas
import re
from cpgintegrate import ProcessingException

def match_indices(match_from: pandas.DataFrame, match_in: pandas.DataFrame,
                  index_transform: Callable = lambda x: int(re.compile(r'[^\d]+').sub("", x))) -> pandas.DataFrame:
    """
    Replace index values in a frame by searching using transformed index in another

    Replace indices of match_from with first instance found in match_in when both are transformed using index_transform.
    KeyError if any index of match_from is missing.

    :param match_from: DataFrame whose index values I should check and replace
    :param match_in: DataFrame which I should search in
    :param index_transform: Callable that acts on index value, default takes numeric parts
    :return:
    """
    match_in_reindexed = (match_in
                          .drop(columns=match_in.columns)
                          .assign(orig_index=lambda df: df.index)
                          .pipe(lambda df: df.set_index(df.index.map(index_transform)))
                          # Only want one row for each transformed index to avoid multiplying rows in match_from frame
                          .groupby(level=0)
                          .first())
    matched = (
        match_from
        .assign(**{'transformed_index': lambda df: df.index.map(index_transform)})
        .join(match_in_reindexed, on='transformed_index')
    )
    assert not matched.orig_index.isnull().any(), "Bad IDs {0}".format(matched.loc[matched.orig_index.isnull(),
                                                                                'transformed_index'])
    return match_from.set_index(matched.set_index('orig_index').rename_axis(match_from.index.name).index)

def edit_using(frame_to_edit: pandas.DataFrame, edits: pandas.DataFrame) -> pandas.DataFrame:
    """
    Edit DataFrame using list of edits in another DataFrame.

    Alters each target_field value in frame_to_edit to target_value where match_field == match_value, or removes the row
    if remove_row is > 0
    :param frame_to_edit: DataFrame to edit
    :param edits: DataFrame with edits in columns match_field, match_value, target_field, target_value
    optionally remove_row
    :return:
    """

    frame_to_edit = frame_to_edit.copy(deep=True)

    # remove_rows
    if "remove_row" in edits.columns:
        for _, remove_spec in edits[edits.remove_row > 0].iterrows():
            frame_to_edit = frame_to_edit[~(frame_to_edit[remove_spec.match_field] == remove_spec.match_value)]

    # Use temporary name to avoid clobbering any existing column
    temp_col_name = None
    orig_index_name = None
    if frame_to_edit.index.name and (frame_to_edit.index.name in edits.target_field.values):
        temp_col_name = str(uuid.uuid4())
        orig_index_name = frame_to_edit.index.name
        frame_to_edit[temp_col_name] = frame_to_edit.index
        edits.loc[edits.target_field == orig_index_name, 'target_field'] = temp_col_name

    for _, row in edits.loc[edits.target_field.fillna("") != ""].iterrows():
        try:
            frame_to_edit.loc[frame_to_edit[row.match_field] == row.match_value, row.target_field] \
                = row.get("target_value", None)
        except KeyError:
            raise ProcessingException("Edits error on %s , %s, %s, %s"
                                      % (row.match_field, row.match_value,
                                         row.target_field, row.get("target_value", None)))

    if temp_col_name:
        return frame_to_edit.set_index(temp_col_name).rename_axis(orig_index_name)
    return frame_to_edit

def replace_indices(target: pandas.DataFrame, index_source: pandas.DataFrame) -> pandas.DataFrame:
    return target.set_index(
        target.index.to_series().replace(to_replace=list(index_source.iloc[:, 0]), value=list(index_source.index))
    )


import random
from direct.actor.Actor import Actor
from utils import address

class TransportManager:
    """Transport manager rules transport loading and preparing.

    It prepares transport models and then propagates
    its instances to the given units.
    """

    def __init__(self):
        self._models = {
            "moto1": Actor(address("motocycle1")),
            "moto2": Actor(address("motocycle2")),
            "moto3": Actor(address("motocycle3")),
            "dodge": Actor(address("car1")),
        }
        self._models["moto1"].setPlayRate(1.5, "ride")
        self._models["moto2"].setPlayRate(1.5, "ride")
        self._models["moto3"].setPlayRate(1.5, "ride")
        self._models["dodge"].setPlayRate(2.5, "ride")

    def _load_snd(self, unit, type_):
        """Load transport move sound.

        Args:
            unit (units.enemy.enemy_unit.EnemyUnit):
                Unit to put on transport.
            type_ (str): The transport type: car or motorcycle.
        """
        unit.transport_snd = base.sound_mgr.loadSfx(  # noqa: F821
            "sounds/{type}_moves1.ogg".format(type=type_)
        )
        unit.transport_snd.setLoop(True)
        unit.transport_snd.setPlayRate(random.uniform(0.7, 1))
        unit.transport_snd.setVolume(0.5)
        unit.transport_snd.play()
        base.sound_mgr.attachSoundToObject(  # noqa: F821
            unit.transport_snd, unit.transport
        )

    def load_transport(self, unit):
        """Load transport for the given unit.

        Args:
            unit (units.enemy.enemy_unit.EnemyUnit):
                The unit to put on transport.
        """
        transport_model = unit.class_data["transport_model"]

        unit.transport = unit.model.attachNewNode("transport_" + unit.id)
        self._models[transport_model].instanceTo(unit.transport)

        if not self._models[transport_model].getCurrentAnim():
            self._models[transport_model].loop("ride")

        taskMgr.doMethodLater(  # noqa: F821
            4,
            self._load_snd,
            "load_transport_sound_" + unit.id,
            extraArgs=[unit, "moto" if transport_model.startswith("moto") else "car"],
        )

    def stop(self):
        """Stop all the transport animations."""
        for model in self._models.values():
            model.stop()


from django_bootstrap import bootstrap
bootstrap()

import json
import sys

from regis.models import Applicant

def main():
    filename = sys.argv[1]

    lines = open(filename).readlines()

    count = len(lines) // 2
    for i in range(count):
        nat_id = lines[i*2].strip()
        data = json.loads(lines[i*2+1].strip())

        if 'StatusMessage' in data:
            print('MISSING:', nat_id)
            continue

        try:
            applicant = Applicant.objects.get(national_id=nat_id)
        except:
            print('NAT-MISSING:', nat_id)
            continue

        if ((applicant.prefix != data['Prefix']) or
            (applicant.first_name.strip() != data['Name']) or
            (applicant.last_name.strip() != data['Surname'])):
            print('MISMATCH:',
                  nat_id,
                  applicant,
                  'vs',
                  data['Prefix'],
                  data['Name'],
                  data['Surname'])

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""
Created on Thu Dec  9 12:13:24 2021

@author: E
"""

import cv2
import time
from PIL import Image

face_cascade_path = "./face_data/haarcascade_frontalface_default.xml"
face_cascade = cv2.CascadeClassifier(face_cascade_path)

cap = cv2.VideoCapture(0)

start_time = 0
end_time = 0
count_face = 1
count_background = 1

# スクショしたかどうかを保存する変数 (まだ撮っていないのでFalse)
screenshot = False
# スクショを保存する変数
photo = None

# 実行
while True:
    # Webカメラのフレーム取得
    ret, img = cap.read()
    # キーボードの入力の受付
    k = cv2.waitKey(1)
    cv2.imshow("video image", img)
    img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    pil_im = Image.fromarray(img)
    pil_im.show()

    # 終了
    if k == ord("q"):
        break
    # 背景の写真を保存
    elif k == ord("b") and count_background < 20:
        cv2.imwrite('face_data/background/background' + str(count_background) + '.jpg', img)
        count_background += 1
        time.sleep(0.1)

    # 顔の写真を保存
    elif k == ord("f"):
    # グレースケールに変換
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # 分類器で顔のx座標,y座標,幅,高さを取得
        faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5)

        # 各顔について
        for x, y, w, h in faces:

            # 顔の外接短形を描画、平均値
            cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
            face = img[y : y + h, x : x + w]
            cv2.imshow("face image", face)
            if count_face < 20:
                count_face += 1
                print('face_data/sho' + str(count_face) + '.jpg')
                cv2.imwrite('face_data/A/face' + str(count_face) + '.jpg',face)
            face_gray = gray[y : y + h, x : x + w]

# 終了処理
cv2.destroyAllWindows()
cap.release()


from collections import deque
import sys
input = sys.stdin.readline

n, m, k, x = map(int, input().split())
graph = [[] for _ in range(n + 1)]

for _ in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)

distance = [-1] * (n + 1)
distance[x] = 0

q = deque([x])

while q:
    now = q.popleft()
    for next_node in graph[now]:
        if distance[next_node] == -1:
            distance[next_node] = distance[now] + 1
            q.append(next_node)

flag = 0

for index in range(n + 1):
    if distance[index] == k:
        flag = 1
        print(index)
if flag == 0:
    print(-1)


# Stephanie Cheng
# CIS 41A Spring 2019
# Unit J take-home assignment
#

# Part 1 of 1 - Part 1 of 1 – Nested Loop Dice Game

import random

def playgame():
    earnings = 0
    thenum = random.randrange(1,7)

    while thenum != 1 and thenum != 2 and thenum != 3:
        earnings += thenum
        thenum = random.randrange(1,7)
    return earnings

largest = 0
allearnings = 0

for x in range(1, 10001):
    earn = playgame()
    allearnings += earn
    if earn > largest:
        largest = earn

print("Average amount won:", round(allearnings/10000, 2))
print("Max amount won:", largest)

'''
Execution results:
Average amount won: 5.04
Max amount won: 62
'''


# -*- coding: utf-8 -*-
"""
Python 18_11_05

"""

# 맞교환

a = 20
b = 30

a = b
a

k = 'Korea'
j = 'Japan'

k, j = j, k
k
j

# 원소 넣기 / packing, unpacking

d = (1, 2, 3, 4)
t = d
t
t1, t2, t3, t4 = t
print(t1, t2, t3, t4)

# 데코레이터, @staticmethod, @classmethod
class Date(object):
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
        print(" Date__init__ ")

    def __str__(self):
        return "{}년 {}월 {}일 생산".format(self.year, self.month, self.day)

class Ktx:
    def __init__(self, station, fee):
        self.station = station
        self.fee = fee
        print("인수 2개 __init__")

    def __del__(self):
        print(" __del__ ")

    def __str__(self):
        return " {} *** {}원 ".format(self.station, self.fee)

k1 = Ktx("부산역", 49000)
k2 = Ktx("대전역", 24000)

print(k1)
print(k2)

k3 = Ktx() ## error. station, fee argument를 안 받았기 때문.

class Ktx:
    def __init__(self, station, fee):
        self.station = station
        self.fee = fee
        print("인수 2개 __init__")
    # 다음 부분 추가
    def __init__(self):
        self.station = "이름 없음"
        self.fee = 0
        print("인수 없음 __init__")

    def __del__(self):
        print(" __del__ ")

    def __str__(self):
        return " {} *** {}원 ".format(self.station, self.fee)

k3 = Ktx()

print(k3)

# 합쳐서 다음과 같이 표현 가능
class Ktx:
    def __init__(self, station = "이름 없음", fee = 0): ## Default 설정
        self.station = station
        self.fee = fee
        print("인수 2개 __init__")

    def __del__(self):
        print(" __del__ ")

    def __str__(self):
        return " {} *** {}원 ".format(self.station, self.fee)

k4 = Ktx() # 인자를 하나도 안 준 경우 default
print(k4)

k5 = Ktx("울산역") # 하나만 준 경우 할당된 인자 외에 default
print(k5)

k5.station
a = k5.station
a

# get, set 추가
class Ktx:
    def __init__(self, station = "이름 없음", fee = 0): ## Default 설정
        self.station = station
        self.fee = fee
        print("인수 2개 __init__")

    def __del__(self):
        print(" __del__ ")

    def __str__(self):
        return " {} *** {}원 ".format(self.station, self.fee)

    def get_station(self):
        return self.station

    def get_fee(self):
        return self.fee

    def set_station(self, station):
        self.station = station

    def set_fee(self, fee):
        self.fee = fee

k1 = Ktx("부산역", 49000)
k2 = Ktx("대전역", 24000)
k2.set_station("목포역")
k2.set_fee(47000)
print(k1, k2)

# cnt 추가(class 변수)
## classmethod(객체 하나하나에 종속되는 것이 아닌 class 전체에서 사용하는 method)
class Ktx:
    cnt = 0  ## class 변수

    @staticmethod
    def get_cnt_st():
        print("현재 객체수는 : ", Ktx.cnt)

    @classmethod
    def get_cnt(cls):
        print("현재 객체 수는 : ", Ktx.cnt)

    def __init__(self, station = "이름 없음", fee = 0): ## Default 설정
        self.station = station
        self.fee = fee
        Ktx.cnt += 1
        print("인수 2개 __init__")

    def __del__(self):
        Ktx.cnt -= 1
        print(" __del__ ")

    def __str__(self):
        return " {} *** {}원 ".format(self.station, self.fee)

    def get_station(self):
        return self.station

    def get_fee(self):
        return self.fee

    def set_station(self, station):
        self.station = station

    def set_fee(self, fee):
        self.fee = fee

k1 = Ktx("부산역", 49000)
k2 = Ktx("대전역", 24000)
k3 = Ktx()
k4 = Ktx("울산역")

Ktx.cnt
k1.cnt ## 객체를 통해서도 class 변수에 접근 가능( 왜?? )
Ktx.get_cnt()

del Ktx, k1, k2, k3, k4

# comprehension method

import sys

a = 100
b = 200
aa = [2, 4, 6]
bb = ["kbs", "mbc", "sbs"]

sys.getsizeof(a)
sys.getsizeof(b)
sys.getsizeof(aa)
sys.getsizeof(bb)

aa = []
len(aa)
for i in range(20):
    aa.append(i + 5)

aa
sys.getsizeof(aa)

jj = [j + 5 for j in range(10)]
jj
sys.getsizeof(jj)

kk = (i for i in range(20))
kk

kk.__next__()
sys.getsizeof(kk)
next(kk)

jj = [j for j in range(100)]
jj
j3 = iter(jj)
sys.getsizeof(jj)
sys.getsizeof(j3)

sys.path
sys.maxsize

# time
import time

## 1970년 1월 1일 0시 0분 0초 기준
t1 = time.time()
print(" {} 초".format(t1))
print(" {} 초".format(int(t1)))

## 구조체 : method가 없고 field만 있는 class
t2 = time.gmtime() ## global time
print(t2)
print("{}/{}/{}".format(t2.tm_year, t2.tm_mon, t2.tm_mday))
print("{}:{}:{}".format(t2.tm_hour, t2.tm_min, t2.tm_sec))

t3 = time.localtime() ## 내 컴퓨터 시간
print(t3)
print("{}/{}/{}".format(t3.tm_year, t3.tm_mon, t3.tm_mday))
print("{}:{}:{}".format(t3.tm_hour, t3.tm_min, t3.tm_sec))

start = time.time()
for i in range(1000):
    print("싫어", end = '')
end = time.time()

print("\n")
print( " 소요 시간 : ", end - start)

# datetime
import datetime as dt

now = dt.datetime.now()
print("{}/{}/{}".format(now.year, now.month, now.day))
print("{}:{}:{}".format(now.hour, now.minute, now.second))

import calendar as cld

c = cld.calendar(2018)
print(c)

print(cld.month(2019,5))

def whatwdy():
    week = ["월", "화", "수", "목", "금", "토", "일"]
    print(" 생년월일을 입력하세요.")
    year = int(input(" 연도 > "))
    month = int(input(" 월 > "))
    day = int(input(" 일 > "))

    q = cld.weekday(year, month, day)
    print(" 나는 {}요일에 태어났어요.".format(week[q]))

whatwdy()

# file 다루기

f = open("c:\\dd\\mon.txt", "r")
a = f.read()
print(a)
f.close()

f = open("c:\\dd\\33.txt", "w")
f.write("배가 고파요\n")
f.write("배꼽시계가 울려요\n")
f.close()
## 그냥 w로 불러와 쓰면 덮어쓴다. a 사용
f = open("c:\\dd\\33.txt", "a")
f.write("빨리 끝내주세요\n")
f.close()
f = open("c:\\dd\\44.txt", "a")
for i in range(50):
    f.write("배고파")
f.close()

f.write("\n")
for i in range(5):
    name = input(" 이름 > ")
    f.write(name)
    f.write("\n")

f.close()

f = open("c:\\dd\\ace.txt", "r")
print(f.read())

# sql 연결

import sqlite3 as sql

conn = sql.connect('c:\\dd\\adb') # db 연결
c = conn.cursor() # 커서 연결

c.execute('drop table if exists Lunch')
c.execute("create table Lunch(menu char(20), price int)")
c.execute("insert into Lunch values('비빔밥', 7000)")
c.execute("insert into Lunch values('볶음밥', 8000)")
c.execute("insert into Lunch values('짜장면', 6000)")

conn.commit()

c.execute("select * from Lunch")
k = c.fetchall()

for i in k:
    print(" {} {}원".format(i[0], i[1]))

c.execute('drop table if exists ltx')

c.close() # 커서 닫고
conn.close() # db 닫고

menu = input(" 좋아하는 메뉴 : ")
price = int(input(" 가격 : "))
c.execute("insert into Lunch(menu, price) values(?, ?)", (menu, price))

#################################
a = []

with open("c:\\dd\\ss.txt", 'r') as f:
	for i in range(10):
		a.append(f.readline().split())

for i in range(len(a)):
	for j in range(1,4):
		a[i][j] = int(a[i][j])
	a[i].append(sum(a[i][1:4]))
	a[i].append(round((a[i][4] / 3), 2))

korT = 0
engT = 0
matT = 0

for i in range(len(a)):
	korT += a[i][1]
	engT += a[i][2]
	matT += a[i][3]

korA = korT / len(a)
engA = engT / len(a)
matA = matT / len(a)

everyT = korT + engT + matT
everyA = everyT / (3 * len(a))
#########################

## 성적 처리

conn = sql.connect('c:\\dd\\adb')
c = conn.cursor()

c.execute("drop table if exists students")
c.execute("create table students(\
        name char(20), kor int, eng int, mat int, tot int, avg int)")

sql1 = "insert into students(name, kor, eng, mat, tot, avg) values(?, ?, ?, ?, ?, ?)"

for i in range(10):
    c.execute(sql1, (a[i][0], a[i][1], a[i][2], a[i][3], a[i][4], round(a[i][5])))

c.execute("select * from students")
conn.commit()
kk = c.fetchall()

f = open('c:\\dd\\source.txt', 'w')

f.write(" *************** 성 적 표 ************** \n")
f.write(" *************************************** \n")
f.write("  이 름  국어  영어  수학  총점    평균  \n")
f.write(" *************************************** \n")

for i in range(len(a)):
	f.write(" {} {:5d} {:5d} {:5d} {:5d} {:7.2f} \n"
              .format(kk[i][0], kk[i][1], kk[i][2], kk[i][3], kk[i][4], kk[i][5]))

f.write(" ************************************** \n")
f.write(" 총평균 {:5.1f} {:5.1f} {:5.1f} {:5d} {:7.2f} \n"
      .format(korA, engA, matA, everyT, everyA))

f.close()

#############################성적 처리 source.txt로 저장
########################################################

# 엑셀 파일 부르기

import openpyxl

exf = openpyxl.load_workbook('c:\\dd\\ss.xlsx')
aws = exf.active

print(" *************** 성 적 표 ************** ")
print(" *************************************** ")
print("  이 름  국어  영어  수학  총점    평균  ")
print(" *************************************** ")

for i in aws.rows:
    index = i[0].row
    name = i[0].value
    kor = i[1].value
    eng = i[2].value
    mat = i[3].value
    total = kor + eng + mat
    avg = total / 3

    aws.cell(row = index, column = 5).value = total
    aws.cell(row = index, column = 6).value = avg

    print(" {} {:5d} {:5d} {:5d} {:5d} {:7.2f} "
              .format(name, kor, eng, mat, total, avg))

print(" *************************************** ")
exf.save("c:\\dd\\report.xlsx")
exf.close()

# 예외 처리
g = [j*5 for j in range(10)]
gg = iter(g)
while True:
    try:
        num = next(gg)

    except:
        print(" 범위 끝났어 ")
        break
    print(num)

a = [1, 2, 3]

try:
    #a[0] / 0
    #a[5] = 6
    a[2] + "good"

except ZeroDivisionError:
    print(" 0으로 못나눠용 ")

except IndexError:
    print(" 인덱스를 벗어났어 ")

except TypeError:
    print(" type이 맞지 않아 ")

finally:
    print(" 무조건 실행 ")

# 난수 생성

import random

print(" * 0 ~ 1 사이의 값 * ")
print(" ****************** ")
for i in range(10):
    print(random.random())

print(" * 1 ~ 1000 사이의 값 * ")
print(" ********************* ")
for i in range(10):
    print(random.randint(1,1000))

## 로또 번호 추출
for i in range(5):
    num = random.sample(range(1,46), 6)
    num.sort()
    print(num)

# os modules

import os
os.system("notepad")
os.system("mspaint")
os.sys
os.path
os.mkdir("dir")
os.mkdir("c:\\dd\\OK")
os.mkdir("c:\\dd\\파이썬")

## os 모듈 이용
def osmodules():
    import os
    import random as rd

    while True:
        print(" ***** 메 뉴 ***** ")
        print(" ***************** ")
        print("  1. 계산기        ")
        print("  2. 메모장        ")
        print("  3. 명령 프롬프트 ")
        print("  4. 숫자 맞추기   ")
        print("  0. 프로그램 종료 ")
        print(" ***************** ")
        menu = int(input(" 메뉴를 고르세요 > "))

        if menu == 0:
            print(" 종료헙니다. ")
            break

        if menu == 1:
            print(" 계산기 실행 ")
            os.system('calc')

        if menu == 2:
            print(" 메모장 실행 ")
            os.system('calc')

        if menu == 3:
            print(" 명령 프롬프트 실행 ")
            os.system('cmd')

        if menu == 4:
            print(" 숫자 맞추기 실행 ")
            num = int(input(" 1부터 원하는 숫자 범위를 고르세요 > "))
            random_number = rd.randint(1,num)

            cnt = 0
            print("1 ~", num, " 중에 고르세요!")

            while True:
                pick = int(input("Pick > "))
                cnt += 1
                if pick == random_number:
                    print("{}번 만에 맞추셨습니다!".format(cnt))
                    break

                elif pick > random_number:
                    print("{} 보다는 작습니다!".format(pick))

                else:
                    print("{} 보다는 큰 것 같습니다!".format(pick))
                    continue

        else:
            print(" 존재하지 않는 메뉴입니다. ")
            print(" 다시 고르세요. ")
            continue


def bro():
    n1 = int(input("Введите целое число: "))
    b1 = n1
    n2 = 0
    while n1 > 0:
        digit = n1 % 10
        n1 = n1 // 10
        n2 = n2 * 10
        n2 = n2 + digit
    print('"Обратное" ему число:', n2)
    n3 = b1 - n2
    print('Разность', n3)
bro()


from rest_framework import serializers
from skill.serializers import SkillModelSerializer
from auth_r.models import User
from skill.models import Skill

class UserProfileSerializer(serializers.ModelSerializer):
    skills = SkillModelSerializer(many=True)

    class Meta:
        model = User
        fields = (
            "username",
            "first_name",
            "last_name",
            "role",
            "date_of_birth",
            "phone",
            "email",
            "bio",
            "skills",
        )

    def update(self, instance, validated_data):
        # Pop the skills list from validated_data and process it separately
        skills = validated_data.pop("skills", [])

        # Update user profile fields
        instance = super().update(instance, validated_data)

        # Update user's skills
        if skills:
            skill_titles = [skill["title"] for skill in skills]
            new_skills = Skill.objects.filter(title__in=skill_titles)
            instance.skills.set(new_skills)
        else:
            # If skills list is empty, remove all existing skills
            instance.skills.clear()

        return instance


# To hold the utility functions used in llqd
import shutil
from os import listdir
import numpy as np
import torch
import src.torch.pytorch_util as ptu

from src.models.dynamics_models.deterministic_model import DeterministicDynModel
from src.models.dynamics_models.probabilistic_ensemble import ProbabilisticEnsemble

def gaussian_pdf(datapoint, mean, variance):
    """
    likelihood for each dimension in next state, acc. to pdf of Gaussian specified by mean and variance

    mean: np.array of shape (ensemble_size, num_samples, next_state_dims)
    variance: np.array of shape (ensemble_size, num_samples, next_state_dims)

    returns: np.array of shape (ensemble_size, num_samples, next_state_dims)
    """
    return (1 / np.sqrt(2 * np.pi * variance)) * np.exp(-((datapoint - mean) ** 2) / (2 * variance))

def get_log_likelihoods(likelihoods_per_model, reduction='mean'):
    """
    Retrieves some summary measure (e.g. mean across samples) of the sum of log likelihoods (across all
    next_state dimensions), for each ensemble member

    likelihoods_per_model: array containing likelihoods
        np.array of shape (ensemble_size, num_samples, next_state_dims)

    reduction: sum, median, or mean

    returns: aggregate likelihoods per ensemble member
        np.array of shape (ensemble_size,)
    """
    if reduction == 'sum':
        return np.log(likelihoods_per_model).sum(axis=2).sum(axis=1)
    elif reduction == 'median':
        return np.median(np.log(likelihoods_per_model).sum(axis=2), axis=1)
    elif reduction == 'mean':
        return np.mean(np.log(likelihoods_per_model).sum(axis=2), axis=1)
    else:
        raise (NotImplementedError)

def get_log_likelihoods_mean_std(likelihoods_per_model, reduction='mean'):
    """
    Retrieves some summary measure (e.g. mean across samples) and std of the sum of log likelihoods (across all
    next_state dimensions), for each ensemble member. Mean and std across samples are adjusted to ignore -inf values.

    likelihoods_per_model: array containing likelihoods
        np.array of shape (ensemble_size, num_samples, next_state_dims)

    reduction: median, mean, or no reduction to retrieve likelihoods per transition

    returns: aggregate likelihoods per ensemble member, std of likelihoods per ensemble member
        Two np.arrays of shape (ensemble_size,) each
    """
    sum_of_log_likelihoods = np.log(likelihoods_per_model).sum(axis=2)  # shape (ensemble_size, num_samples)

    if reduction == 'median':
        return np.median(sum_of_log_likelihoods, axis=1), np.ma.masked_invalid(sum_of_log_likelihoods).std(axis=1).data
    elif reduction == 'mean':
        return np.ma.masked_invalid(sum_of_log_likelihoods).mean(axis=1).data, np.ma.masked_invalid(
            sum_of_log_likelihoods).std(axis=1).data
    elif reduction == 'no':
        return np.ma.masked_invalid(sum_of_log_likelihoods).data, None
    else:
        raise (NotImplementedError)

def get_random_sample_from_transitions(transitions, num_samples, state_dims, action_dims):
    """
    Retrieves a random sample of transitions (state, action, next_state) from a transitions Dataset, which is retrieved
    from buffer

    transitions: dataset containing state, action, reward(0), done(0), next_state
        np.array of shape(num_transitions, state_dims + action_dims + 2 + next_state_dims)

    num_samples: number of transition samples we want to randomly draw (-1: use all samples)
        int

    state_dims: dimensionality of state(48)
        int

    action_dims: dimensionality of action(18)

    returns: states, actions, next_states
        np.arrays of shape(num_samples, state_dims or action_dims)
    """
    if num_samples == -1:
        random_sample = transitions
    else:
        rand_indices = [np.random.randint(len(transitions)) for i in range(num_samples)]
        random_sample = transitions[rand_indices]
    states = random_sample[:, 0:state_dims]
    actions = random_sample[:, state_dims: state_dims + action_dims]
    next_states = random_sample[:, state_dims + action_dims + 2:]
    return states, actions, next_states

def evaluate_transition_likelihood(transitions_data, num_samples, model, inf_adjusted=False):
    """
    Aggregation function to retrieve aggregated log likelihoods per ensemble member for a set of transitions

    transitions: dataset containing state, action, reward(0), done(0), next_state
        np.array of shape(num_transitions, state_dims + action_dims + 2 + next_state_dims)

    num_samples: number of transition samples we want to randomly draw
        int

    model: trained probabilistic ensemble model

    inf_adjusted: if True, adjusts log_likelihoods to ignore -inf values, so that mean and std are not distorted

    returns: aggregate likelihoods per ensemble member
        np.array of shape (ensemble_size,)
    """
    states, actions, next_states = get_random_sample_from_transitions(transitions_data, num_samples, 48, 18)
    states_actions_array = np.concatenate((states, actions), axis=1)
    states_actions_tensor = torch.tensor(states_actions_array).float()
    model.eval()
    with torch.no_grad():
        samples, mean, logstd = model.forward(torch.nn.Parameter(states_actions_tensor), deterministic=False,
                                              return_dist=True)
    next_state_deltas = next_states - states
    next_state_delta_observations = torch.tensor([next_state_deltas]).float()
    likelihoods_per_model = gaussian_pdf(next_state_delta_observations.detach().numpy(), mean.detach().numpy(), np.exp(
        2 * logstd.detach().numpy()))  # should be 2*logstd for var, but empirically works better without
    if inf_adjusted is False:
        log_likelihoods = get_log_likelihoods(likelihoods_per_model, reduction='median')
    else:
        log_likelihoods, _ = get_log_likelihoods_mean_std(likelihoods_per_model, reduction='mean')  #'no' to show likelihoods per transition
    return log_likelihoods

def evaluate_holdout_likelihoods(x_test, y_test, model):
    """
    Aggregation function to retrieve aggregated log likelihoods per ensemble member for a holdout set from ModelTrainer

    x_test: dataset containing state, action
        np.array of shape(num_transitions, state_dims + action_dims)

    y_test: dataset containing next state
        np.array of shape(num_transitions, state_dims)

    model: the model on which we evaluate the holdout set
        trained probabilistic ensemble model

    returns: mean likelihood and standard deviation across num_transitions. Adjusted to ignore -inf
        float, float
    """
    states_actions_tensor = torch.tensor(x_test).float()
    model.eval()
    with torch.no_grad():
        samples, mean, logstd = model.forward(torch.nn.Parameter(states_actions_tensor), deterministic=False,
                                              return_dist=True)
    next_state_delta_observations = torch.tensor([y_test]).float()
    likelihoods_per_model = gaussian_pdf(next_state_delta_observations.detach().numpy(), mean.detach().numpy(), np.exp(
        2 * logstd.detach().numpy()))  # should be 2*logstd for var, but empirically works better without
    log_likelihoods_mean, log_likelihoods_std = get_log_likelihoods_mean_std(likelihoods_per_model, reduction='mean')
    return log_likelihoods_mean.mean(), log_likelihoods_std.mean()

# Functions and imports to generate the likelihood of all models using the data of one sim

def convert_states_actions_to_transitions(states, actions):
    """
    Takes in states, actions, and converts them into transitions dataset
    This means adjusting states and actions to exclude the last observation,
    inserting zero rewards and done indicators, as well as generating next states
    states and actions would typically come from Species.obj_traj and Species.act_traj

    states: arrays of shape (num_obs, state_dims), usually (300, 48)
    actions: arrays of shape (num_obs, action_dims), usually (300, 18)

    transitions: dataset containing state, action, reward(0), done(0), next_state
        np.array of shape(num_transitions, state_dims + action_dims + 2 + next_state_dims)
    """
    states_usable = states[:-1]
    actions_usable = actions[:-1]
    next_states_usable = states[1:]
    rewards_dones = np.zeros((len(states_usable), 2))
    return np.hstack((states_usable, actions_usable, rewards_dones, next_states_usable))

def get_all_model_likelihoods(models_path, transitions):
    """
    Calculates the likelihoods for all models using all datapoints in transitions.

    models_path: path to models directory
        str

    transitions: dataset containing state, action, reward(0), done(0), next_state
        np.array of shape(num_transitions, state_dims + action_dims + 2 + next_state_dims)

    returns: dict containing for each available model the aggregated (across samples) likelihoods per ensembble
        member
    """
    likelihoods_dict = {}
    model_name_list = [f for f in listdir(models_path)]

    # Check if any model is available, if not exit
    if len(model_name_list) == 0:
        print("No models currently exist")
        return

    for model_name in model_name_list:
        dynamics_model, _ = get_dynamics_model("prob")
        model_path = models_path + '/' + model_name
        dynamics_model = ptu.load_model(dynamics_model, model_path)
        dynamics_model.eval()
        with torch.no_grad():
            print(f"-----------------{model_name}------------------------")
            likelihood = evaluate_transition_likelihood(transitions, -1, dynamics_model, True)
            print(likelihood.mean())
            likelihoods_dict[model_name] = likelihood

    return likelihoods_dict

def get_dynamics_model(dynamics_model_type):
    """
    Helper function to retrieve the dynamics model
    """
    obs_dim = 48
    action_dim = 18

    ## INIT MODEL ##
    if dynamics_model_type == "prob":
        from src.trainers.mbrl.mbrl import MBRLTrainer
        variant = dict(
            mbrl_kwargs=dict(
                ensemble_size=4,
                layer_size=500,
                learning_rate=1e-3,
                batch_size=512,
            )
        )
        M = variant['mbrl_kwargs']['layer_size']
        dynamics_model = ProbabilisticEnsemble(
            ensemble_size=variant['mbrl_kwargs']['ensemble_size'],
            obs_dim=obs_dim,
            action_dim=action_dim,
            hidden_sizes=[M, M]
        )
        dynamics_model_trainer = MBRLTrainer(
            ensemble=dynamics_model,
            **variant['mbrl_kwargs'],
        )

        # ensemble somehow cant run in parallel evaluations
    elif dynamics_model_type == "det":
        from src.trainers.mbrl.mbrl_det import MBRLTrainer
        dynamics_model = DeterministicDynModel(obs_dim=obs_dim,
                                               action_dim=action_dim,
                                               hidden_size=500)
        dynamics_model_trainer = MBRLTrainer(
            model=dynamics_model,
            batch_size=512, )

    return dynamics_model, dynamics_model_trainer

def evaluate_likelihood_by_model_for_slist(s_list, models_path):
    """
    Evaluate the likelihood of observing the transitions from the s_list species members, for each available model
    Use this to check if still in same environment.

    Returns a dictionary with the models as keys, and values as a 1d array containing the median (across transitions) sum (across
    next_state dimensions) of log likelihoods, for each ensemble member (i.e. 4)

    Insert this function after the real evaluations have taken place; then use it to attribute datapoints

    models_path: usually 'models'

    """
    transition_list = []
    for sol in s_list:
        states = sol.obs_traj
        actions = sol.act_traj
        sol_transitions = convert_states_actions_to_transitions(states, actions)
        transition_list.append(sol_transitions)

    transitions = np.vstack(transition_list)

    likelihoods_dict = get_all_model_likelihoods(models_path, transitions)

    return likelihoods_dict

def evaluate_likelihood_for_slist(s_list, dynamics_model):
    """
    Evaluate the likelihood of observing the transitions from the s_list species members, for some model.
    Use this to check if still in same environment.

    Returns a float containing the mean (across transitions) sum (across
    next_state dimensions) of log likelihoods (adj to ignore -inf), averaged across ensemble members (i.e. 4).

    Use it to attribute datapoints to models.
    """
    transition_list = []
    for sol in s_list:
        states = sol.obs_traj
        actions = sol.act_traj
        sol_transitions = convert_states_actions_to_transitions(states, actions)
        transition_list.append(sol_transitions)

    transitions = np.vstack(transition_list)

    likelihood = evaluate_transition_likelihood(transitions, -1, dynamics_model, True)

    return likelihood.mean()

def make_random_int_list(list_length, num_envs, initialise=False):
    """
    Function to generate a random list of integers, used to later determine which environment is chosen.
    list_length: the length of the desired list, ie the number of environment changes
    num_envs: the number of environments we want to test
    initialise: if True, then the list will start with the environments in order, and random integers after
                This is useful to ensure that all envs are initialised and to keep the envs in order when we later
                check the list vs the list of identified environments in experiment 1.
    """
    if initialise is False:
        random_list = np.random.randint(num_envs, size=list_length).tolist()
        # random_list[1] = random_list[0]
        return random_list
    else:
        random_list = np.random.randint(num_envs, size=list_length - num_envs).tolist()
        starter = [i for i in range(num_envs)]
        return starter + random_list

def switch_env(env_id):
    if env_id == 0:
        shutil.copy2('src/envs/hexapod_dart/robot_model/alternative_models/hexapod_06791_0_0_0.urdf',
                     'src/envs/hexapod_dart/robot_model/hexapod_v2.urdf')
        shutil.copy2('src/envs/hexapod_dart/alternative_envs/even_floor.txt',
                     'src/envs/hexapod_dart/floor.txt')
        # shutil.copy2('src/envs/hexapod_dart/alternative_envs/hexapod_env_even.py',
        #              'src/envs/hexapod_dart/hexapod_env.py')
    elif env_id == 1:
        shutil.copy2('src/envs/hexapod_dart/robot_model/alternative_models/hexapod_10_-02_02_-03.urdf',
                     'src/envs/hexapod_dart/robot_model/hexapod_v2.urdf')
        shutil.copy2('src/envs/hexapod_dart/alternative_envs/slanted_floor_2.txt',
                     'src/envs/hexapod_dart/floor.txt')
        # shutil.copy2('src/envs/hexapod_dart/alternative_envs/hexapod_env_slanted_2.py',
        #              'src/envs/hexapod_dart/hexapod_env.py')
    elif env_id == 2:
        shutil.copy2('src/envs/hexapod_dart/robot_model/alternative_models/hexapod_06791_0_0_0.urdf',
                     'src/envs/hexapod_dart/robot_model/hexapod_v2.urdf')
        shutil.copy2('src/envs/hexapod_dart/alternative_envs/slanted_floor.txt',
                     'src/envs/hexapod_dart/floor.txt')
        # shutil.copy2('src/envs/hexapod_dart/alternative_envs/hexapod_env_slanted.py',
        #              'src/envs/hexapod_dart/hexapod_env.py')

    return

def get_strict_score(env_list, estimate):
    """
    Retrieves the mapping from identified env to dict, and whether the identified envs are correct.
    """
    map_dict = {}

    # Get the correct mapping
    for i in range(len(env_list)):
        real_env = env_list[i]
        est_env = estimate[i]
        if real_env not in map_dict.values():  # Check the env is not already mapped to
            map_dict.setdefault(est_env,
                                real_env)  # Check we are not overwriting an estimate -> env mapping where an estimate value has already been mapped

    # print(map_dict)
    scores = []

    for i in range(len(env_list)):
        if estimate[i] in map_dict.keys() and env_list[i] == map_dict[estimate[i]]:
            scores.append(1)
        else:
            scores.append(0)

    return map_dict, scores

def gen_random_sequence(length):
    """
  Generates a random sequence of environment estimates, that conforms to
  environments being built sequentially
  """
    sequence_list = []
    for i in range(length):
        if i == 0:
            sequence_list.append(0)
        else:
            sequence_list.append(np.random.randint(low=0, high=len(set(sequence_list)) + 1))
    return sequence_list

def random_strict_score():
    num_correct = []
    for i in range(100000):
        env_list = make_random_int_list(6, 3)
        visited = gen_random_sequence(6)
        corrects = 0
        for num in range(1, len(env_list)):
            if env_list[num] == visited[num]:
                corrects += 1
        num_correct.append(corrects)
    print('Mean correct (random)', np.mean(num_correct), '{:.1%}'.format(np.mean(num_correct) / (len(env_list) - 1)))
    print('Median correct (random)', np.median(num_correct),
          '{:.1%}'.format(np.median(num_correct) / (len(env_list) - 1)))
    print('25th percentile (random)', np.percentile(num_correct, 25),
          '{:.1%}'.format(np.percentile(num_correct, 25) / (len(env_list) - 1)))
    print('75th percentile (random)', np.percentile(num_correct, 75),
          '{:.1%}'.format(np.percentile(num_correct, 75) / (len(env_list) - 1)))

def make_switching_int_list(list_length, num_envs):
    """
    Make int list where next number is always different from previous number, ie always switching
    """
    random_list = np.random.randint(num_envs, size=1).tolist() # Generate first entry
    for i in range(1, list_length):
      choices = [k for k in range(num_envs)]
      choices.remove(random_list[i-1])
      random_list.append(int(np.random.choice(choices,1)))
    return random_list


"""
    1st: sort
    - pop the minimum tokens to get score
    - pop the maximum tokens to get power
    - since tokens can be used once, we must pass through the max score along the way

    Buy the cheapests and sell the most expensives

    Time    O(NlogN)
    Space   O(N)
    52 ms, faster than 81.25%
"""

class Solution:
    def bagOfTokensScore(self, tokens: List[int], P: int) -> int:
        res = 0
        score = 0
        arr = sorted(tokens)
        while len(arr) > 0:
            if arr[0] <= P:
                score += 1
                P -= arr.pop(0)
            else:
                score -= 1
                P += arr.pop()
            res = max(res, score)
        return res


#!/usr/bin/env python3

"""
    Converts your input into celsius or fahrenheit. It only accepts values
    between 0 and 250.

    It uses these formulas: c = (f - 32) * 5 / 9
                           f = (c * 9 / 5) + 32
"""

import tkinter as tk

__program_name__ = "Temperature Converter"
__author__ = "Alex Ocegueda"
__version__ = "2.0"
__github__ = "https://github.com/AlexOcegueda/Python_Assignments/temp_calc"

def destroy_label(label):
    label.destroy()

# Only returns true if user enters numbers in the range of 0 - 250
def get_valid_range(root, temperature_entry):
    if 0 < float(temperature_entry.get()) < 250:
        return True
    else:
        error_message = tk.Label(root, text='Limit 0 - 250')
        error_message.place(relx=.3, rely=.7)
        root.after(2500, destroy_label, error_message)

# Only returns true if the user entered a string with NO letters or symbols
def get_valid_float(root, temperature_entry):
    try:
        float(temperature_entry.get())
        return True

    except ValueError:
        error_message = tk.Label(root, text="Must Enter a Number!")
        error_message.place(relx=.25, rely=.7)
        root.after(2500, destroy_label, error_message)

# converts celsius to fahrenheit
def convert_to_fahrenheit(root, temperature_entry):
    if get_valid_float(root, temperature_entry):

        if get_valid_range(root, temperature_entry):
            # this is the fahrenheit formula
            f = (float(temperature_entry.get()) * 9 / 5) + 32

            # Displays conversion rounded to 1 decimal place
            output = f'Your F temp is {round(f, 1)}'
            f_output_label = tk.Label(root, text=output)
            f_output_label.place(relx=.25, rely=.6)
            root.after(3000, destroy_label, f_output_label)

# converts fahrenheit to Celsius
def convert_to_celsius(root, temperature_entry):
    if get_valid_float(root, temperature_entry):

        if get_valid_range(root, temperature_entry):
            # this is the fahrenheit formula
            c = (float(temperature_entry.get()) * 5 / 9) + 32

            # Displays conversion rounded to 1 decimal place
            output = f'Your C temp is {round(c, 1)}'

            c_output_label = tk.Label(root, text=output)
            c_output_label.place(relx=.25, rely=.6)
            root.after(3000, destroy_label, c_output_label)

def display_title(root):
    title_font = ("Comic Sans MS", 23, "bold")

    title_label = tk.Label(root, text='Temperature Converter')
    title_label.configure(font=title_font)
    title_label.place(relx=.03, rely=.1)

# displays and returns the user's input
def display_temperature_input(root):
    # Label and button to take input to convert
    temperature_label = tk.Label(root, text="Enter Temperature:", )
    temperature_label.place(relx=.1, rely=.3)
    temperature_entry = tk.Entry(root, width=3)
    temperature_entry.place(relx=.7, rely=.3)
    return temperature_entry

def display_fahrenheit_button(root, user_input):
    fahrenheit_label = tk.Button(root, text="C to F", bg='red', fg='white',
                                 command=lambda: convert_to_fahrenheit(root, user_input))
    fahrenheit_label.place(relx=.2, rely=.4)

def display_celsius_button(root, user_input):
    celsius_label = tk.Button(root, text="F to C", bg='blue', fg='white',
                              command=lambda: convert_to_celsius(root, user_input))
    celsius_label.place(relx=.6, rely=.4)

def main():
    root = tk.Tk()
    root.title("Temperature Converter")
    root.geometry("300x250")
    display_title(root)

    # displays temperature input for users and assigns it
    user_input = display_temperature_input(root)

    # Button which converts celsius input into fahrenheit when clicked
    display_fahrenheit_button(root, user_input)

    # Button which converts fahrenheit input into celsius when clicked
    display_celsius_button(root, user_input)

    root.mainloop()

if __name__ == '__main__':
    main()


"""
This implementation of DeepLog is based on the open-source code at
https://github.com/wuyifan18/DeepLog
"""
import time
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import TensorDataset, DataLoader
import torch.optim as optim
import numpy as np

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Hyperparameters
num_classes = 28 # Fixed for this demo
window_size = 10 # Fixed for this demo
num_layers = 2
hidden_size = 64
num_epochs = 300
batch_size = 2048
num_candidates = 9

class LSTM_onehot(nn.Module):
    def __init__(self, hidden_size, num_layers, num_keys):
        super(LSTM_onehot, self).__init__()
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.lstm = nn.LSTM(num_keys, hidden_size, num_layers, batch_first=True)
        self.fc = nn.Linear(hidden_size, num_keys)

    def forward(self, x):
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
        out, _ = self.lstm(x, (h0, c0))
        out = self.fc(out[:, -1, :])
        return out

def train_deeplog(input_seq, output_label):
    seq_dataset = TensorDataset(torch.tensor(input_seq, dtype=torch.long), torch.tensor(output_label))
    dataloader = DataLoader(seq_dataset, batch_size=batch_size, shuffle=True, pin_memory=True)
    model = LSTM_onehot( hidden_size, num_layers, num_classes).to(device)
    # Loss and optimizer
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters())

    # Train the model
    start_time = time.time()
    total_step = len(dataloader)
    for epoch in range(num_epochs):  # Loop over the dataset multiple times
        train_loss = 0
        for step, (seq, label) in enumerate(dataloader):
            seq = seq.clone().detach().view(-1, window_size).to(device)
            seq = F.one_hot(seq,num_classes=num_classes).float()
            output = model(seq)

            loss = criterion(output, label.to(device))
            # Backward and optimize
            optimizer.zero_grad()
            loss.backward()
            train_loss += loss.item()
            optimizer.step()
        print('Epoch [{}/{}], train_loss: {:.4f}'.format(epoch + 1, num_epochs, train_loss / total_step))

    elapsed_time = time.time() - start_time
    print('elapsed_time: {:.3f}s'.format(elapsed_time))

    return model

def test_deeplog(model, test_normal_loader, test_abnormal_loader):
    model.eval()
    TP = 0
    FP = 0
    # Test the model
    start_time = time.time()
    with torch.no_grad():
        for line in test_normal_loader:
            for i in range(len(line) - window_size):
                seq = line[i:i + window_size]
                label = line[i + window_size]
                seq = torch.tensor(seq, dtype=torch.long).view(-1, window_size).to(device)
                seq = F.one_hot(seq,num_classes=num_classes).float()
                label = torch.tensor(label).view(-1).to(device)
                output = model(seq)
                predicted = torch.argsort(output, 1)[0][-num_candidates:]
                if label not in predicted:
                    FP += 1
                    break

    with torch.no_grad():
        for line in test_abnormal_loader:
            for i in range(len(line) - window_size):
                seq = line[i:i + window_size]
                label = line[i + window_size]
                if label == -1:
                    TP += 1
                    break
                seq = torch.tensor(seq, dtype=torch.long).view(-1, window_size).to(device)
                seq = F.one_hot(seq,num_classes=num_classes).float()
                label = torch.tensor(label).view(-1).to(device)
                output = model(seq)
                predicted = torch.argsort(output, 1)[0][-num_candidates:]
                if label not in predicted:
                    TP += 1
                    break

    elapsed_time = time.time() - start_time
    print('elapsed_time: {:.3f}s'.format(elapsed_time))
    # Compute precision, recall and F1-measure
    FN = len(test_abnormal_loader) - TP
    P = 100 * TP / (TP + FP)
    R = 100 * TP / (TP + FN)
    F1 = 2 * P * R / (P + R)
    print('false positive (FP): {}, false negative (FN): {}, Precision: {:.3f}%, Recall: {:.3f}%, F1-measure: {:.3f}%'.format(FP, FN, P, R, F1))
    print('Finished Predicting')


from pathlib import Path
import rosbag
import numpy as np
import matplotlib.pyplot as plt
import argparse

from rospy import Duration

def plot(bag_file: Path):
    # read from bag file
    bag = rosbag.Bag(str(bag_file))
    altitudes = np.zeros((0, 2))
    thrusts = np.zeros((0, 2))
    alt_targets = np.zeros((0, 2))

    time_offset = Duration(secs=0)

    csv_text = ["", "", ""]

    for topic, msg, t in bag.read_messages():
        duration = (t - time_offset).to_sec()
        if topic == "/pid_controller/in":
            altitudes = np.append(altitudes, np.array([[duration, msg.data]]), axis=0)
            csv_text[0] += f"{duration},{msg.data}\n"
        if topic == "/pid_controller/out":
            thrusts = np.append(thrusts, np.array([[duration, msg.data]]), axis=0)
            csv_text[1] += f"{duration},{msg.data}\n"
        if topic == "/normalized_rc/in":
            alt_targets = np.append(
                alt_targets, np.array([[duration, msg.channel_states[9].value * 1.5]]), axis=0
            )
            csv_text[2] += f"{duration},{msg.channel_states[9].value * 1.5}\n"

    with open(f"result_{bag_file.name}_0.csv", "w") as f:
        f.write(csv_text[0])
    with open(f"result_{bag_file.name}_1.csv", "w") as f:
        f.write(csv_text[1])
    with open(f"result_{bag_file.name}_2.csv", "w") as f:
        f.write(csv_text[2])

    # plot
    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    ax2 = ax1.twinx()

    ax1.grid(True)
    ax2.grid(False)
    ax1.set_axisbelow(True)

    ax1.plot(altitudes[:, 0], altitudes[:, 1], label="Estimated altitude", color="blue")
    ax2.plot(thrusts[:, 0], thrusts[:, 1], label="Thrust", color="red")
    ax1.plot(alt_targets[:, 0], alt_targets[:, 1], label="Target altitude", color="black")

    handler1, label1 = ax1.get_legend_handles_labels()
    handler2, label2 = ax2.get_legend_handles_labels()
    ax1.legend(handler1 + handler2, label1 + label2, borderaxespad=0.)

    plt.show()

    bag.close()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("bag_file_path", type=Path)

    args = parser.parse_args()
    plot(args.bag_file_path)


"""
    https://leetcode.com/discuss/interview-question/551052/Facebook-or-Phone-or-Enterprise-Engineer-or-Addition-of-String-Numbers

    Problem: Given 2 strings str1 and str2, which represent numbers in string, perform addition of the numbers and return the result as a string.

    Example 1: str1 = "123.52" and str2 = "11.2", output should be "134.72"
    Example 2: str1 = "110.75" and str2 = "9", output should be "119.75"

    Constraints: You may not convert entire string to integer directly. Strings may be null and will always have values >= 0.0
"""
def addFloatStrings(s1, s2):
    arr1 = s1.split('.')
    arr2 = s2.split('.')

    s1Int, s1Deci = '0', '0'
    s2Int, s2Deci = '0', '0'

    if len(arr1) == 2:
        s1Int, s1Deci = arr1[0], arr1[1]
    elif len(arr1) == 1:
        s1Int = arr1[0]

    if len(arr2) == 2:
        s2Int, s2Deci = arr2[0], arr2[1]
    elif len(arr2) == 1:
        s2Int = arr2[0]

    # integer
    integer = add2Integers(s1Int, s2Int)

    # the number after the decimal point
    s1Deci, s2Deci = prcocessDecimals(s1Deci, s2Deci)
    decimal = add2Integers(s1Deci, s2Deci)
    if len(decimal) > max(len(s1Deci), len(s2Deci)):
        integer = add2Integers(integer, '1')
        decimal = decimal[1:]

    return integer + '.' + decimal

def prcocessDecimals(s1, s2):
    maxLen = max(len(s1), len(s2))
    if len(s1) < maxLen:
        return s1 + (maxLen - len(s1)) * '0', s2
    return s1, s2 + (maxLen - len(s2)) * '0'

def add2Integers(num1, num2):
    res = ""
    carry = 0
    i = len(num1) - 1
    j = len(num2) - 1
    while i >= 0 or j >= 0:
        a = 0
        if i >= 0:
            a = int(num1[i])
            i -= 1
        b = 0
        if j >= 0:
            b = int(num2[j])
            j -= 1
        temp = a + b + carry
        d = temp%10
        carry = temp//10
        res = str(d) + res
    if carry > 0:
        res = str(carry) + res
    return res

a = "123.52"
b = "11.2"
print(addFloatStrings(a, b)) # "134.72"

a = "110.75"
b = "9"
print(addFloatStrings(a, b)) # "119.75"

a = "9"
b = "110.75"
print(addFloatStrings(a, b)) # "119.75"

a = '199.999'
b = '199.99'
print(addFloatStrings(a, b)) # 399.989

a = '199.999'
b = '0.001'
print(addFloatStrings(a, b)) # 200.000


import numpy
from nutils import matrix
from . import *

@parametrize
class solver(TestCase):

  ifsupported = parametrize.skip_if(lambda backend, args: not hasattr(matrix, backend), reason='not supported')
  n = 100

  def setUp(self):
    super().setUp()
    self._backend = matrix.backend(self.backend)
    self._backend.__enter__()
    r = numpy.arange(self.n)
    index = numpy.concatenate([[r, r], [r[:-1], r[1:]], [r[1:], r[:-1]]], axis=1)
    data = numpy.hstack([2.] * self.n + [-1.] * (2*self.n-2))
    self.matrix = matrix.assemble(data, index, shape=(self.n, self.n))
    self.exact = 2 * numpy.eye(self.n) - numpy.eye(self.n, self.n, -1) - numpy.eye(self.n, self.n, +1)
    self.tol = self.args.get('atol', 1e-10)

  def tearDown(self):
    self._backend.__exit__(None, None, None)

  @ifsupported
  def test_scalar(self):
    s = matrix.assemble(numpy.array([1.,2.]), index=numpy.empty((0,2), dtype=int), shape=())
    self.assertEqual(s, 3.)

  @ifsupported
  def test_vector(self):
    v = matrix.assemble(numpy.array([1.,2.,3.]), index=numpy.array([[0,2,0]]), shape=(3,))
    self.assertEqual(tuple(v), (4.,0.,2.))

  @ifsupported
  def test_size(self):
    self.assertEqual(self.matrix.size, self.n**2)

  @ifsupported
  def test_export_dense(self):
    array = self.matrix.export('dense')
    self.assertEqual(array.shape, (self.n, self.n))
    numpy.testing.assert_equal(actual=array, desired=self.exact)

  @ifsupported
  def test_export_coo(self):
    data, (row, col) = self.matrix.export('coo')
    numpy.testing.assert_equal(row[0::3], numpy.arange(self.n))
    numpy.testing.assert_equal(col[0::3], numpy.arange(self.n))
    numpy.testing.assert_equal(data[0::3], 2)
    numpy.testing.assert_equal(row[1::3], numpy.arange(self.n-1))
    numpy.testing.assert_equal(col[1::3], numpy.arange(1, self.n))
    numpy.testing.assert_equal(data[1::3], -1)
    numpy.testing.assert_equal(row[2::3], numpy.arange(1, self.n))
    numpy.testing.assert_equal(col[2::3], numpy.arange(self.n-1))
    numpy.testing.assert_equal(data[2::3], -1)

  @ifsupported
  def test_export_csr(self):
    data, indices, indptr = self.matrix.export('csr')
    self.assertEqual(indptr[0], 0)
    self.assertEqual(indptr[-1], len(data))
    numpy.testing.assert_equal(data[0::3], 2)
    numpy.testing.assert_equal(data[1::3], -1)
    numpy.testing.assert_equal(data[2::3], -1)
    numpy.testing.assert_equal(indices[0::3], numpy.arange(self.n))
    numpy.testing.assert_equal(indices[1::3], numpy.arange(1, self.n))
    numpy.testing.assert_equal(indices[2::3], numpy.arange(self.n-1))
    numpy.testing.assert_equal(indptr[1:-1], numpy.arange(2, 3*(self.n-1), 3))

  @ifsupported
  def test_neg(self):
    neg = -self.matrix
    numpy.testing.assert_equal(actual=neg.export('dense'), desired=-self.exact)

  @ifsupported
  def test_mul(self):
    mul = self.matrix * 1.5
    numpy.testing.assert_equal(actual=mul.export('dense'), desired=self.exact * 1.5)

  @ifsupported
  def test_rmul(self):
    rmul = 1.5 * self.matrix
    numpy.testing.assert_equal(actual=rmul.export('dense'), desired=self.exact * 1.5)

  @ifsupported
  def test_div(self):
    div = self.matrix / 1.5
    numpy.testing.assert_equal(actual=div.export('dense'), desired=self.exact / 1.5)

  @ifsupported
  def test_add(self):
    j = self.n//2
    v = 10.
    other = matrix.assemble(numpy.array([v]*self.n), numpy.array([numpy.arange(self.n),[j]*self.n]), shape=(self.n, self.n))
    add = self.matrix + other
    numpy.testing.assert_equal(actual=add.export('dense'), desired=self.exact + numpy.eye(self.n)[j]*v)

  @ifsupported
  def test_sub(self):
    j = self.n//2
    v = 10.
    other = matrix.assemble(numpy.array([v]*self.n), numpy.array([numpy.arange(self.n),[j]*self.n]), shape=(self.n, self.n))
    sub = self.matrix - other
    numpy.testing.assert_equal(actual=sub.export('dense'), desired=self.exact - numpy.eye(self.n)[j]*v)

  @ifsupported
  def test_transpose(self):
    asym = matrix.assemble(numpy.array([1,2,3,4], dtype=float), numpy.array([[0,0,1,1],[0,1,1,2]]), shape=(2,3))
    exact = numpy.array([[1,2,0],[0,3,4]], dtype=float)
    transpose = asym.T
    numpy.testing.assert_equal(actual=transpose.export('dense'), desired=exact.T)

  @ifsupported
  def test_rowsupp(self):
    sparse = matrix.assemble(numpy.array([1e-10,0,1,1]), numpy.array([[0,0,2,2],[0,1,1,2]]), shape=(3,3))
    self.assertEqual(tuple(sparse.rowsupp(tol=1e-5)), (False,False,True))
    self.assertEqual(tuple(sparse.rowsupp(tol=0)), (True,False,True))

  @ifsupported
  def test_solve(self):
    rhs = numpy.arange(self.matrix.shape[0])
    lhs = self.matrix.solve(rhs, **self.args)
    res = numpy.linalg.norm(self.matrix.matvec(lhs) - rhs)
    self.assertLess(res, self.tol)

  @ifsupported
  def test_singular(self):
    singularmatrix = matrix.assemble(numpy.arange(self.n)-self.n//2, numpy.arange(self.n)[numpy.newaxis].repeat(2,0), shape=(self.n, self.n))
    rhs = numpy.ones(self.n)
    with self.assertRaises(matrix.MatrixError):
      lhs = singularmatrix.solve(rhs, **self.args)
      print(lhs)

  @ifsupported
  def test_solve_repeated(self):
    rhs = numpy.arange(self.matrix.shape[0])
    for i in range(3):
      lhs = self.matrix.solve(rhs, **self.args)
      res = numpy.linalg.norm(self.matrix.matvec(lhs) - rhs)
      self.assertLess(res, self.tol)

  @ifsupported
  def test_constraints(self):
    cons = numpy.empty(self.matrix.shape[0])
    cons[:] = numpy.nan
    cons[0] = 10
    cons[-1] = 20
    lhs = self.matrix.solve(constrain=cons, **self.args)
    self.assertEqual(lhs[0], cons[0])
    self.assertEqual(lhs[-1], cons[-1])
    cons[1:-1] = 0
    res = numpy.linalg.norm(self.matrix.matvec(lhs)[1:-1])
    self.assertLess(res, self.tol)

solver(backend='Numpy', args=dict())
solver(backend='Scipy', args=dict())
solver(backend='Scipy', args=dict(atol=1e-5, solver='gmres', restart=100, precon='spilu'))
solver(backend='Scipy', args=dict(atol=1e-5, solver='gmres', precon='splu'))
solver(backend='Scipy', args=dict(atol=1e-5, solver='cg', precon='diag'))
solver(backend='Scipy', args=dict(atol=1e-5, solver='lgmres'))
solver(backend='MKL', args=dict())


class Exploration:

	def __init__(self, playerPositionX=0, playerPositionY=0):
		self.playerPositionX = 0
		self.playerPositionY = 0

	#Moves the player across the overworld, using checkPositionValidity() to ensure they stay in-bounds
	#Was originally made using a case statement in Java
	def moveOverworld(self, direction):
		#North
		if (direction == 'n'):
			#North sends you down and south up. Must be Australia.
			if (checkPositionValidity(self.playerPositionX, self.playerPositionY-1)):
				print("Moving north...")
				self.playerPositionY-=1
			else:
				print("You can't go that far north.")
		#South
		elif (direction == 's'):
			if (checkPositionValidity(self.playerPositionX, self.playerPositionY+1)):
				print("Moving south...")
				self.playerPositionY+=1
			else:
				print("You can't go that far south.")
		#East
		elif (direction == 'e'):
			if (checkPositionValidity(self.playerPositionX+1, self.playerPositionY)):
				print("Moving east...")
				self.playerPositionX+=1
			else:
				print("You can't go that far east.")
		#West
		elif (direction == 'w'):
			if (checkPositionValidity(self.playerPositionX-1, self.playerPositionY)):
				print("Moving west...")
				self.playerPositionX-=1

			else:
				print("You can't go that far west.")
		#This default is an input statement for all other inputs
		else:
			print("You can't go that way." + str(direction) );

		print("You are at location " + str(self.playerPositionX) + "," + str(self.playerPositionY) )


from rest_framework import serializers
from . import models
from albums.models import Album
# from albums.serializers import AlbumSerializer

class PhotoSerializer(serializers.ModelSerializer):
    # albums = AlbumSerializer(many=True)

    class Meta:
        fields = (
            'id',
            'image',
            'filename',
            'caption',
            'local_filename',
            'local_id',
            'local_path',
            'created_at',
            'updated_at',
            'albums',
        )
        model = models.Photo


"""File to define River class."""
__author__: str = "730316038"

from exercises.ex09.fish import Fish
from exercises.ex09.bear import Bear

class River:
    """River."""

    day: int  # what day of the river's lifecycle you are modeling
    bears: list  # list of Bears that stores the river's bear population
    fish: list  # list of Fish that stores the river's fish population

    def __init__(self, num_fish: int, num_bears:int):
        """New River with num_fish Fish and num_bears Bears."""
        self.day: int = 0
        self.fish: list[Fish] = []
        self.bears: list[Bear] = []
        # populate the river with fish and bears
        for x in range(0, num_fish):
            self.fish.append(Fish())
        for x in range(0, num_bears):
            self.bears.append(Bear())

    def check_ages(self):
        """Check ages."""
        self.surviving_fish: list[Fish] = []
        self.surviving_bears: list[Bear] = []

        for fish in self.fish:
            if fish.age <= 3:
                self.surviving_fish.append(fish)

        for bear in self.bears:
            if bear.age <= 5:
                self.surviving_bears.append(bear)

        self.fish = self.surviving_bears
        self.bears = self.surviving_fish
        return None

    def bears_eating(self):
        """For each bear if there are at least 5 fish, the bear will eat 3 fish."""
        for bear in self.bears:
            if len(self.fish) >= 5:
                self.remove_fish(3)
                bear.eat(3)

        return None

    def check_hunger(self):
        """Check hunger score of every bear in the river."""
        self.not_starving_bears: list[Bear] = []
        for bear in self.bears:
            if bear.hunger_score > 0:
                self.not_starving_bears.append(bear)
        return None

    def repopulate_fish(self):
        """Repopulate fish."""
        self.fish = self.fish + ([((len(self.fish))//2)] * 4)
        return None

    def repopulate_bears(self):
        """Repopulate bears."""
        self.bears = self.bears + [((len(self.bears))//2)]
        return None

    def view_river(self) -> None:
        """View the number of days in the river, and number of fish and bears."""
        print(f"~~~ Day {self.day}: ~~~")
        print(f"Fish population: {len(self.fish)}")
        print(f"Bear population: {len(self.bears)}")
        return None

    def one_river_day(self):
        """Simulate one day of life in the river."""
        # Increase day by 1
        self.day += 1
        # Simulate one day for all Bears
        for bear in self.bears:
            bear.one_day()
        # Simulate one day for all Fish
        for fish in self.fish:
            fish.one_day()
        # Simulate Bear's eating
        self.bears_eating()
        # Remove hungry Bear's from River
        self.check_hunger()
        # Remove old Fish and Bear's from River
        self.check_ages()
        # Simulate Fish repopulation
        self.repopulate_fish()
        # Simulate Bear repopulation
        self.repopulate_bears()
        # Visualize River
        self.view_river()

    def one_river_week(self):
        self.one_river_day()
        self.one_river_day()
        self.one_river_day()
        self.one_river_day()
        self.one_river_day()
        self.one_river_day()
        self.one_river_day()
        return None

    def remove_fish (self, amount: int):
        """Remove the amount of Fish from the River."""

        self.remaining_fish: list[Fish] = []

        idx: int = 0

        while idx > amount:
            self.fish.pop(idx)
            idx += 1
        return None


def extract_chain(server_handshake_bytes):
    """
    Extracts the X.509 certificates from the server handshake bytes for use
    when debugging

    :param server_handshake_bytes:
        A byte string of the handshake data received from the server

    :return:
        A list of asn1crypto.x509.Certificate objects
    """

    output = []

    chain_bytes = None

    for record_type, _, record_data in parse_tls_records(server_handshake_bytes):
        if record_type != b'\x16':
            continue
        for message_type, message_data in parse_handshake_messages(record_data):
            if message_type == b'\x0b':
                chain_bytes = message_data
                break
        if chain_bytes:
            break

    if chain_bytes:
        # The first 3 bytes are the cert chain length
        pointer = 3
        while pointer < len(chain_bytes):
            cert_length = int_from_bytes(chain_bytes[pointer:pointer + 3])
            cert_start = pointer + 3
            cert_end = cert_start + cert_length
            pointer = cert_end
            cert_bytes = chain_bytes[cert_start:cert_end]
            output.append(Certificate.load(cert_bytes))

    return output


from __future__ import print_function

import itertools
import numpy as np
import pandas as pd
import sys
from collections import defaultdict
from scipy.stats import fisher_exact
from scipy.stats import chi2_contingency
import pdb
import time

from Bio import motifs

class ScanRNACompete():

    def __init__(self, fn_master_idx, pfm_dir):
        """
        requires inputs from
        http://hugheslab.ccbr.utoronto.ca/supplementary-data/RNAcompete_eukarya/
        namely
            master_idx:
                http://hugheslab.ccbr.utoronto.ca/\
                supplementary-data/RNAcompete_eukarya/\
                SupplementaryData1_RNAcompete_master_file.xlsx
            PFMs:
                http://hugheslab.ccbr.utoronto.ca/\
                supplementary-data/RNAcompete_eukarya/\
                top10align_motifs.tar.gz
        """
        self.master_idx = pd.read_csv(fn_master_idx, header=0, sep="\t")
        self.pfm_dir = pfm_dir
        self.pwms_by_id = {}
        for fn in os.listdir(self.pfm_dir):
            F = open("{path}/{fn}".format(path=self.pfm_dir,fn=fn))
            F.readline()
            self.pwms_by_id[id] = motifs.read(F,'pfm')

    def count_kmers(self, seqs1, seqs2, n_procs = 16):
        """
        pass in two lists of stringsa
        return counts
        """

        self.seqs1 = seqs1
        self.seqs2 = seqs2

        l1 = np.sum([len(s)-self.kmer_len for s in seqs1])
        l2 = np.sum([len(s)-self.kmer_len for s in seqs2])

        s1 = "|".join(seqs1).upper()
        s2 = "|".join(seqs2).upper()

        q_input = mp.JoinableQueue()
        q_output = mp.JoinableQueue()

        n_procs_remain = n_procs
        n_jobs_total = 4**self.kmer_len
        n_jobs_remain = n_jobs_total
        procs = []

        for i in range(n_procs):
            n_proc_jobs = int(math.ceil(n_jobs_remain/float(n_procs_remain)))
            n_procs_remain-=1
            n_jobs_remain-=n_proc_jobs

            p=count_kmers_process()
            p.set_params(i, q_input, q_output, s1, s2, l1, l2, n_proc_jobs)
            p.daemon=True
            p.start()
            print("process %d started"%i, file=sys.stderr)
            procs.append(p)

        curr_count = 0
        for kmer in self.kmer_gen:
            kmer_str = "".join(kmer)
            q_input.put(kmer_str)

        while not q_input.empty():
            time.sleep(10)
            print(q_input.qsize(), n_jobs_total, file=sys.stderr)

        self.kmer_counts = []

        for p in procs:
            print("extracting from queue... ", file=sys.stderr)
            _kmer_counts = q_output.get()
            q_output.task_done()
            self.kmer_counts.extend(_kmer_counts)
            print("done", file=sys.stderr)

    def get_kmer_stats(self, kmer_count):
        kmer = kmer_count['kmer']
        s1_cs = np.array([seq.count(kmer) for seq in self.seqs1])
        s2_cs = np.array([seq.count(kmer) for seq in self.seqs2])

        mu_s1, med_s1, mx_s1 = np.mean(s1_cs), np.median(s1_cs), np.amax(s1_cs)
        mu_s2, med_s2, mx_s2 = np.mean(s2_cs), np.median(s2_cs), np.amax(s1_cs)
        n_s1_gt0 = np.sum(s1_cs>0)
        n_s2_gt0 = np.sum(s2_cs>0)

        return {"mu_s1_count":mu_s1,
                "med_s1_count":med_s1,
                "max_s1_count":mx_s1,
                "n_s1_w_kmer":n_s1_gt0,
                "mu_s2_count":mu_s2,
                "med_s2_count":med_s2,
                "max_s2_count":mx_s2,
                "n_s2_w_kmer":n_s2_gt0}

    def get_significant_kmers(self, fdr = 0.01, Yekuteili=True):
        self.kmer_counts  = sorted(self.kmer_counts, key = lambda x: x['p'])
        m = float(len(self.kmer_counts))
        cm=1
        if Yekuteili:
            """
            correct for non-independence of tests
            """
            cm =  np.sum(1/(np.arange(m)+1))

        outrows = []
        for i, kmer_count in enumerate(self.kmer_counts):
            p = kmer_count['p']
            j=i+1
            if p<=((j/(m*cm))*fdr):
                BHY_sig = True
            else:
                BHY_sig = False

            kmer_stats = self.get_kmer_stats(kmer_count)
            kmer_count.update(kmer_stats)
            kmer_count.update({"BHY-significant":BHY_sig})
            outrows.append(kmer_count)

        return pd.DataFrame(outrows)


from fastapi import FastAPI
from fastapi.responses import JSONResponse
from fastapi.encoders import jsonable_encoder
from datetime import datetime
from eco_explore_api.schemas.responses import HealthCheckResponse, VersionResponse
import eco_explore_api.schemas.response_constants as rcodes

app = FastAPI()

@app.get("/health")
async def health():
    response = HealthCheckResponse(message="Is Health")
    return JSONResponse(status_code=rcodes.OK, content=jsonable_encoder(response))

@app.get("/status")
async def statue():
    time = datetime.now()
    return JSONResponse(
        status_code=rcodes.OK,
        content=jsonable_encoder(
            VersionResponse(version=1.0, detail=(HealthCheckResponse(time=time)))
        ),
    )


import argparse
import pytorch_lightning as pl

from data import SNLIDataModule
from model import NLI
from pytorch_lightning.loggers import TensorBoardLogger
from pytorch_lightning.callbacks import ModelCheckpoint, EarlyStopping

def main(args):
    # Set up the SNLI data module
    dm = SNLIDataModule(batch_size=args.batch_size, data_dir=args.data_dir); dm.setup()

    # Set up the NLI model
    model = NLI(dm.vocab, args.encoder, args.lstm_hidden_dim, args.data_dir)

    # Set up the model checkpointing and logging
    tb_logger = TensorBoardLogger(
        save_dir='./tb_logs',
        name=args.encoder,
        default_hp_metric=False,
    )

    checkpoint_callback = ModelCheckpoint(
        dirpath=f'./pretrained/{args.encoder}/version_{tb_logger.version}',
        filename=f'{args.encoder}' + '-epoch={epoch}',
        monitor='accuracy/validation',
        mode='max',
        save_weights_only=True,
        auto_insert_metric_name=False,
        every_n_epochs=1,
    )

    early_stopping_callback = EarlyStopping(
        monitor='accuracy/validation',
        min_delta=0.01,
        mode='max',
    )

    # Set up the training loop
    trainer = pl.Trainer(
        accelerator='auto',
        callbacks=[checkpoint_callback, early_stopping_callback],
        logger=tb_logger,
        max_epochs=args.num_epochs,
    )

    # Train on SNLI
    trainer.fit(model, dm)

    # Test on SNLI
    trainer.test(model, dm)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('--data_dir', type=str, default='./data',
                        help='Directory to store datasets, vocabulary and embeddings.')

    # model hyperparameters
    parser.add_argument('--encoder', type=str, choices=['AWE', 'LSTM', 'BiLSTM', 'BiLSTM-MaxPool'],
                        help='Sentence encoder to use.')
    parser.add_argument('--lstm_hidden_dim', type=int, default=2048,
                        help='Number of hidden units in the LSTM.')

    # training hyperparameters
    parser.add_argument('--batch_size', type=int, default=64,
                        help='Batch size.')
    parser.add_argument('--num_epochs', type=int, default=20,
                        help='Number of training epochs.')

    args = parser.parse_args()

    main(args)


def sentimentDF(symbol, type='daily', date=None, token='', version=''):
    '''This endpoint provides social sentiment data from StockTwits. Data can be viewed as a daily value, or by minute for a given date.

    https://iexcloud.io/docs/api/#social-sentiment
    Continuous

    Args:
        symbol (string); Ticker to request
        type (string); 'daily' or 'minute'
        date (string); date in YYYYMMDD or datetime
        token (string); Access token
        version (string); API version

    Returns:
        DataFrame: result
    '''
    ret = sentiment(symbol, type, date, token, version)
    if type == 'daiy':
        ret = [ret]
    df = pd.DataFrame(ret)
    _toDatetime(df)
    return df


"""
@brief      test tree node (time=6s)
"""
import sys
import os
import unittest
import re

from pyquickhelper.loghelper.flog import fLOG
from pyquickhelper.filehelper.file_tree_node import FileTreeNode
from pyquickhelper.filehelper.synchelper import synchronize_folder, remove_folder

class TestFileCol (unittest.TestCase):

    def test_synchro(self):
        fLOG(
            __file__,
            self._testMethodName,
            OutputPrint=__name__ == "__main__")

        try:
            import pysvn as skip_
        except ImportError:
            fLOG("pysvn is not available")
            return

        path = os.path.split(__file__)[0]
        p1 = os.path.abspath(os.path.join(path, "..", "ut_loghelper", "data"))
        p2 = os.path.abspath(os.path.join(path, "pyapptemp"))
        if not os.path.exists(p2):
            os.mkdir(p2)
        fLOG("form ", p1)
        fLOG("to   ", p2)
        exp = re.compile("[.]svn")

        def filter(root, path, f, d):
            root = root.lower()
            path = path.lower()
            f = f.lower()
            be = os.path.join(path, f)
            if "build" in be:
                return False
            if exp.search(be):
                return False
            return True

        f1 = p1
        f2 = p2

        fLOG("p1=", p1)
        fLOG("p2=", p2)

        node1 = FileTreeNode(f1, filter=filter, repository=True)
        node2 = FileTreeNode(f2, filter=filter, repository=False)
        fLOG("number of found files (p1)", len(node1), node1.max_date())
        fLOG("number of found files (p2)", len(node2), node2.max_date())

        res = node1.difference(node2, hash_size=1024 ** 2)
        for r in res:
            if r[0] == ">+":
                r[2].copy_to(p2)

        node1 = FileTreeNode(f1, filter=filter, repository=True)
        node2 = FileTreeNode(f2, filter=filter, repository=False)
        fLOG("number of found files (p1)", len(node1), node1.max_date())
        fLOG("number of found files (p2)", len(node2), node2.max_date())
        res = node1.difference(node2, hash_size=1024 ** 2)
        for r in res:
            if r[0] == "==":
                r[3].remove()

    def test_synchro2(self):
        fLOG(
            __file__,
            self._testMethodName,
            OutputPrint=__name__ == "__main__")
        fold = os.path.abspath(os.path.split(__file__)[0])
        data = os.path.join(fold, "data")
        seco = os.path.join(fold, "data", "temp_seco")
        troi = os.path.join(fold, "temp_troi")
        sec2 = os.path.join(troi, "temp_seco")

        stay = os.path.join(sec2, "notfile.txt")
        nocp = os.path.join(seco, "file.txt")

        def filter_copy(file):
            return "temp_seco" not in file
        fLOG(filter_copy(stay), stay)
        assert not filter_copy(stay)

        if os.path.exists(troi):
            remove_folder(troi)

        if not os.path.exists(seco):
            os.mkdir(seco)
        if not os.path.exists(troi):
            os.mkdir(troi)
        if not os.path.exists(sec2):
            os.mkdir(sec2)

        with open(nocp, "w") as f:
            f.write("should not be here")
        with open(stay, "w") as f:
            f.write("should stay")

        synchronize_folder(data, troi, hash_size=0,
                           repo1=True, filter_copy=filter_copy)

        assert os.path.exists(os.path.join(troi, "sub", "filetwo.txt"))
        assert os.path.exists(stay)
        assert not os.path.exists(stay.replace("notfile.txt", "file.txt"))

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


list1 = [1,2,3,4,5]
list2 = ['m','h','a','n']

tuple = (1,'mohan',3,4)

dict = {'J':'java','p':'python'}

#assigning elements to lists

list1.append('numbers')  #addeds the element 'numbers' at the last of the list1
print(list1)

list2.insert(1,'o')
print(list2)

#accessing elements from tuple

print(tuple[1]) #prints mohan as mohan is at index 1

#deleting elements from dictionary

dict['p1'] = 'pearl' # adds this element to the dictionary
print(dict)

del dict['p1'] # deletes the element 'p1':'pearl'
print(dict)

dict.pop('J') # this will diplay the element and deletes the element from the dictionary

dict.clear() # this will clear all the elements but dictionary will be avilable. we can add elements to the dictionary
print(dict)


# Author: Mitchell Fehr
# Date: 10/14/2016
#
# "CompareTheTriplets" Python 3 Solution

#!/bin/python3

import sys

n = int(input().strip())
arr = [int(arr_temp) for arr_temp in input().strip().split(' ')]
m = 0
for i in arr:
    m += i
print(m)


import json

class RPCStub:
    def __getattr__(self, item):
        def format_data(*args, **kwargs):
            d = {'method_name': item,
                 'method_args': args,
                 'method_kwargs': kwargs,
                 }
            self.send(json.dumps(d).encode('utf-8'))
        setattr(self, item, format_data)
        return format_data


import warnings

import numpy as np
from scipy.integrate import IntegrationWarning, quad, quad_vec
from scipy.special import voigt_profile

# Load the C library
import ctypes
from pathlib import Path
# # Commands to manually generate
# gcc -Wall -fPIC -c voigt.c
# gcc -shared -o libvoigt.so voigt.o
dllabspath = Path(__file__).absolute().parent  # Path to libraries directory
try:
    libfile = [str(i) for i in dllabspath.glob('ext_voigtlib.*.so')][0]  # Select first (and only) library
    lib = ctypes.CDLL(libfile)  # Load the library
    lib.func.restype = ctypes.c_double  # Specify the expected result type
    lib.func.argtypes = (ctypes.c_int, ctypes.c_double)  # Specify the type of the input parameters
    cvoigt = lib.func  # Create alias for the specific function used in functions below
    CLIB_INSTALLED = True
except IndexError:  # File does not exist
    CLIB_INSTALLED = False

# Parameters for `voigt_approx_nobg` and other approx. Voigt functions
params = np.array([[-1.2150, -1.3509, -1.2150, -1.3509],
                   [1.2359, 0.3786, -1.2359, -0.3786],
                   [-0.3085, 0.5906, -0.3085, 0.5906],
                   [0.0210, -1.1858, -0.0210, 1.1858]])
sqrt_ln2 = np.sqrt(np.log(2))
sqrt_pi = np.sqrt(np.pi)
A, B, C, D = params

__all__ = ['voigt_integrate', 'voigt_faddeeva', 'voigt_mclean',
           'voigt_nobg', 'voigt', 'double_voigt_nobg', 'double_voigt']

def voigt_integrate(x, s, g, clib=CLIB_INSTALLED, **kwargs):
    """Voigt function implementation (calculated by integrating).

    The default Voigt implementation.

    Parameters
    ----------
    x : numpy.ndarray
        Wavelengths to evaluate Voigt function at.
    s : float
        Sigma (for Gaussian).
    g : float
        Gamma (for Lorentzian).
    clib : bool, optional, default=True
        Whether to use the complied C library or a slower Python version. If using the C library, the accuracy
        of the integration is reduced to give the code a significant speed boost. Python version can be used when
        speed is not a priority. Python version will remove deviations that are sometimes present around the wings
        due to the reduced accuracy. If the C extensions is not installed, will default to false.

    Returns
    -------
    result : numpy.ndarray, shape=`x.shape`
        The value of the Voigt function here.

    Notes
    -----
    More information on the Voigt function can be found here: https://en.wikipedia.org/wiki/Voigt_profile
    """
    # return a * voigt_profile(x - b, s, g)
    warnings.filterwarnings("ignore", category=IntegrationWarning)
    if clib:
        i = [quad(cvoigt, -np.inf, np.inf, args=(v, s, g), epsabs=1.49e-1, epsrel=1.49e-4)[0] for v in x]
    else:
        i = quad_vec(lambda y: np.exp(-y**2 / (2 * s**2)) / (g**2 + (x - y)**2), -np.inf, np.inf)[0]
    const = g / (s * np.sqrt(2 * np.pi**3))
    return const * np.array(i)

def voigt_faddeeva(x, s, g, **kwargs):
    """Voigt function implementation (Faddeeva).

    Parameters
    ----------
    x : numpy.ndarray
        Wavelengths to evaluate Voigt function at.
    s : float
        Sigma (for Gaussian).
    g : float
        Gamma (for Lorentzian).

    Returns
    -------
    result : numpy.ndarray, shape=`x.shape`
        The value of the Voigt function here.
    """
    return voigt_profile(x, s, g)

def voigt_mclean(x, s, g, **kwargs):
    """Voigt function implementation (efficient approximation).

    Not implemented in any models yet as initial tests exhibited slow convergence.

    Parameters
    ----------
    x : numpy.ndarray
        Wavelengths to evaluate Voigt function at.
    s : float
        Sigma (for Gaussian).
    g : float
        Gamma (for Lorentzian).

    Returns
    -------
    result : numpy.ndarray, shape=`x.shape`
        The value of the Voigt function here.

    Notes
    -----
    This algorithm is taken from A. B. McLean et al. [1]_.

    References
    ----------
    .. [1] A. B. McLean, C. E. J. Mitchell and D. M. Swanston, "Implementation of an efficient analytical
      approximation to the Voigt function for photoemission lineshape analysis," Journal of Electron Spectroscopy and
      Related Phenomena, vol. 69, pp. 125-132, 1994. https://doi.org/10.1016/0368-2048(94)02189-7
    """
    fwhm_g = 2 * s * np.sqrt(2 * np.log(2))
    fwhm_l = 2 * g
    xx = x * 2 * sqrt_ln2 / fwhm_g
    xx = xx[..., np.newaxis]
    yy = fwhm_l * sqrt_ln2 / fwhm_g
    yy = yy[..., np.newaxis]
    v = np.sum((C * (yy - A) + D * (xx - B)) / ((yy - A) ** 2 + (xx - B) ** 2), axis=-1)
    return fwhm_l * sqrt_pi / fwhm_g * v

def voigt_nobg(x, a, b, s, g, impl=voigt_faddeeva, **kwargs):
    """Voigt function with no background (Base Voigt function).

    This is the base of all the other Voigt functions.

    Parameters
    ----------
    ${SINGLE_VOIGT}

    ${SEE_ALSO}
    """
    return a * impl(x - b, s, g, **kwargs)

def voigt(x, a, b, s, g, d, **kwargs):
    """Voigt function with background.

    Parameters
    ----------
    ${SINGLE_VOIGT}
    ${BACKGROUND}

    ${SEE_ALSO}
    """
    return voigt_nobg(x, a, b, s, g, **kwargs) + d

def double_voigt_nobg(x, a1, b1, s1, g1, a2, b2, s2, g2, **kwargs):
    """Double Voigt function with no background.

    Parameters
    ----------
    ${DOUBLE_VOIGT}

    ${SEE_ALSO}
    """
    return voigt_nobg(x, a1, b1, s1, g1, **kwargs) + voigt_nobg(x, a2, b2, s2, g2, **kwargs)

def double_voigt(x, a1, b1, s1, g1, a2, b2, s2, g2, d, **kwargs):
    """Double Voigt function with background.

    Parameters
    ----------
    ${DOUBLE_VOIGT}
    ${BACKGROUND}

    ${SEE_ALSO}
    """
    return double_voigt_nobg(x, a1, b1, s1, g1, a2, b2, s2, g2, **kwargs) + d

# Define "Parameters" options
__input_x = """
    x : numpy.ndarray
        Wavelengths to evaluate Voigt function at."""
__single_voigt = __input_x + """
    a : float
        Amplitude of the Lorentzian.
    b : float
        Central line core.
    s : float
        Sigma (for Gaussian).
    g : float
        Gamma (for Lorentzian)."""
__double_voigt = __input_x + """
    a1 : float
        Amplitude of 1st Voigt function.
    b1 : float
        Central line core of 1st Voigt function.
    s1 : float
        Sigma (for Gaussian) of 1st Voigt function.
    g1 : float
        Gamma (for Lorentzian) of 1st Voigt function.
    a2 : float
        Amplitude of 2nd Voigt function.
    b2 : float
        Central line core of 2nd Voigt function.
    s2 : float
        Sigma (for Gaussian) of 2nd Voigt function.
    g2 : float
        Gamma (for Lorentzian) of 2nd Voigt function."""
__background = """
    d : float
        Background."""

def __see_also(func):
    """Return the "See Also" section with the current function removed."""
    see_also = filter(lambda x: f" {func.__name__} " not in x, [
        '    voigt_nobg : Base Voigt function with no background.',
        '    voigt : Voigt function with background added.',
        '    double_voigt_nobg : Two Voigt functions added together.',
        '    double_voigt : Two Voigt function and a background added together.',
    ])
    return """
    Returns
    -------
    result : numpy.ndarray, shape=`x.shape`
        The value of the Voigt function here.

    See Also
    --------
    """ + "\n".join(see_also).lstrip()

for f in [voigt_nobg, voigt, double_voigt_nobg, double_voigt]:
    f.__doc__ = f.__doc__.replace('${SINGLE_VOIGT}', __single_voigt.lstrip())
    f.__doc__ = f.__doc__.replace('${DOUBLE_VOIGT}', __double_voigt.lstrip())
    f.__doc__ = f.__doc__.replace('${BACKGROUND}', __background.lstrip())
    f.__doc__ = f.__doc__.replace('${SEE_ALSO}', __see_also(f).lstrip())

del __input_x
del __single_voigt
del __double_voigt
del __background
del __see_also

def voigt_approx_nobg(*args, **kwargs):
    # For backwards compatibility
    return voigt_nobg(*args, impl=voigt_mclean, **kwargs)

def voigt_approx(*args, **kwargs):
    # For backwards compatibility
    return voigt(*args, impl=voigt_mclean, **kwargs)

def double_voigt_approx_nobg(*args, **kwargs):
    # For backwards compatibility
    return double_voigt_nobg(*args, impl=voigt_mclean, **kwargs)

def double_voigt_approx(*args, **kwargs):
    # For backwards compatibility
    return double_voigt(*args, impl=voigt_mclean, **kwargs)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Jan 26 21:20:41 2022

@author: paul
"""

import matplotlib.pyplot as plt
import sys, os
import statistics as stats
import numpy as np

name = sys.argv[1]

#name="Paul Astudillo"

arch ="ip.txt"
file= open(arch)
datos = file.readlines()
flag=0
for i in datos:
    encontrar=i.rfind("tun0:")
    if encontrar>=0:
        flag=1

    if flag==1:
        encontrar2=i.find("inet")
        if encontrar2>=0:
            final=i.find("netmask")
            ip=i[encontrar2+5:final-2]
            flag=0

file = open("name_ip.txt", "w")
file.write(str(name)+" "+str(ip))
file.close()

print(str(ip))


def snapengage(parser, token):
    """
    SnapEngage set-up template tag.

    Renders Javascript code to set-up SnapEngage chat.  You must supply
    your widget ID in the ``SNAPENGAGE_WIDGET_ID`` setting.
    """
    bits = token.split_contents()
    if len(bits) > 1:
        raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
    return SnapEngageNode()


# -- coding: utf-8 -*-

r"""
Copyright (c) 2023-present, Dankook Univ, South Korea
Allright Reserved.
Author : Sooin Kim
"""

import os
import numpy as np
import warnings
import random
warnings.filterwarnings('ignore')

import torch
import torch.nn as nn
import torch.distributed as dist
import torch.backends.cudnn as cudnn
import torch.multiprocessing as mp

from torch.nn.parallel import DistributedDataParallel as DDP
from torch.utils.data import DataLoader
from torch.utils.data.distributed import DistributedSampler
from torch.optim import Adam, lr_scheduler

from torchvision.transforms import Compose, RandomHorizontalFlip, RandomVerticalFlip, Resize

from core.model import UNet
from core.criterion.Loss import DiceLoss
from utils.data_loader import ImageDataset
from utils.train_model import train_one_epoch, evaluate
from utils.data_transform import SelectRotation
from interface.argparse import get_args

def main():

    args = get_args()

    if args.seed is not None:
        random.seed(args.seed)
        torch.manual_seed(args.seed)
        cudnn.deterministic = True
        warnings.warn(
            f'[Info] You have chosen specific seed : {args.seed}'
            )

    if args.gpu is not None:
        warnings.warn(
            f'[Info] You have chosen specific GPU. This will be completely disable data parallelism.'
        )

    if args.dist_url == 'env://' and args.world_size == -1:
        args.world_size = int(os.environ["WORLD_SIZE"])

    args.distributed = args.world_size > 1 or args.multiprocessing_distributed

    ngpus_per_node = torch.cuda.device_count()

    if args.multiprocessing_distributed:

        args.world_size = ngpus_per_node * args.world_size

        mp.spawn(
            main_worker,
            nprocs=ngpus_per_node,
            args=(ngpus_per_node, args)
        )
    else:

        main_worker(
            args.gpu,
            ngpus_per_node,
            args
        )

def main_worker(
        gpu: object,
        ngpus_per_node: int,
        args: object
):
    args.gpu = gpu

    if args.distributed:

        if args.dist_url == "env://" and args.rank == -1:
            args.rank = int(os.environ["RANK"])

        if args.multiprocessing_distributed:
            args.rank = args.rank * ngpus_per_node + gpu

        print(
            f'\n[GPU INFO] dist_backend : {args.dist_backend}'
            )
        print(
            f'[GPU INFO] world_size : {args.world_size}'
            )
        print(
            f'[GPU INFO] rank : {args.rank}'
        )

        dist.init_process_group(
            backend=args.dist_backend,
            init_method=args.dist_url,
            world_size=args.world_size,
            rank=args.rank
        )

    #Set image transformer
    transform = Compose([
        SelectRotation(
            angles=[-90, 90]
        ),
        RandomHorizontalFlip(),
        RandomVerticalFlip(),
        Resize((256,256))

    ])

    #Preparing and loading data
    train_dataset=ImageDataset(
        data_path=args.img_path,
        transform=None,
        scaling=True,
        mode='train'
    )

    train_sampler = DistributedSampler(train_dataset)

    #Load data with cpu
    train_data = DataLoader(
        train_dataset,
        sampler=train_sampler,
        batch_size=args.batch_size,
        collate_fn=None,
        shuffle=False,
        num_workers=args.num_workers
    )

    #Preparing and loading data
    validation_dataset=ImageDataset(
        data_path=args.img_path,
        transform=None,
        scaling=True,
        mode='test'
    )

    #Load data with cpu
    validation_sampler = DistributedSampler(validation_dataset)

    validation_data = DataLoader(
        validation_dataset,
        sampler=validation_sampler,
        batch_size=1,
        collate_fn=None,
        shuffle=False,
        num_workers=args.num_workers
    )

    #Load model and set it into GPUs
    machine = UNet(
        n_channels=args.n_channels,
        n_classes=args.n_classes,
        bilinear=False
    )

    if not torch.cuda.is_available():
        print(
            f'[INFO] Using CPU'
            )

    elif args.distributed:
        if args.gpu is not None:

            torch.cuda.set_device(args.gpu)
            machine.cuda(args.gpu)

            args.batch_size = int(args.batch_size / ngpus_per_node)
            args.workers = int((args.workers + ngpus_per_node -1) / ngpus_per_node)

            machine = DDP(
                machine,
                device_ids=[args.gpu],
                find_unused_parameters=False
            )

            if args.gpu == 0:
                print(
                    f'\n[INFO] Using DDP with sepcific GPUs '
                )

        else:

            machine.cuda()

            machine = DDP(machine)
            print(
                f'\n[INFO] Using DDP with single GPUs'
            )

    else:
        machine = torch.nn.DataParallel(machine).cuda()

    # set optimizer, scheduler, device
    optimizer = Adam(
        machine.parameters(),
        lr=args.learning_rate
    )
    scheduler = lr_scheduler.CosineAnnealingLR(
        optimizer,
        T_max=100
    )
    device = args.gpu
    criterion = nn.CrossEntropyLoss()
    #criterion = DiceLoss()

    for epoch in range(1, args.epochs):

        if args.gpu is not None:
            train_sampler.set_epoch(epoch)
            validation_sampler.set_epoch(epoch)

        train_one_epoch(
            model=machine,
            data_loader=train_data,
            optimizer=optimizer,
            scheduler=scheduler,
            loss_fn=criterion,
            epoch=epoch,
            args=args,
            log=None,
            device=device
        )

        evaluate(
            model=machine,
            data_loader=validation_data, #TODO have to load test_data
            loss_fn=criterion,
            epoch=epoch,
            device=device,
            args=args
        )

if __name__ == '__main__':

    main()


import os
import io
import json
import sys
import logging
import time

from collections import Counter
import string
import re

import tensorflow as tf
import numpy as np

from qa_model import QAModel
from data_batcher import get_batch_generator

def normalize_answer(s):
    """Lower text and remove punctuation, articles and extra whitespace."""
    def remove_articles(text):
        return re.sub(r'\b(a|an|the)\b', ' ', text)

    def white_space_fix(text):
        return ' '.join(text.split())

    def remove_punc(text):
        exclude = set(string.punctuation)
        return ''.join(ch for ch in text if ch not in exclude)

    def lower(text):
        return text.lower()

    return white_space_fix(remove_articles(remove_punc(lower(s))))

def exact_match_score(prediction, ground_truth):
    return (normalize_answer(prediction) == normalize_answer(ground_truth))

def f1_score(prediction, ground_truth):
    prediction_tokens = normalize_answer(prediction).split()
    ground_truth_tokens = normalize_answer(ground_truth).split()
    common = Counter(prediction_tokens) & Counter(ground_truth_tokens)
    num_same = sum(common.values())
    if num_same == 0:
        return 0
    precision = 1.0 * num_same / len(prediction_tokens)
    recall = 1.0 * num_same / len(ground_truth_tokens)
    f1 = (2 * precision * recall) / (precision + recall)
    return f1

def evaluate(model, word2id, FLAGS, dev_context_path, dev_qn_path, dev_ans_path):
    logging.info("Calculating F1/EM for all examples in dev set...")

    f1_total = 0.
    em_total = 0.
    example_num = 0

    tic = time.time()

    for batch in get_batch_generator(word2id, dev_context_path, dev_qn_path, dev_ans_path, FLAGS.batch_size, context_len=FLAGS.context_len, question_len=FLAGS.question_len, discard_long=False):
        # print(type(batch))
        prob_start, prob_end = model.predict([batch.context_ids, batch.context_mask, batch.qn_ids, batch.qn_mask])

        start_pos = np.argmax(prob_start, axis=1)
        end_pos = np.argmax(prob_end, axis=1)

        pred_start_pos = start_pos.tolist()
        pred_end_pos = end_pos.tolist()

        for ex_idx, (pred_ans_start, pred_ans_end, true_ans_tokens) in enumerate(zip(pred_start_pos, pred_end_pos, batch.ans_tokens)):
            example_num += 1

            # Get the predicted answer
            # Important: batch.context_tokens contains the original words (no UNKs)
            # You need to use the original no-UNK version when measuring F1/EM
            pred_ans_tokens = batch.context_tokens[ex_idx][pred_ans_start : pred_ans_end + 1]
            pred_answer = " ".join(pred_ans_tokens)

            # Get true answer (no UNKs)
            true_answer = " ".join(true_ans_tokens)

            # Calc F1/EM
            f1 = f1_score(pred_answer, true_answer)
            em = exact_match_score(pred_answer, true_answer)
            f1_total += f1
            em_total += em

            # print(f1, em, example_num)

    f1_total /= example_num
    em_total /= example_num

    toc = time.time()
    print("Calculating F1/EM for %i examples in %s set took %.2f seconds" % (example_num, "dev", toc-tic))

    return f1_total, em_total


from locust import task
from locust_files.base import KelvinClient

URL_NAME = f"{KelvinClient.base_path}/users/"

class GetUser(KelvinClient):
    @task
    def get_user(self):
        school = self.test_data.random_school()
        username = self.test_data.random_user(school)
        with self.client.rename_request(URL_NAME):
            url = f"{self.base_url}/users/{username}"
            self.request("get", url, response_codes=[200])