import asyncio
import json
import time
import re
from send_message import *

def build(message,client):
	asyncio.create_task(_build(message,client))

async def _build(message,client):
	try:
		file_name = message[1]
	except IndexError:
		file_name = "G:\\python\\projects\\minecraft\\function\\files\\fun1.mcfunction"

	fps = "50"
	try:
		for each in message[2:]:
			each = each.split(":")
			if each[0] == "":
				pass
			elif each[0] == "t":
				fps = each[1]
			else:
				await client.send(command(alert("错误的参数:"+each[0])))
				await client.recv()
				await client.recv()
	except IndexError:
		fps = "50"

	try:
		fps = float(fps)
	except:
		await client.send(command(alert("错误的值:"+fps)))
		await client.recv()
		await client.recv()
		return

	try:
		open(file_name,"r").close()
	except:
		await client.send(command(alert("您的文件路径输入有误,无法找到您的文件!")))
		await client.recv()
		await client.recv()
		return

	with open(file_name,"r") as f:
		lines = f.readlines()

		# 获取玩家坐标
		await client.send(command("tp @s ~~~"))
		result = json.loads(await client.recv())
		try:
			player_pos = result["body"]["destination"]
		except:
			await client.send(command(alert("请稍等一会，您的世界处理不了这么多方块~~~")))
			return
		for each in player_pos:
			player_pos[each] = int(player_pos[each])

		await client.send(command(status("正在将相对坐标转换为绝对坐标...")))
		for i in range(len(lines)):
			time = 0		# 用来计算坐标是 x , y 还是 z
			cmd = lines[i].split(" ")
			# cmd = [setblock,~-8,~-32,~-4,stained_hardened_clay,10]
			for each in cmd:
				# each = "~-8"
				if "~" in each:
					# pos = ["-8"]
					pos = each.split("~")
					pos.pop(0)
					for j in pos:
						# i = -8
						try:
							j = int(j)
						except:
							j = 0
						# x 轴
						if time == 0 or time == 3:
							j = player_pos["x"] + j
							pos
						if time == 1 or time == 4:
							j = player_pos["y"] + j
						if time == 2 or time == 5:
							j = player_pos["z"] + j

						cmd_span = re.search(r"~-*\d*",lines[i]).span()
						cmd_pos = lines[i][cmd_span[0]:cmd_span[1]]
						lines[i] = lines[i].replace(cmd_pos,str(j)+" ",1)
						time += 1
		await client.send(command(status("转换完毕! 正在导入建筑... 期间您可以自由活动")))

		while True:
			recvs = []
			most = False			# 指令未被拒绝
			for each in lines:
				await client.send(command(each))
				print(await client.recv())
				"""
				recvs.append(await client.recv(),each)
	# 			await asyncio.sleep(fps/1000)
			# 检查是否有遗漏
			for each in recvs:
				if "请求" in each[0]:
					await client.send(command(each[1]))
					most = True
			if not most:
				break
			"""
			break

		await client.send(command((ok("导入完毕!"))))


import plotting
import matplotlib.pyplot as plt
import numpy as np
import json

from PATHS import WORKINGDATAPATH

data = np.load(WORKINGDATAPATH)

# axis = data['ax1Values']
# chi2vals = data['chi2']
be1meas = data['bjet1_e']
be2meas = data['bjet2_e']
fac = data['bie_to_bje']
be1be2measpos = fac/be2meas
minpos = data['chi2val']
be1fit = data['fitbjet1_e']
be2fit = data['fitbjet2_e']
be1be2fitpos = fac/be2fit

dicts = data['chi2dict']

indices = []
xAxis = []
values = []

for ds in dicts:
    d = json.loads(ds)
    indices.append(d['index'])
    xAxis.append(d['xAxis'])
    values.append(d['values'])

for i in [1, 4026]:
    fig = plt.figure()

    ax = xAxis[i]
    ay = values[i]

    plt.scatter(ax ,ay, marker='x', label = 'Los')
    plt.axvline(be1meas[i], c='red', label = 'E_B1 measured ' + str(be1meas[i]))
    plt.axvline(be1be2measpos[i], c='orange', label = 'E_B2 measured mapped to Eb1 '+ str(be1be2measpos[i]))
    plt.axvline(be1fit[i], c='magenta', label = 'Eb1 fit')
    plt.legend(fontsize=10)
    plt.xlabel('E_B1')
    plt.ylabel('Los value')

    plt.savefig('chi2forsingleevent' + str(i) + '.png')


import requests, praw, time, logging
from datetime import timezone, datetime
from authenticate import getToken
from secret import credentials
from database import Post, PostScores, Comments, CommentsClosure, CommentScores, getSession

format = "%(asctime)s: %(message)s"
logging.basicConfig(format=format, level=logging.INFO, datefmt="%H:%M:%S")

user_agent = "canaryScanner by verykarmamuchreddit"

reddit = praw.Reddit(client_id=credentials["clientId"],
    client_secret=credentials["clientSecret"],
    user_agent=user_agent)

def addNewPosts(subredditName, session):

    subreddit = reddit.subreddit(subredditName)

    newPosts = []
    existingPosts = [pId for pId, in session.query(Post.postId)]

    for submission in subreddit.new(limit=100):
        if submission.id not in existingPosts:
            post = Post(postId=submission.id, title=submission.title, subreddit=submission.subreddit.display_name,
            created=int(submission.created_utc), author=submission.author.name)
            newPosts.append(post)

    session.add_all(newPosts)
    session.commit()
    logging.info(f"{subredditName}: added {len(newPosts)} new posts")

def addPostScores(subredditName, session):

    existingPosts = [p for p in session.query(Post).filter(Post.subreddit==subredditName)]

    #get a list of posts
    for existingPost in existingPosts:
        now = int(datetime.now(tz=timezone.utc).timestamp())
        count = len(existingPost.postScores)

        if count > 0:
            postScoreTime = existingPost.postScores[count - 1].age + existingPost.created
            if (now - postScoreTime > 10*60) and (now - existingPost.created < 60*60*24):
                post = reddit.submission(id=existingPost.postId)
                age = now - post.created_utc
                currentPostScore = PostScores(postId=existingPost.postId, score=post.score,
                age=age, numberOfComments=post.num_comments)
                existingPost.postScores.append(currentPostScore)
                session.add(existingPost)
                logging.info(f"{subredditName}: updating score for {post.title}")
        else:
            post = reddit.submission(id=existingPost.postId)
            age = now - post.created_utc
            currentPostScore = PostScores(postId=existingPost.postId, score=post.score,
            age=age, numberOfComments=post.num_comments)
            existingPost.postScores.append(currentPostScore)
            session.add(existingPost)
            logging.info(f"{subredditName}: initial score for {post.title}")

    session.commit()

def addNewComments(subredditName, session):
    now = int(datetime.now(tz=timezone.utc).timestamp())
    commentsAdded = 0

    existingPosts = [p for p in session.query(Post).filter(Post.subreddit==subredditName)]
    for existingPost in existingPosts:
        if (now - existingPost.created) < 60*60*24:

            existingComments = [com.commentId for com in session.query(Comments).filter(Comments.postId==existingPost.postId)]

            post = reddit.submission(id=existingPost.postId)
            post.comments.replace_more(limit=None)
            commentList = post.comments.list()

            levelMap = {}
            for comment in commentList:
                if comment not in existingComments:
                    parentId = comment.parent_id[3:] #trim off prefix of t1_ or t3_
                    levelMap[comment.id] = levelMap.get(parentId, 0) + 1

                    #this is lazy nonetype reference handling. don't judge.
                    try:
                        author = "" if comment.author is None else comment.author.name
                    except:
                        author = ""

                    newComment = Comments(commentId=comment.id, parentId=parentId, level=levelMap[comment.id], commentText=comment.body,
                    author=author, postId=comment.submission, created=int(comment.created_utc), edited=bool(comment.edited))

                    existingPost.comments.append(newComment)
                    commentsAdded += 1

                #logic to add to closure table goes here
                parentId = comment.parent_id[3:] #starts at the existing parent
                existingComment = session.query(Comments).filter(Comments.commentId == comment.id).one()
                while(parentId != existingComment.postId):
                    newCommentClosure = CommentsClosure(parentId=parentId, childId=existingComment.commentId, postId=existingComment.postId)

                    isInClosureAlready = False
                    for dClosure in existingComment.commentsClosures:
                        if dClosure.parentId == newCommentClosure.parentId and dClosure.childId == newCommentClosure.childId:
                            isInClosureAlready = True

                    if not isInClosureAlready:
                        existingComment.commentsClosures.append(newCommentClosure)

                    parentComment = session.query(Comments).filter(Comments.commentId == parentId).one()
                    if parentComment is None:
                        break

                    parentId = parentComment.parentId

                session.add(existingComment)

            session.add(existingPost)

    session.commit()
    logging.info(f"{subredditName}: {commentsAdded} comments added")

def addCommentScores(subredditName, session):
    existingComments = session.query(Comments).join(Comments.post).filter(Post.subreddit==subredditName).all()

    #get a list of posts
    for existingComment in existingComments:
        now = int(datetime.now(tz=timezone.utc).timestamp())
        count = len(existingComment.commentScores)

        if count > 0:
            commentScoreTime = existingComment.commentScores[count - 1].age + existingComment.created
            if (now - commentScoreTime > 10*60) and (now - existingComment.created < 60*60*24):
                feedComment = reddit.comment(id=existingComment.commentId)
                age = now - existingComment.created
                newCommentScore = CommentScores(commentId=existingComment.commentId, score=feedComment.score,
                age=age)
                existingComment.commentScores.append(newCommentScore)
                session.add(existingComment)
                logging.info(f"{subredditName}: updating score for {existingComment.commentId}")

        else:
            feedComment = reddit.comment(id=existingComment.commentId)
            age = now - existingComment.created
            newCommentScore = CommentScores(commentId=existingComment.commentId, score=feedComment.score,
            age=age)
            existingComment.commentScores.append(newCommentScore)
            session.add(existingComment)
            logging.info(f"{subredditName}: initial score for {existingComment.commentId}")

    session.commit()

def quick():
    # begin = int(datetime.now(tz=timezone.utc).timestamp())
    # time.sleep(5)
    # end = int(datetime.now(tz=timezone.utc).timestamp())
    # print(f'end is {end}, begin is {begin} and diff is {end - begin}')
    reddit = praw.Reddit(client_id=credentials["clientId"],
    client_secret=credentials["clientSecret"],
    user_agent=user_agent)

    submission = reddit.comment(id="g1dpr0t")
    print(submission.score)

#need to find out how to get comment Id, parent comment Id

def monitoring():
    #os.path.getsize("canary.db")

    #texts number of posts and comments added, as well as file size of database

    #on error text error hit
    pass

def runUpdate(subreddit, session):
    addNewPosts(subreddit, session)
    addPostScores(subreddit, session)
    addNewComments(subreddit, session)
    addCommentScores(subreddit, session)

if __name__ == "__main__":
    # quick()
    runUpdate("ProgrammerHumor")


import numpy as np
import pandas as pd

# from pandasgui import show
import utils as u
from timer import Timer
from tqdm import tqdm

ourDepartment = ["ESD02 - Pflugerville", "ESD02"]

def recalcDict(arr, time):
    # print("=========================\n", arr)
    for bucket in arr:
        arr[bucket] = list(filter(lambda x: x > time, arr[bucket]))
    # print("\n------\n", arr, "\n")
    return arr

def addConcurrentUse(orig, startName, endName):
    """
    Add a column of concurrent values to a dataset

    Parameters
    --------------------------------
    Original : dataframe
        data to which you want to add the columns
    Start Name : str - ex: Unit Time Assigned
        the time the bucket shipped out
    End Name : str - ex: Unit Time Call Cleared
        the time the bucket will finish its current call

    Returns
    --------------------------------
    Dataframe
        a new dataframe which is a copy of orig, but with an extra column used to identify concurrent use at the time of bucket assignment
    """
    # create a dictionary of buckets, and when they will be done
    bucketDict = {}

    # create the column with a obviously default number
    orig["Concurrent Usage"] = np.NaN

    # ---------------- SECONDARY - TIME IN RANGE CALCULATIONS ---------------
    # =======================================================================
    # set up timeInterval for easier overlap detection

    # dont crash the program when no close is given please...
    def makeInterval(inc, start, end):
        interval = pd.Interval(0, 0, closed="neither")
        try:
            interval = pd.Interval(start, end, closed="right")
        except Exception as e:
            if not (pd.isnull(start) or pd.isnull(end)):
                print(f"{inc}: {start} - {end} : {e}")
            else:
                pass
            try:
                interval = pd.Interval(start, start, closed="right")
            except Exception as err:
                if not (pd.isnull(start)):
                    print(err)
        return interval

    orig["Time_Interval"] = orig.apply(
        lambda row: makeInterval(
            row["Master Incident Number"], row[startName], row[endName]
        ),
        axis=1,
    )

    # Set up columns to reveal specific time overlap
    for x in range(10):
        orig[f"Time_{x}_Active"] = 0
    #  -----------------------------------------------------------------------

    # limit the dictionary as much as possible, since this will go quite slow
    # start with just our jurisdiction
    # distArr = orig.index[(orig["Jurisdiction"].isin(["ESD02", "ESD17"]))].tolist()
    distArr = orig.index[(orig["Department"].isin(ourDepartment))].tolist()
    with tqdm(total=len(distArr), desc=f"Getting Concurrency") as pbar:
        for ind in distArr:
            # get start and end time of incident
            startTime = orig.loc[ind, startName]
            endTime = orig.loc[ind, endName]

            # get bucket type from the name
            # use the column if it exists, since this work should already be done.
            try:
                bucketType = str(orig.loc[ind, "Bucket Type"])
            except:
                bucketType = u.getUnitBucket(u.getUnitType(orig.loc[ind, "Radio_Name"]))

            # store end time for this type into the dictionary
            bucketDict[bucketType] = [endTime] + (
                bucketDict[bucketType] if bucketType in bucketDict else []
            )

            # remove those that are already finished
            recalcDict(bucketDict, startTime)

            # store current count as concurrent usage
            orig.loc[ind, "Concurrent Usage"] = (
                len(bucketDict[bucketType])
                - 1  # remove on since this one is being counted
            )

            # ---------------- SECONDARY - TIME IN RANGE CALCULATIONS ---------------
            # =======================================================================
            orig = getTimes(orig, ind, orig.loc[ind, "Time_Interval"], bucketType)
            # =======================================================================
            pbar.update(1)

    # remove the new useless interval column
    orig = orig.drop(
        [
            "Time_Interval",
        ],
        axis=1,
    )
    return orig  # .astype({"Concurrent Usage": "Int64"})

# ===================================
#       SECONDARY - TIME IN RANGE CALCULATIONS
# ===================================
def getTimes(df, ind, interval, bucket):
    """
    Get get all time breakdowns for a specific passed row of the passed DF
    """
    # filter on same bucket
    nearbyInd = df[abs(df.index - ind) < 15]
    commonTimes = nearbyInd[
        (nearbyInd["Bucket Type"] == bucket)
        & (nearbyInd["Department"].isin(ourDepartment))
        # & (nearbyInd["include_in_concurrency"])
    ]

    # Remove broken time intervals before comparing them

    # filter that on overlap times - lets use only those within 20
    try:
        commonTimes = commonTimes[
            commonTimes.apply(
                lambda row: interval.overlaps(row["Time_Interval"]), axis=1
            )
        ]
    except Exception as e:
        print(f"{ind} - {interval}")

    # this should never actually happen afterall, you should ALWAYS find yourself.
    # if commonTimes.empty:
    #     return df

    # get list of all overlapping start/end points
    timeList = (
        commonTimes["Unit Time Assigned"].tolist()
        + commonTimes["Unit Time Call Cleared"].tolist()
    )

    timeList.sort()
    # remove everything before this units start and everything after this unit end
    # after opening set to eliminate overlap issues, the original interval now needs to be added in manually
    tempTime = [interval.left]
    for x in timeList:
        if (x in interval) and (x not in tempTime):
            tempTime.append(x)

    # WTF is this list not sorted?

    # print(f"---------------------------------------------------------\n{timeList}")
    # print(f"\nfiltered:\n{tempTime}\n\n")

    # use the list to group out concurrency
    # -----------------------
    inc = df.loc[ind, "Master Incident Number"]
    # print(
    #     f"==================================================================================\n----- {inc}: \n{interval}\n\n{timeList}"
    # )
    timeList = tempTime

    timeDict = {}
    prevTime = timeList[0]
    # create a breakdown of
    # skip the first, as it should always be 0 seconds
    for time in timeList[1:]:
        timeRange = time - prevTime
        try:
            setLength = (
                commonTimes[
                    commonTimes.apply(lambda row: time in row["Time_Interval"], axis=1)
                ].shape[0]
                - 1
            )
        except Exception as e:
            pass
            # show(commonTimes)I just want to finish my cabinets
        # print(f"  {str(time):<30}: {str(timeRange):<23}-   {setLength}")
        # max out the time to be 9+ units
        if setLength > 9:
            setLength = 9
        try:
            timeDict[setLength] += timeRange
        except:
            timeDict[setLength] = timeRange
        prevTime = time

    # print(timeDict)
    for x in timeDict:
        # store each time as seconds into the rows new fields
        df.loc[ind, f"Time_{x}_Active"] = int(timeDict[x] / np.timedelta64(1, "s"))

    # show(commonTimes)

    return df

## Main - Used for testing, and will be ignored on import.
def main():
    import loadTestFile

    df = loadTestFile.get()

    # remove data not useful for the testing
    # limit = [
    #     "Master Incident Number",
    #     "Department",
    #     "Radio_Name",
    #     "Unit Time Assigned",
    #     "Unit Time Call Cleared",
    # ]
    # df = df[limit]

    # =================================================================
    #     Add unit type column to simplify analysis
    # =================================================================
    df = u.addUnitType(df)
    df = u.addBucketType(df)

    # test the function
    df = addConcurrentUse(df, "Unit Time Assigned", "Unit Time Call Cleared")
    # show the results
    show(df)

if __name__ == "__main__":
    main()


import cv2
import numpy as np
import cv2 as cv

def main():
    H1 = np.load("../rectification/H1.npy")
    H2 = np.load("../rectification/H2.npy")

    cap = cv2.VideoCapture(0)
    cap2 = cv2.VideoCapture(2)

    if not cap.isOpened() or not cap2.isOpened():
        print("Cannot open camera")
        exit()
    count = 0

    def nothing(x):
        pass

    cv2.namedWindow('Disparity', cv2.WINDOW_NORMAL)
    cv2.resizeWindow('Disparity', 450, 450)
    cv2.createTrackbar('max_disp', 'Disparity', 1, 16, nothing)
    cv2.createTrackbar('min_disp', 'Disparity', 0, 32, nothing)
    cv2.createTrackbar('blockSize', 'Disparity', 5, 50, nothing)
    cv2.createTrackbar('uniquenessRatio', 'Disparity', 15, 100, nothing)
    cv2.createTrackbar('speckleRange', 'Disparity', 0, 100, nothing)
    cv2.createTrackbar('speckleWindowSize', 'Disparity', 3, 200, nothing)
    cv2.createTrackbar('disp12MaxDiff', 'Disparity', 0, 25, nothing)

    while True:
        # Capture frame-by-frame
        ret, img1 = cap.read()
        ret2, img2 = cap2.read()
        h1, w1 = img1.shape[:2]
        h2, w2 = img1.shape[:2]

        # Updating the parameters based on the trackbar positions
        max_disp = cv2.getTrackbarPos('max_disp', 'Disparity') * 16
        min_disp = (cv2.getTrackbarPos('min_disp', 'Disparity') - 16) * 16
        block_size = cv2.getTrackbarPos('blockSize', 'Disparity') * 2 + 5
        uniquenessRatio = cv2.getTrackbarPos('uniquenessRatio', 'Disparity')
        speckleRange = cv2.getTrackbarPos('speckleRange', 'Disparity')
        speckleWindowSize = cv2.getTrackbarPos('speckleWindowSize', 'Disparity') * 2
        disp12MaxDiff = cv2.getTrackbarPos('disp12MaxDiff', 'Disparity')

        img1_rectified = cv.warpPerspective(img1, H1, (w1, h1))
        img2_rectified = cv.warpPerspective(img2, H2, (w2, h2))

        num_disp = max_disp - min_disp

        stereo = cv.StereoSGBM_create(
            minDisparity=min_disp,
            numDisparities=num_disp,
            blockSize=block_size,
            uniquenessRatio=uniquenessRatio,
            speckleWindowSize=speckleWindowSize,
            speckleRange=speckleRange,
            disp12MaxDiff=disp12MaxDiff,
            P1=8 * 1 * block_size * block_size,
            P2=32 * 1 * block_size * block_size,
        )

        disparity_SGBM = stereo.compute(img1_rectified, img2_rectified)

        # Normalize the values to a range from 0..255 for a grayscale image
        disparity_SGBM = cv.normalize(disparity_SGBM, disparity_SGBM, alpha=255,
                                      beta=0, norm_type=cv.NORM_MINMAX)
        disparity_SGBM = np.uint8(disparity_SGBM)

        imgg = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

        imgg = cv2.resize(imgg, (320, 240))
        disparity_SGBM = cv2.resize(disparity_SGBM, (320, 240))

        # Display the resulting frame
        img_concate_Hori = np.concatenate((imgg, disparity_SGBM), axis=0)
        cv2.imshow('Output', img_concate_Hori)
        key = cv2.waitKey(1)
        if key == ord('q'):
            break
        if key == ord('s'):
            print("Saving image")
            cv2.imwrite("./testData/" + str(count) + "L.jpg", img1)
            cv2.imwrite("./testData/" + str(count) + "R.jpg", img2)
            count = count + 1
    # When everything done, release the capture
    cap.release()
    cap2.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()


import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.svm import SVR
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import matplotlib.pyplot as plt
from sklearn.metrics import accuracy_score

# Đọc dữ liệu từ tệp CSV và thay đổi dấu phẩy thành dấu chấm cho các giá trị số thập phân
data = pd.read_csv('Book1.csv')
# Thay thế các giá trị trống hoặc '-' bằng 0 để xử lý
data.replace(['-', ''], 0, inplace=True)
# Loại bỏ bất kỳ hàng nào chứa giá trị NaN trong cột 'Chỉ số AQI'
data.dropna(subset=['Chỉ số AQI'], inplace=True)

# Chọn các biến đầu vào và biến mục tiêu
X = data[['CO', 'Sương', 'Độ ẩm', 'NO2', 'O3', 'Áp suất', 'Bụi PM10', 'Bụi PM2.5', 'Nhiệt độ', 'Tốc độ gió']]
y = data['Chỉ số AQI']

# Tạo mô hình hồi quy tuyến tính và mô hình SVM
regression_model = LinearRegression()
svm_regressor = SVR(kernel='linear')

# Tạo mô hình hồi quy đa biến cho toàn bộ dữ liệu
regression_model.fit(X, y)
svm_regressor.fit(X, y)

# Dự đoán Chỉ số AQI
y_pred = regression_model.predict(X)
y_pred_svm = svm_regressor.predict(X)

# Kết hợp dự đoán từ cả hai mô hình bằng trung bình cộng
y_pred_combined = (y_pred + y_pred_svm) / 2

# Đánh giá mô hình bằng Mean Squared Error, Mean Absolute Error và R-squared

mse = mean_squared_error(y, y_pred) # hồi quy tuyến tính
mse_svm = mean_squared_error(y, y_pred_svm) # svm
mse_combined = mean_squared_error(y, y_pred_combined) # mô hình kết hợp

mae = mean_absolute_error(y, y_pred) # hồi quy tuyến tính
mae_svm = mean_absolute_error(y, y_pred_svm)#svm
mae_combined = mean_absolute_error(y, y_pred_combined) # mô hình kết hợp

r2 = r2_score(y, y_pred) # hồi quy tuyến tính
r2_svm = r2_score(y, y_pred_svm) # svm
r2_combined = r2_score(y, y_pred_combined) # mô hình kết hợp

# In kết quả đánh giá
print("Kết quả đánh giá MSE:")
print(f"MSE Hồi quy tuyến tính: {mse}")
print(f"MSE SVM: {mse_svm}")
print(f"MSE mô hình kết hợp: {mse_combined}")

print("\nKết quả đánh giá MAE:")
print(f"MAE Hồi quy tuyến tính: {mae}")
print(f"MAE SVM: {mae_svm}")
print(f"MAE mô hình kết hợp: {mae_combined}")

print("\nKết quả đánh giá R-squared:")
print(f"R-squared Hồi quy tuyến tính: {r2}")
print(f"R-squared SVM: {r2_svm}")
print(f"R-squared mô hình kết hợp: {r2_combined}")

# Vẽ biểu đồ thể hiện kết quả dự đoán từ cả hai mô hình và mô hình kết hợp
plt.scatter(y, y_pred, label='AQI Dự Đoán (Hồi quy tuyến tính)')
plt.scatter(y, y_pred_svm, label='AQI Dự Đoán (SVM)')
plt.scatter(y, y_pred_combined, label='AQI Dự Đoán (Kết hợp)')
plt.xlabel("Chỉ số AQI ban đầu")
plt.ylabel("Chỉ số AQI dự đoán")
plt.title("Biểu đồ kết quả dự đoán và AQI ban đầu")
plt.legend()
plt.show()

# Dự đoán chỉ số mới
new_data = pd.DataFrame({'CO': [0.5], 'Sương': [1.0], 'Độ ẩm': [70.0], 'NO2': [15.0], 'O3': [30.0], 'Áp suất': [1000.0], 'Bụi PM10': [60.0], 'Bụi PM2.5': [40.0], 'Nhiệt độ': [25.0], 'Tốc độ gió': [8.0]})
predicted_aqi = regression_model.predict(new_data)
predicted_aqi_svm = svm_regressor.predict(new_data)
predicted_aqi_combined = (predicted_aqi + predicted_aqi_svm) / 2
print("\nDự đoán Chỉ số AQI cho dữ liệu mới (hồi quy tuyến tính):", predicted_aqi)
print("Dự đoán Chỉ số AQI cho dữ liệu mới (SVM):", predicted_aqi_svm)
print("Dự đoán Chỉ số AQI cho dữ liệu mới (Kết hợp):", predicted_aqi_combined)

# Hiển thị 20 dòng đầu tiên của DataFrame kết quả
results = pd.DataFrame({'AQI Ban Đầu': y, 'AQI Dự Đoán': y_pred, 'AQI Dự Đoán SVM': y_pred_svm, 'AQI Kết hợp': y_pred_combined})
print("\n20 dòng đầu tiên của DataFrame kết quả:")
print(results.head(20))

# Chuyển numpy array thành DataFrame
y_pred_df = pd.DataFrame(y_pred, columns=['AQI_DuDoan'])
# Chuyển Chỉ số AQI thực tế và dự đoán thành các nhãn phân loại
# Chia thành 4 nhóm: "Tốt", "Trung bình", "Kém","Xấu"
def convert_to_category(aqi):
    if aqi <= 50:
        return "Tốt"
    elif 50 < aqi <= 100:
        return "Trung bình"
    elif 100< aqi <=150:
        return "Kém"
    else:
        return 'Xấu'
# Áp dụng hàm convert_to_category cho cột AQI_DuDoan
y_pred_categories = y_pred_df['AQI_DuDoan'].apply(convert_to_category)

# Chuyển Chỉ số AQI thực tế thành các nhãn phân loại
y_true_categories = y.apply(convert_to_category)
# Tính độ chính xác
accuracy = accuracy_score(y_true_categories, y_pred_categories)

# In kết quả độ chính xác
print(f"Độ chính xác: {accuracy}")


import os
import torch.utils.data
import torchvision.datasets as dsets
import torchvision.transforms as transforms
from tqdm import tqdm
import pathlib
from flow_modules.misc import ShiftTransform, MnistGlowTransform
import torchvision.utils as vutils

def get_dataset(dataset_name, batch_size, data_root=None, train_workers=2, test_workers=2):
    assert dataset_name in ['cifar10', 'mnist', 'imagenet_32', 'imagenet_64'], "Invalid Dataset Name"

    if dataset_name == 'cifar10':
        if data_root is None:
            data_root = '../cifar_data'

        image_shape = [32, 32, 3]

        transform_train = transforms.Compose([
            ShiftTransform(3),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        transform_test = transforms.Compose([transforms.ToTensor(),
                                             transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        trainset = dsets.CIFAR10(root=data_root, train=True, download=True, transform=transform_train)
        train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, drop_last=True,
                                                   num_workers=train_workers)

        testset = dsets.CIFAR10(root=data_root, train=False, download=True, transform=transform_test)
        test_loader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, drop_last=True,
                                                  num_workers=test_workers)

    elif dataset_name == 'mnist':
        if data_root is None:
            data_root = '../mnist_data'

        image_shape = [32, 32, 3]

        transform_train = transforms.Compose([
            MnistGlowTransform(2),
            transforms.ToTensor(),
            transforms.Normalize((0.5,), (1.0,))])

        transform_test = transforms.Compose([
            MnistGlowTransform(2),
            transforms.ToTensor(),
            transforms.Normalize((0.5,), (1.0,))])

        trainset = dsets.MNIST(root=data_root, train=True, download=True, transform=transform_train)
        train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, drop_last=True,
                                                   num_workers=train_workers)

        testset = dsets.MNIST(root=data_root, train=False, download=True, transform=transform_test)
        test_loader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, drop_last=True,
                                                  num_workers=train_workers)

    elif dataset_name == 'imagenet_32':
        if data_root is None:
            data_root = '../imagenet_data/'

        image_shape = [32, 32, 3]

        transform_train = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        transform_test = transforms.Compose([transforms.ToTensor(),
                                             transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        trainset = dsets.ImageFolder(root=os.path.join(data_root, 'train_32x32'), transform=transform_train)
        train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, drop_last=True,
                                                   num_workers=train_workers)

        testset = dsets.ImageFolder(root=os.path.join(data_root, 'valid_32x32'), transform=transform_test)
        test_loader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, drop_last=True,
                                                  num_workers=test_workers)

    elif dataset_name == 'imagenet_64':
        if data_root is None:
            data_root = '../imagenet_data/'

        image_shape = [64, 64, 3]

        transform_train = transforms.Compose([
            transforms.ToTensor(),
            transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        transform_test = transforms.Compose([transforms.ToTensor(),
                                             transforms.Normalize((0.5, 0.5, 0.5), (1, 1, 1))])

        trainset = dsets.ImageFolder(root=os.path.join(data_root, 'train_64x64'), transform=transform_train)
        train_loader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, drop_last=True,
                                                   num_workers=train_workers)

        testset = dsets.ImageFolder(root=os.path.join(data_root, 'valid_64x64'), transform=transform_test)
        test_loader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, drop_last=True,
                                                  num_workers=test_workers)

    return train_loader, test_loader, image_shape

def rm_tree(pth):
    pth = pathlib.Path(pth)
    for child in pth.glob('*'):
        if child.is_file():
            child.unlink()
        else:
            rm_tree(child)
    pth.rmdir()

def create_sample_directory(model, sample_dir, device='cpu', num_samples=10000, overwrite=False):
    """Creates a directory of randomly sampled images. Probably used to create
    a fake dataset to compute FID.
    Note:
        The FID authors suggest to use a minimum sample size of 10000 to not
        underestimate the FID value.
    Args:
        model:          The generator model
        sample_dir:     Target directory to create images
        num_samples:    Number of samples to create
        device:         CPU or CUDA device object
        overwrite:      If True, then overwrite sample directory if it already exists
    """
    sample_path = pathlib.Path(sample_dir)

    path_exists = sample_path.exists()
    if path_exists:
        if overwrite:
            # Careful!
            rm_tree(sample_path)
        else:
            raise FileExistsError('Directory already exists, not overwriting!')
    sample_path.mkdir(parents=True)
    model.eval()

    with torch.no_grad():
        for i in tqdm(range(num_samples)):
            rev = model(None, None, reverse=True, eps_std=1.0)
            rev[torch.isnan(rev)] = -0.5
            rev = torch.clamp(rev, -0.5, 0.5)
            for j in range(0,16):
                vutils.save_image(rev[j].clone().detach().cpu(), str(sample_path / f'img{i}.png'), normalize=True)
                i+=1

def create_cifar10_sample_directory(cifar10_root_dir, sample_dir, num_samples=10000, overwrite=False,
                                   image_size=(32, 32)):
    """Selects and prepares randomly sampled CIFAR10 images.

    Note:
        The FID authors suggest to use a minimum sample size of 10000 to not
        underestimate the FID value.
    Args:
        celeba_root_dir:    Directory of the root 'celeba' directory
        sample_dir:         Target directory to create images
        num_samples:        Number of samples to create
        device:             CPU or CUDA device object
        overwrite:          If True, then overwrite sample directory if it already exists
        image_size:         Saved image size
    """
    sample_path = pathlib.Path(sample_dir)

    dataset = dsets.CIFAR10(root=cifar10_root_dir, download=False, transform=transforms.Compose([
        transforms.Resize(image_size),
        transforms.CenterCrop(image_size),
        transforms.ToTensor(),
        transforms.Normalize([0.5, 0.5, 0.5], [1, 1, 1])
    ]))
    dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True)
    dataloader_iter = iter(dataloader)

    for i in tqdm(range(num_samples)):
        try:
            sample = next(dataloader_iter)
        except StopIteration:
            # Re-roll the iterator
            dataloader_iter = iter(dataloader)
            sample = next(dataloader_iter)
        sample = sample[0].squeeze(0)
        # Unnormalize
        sample = 0.5 * sample + 0.5
        image = transforms.ToPILImage()(sample)
        image.save(str(sample_path / f'img{i}.png'), format='png')


# ---
# jupyter:
#   jupytext:
#     cell_metadata_filter: ExecuteTime,collapsed,code_folding,-autoscroll
#     cell_metadata_json: true
#     formats: ipynb,py:percent
#     notebook_metadata_filter: all,-widgets,-varInspector
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.14.5
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
#   language_info:
#     codemirror_mode:
#       name: ipython
#       version: 3
#     file_extension: .py
#     mimetype: text/x-python
#     name: python
#     nbconvert_exporter: python
#     pygments_lexer: ipython3
#     version: 3.10.8
#   latex_envs:
#     LaTeX_envs_menu_present: true
#     autoclose: false
#     autocomplete: true
#     bibliofile: biblio.bib
#     cite_by: apalike
#     current_citInitial: 1
#     eqLabelWithNumbers: true
#     eqNumInitial: 1
#     hotkeys:
#       equation: Ctrl-E
#       itemize: Ctrl-I
#     labels_anchors: false
#     latex_user_defs: false
#     report_style_numbering: false
#     user_envs_cfg: false
#   toc:
#     base_numbering: 1
#     nav_menu: {}
#     number_sections: true
#     sideBar: true
#     skip_h1_title: false
#     title_cell: Table of Contents
#     title_sidebar: Contents
#     toc_cell: false
#     toc_position: {}
#     toc_section_display: true
#     toc_window_display: false
# ---

# %% [markdown]
# # Spending on Nondurables During the Great Recession
#
# [![badge](https://img.shields.io/badge/Launch%20using%20-Econ--ARK-blue)](https://econ-ark.org/materials/nondurables-during-great-recession#launch)
#
#
Generator: QuARK-make/notebooks_byname

# %% {"code_folding": [0]}
# Initial imports and notebook setup, click arrow to show

from HARK.distribution import Uniform
from HARK.ConsumptionSaving.ConsIndShockModel import IndShockConsumerType
import matplotlib.pyplot as plt

# Import some things from cstwMPC

from tqdm import tqdm

import numpy as np
from copy import deepcopy

from HARK.utilities import plot_funcs

# %% [markdown]
# ### There Was a Big Drop in Consumption ...
# Between the second and fourth quarters of 2008, "discretionary" spending on nondurables and services in the U.S. dropped by about 4 percent -- an unprecedented collapse.  Subsequent analyses of the Great Recession concluded that it was the large drop in consumption expenditures that turned what would otherwise have been a moderate downturn into the largest economic decline since the Great Depresssion.
#
#

# %% [markdown]
# ### ... and Uncertainty Could Induce A Drop In Consumption ...
# Increased "uncertainty" has become a popular explanation of much of what happened in the Great Recession -- including this drop.  Qualitatively, it is well known that a perceived increase in labor income uncertainty should induce more saving (less consumption) for precautionary reasons.
#
# ### ... But Is the Story _Quantitatively_ Plausible?
# But if explaining a 4 percent drop in discretionary consumption would require an implausibly large increase in uncertainty, the story that uncertainty explains the consumption drop is implausible.
#
# ### Transitory Shocks, Permanent Shocks, or Unemployment
# The $\texttt{ConsIndShockConsumerType}$ model incorporates three kinds of uncertainty: Unemployment spells, during which income is reduced to some small proportion of its normal level; and, for consumers who remain employed, transitory and permanent shocks with standard deviations $\sigma_{\theta}$ and $\sigma_{\psi}$.
#
# ### The Question:
# How large an increase in the standard deviation of $\sigma_{\psi}$ would be necessary to induce a 4 percent drop in consumption in one quarter?  What about $\sigma_{\theta}$?  How high would the perceived unemployment probability have to be?
#
# The first step is to create the agents we want to solve the model for.
#
# Model set up:
# - "Standard" infinite horizon consumption/saving model, with mortality and permanent and temporary shocks to income
# - Ex-ante heterogeneity in consumers' discount factors
#
# With this basic setup, HARK's `IndShockConsumerType` is the appropriate subclass of $\texttt{AgentType}$. So we need to prepare the parameters to create instances of that class.
#

# %% {"code_folding": [0]}
# Choose some calibrated parameters that roughly match steady state
init_infinite = {
    "CRRA": 1.0,  # Coefficient of relative risk aversion
    "Rfree": 1.01 / (1.0 - 1.0 / 240.0),  # Survival probability,
    # Permanent income growth factor (no perm growth),
    "PermGroFac": [1.000**0.25],
    "PermGroFacAgg": 1.0,
    "BoroCnstArt": 0.0,
    "CubicBool": False,
    "vFuncBool": False,
    "PermShkStd": [
        (0.01 * 4 / 11) ** 0.5
    ],  # Standard deviation of permanent shocks to income
    "PermShkCount": 7,  # Number of points in permanent income shock grid
    "TranShkStd": [
        (0.01 * 4) ** 0.5
    ],  # Standard deviation of transitory shocks to income,
    "TranShkCount": 5,  # Number of points in transitory income shock grid
    "UnempPrb": 0.07,  # Probability of unemployment while working
    "IncUnemp": 0.15,  # Unemployment benefit replacement rate
    "UnempPrbRet": 0.07,
    "IncUnempRet": 0.15,
    "aXtraMin": 0.00001,  # Minimum end-of-period assets in grid
    "aXtraMax": 20,  # Maximum end-of-period assets in grid
    "aXtraCount": 20,  # Number of points in assets grid,
    "aXtraExtra": [None],
    "aXtraNestFac": 3,  # Number of times to 'exponentially nest' when constructing assets grid
    "LivPrb": [1.0 - 1.0 / 240.0],  # Survival probability
    "DiscFac": 0.97,  # Default intertemporal discount factor, # dummy value, will be overwritten
    "cycles": 0,
    "T_cycle": 1,
    "T_retire": 0,
    # Number of periods to simulate (idiosyncratic shocks model, perpetual youth)
    "T_sim": 2000,
    "T_age": 1000,
    "IndL": 10.0 / 9.0,  # Labor supply per individual (constant),
    "aNrmInitMean": np.log(0.00001),
    "aNrmInitStd": 0.0,
    "pLvlInitMean": 0.0,
    "pLvlInitStd": 0.0,
    "AgentCount": 10000,
}

# %% [markdown]
# Now we import the class itself and make a baseline type.

# %%
BaselineType = IndShockConsumerType(**init_infinite)

# %% [markdown]
# For this exercise, we will introduce _ex ante_ heterogeneity, so the baseline type will be copied several times.
#
# First, let's create a list with seven copies of our baseline type.

# %% {"code_folding": []}
# A list in python can contain anything -- including consumers
num_consumer_types = 7  # declare the number of types we want
ConsumerTypes = []  # initialize an empty list

for nn in range(num_consumer_types):
    # Now create the types, and append them to the list ConsumerTypes
    NewType = deepcopy(BaselineType)
    NewType.seed = nn  # give each consumer type a different RNG seed
    ConsumerTypes.append(NewType)

# %% [markdown]
# Now we can give each of the consumer types their own discount factor. (This approximates the distribution of parameters estimated in ["The Distribution of Wealth and the Marginal Propensity to Consume"](https://www.econ2.jhu.edu/people/ccarroll/papers/cstwMPC)).

# %% {"code_folding": []}
# Seven types is enough to approximate the uniform distribution (5 is not quite enough)

# Calibrations from cstwMPC
bottomDiscFac = 0.9800
topDiscFac = 0.9934
DiscFac_list = (
    Uniform(bot=bottomDiscFac, top=topDiscFac)
    .discretize(N=num_consumer_types)
    .atoms.flatten()
)

# Now, assign the discount factors
for j in range(num_consumer_types):
    ConsumerTypes[j].DiscFac = DiscFac_list[j]
    ConsumerTypes[j].quiet = True  # Turn off some output

# %% [markdown]
# Our agents now exist and have a concept of the problem they face, but we still need them to solve that problem.
#
# Once we have solved each type of consumer's individual problem, we need to know the distribution of wealth (and permanent income) that the population would achieve in the long run.
#
# The cell below does both of those tasks, looping through the consumer types. For each one, it solves that type's infinite horizon model, then simulates 1000 periods to generate an approximation to the long run distribution of wealth.

# %% {"code_folding": []}
# tqdm presents a pretty bar that interactively shows how far the calculations have gotten
for ConsumerType in tqdm(ConsumerTypes):
    # We configured their discount factor above.  Now solve
    ConsumerType.solve(verbose=False)

    # Now simulate many periods to get to the stationary distribution
    ConsumerType.T_sim = 2000
    ConsumerType.initialize_sim()
    ConsumerType.simulate()

# %% [markdown]
# With all of that setup taken care of, let's write some functions to run our counterfactual exercise and extract the information we want.
#
# First, let's define a simple function that merely calculates the average consumption level across the entire population in the most recent simulated period.

# %% {"code_folding": []}
# We just merge the cNrm and pNrm lists already constructed for each ConsumerType

def calcAvgC(ConsumerTypes):
    """
    This function calculates average consumption in the economy in last simulated period,
    averaging across ConsumerTypes.
    """
    # Make arrays with all types' (normalized) consumption and permanent income level
    # The brackets indicate that the contents will be a list (in this case, of lists)
    cNrm = np.concatenate([ThisType.controls["cNrm"] for ThisType in ConsumerTypes])
    pLvl = np.concatenate([ThisType.state_now["pLvl"] for ThisType in ConsumerTypes])

    # Calculate and return average consumption level in the economy
    avgC = np.mean(cNrm * pLvl)  # c is the ratio to p, so C = c*p
    return avgC

# %% [markdown]
# Now let's create a function to run the experiment we want -- change income uncertainty, and see how consumption changes.
# To keep the code block below (mostly) clean, we'll describe the procedure below step by step here, with accompanying annotations in the codeblock.
#
# 1. Initialize an empty list to
#    * hold the changes in consumption that happen after parameters change, and
#    * calculate average consumption before the change in uncertainty
# 2. Loop through the new uncertainty parameter values to assign. For each:
#    1. Assign the parameter value to the agents
#    2. Re-solve the agent's model under that degree of uncertainty
#    3. Construct a popn of agents distributed in the pre-crisis steady state
#    4. Simulate one more period-- the first period after the change in risk.
#    5. Calculate the popn avg C level given the new consumption rule
#    6. Calculate the new average consumption level as percentage change vs the prior level.
#    7. Return the list of percentage changes

# %% {"code_folding": []}
# Whenever you define a function, you should describe it (with a "docstring")
def calcConsChangeAfterUncertaintyChange(OriginalTypes, NewVals, ParamToChange):
    """
    Calculate the change in aggregate consumption for a list of values that a
    parameter will take on.

    Parameters
    ----------
    OriginalTypes : [IndShockConsumerType]
        List of consumer types, who have already had their "pre-shock" problem solved and simulated.
    NewVals : np.array
        List or array of new values that the parameter of interest will take on.
    ParamToChange : str
        Name of the income distribution parameter that will be changed.

    Returns
    -------
    ChangesInConsumption : [float]
        List of changes in aggregate consumption corresponding to the values in NewVals, as a percentage
        of the original aggregate consumption level.
    """
    ChangesInConsumption = []  # Step 1
    OldAvgC = calcAvgC(OriginalTypes)

    # Step 2 (the loop over counterfactual parameter values)
    for NewVal in tqdm(NewVals):
        if ParamToChange in ["PermShkStd", "TranShkStd"]:
            ThisVal = [NewVal]
        else:
            ThisVal = NewVal

        ConsumerTypesNew = deepcopy(OriginalTypes)
        for index, ConsumerTypeNew in enumerate(ConsumerTypesNew):
            setattr(ConsumerTypeNew, ParamToChange, ThisVal)  # Step 2A
            ConsumerTypeNew.update_income_process()
            ConsumerTypeNew.solve()  # Step 2B

            ConsumerTypeNew.initialize_sim()  # Step 2C
            ConsumerTypeNew.aNrm = OriginalTypes[index].state_now["aNrm"]
            ConsumerTypeNew.pLvl = OriginalTypes[index].state_now["pLvl"]

            ConsumerTypeNew.sim_one_period()  # Step 2D

        NewAvgC = calcAvgC(ConsumerTypesNew)  # Step 2E
        ChangeInConsumption = 100.0 * (NewAvgC - OldAvgC) / OldAvgC  # Step 2F
        ChangesInConsumption.append(ChangeInConsumption)

    return ChangesInConsumption  # Step 3, returning the output

# %% [markdown]
# Our counterfactual experiment function takes three inputs-- consumer types, counterfactual values, and the name of the parameter we want to change. For the sake of convenience, let's define small functions to run the experiment for each parameter with just a single input.

# %% {"code_folding": []}
# Trivial functions can be useful in making the logic of your program clear
def calcConsChangeAfterPermShkChange(newVals):
    return calcConsChangeAfterUncertaintyChange(ConsumerTypes, newVals, "PermShkStd")

def calcConsChangeAfterTranShkChange(newVals):
    return calcConsChangeAfterUncertaintyChange(ConsumerTypes, newVals, "TranShkStd")

def calcConsChangeAfterUnempPrbChange(newVals):
    return calcConsChangeAfterUncertaintyChange(ConsumerTypes, newVals, "UnempPrb")

# %% [markdown]
# Now we can finally run our experiment.  In the cell below, we generate a plot of the change in aggregate consumption vs the (underlying) standard deviation of permanent income shocks.

# %%
# Calculate the consequences of a permanent "MIT shock" to the standard deviation of permanent shocks
ratio_min = 0.8  # minimum number to multiply uncertainty parameter by
TargetChangeInC = -4.1  # Source: see comment above
num_points = 10  # number of parameter values to plot in graphs. More=slower

# First change the variance of the permanent income shock
# Put whatever value in you want!  maximum number to multiply var of perm income shock by
perm_ratio_max = 2.5

perm_min = BaselineType.PermShkStd[0] * ratio_min
perm_max = BaselineType.PermShkStd[0] * perm_ratio_max

plt.ylabel("% Change in Consumption")
plt.xlabel(
    "Std. Dev. of Perm. Income Shock (Baseline = "
    + str(round(BaselineType.PermShkStd[0], 2))
    + ")"
)
plt.title("Change in Cons. Following Increase in Perm. Income Uncertainty")
plt.ylim(-40.0, 5.0)
plt.hlines(TargetChangeInC, perm_min, perm_max)
# The expression below shows the power of python
plot_funcs([calcConsChangeAfterPermShkChange], perm_min, perm_max, N=num_points)

# %%

# %% [markdown]
# The figure shows that if people's beliefs about the standard deviation of permanent shocks to their incomes had changed from 0.06 (the default value) to about 0.012, the model would predict an immediate drop in consumption spending of about the magnitude seen in 2008.
#
# The question is whether this is a reasonable or an unreasonable magnitude for a change in uncertainty.  Some perspective on that question is offered by the large literature that attempts to estimate the magnitude of persistent or permanent shocks to household income.  The answer varies substantially across household types, countries, and time periods, but our sense of the literature is that the whole span of the territory between 0.04 and ranging nearly up to 0.20 is well populated (in the sense that substantial populations of people or countries have been estimated to experience shocks of this magnitude).
#
# The conclusion is that, in order for an increase in permanent income uncertainty to explain the entire drop in consumption spending, uncertainty in permanent income would have to have roughly doubled between Q2 and Q4 of 2008.  While this seems rather a large increase in uncertainty, it is by no means an absurdly large increase.  And, there is no reason to rule out the possibility that people perceived a likely change in the _level_ of their permanent income as well, which of course would translate one-for-one into a change in the appropriate level of consumption.
#
# The point is that it is not at all implausible, as a quantitative proposition, that an increase in uncertainty could have been responsible for a substantial portion of the decline in nondurable expenditures in the Great Recesssion.  (And it is even easier for an increase in uncertainty to induce a decline in durable goods purchases.


import tensorflow as tf
import numpy as np
import pickle
from sqlalchemy import create_engine
import pandas as pd
import time
from tensorflow.keras.preprocessing.sequence import pad_sequences
import tensorflow
import youtokentome as yttm

def multi_pred(model,query,neg_list,anchor_pos_list,anchor_neg_list):
    """
    Needs refactoring(for handling triplet loss model) and additional
    analysis to determine stability in prediction, i.e. relative
    distances in the learned metric space can have significant
    variances depending on the positive anchor chosen.
    """
    predictions = model.predict([len(neg_list)*[query],neg_list,anchor_pos_list,anchor_neg_list])
    #mean_dist = predictions[:,0].mean()
    mean_rel = (predictions[:,0]>predictions[:,3]).mean()
    #print('Dist',mean_dist,'Rel',mean_rel)
    return mean_rel#np.min([mean_dist,mean_rel])

def load_gravity(dir='/etc/pihole/',table='gravity'):
    db_connect = create_engine('sqlite:///'+dir+'gravity.db')
    connection = db_connect.raw_connection()
    df = pd.read_sql("SELECT * FROM {}".format(table), con=connection)
    connection.close()
    return df

def load_query_list(timestamp=None):
    if not timestamp:
        timestamp = 0
    db_connect = create_engine('sqlite:////etc/pihole/pihole-FTL.db')
    connection = db_connect.raw_connection()
    df = pd.read_sql("SELECT * FROM queries WHERE timestamp > {0}".format(timestamp), con=connection)
    connection.close()
    df['blocked'] = df.status.apply(lambda x: 0 if x in [2,3] else 1)
    return df

def update_gravity(df):
    """
    Not advisable to use. Simultaneous writing to the sql db
    causes corruption isses. Adding domains by command line
    is recommended.
    """
    db_connect = create_engine('sqlite:////etc/pihole/gravity.db', connect_args={'timeout': 15})
    connection = db_connect.raw_connection()
    df.to_sql('domainlist', con=connection,if_exists='replace',index=None)
    connection.close()

def create_dframe(domains,timestamp):
    new_dataframe = pd.DataFrame({'id':len(domains)*[1],'type':len(domains)*[1],'domain':domains,
                                  'enabled':len(domains)*[1],'date_added':len(domains)*[timestamp],
                                  'date_modified':len(domains)*[timestamp],
                                  'comment':len(domains)*['Added by Photon Sphere.']})
    return new_dataframe

def load_yttm():
    model_path = './yttm_model/yttm_ads.model'
    bpe = yttm.BPE(model=model_path)
    return bpe

def prep_data(df,timestamps,tokenizer=None):
    """Needs to be refactored for a triplet loss based model."""
    encoded_queries = pad_sequences(tokenizer.encode(list(df.loc[df.timestamp>timestamps[1]].domain.values), output_type=yttm.OutputType.ID),30,padding='post')
    df_neg = df.loc[(df.blocked==1)&(df.timestamp<timestamps[1])].domain.values
    df_pos_anchors = df.loc[(df.blocked==0)&(df.timestamp<timestamps[1])].domain.values
    df_neg_anchors = df.loc[(df.blocked==1)&(df.timestamp<timestamps[1])].domain.values
    df_pos = df.loc[(df.blocked==0)&(df.timestamp<timestamps[1])].domain.values
    min_len = np.min([len(encoded_queries),len(df_neg),len(df_pos_anchors),len(df_neg_anchors)])
    df_neg = df_neg[:min_len]
    df_pos = df_pos[-min_len:]
    df_pos_anchors = df_pos_anchors[:min_len]
    df_neg_anchors = df_neg_anchors[-min_len:]
    encoded_neg = pad_sequences(tokenizer.encode(list(df_neg), output_type=yttm.OutputType.ID),30,padding='post')
    encoded_pos_anchors = pad_sequences(tokenizer.encode(list(df_pos_anchors), output_type=yttm.OutputType.ID),30,padding='post')
    encoded_neg_anchors = pad_sequences(tokenizer.encode(list(df_neg_anchors), output_type=yttm.OutputType.ID),30,padding='post')
    encoded_pos = pad_sequences(tokenizer.encode(list(df_pos), output_type=yttm.OutputType.ID),30,padding='post')
    return encoded_queries,encoded_pos,encoded_neg,encoded_pos_anchors,encoded_neg_anchors

def run_all(tokenizer=None,timestamp=None):
    if not tokenizer:
        tokenizer = load_tokenizer()
    buffer_timestamp = str(int(timestamp)-1000)
    dframe = load_query_list(timestamp=buffer_timestamp)
    new_entries = np.sum(dframe.timestamp>timestamp)
    i = 0
    while new_entries < 1:
        if i == 0:
            print('Awaiting additional matter...')
        time.sleep(2)
        dframe = load_query_list(timestamp=buffer_timestamp)
        new_entries = np.sum(dframe.timestamp>timestamp)
        i+=1
    most_recent_timestamp = dframe.timestamp.iloc[-1]
    token_queries,token_pos,token_neg,token_pos_anchor,token_neg_anchor = prep_data(dframe,timestamps=[buffer_timestamp,timestamp],tokenizer=tokenizer)
    dframe = dframe.loc[dframe.timestamp > timestamp].reset_index()
    return token_queries,token_pos,token_neg,token_pos_anchor,token_neg_anchor,dframe,most_recent_timestamp

def triplet_loss(true,pred):
    M = 1.
    loss = tf.reduce_mean(tf.maximum(pred[:,0]**2 - pred[:,1]**2 + M,0))
    return loss

def quadruplet_loss(true,pred):
    """Modified quadruplet loss with online semi-hard negative mining."""
    m1 = 1.
    m2 = .5
    mask1 = tf.cast((pred[:,3] < pred[:,0] + m1) & (pred[:,1] < pred[:,2] + m2),tf.float32)
    loss = tf.reduce_sum(tf.maximum(tf.multiply(pred[:,0]**2 - pred[:,1]**2 + m1,mask1),0)) +\
               tf.reduce_sum(tf.maximum(tf.multiply(pred[:,2]**2 - pred[:,3]**2 + m2,mask1),0))
    return loss

def custom_acc(true,pred):
    """Needs refactoring."""
    try:
        pred_compare = tf.where(pred[:,0] < pred[:,1],True,False) & tf.where(pred[:,2] < pred[:,1],True,False)
        total = tf.keras.backend.sum(tf.cast(pred_compare,tf.float32))
        return total/tf.cast(tf.size(pred_compare),tf.float32)
    except:
        return 0

def load_model():
    """Needs refactoring."""
    model = tf.keras.models.load_model('./models/siamese_metric_quadruplet_loss_v1.h5',custom_objects={'quadruplet_loss':quadruplet_loss,'custom_acc':custom_acc})
    return model

def online_learn(learner,ref,eps=0.1):
    """Developmental."""
    ref_labels = np.where(ref > 0.5, 1, 0)
    print('Models diverge: {0}'.format(np.sum(learner_labels==ref_labels)/ref_labels.size < 1))
    if np.random.rand() > eps:
        candidate_labels = np.where(ref > 0.5, 1, 0)
    else:
        print('Epsilon!')
        candidates = np.argmin(masks[test][i:i+1])
        candidate_labels = make_multilabel(' '.join([str(int(i)) for i in np.random.randint(0,2,size=(candidates))])).reshape(1,-1)
    return candidate_labels

if __name__=='__main__':
    print('Success.')
#    df = load_gravity(table='domainlist')
#    test_df = pd.DataFrame({'id':[1],'type':[1],'domain':'old.reddit.com','enabled':[1],'date_added':1600316117,
#                            'date_modified':1600316117,'comment':'just a test domain'})
#    update_gravity(pd.concat([df,test_df]))


import sys
import time
from collections import deque

def update_queue(queue, item):
    for q in queue:
        q[0]  -= item[0]
        q[1] -= item[1]

def find_converved_region(s1, s2, p):
    longest_len = 0
    mat = 0
    mis = 0
    total = 0
    k = 0
    q = deque()
    for c1, c2 in zip(s1, s2):
        if c1 == c2:
            mat += 1
        else:
            mis += 1
            q.append([mat, mis])
        total += 1
    print("total: {}, mat: {}, mis: {}".format(total, mat, mis))
    if mat == 0:
        return "No solution"
    elif mat == 1:
        return 1
    else:
        error = int((mis / total) * 100)
        print("error: {}".format(error))
        if error < p:
            return len(s1)
        else:
            while len(q) > 0:
                item = q.popleft()
                update_queue(q, item)
                mis -= item[1]
                total -= (item[0] + item[1])
                error = int((mis / total) * 100)
                print("total: {}, mat: {}, mis: {}, error: {}".format(total, item[0], item[1], error))
                if error <= p:
                    if longest_len < total:
                        longest_len = total
    return longest_len

print(find_converved_region('ACTGGATACGTAAA', 'ACCGGTAACGTGAA', int(25)))

"""
def main(argv):
    start_time = time.time()
    print("start_time: {}".format(start_time))
    test_info = input("Seq_len percentage: ")
    n, p = test_info.split()
    while int(n) != 0:
        seq1 = input("seq1: ")
        seq2 = input("seq2: ")
        assert len(seq1) == int(n) and len(seq2) == int(n)
        print("Find the longest conserved sequence ")
        print("Seq len: {}".format(n))
        print("Allowed perc: {}".format(p))
        print("Seq1: {}".format(seq1))
        print("Seq2: {}".format(seq2))

        print(find_converved_region(seq1, seq2, int(p)))

        test_info = input("Seq_len percentage: ")
        n, p = test_info.split()

    end = time.time()
    print("Time being taken:L {}".format(time.time() - start_time))

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

"""


from config import keys, TOKEN
from extensions import ConverterException, Converter
import telebot

bot = telebot.TeleBot(TOKEN)

@bot.message_handler(commands=['start', 'help'])
def greet_function(message):
    text = "Добро пожаловать в бот пересчета валюты.\n" \
           "Для получения информации о доступных\n" \
           "валютах используйте /info.\n" \
           "Формат ввода для пересчета:\n" \
           "<Базовая валюта> <Валюта, в которую пересчитывать> <Сумма в базовой валюте>."
    bot.send_message(message.chat.id, text)

@bot.message_handler(commands=['info', ])
def info_function(message):
    text = f"Доступные валюты для пересчета:\n" \
           f"{', '.join(keys.keys())}"
    bot.send_message(message.chat.id, text)

@bot.message_handler(content_types=['text', ])
def converter_function(message):
    try:
        text = Converter.calculate_rate(message)
    except ConverterException as e:
        bot.reply_to(message, f'{e}')
    except Exception as e:
        bot.reply_to(message, f'{e}')
    else:
        bot.send_message(message.chat.id, text)

bot.polling(none_stop=True)


__copyright__ = "Copyright 2017 Renumics GmbH (http://www.renumics.com)"

from bson.dbref import DBRef
from pymongo import MongoClient, database, results, collection

from caeml.management.conf import settings

CONNECTION_NAME = 'db_connection'
_connections = {}
_dbs = {}

def get_connection(con_name: str = CONNECTION_NAME) -> MongoClient:
    if con_name not in _connections:
        _connections[con_name] = MongoClient(
            settings.DATABASE['host'], settings.DATABASE['port'])
    return _connections[con_name]

def get_db(con_name: str = CONNECTION_NAME) -> database.Database:
    if con_name not in _dbs:
        connection = get_connection(con_name)
        _dbs[con_name] = connection[settings.DATABASE['name']]
    return _dbs[con_name]

def create_collection(collection_name: str) -> None:
    collection_names = get_db().collection_names()
    if not collection_name in collection_names:
        collection.Collection(get_db(), collection_name, create=True)

def get_dictById(_id: str, collection_name: str = None) -> dict:
    query = {'_id': _id}
    return get_dictByQuery(query, collection_name)

def get_dictByQuery(query: dict, collection_name: str = None) -> dict:
    collection_names = get_db().collection_names()
    result = None
    if not collection_name is None:
        if not collection_exists(collection_name):
            return None
        result = get_db()[collection_name].find_one(query)
    else:
        for collection_name in collection_names:
            result = get_db()[collection_name].find_one(query)
            if not result is None:
                break

    return result

def add_oneDictIntoCollection(aDict: dict, collection_name: str) -> results.InsertOneResult:
    if not collection_exists(collection_name):
        create_collection(collection_name)
    return get_db()[collection_name].insert_one(aDict)

def replace_oneDictInCollection(aDict: dict, collection_name: str) -> results.UpdateResult:
    if not collection_exists(collection_name):
        raise NameError('Error! the collection "{}" does not exist in the database!'.format(collection_name))
    return get_db()[collection_name].replace_one({'_id': aDict['_id']}, aDict)

def dereference(dbRef: DBRef) -> dict:
    return get_db().dereference(dbRef)

def collection_exists(collection_name: str) -> bool:
    collection_names = get_db().collection_names()
    return collection_name in collection_names


import operator

from llvmlite import ir
from numba.core import cgutils
from numba.core.typing import signature as nb_signature
from numba.cuda.cudaimpl import (
    lower as cuda_lower,
    registry as cuda_lowering_registry,
)
from numba.extending import lower_builtin, types

from cudf.core.udf import api
from cudf.core.udf._ops import (
    arith_ops,
    bitwise_ops,
    comparison_ops,
    unary_ops,
)
from cudf.core.udf.masked_typing import (
    MaskedType,
    NAType,
    _supported_masked_types,
)

@cuda_lowering_registry.lower_constant(NAType)
def constant_na(context, builder, ty, pyval):
    # This handles None, etc.
    return context.get_dummy_value()

# In the typing phase, we declared that a `MaskedType` can be
# added to another `MaskedType` and specified what kind of a
# `MaskedType` would result. Now we have to actually fill in
# the implementation details of how to do that. This is where
# we can involve both validities in constructing the answer

def make_arithmetic_op(op):
    """
    Make closures that implement arithmetic operations. See
    register_arithmetic_op for details.
    """

    def masked_scalar_op_impl(context, builder, sig, args):
        """
        Implement `MaskedType` <op> `MaskedType`
        """
        # MaskedType(...), MaskedType(...)
        masked_type_1, masked_type_2 = sig.args
        # MaskedType(...)
        masked_return_type = sig.return_type

        # Let there be two actual LLVM structs backing the two inputs
        # https://mapping-high-level-constructs-to-llvm-ir.readthedocs.io/en/latest/basic-constructs/structures.html
        m1 = cgutils.create_struct_proxy(masked_type_1)(
            context, builder, value=args[0]
        )
        m2 = cgutils.create_struct_proxy(masked_type_2)(
            context, builder, value=args[1]
        )

        # we will return an output struct
        result = cgutils.create_struct_proxy(masked_return_type)(
            context, builder
        )
        # compute output validity
        valid = builder.and_(m1.valid, m2.valid)
        result.valid = valid
        with builder.if_then(valid):
            # Let numba handle generating the extra IR needed to perform
            # operations on mixed types, by compiling the final core op between
            # the two primitive values as a separate function and calling it
            result.value = context.compile_internal(
                builder,
                lambda x, y: op(x, y),
                nb_signature(
                    masked_return_type.value_type,
                    masked_type_1.value_type,
                    masked_type_2.value_type,
                ),
                (m1.value, m2.value),
            )
        return result._getvalue()

    return masked_scalar_op_impl

def make_unary_op(op):
    """
    Make closures that implement unary operations. See register_unary_op for
    details.
    """

    def masked_scalar_unary_op_impl(context, builder, sig, args):
        """
        Implement <op> `MaskedType`
        """
        # MaskedType(...)
        masked_type_1 = sig.args[0]
        # MaskedType(...)
        masked_return_type = sig.return_type

        m1 = cgutils.create_struct_proxy(masked_type_1)(
            context, builder, value=args[0]
        )

        # we will return an output struct
        result = cgutils.create_struct_proxy(masked_return_type)(
            context, builder
        )

        # compute output validity
        result.valid = m1.valid
        with builder.if_then(m1.valid):
            # Let numba handle generating the extra IR needed to perform
            # operations on mixed types, by compiling the final core op between
            # the two primitive values as a separate function and calling it
            result.value = context.compile_internal(
                builder,
                lambda x: op(x),
                nb_signature(
                    masked_return_type.value_type,
                    masked_type_1.value_type,
                ),
                (m1.value,),
            )
        return result._getvalue()

    return masked_scalar_unary_op_impl

def register_arithmetic_op(op):
    """
    Register a lowering implementation for the
    arithmetic op `op`.

    Because the lowering implementations compile the final
    op separately using a lambda and compile_internal, `op`
    needs to be tied to each lowering implementation using
    a closure.

    This function makes and lowers a closure for one op.

    """
    to_lower_op = make_arithmetic_op(op)
    cuda_lower(op, MaskedType, MaskedType)(to_lower_op)

def register_unary_op(op):
    """
    Register a lowering implementation for the
    unary op `op`.

    Because the lowering implementations compile the final
    op separately using a lambda and compile_internal, `op`
    needs to be tied to each lowering implementation using
    a closure.

    This function makes and lowers a closure for one op.

    """
    to_lower_op = make_unary_op(op)
    cuda_lower(op, MaskedType)(to_lower_op)

def masked_scalar_null_op_impl(context, builder, sig, args):
    """
    Implement `MaskedType` <op> `NAType`
    or `NAType` <op> `MaskedType`
    The answer to this is known up front so no actual operation
    needs to take place
    """

    return_type = sig.return_type  # MaskedType(...)
    result = cgutils.create_struct_proxy(MaskedType(return_type.value_type))(
        context, builder
    )

    # Invalidate the struct and leave `value` uninitialized
    result.valid = context.get_constant(types.boolean, 0)
    return result._getvalue()

def make_const_op(op):
    def masked_scalar_const_op_impl(context, builder, sig, args):
        return_type = sig.return_type
        result = cgutils.create_struct_proxy(return_type)(context, builder)
        result.valid = context.get_constant(types.boolean, 0)
        if isinstance(sig.args[0], MaskedType):
            masked_type, const_type = sig.args
            masked_value, const_value = args

            indata = cgutils.create_struct_proxy(masked_type)(
                context, builder, value=masked_value
            )
            nb_sig = nb_signature(
                return_type.value_type, masked_type.value_type, const_type
            )
            compile_args = (indata.value, const_value)
        else:
            const_type, masked_type = sig.args
            const_value, masked_value = args
            indata = cgutils.create_struct_proxy(masked_type)(
                context, builder, value=masked_value
            )
            nb_sig = nb_signature(
                return_type.value_type, const_type, masked_type.value_type
            )
            compile_args = (const_value, indata.value)
        with builder.if_then(indata.valid):
            result.value = context.compile_internal(
                builder, lambda x, y: op(x, y), nb_sig, compile_args
            )
            result.valid = context.get_constant(types.boolean, 1)
        return result._getvalue()

    return masked_scalar_const_op_impl

def register_const_op(op):
    to_lower_op = make_const_op(op)
    cuda_lower(op, MaskedType, types.Number)(to_lower_op)
    cuda_lower(op, types.Number, MaskedType)(to_lower_op)
    cuda_lower(op, MaskedType, types.Boolean)(to_lower_op)
    cuda_lower(op, types.Boolean, MaskedType)(to_lower_op)
    cuda_lower(op, MaskedType, types.NPDatetime)(to_lower_op)
    cuda_lower(op, types.NPDatetime, MaskedType)(to_lower_op)
    cuda_lower(op, MaskedType, types.NPTimedelta)(to_lower_op)
    cuda_lower(op, types.NPTimedelta, MaskedType)(to_lower_op)

# register all lowering at init
for binary_op in arith_ops + bitwise_ops + comparison_ops:
    register_arithmetic_op(binary_op)
    register_const_op(binary_op)
    # null op impl can be shared between all ops
    cuda_lower(binary_op, MaskedType, NAType)(masked_scalar_null_op_impl)
    cuda_lower(binary_op, NAType, MaskedType)(masked_scalar_null_op_impl)

# register all lowering at init
for unary_op in unary_ops:
    register_unary_op(unary_op)
register_unary_op(abs)

@cuda_lower(operator.is_, MaskedType, NAType)
@cuda_lower(operator.is_, NAType, MaskedType)
def masked_scalar_is_null_impl(context, builder, sig, args):
    """
    Implement `MaskedType` is `NA`
    """
    if isinstance(sig.args[1], NAType):
        masked_type, na = sig.args
        value = args[0]
    else:
        na, masked_type = sig.args
        value = args[1]

    indata = cgutils.create_struct_proxy(masked_type)(
        context, builder, value=value
    )
    result = cgutils.alloca_once(builder, ir.IntType(1))
    with builder.if_else(indata.valid) as (then, otherwise):
        with then:
            builder.store(context.get_constant(types.boolean, 0), result)
        with otherwise:
            builder.store(context.get_constant(types.boolean, 1), result)

    return builder.load(result)

# Main kernel always calls `pack_return` on whatever the user defined
# function returned. This returns the same data if its already a `Masked`
# else packs it up into a new one that is valid from the get go
@cuda_lower(api.pack_return, MaskedType)
def pack_return_masked_impl(context, builder, sig, args):
    return args[0]

@cuda_lower(api.pack_return, types.Boolean)
@cuda_lower(api.pack_return, types.Number)
@cuda_lower(api.pack_return, types.NPDatetime)
@cuda_lower(api.pack_return, types.NPTimedelta)
def pack_return_scalar_impl(context, builder, sig, args):
    outdata = cgutils.create_struct_proxy(sig.return_type)(context, builder)
    outdata.value = args[0]
    outdata.valid = context.get_constant(types.boolean, 1)

    return outdata._getvalue()

@cuda_lower(operator.truth, MaskedType)
@cuda_lower(bool, MaskedType)
def masked_scalar_bool_impl(context, builder, sig, args):
    indata = cgutils.create_struct_proxy(sig.args[0])(
        context, builder, value=args[0]
    )
    result = cgutils.alloca_once(builder, ir.IntType(1))
    with builder.if_else(indata.valid) as (then, otherwise):
        with then:
            builder.store(
                context.cast(
                    builder,
                    indata.value,
                    sig.args[0].value_type,
                    types.boolean,
                ),
                result,
            )
        with otherwise:
            builder.store(context.get_constant(types.boolean, 0), result)
    return builder.load(result)

@cuda_lower(float, MaskedType)
@cuda_lower(int, MaskedType)
def masked_scalar_cast_impl(context, builder, sig, args):
    input = cgutils.create_struct_proxy(sig.args[0])(
        context, builder, value=args[0]
    )
    result = cgutils.create_struct_proxy(sig.return_type)(context, builder)

    casted = context.cast(
        builder,
        input.value,
        sig.args[0].value_type,
        sig.return_type.value_type,
    )
    result.value = casted
    result.valid = input.valid
    return result._getvalue()

# To handle the unification, we need to support casting from any type to a
# masked type. The cast implementation takes the value passed in and returns
# a masked type struct wrapping that value.
@cuda_lowering_registry.lower_cast(types.Any, MaskedType)
def cast_primitive_to_masked(context, builder, fromty, toty, val):
    casted = context.cast(builder, val, fromty, toty.value_type)
    ext = cgutils.create_struct_proxy(toty)(context, builder)
    ext.value = casted
    ext.valid = context.get_constant(types.boolean, 1)
    return ext._getvalue()

@cuda_lowering_registry.lower_cast(NAType, MaskedType)
def cast_na_to_masked(context, builder, fromty, toty, val):
    result = cgutils.create_struct_proxy(toty)(context, builder)
    result.valid = context.get_constant(types.boolean, 0)

    return result._getvalue()

@cuda_lowering_registry.lower_cast(MaskedType, MaskedType)
def cast_masked_to_masked(context, builder, fromty, toty, val):
    """
    When numba encounters an op that expects a certain type and
    the input to the op is not of the expected type it will try
    to cast the input to the appropriate type. But, in our case
    the input may be a MaskedType, which numba doesn't natively
    know how to cast to a different MaskedType with a different
    `value_type`. This implements and registers that cast.
    """

    # We will
    operand = cgutils.create_struct_proxy(fromty)(context, builder, value=val)
    casted = context.cast(
        builder, operand.value, fromty.value_type, toty.value_type
    )
    ext = cgutils.create_struct_proxy(toty)(context, builder)
    ext.value = casted
    ext.valid = operand.valid
    return ext._getvalue()

# Masked constructor for use in a kernel for testing
def masked_constructor(context, builder, sig, args):
    ty = sig.return_type
    value, valid = args
    masked = cgutils.create_struct_proxy(ty)(context, builder)
    masked.value = value
    masked.valid = valid
    return masked._getvalue()

for ty in _supported_masked_types:
    lower_builtin(api.Masked, ty, types.boolean)(masked_constructor)

# Allows us to make an instance of MaskedType a global variable
# and properly use it inside functions we will later compile
@cuda_lowering_registry.lower_constant(MaskedType)
def lower_constant_masked(context, builder, ty, val):
    masked = cgutils.create_struct_proxy(ty)(context, builder)
    masked.value = context.get_constant(ty.value_type, val.value)
    masked.valid = context.get_constant(types.boolean, val.valid)
    return masked._getvalue()


import pygame
import src.Utils.pg_utils as f_pg
from src.entity import Entity

class Projectil(pygame.sprite.Sprite):

    def __init__(self, map_manager):
        super().__init__()
        self.map_manager = map_manager
        self.image = f_pg.pygame_image('assets/images/weapons/projectile/projectile.png', [7, 7])
        self.rect = self.image.get_rect()
        x = self.map_manager.player.position[0]
        y = self.map_manager.player.position[1]
        self.position = [x, y]
        self.feet = pygame.Rect(0, 0, self.rect.width * 0.5, 12)

    def isEnemy(self): return False

    def remove(self):
        self.map_manager.get_map().projectils.remove(self)
        self.map_manager.get_group().remove(self)

    def move(self):
        self.position[1] -= 4
        for enemy in self.map_manager.check_projectile_collision(self, self.map_manager.get_map().enemys):
            self.remove()
            enemy.apply_damage(self.map_manager.player.selected_weapon.damage)

    def update(self):
        self.rect.topleft = self.position
        self.feet.midbottom = self.rect.midbottom


import sqlalchemy
import database as db
from faker import Faker

NUM_USERS = 5000
fake = Faker()

diary1_days = ["Upper", "Lower"]
diary2_days = ["Push", "Pull", "Legs"]
diary1_values = []
diary2_values = []
entries_to_insert = []

users = set()

while len(users) < NUM_USERS:
    users.add(fake.email())

with db.engine.begin() as connection:
    for user in users:
        diary_id_1 = connection.execute(sqlalchemy.text("INSERT INTO diary(owner) VALUES (:user) RETURNING id"), {"user": user}).scalar_one()
        diary1_values.extend({"day_name": day, "diary_id": diary_id_1} for day in diary1_days)
        diary_id_2 = connection.execute(sqlalchemy.text("INSERT INTO diary(owner) VALUES (:user) RETURNING id"), {"user": user}).scalar_one()
        diary2_values.extend({"day_name": day, "diary_id": diary_id_2} for day in diary2_days)
    connection.execute(sqlalchemy.text("INSERT INTO day (day_name, diary_id) VALUES (:day_name, :diary_id)"), diary1_values)
    connection.execute(sqlalchemy.text("INSERT INTO day (day_name, diary_id) VALUES (:day_name, :diary_id)"), diary2_values)

with db.engine.begin() as connection:
    for day_name in diary1_days + diary2_days:
        for user in users:
            day_id = connection.execute(sqlalchemy.text("""
                SELECT day.id
                FROM day
                JOIN diary ON day.diary_id = diary.id
                WHERE day_name = :day_name AND owner = :user
                LIMIT 1"""), {"day_name": day_name, "user": user}).scalar_one()
            entries_to_insert.extend(
                {"day_id": day_id, "exercise": "Barbell Squat", "goal_reps": 5, "goal_weight": 315,
                 "reps": 5, "weight": 315, "comments": "Good."} for _ in range(8))
            entries_to_insert.extend(
                {"day_id": day_id, "exercise": "Chest dip", "goal_reps": 5, "goal_weight": 90,
                 "reps": 5, "weight": 90, "comments": "Good."} for _ in range(8))
            entries_to_insert.extend(
                {"day_id": day_id, "exercise": "Dumbbell Bench Press", "goal_reps": 10, "goal_weight": 110,
                 "reps": 10, "weight": 110, "comments": "Good."} for _ in range(8))
            entries_to_insert.extend(
                {"day_id": day_id, "exercise": "Pullups", "goal_reps": 8, "goal_weight": 45,
                 "reps": 8, "weight": 45, "comments": "Good."} for _ in range(8))
            entries_to_insert.extend(
                {"day_id": day_id, "exercise": "Barbell Deadlift", "goal_reps": 5, "goal_weight": 405,
                 "reps": 5, "weight": 405, "comments": "Good."} for _ in range(8))
    connection.execute(sqlalchemy.text("""
        INSERT INTO entry (day_id, exercise, goal_reps, goal_weight, reps, weight, comments)
        VALUES (:day_id, :exercise, :goal_reps, :goal_weight, :reps, :weight, :comments)
        """), entries_to_insert)


from typing import Any, Sequence, Union, Iterable, Optional
import functools

from flax import linen as nn
from flax.linen import partitioning as nn_partitioning
from flax import struct
import jax.numpy as jnp
from t5x.contrib.gpu.t5.layers import MultiHeadDotProductAttention, make_attention_mask
from flax.linen import DenseGeneral, Conv, LayerNorm, GroupNorm
import jax
from einops import rearrange

param_with_axes = nn_partitioning.param_with_axes
OptionalArray = Optional[jnp.ndarray]
Array = jnp.ndarray

default_embed_init = nn.initializers.variance_scaling(
    1.0, 'fan_in', 'normal', out_axis=0)

@struct.dataclass
class DiffusionConfig:
  dtype: Any = jnp.float32
  model_dim: int = 64
  attn_cond_dim: int = 512
  cond_dim: Optional[int] = None #timestep/pooled text embedding channels. Defaults to model_dim*4
  resblocks_per_level: Union[int, Sequence[int]] = 2
  width_multipliers: Sequence[int] = (1, 2, 3, 4)
  attn_resolutions: Sequence[int] = (32, 16, 8)
  mha_head_dim: int = 64
  attn_heads: Union[int, Sequence[int]] = 2
  unified_qkv_norm: bool = False
  deepfloyd_attnpooling: bool = False
  resblock_activation: str = 'swish'
  resblock_scale_skip: bool = False
  output_ch: int = 3
  dropout_rate: float = 0.1

  # modes are 'shuffle', 'conv' and 'resize'.
  #            (upsampling   , downsampling)
  # shuffle -> pixel shuffle / unshuffle
  # conv    -> resize + conv / strided conv
  # resize  -> interpolation / average pool
  upsample_mode: str = 'shuffle'
  downsample_mode: str = 'shuffle'

  # If True, block will use a 3x3 conv instead of 1x1 conv to correct
  # channel dim mismatch in skip connection (if one exists)
  spatial_skip: bool = False

  # 'shift_scale' or 'addition'. Strategy for incorporating the conditioning vector.
  cond_strategy: str = 'shift_scale'

  # force groupnorm in fp32
  norm_32: bool = True

  # scale attention logits by \sqrt(head_dim)
  scale_attn_logits: bool = True
  float32_attention_logits: bool =False
  text_conditionable: bool = True
  null_text_emb_ct: int = 0

def single_or_idx(possibly_iter, idx):
    if isinstance(possibly_iter, Sequence):
        return possibly_iter[idx]
    else:
        return possibly_iter

class ImagenUNet(nn.Module):
  """ An Imagen diffusion U-net """
  config: DiffusionConfig

  @nn.compact
  def __call__(self, images, time,
               text_enc: OptionalArray=None,
               text_lens: OptionalArray=None,
               low_res_images: OptionalArray=None,
               noise_aug_level: OptionalArray=None,
               enable_dropout=True):
    """
    Args:
    images: samples to denoise. [b, h, w, c]
    time:   time conditioning. [b, 1]
    text_enc: text embeddings (required for text_conditionable) [b, seq_len, embed]
    text_lens: text sequence lengths in binary mask format      [b, seq_len]
    """
    from rosetta.projects.imagen import layers  # to avoid circular import
    cfg = self.config
    activation = layers._convert_to_activation_function(cfg.resblock_activation)
    deterministic=not enable_dropout
    linear = functools.partial(DenseGeneral,
                               axis=-1,
                               use_bias=True,
                               dtype=cfg.dtype,
                               kernel_axes=('embed',))

    spatial_conv = functools.partial(Conv,
                                     kernel_size=(3,3),
                                     strides=1,
                                     padding='SAME',
                                     dtype=cfg.dtype)
    input_ch = images.shape[-1]

    # create time embedding
    if cfg.cond_dim is None:
        time_embed_dim = cfg.model_dim * 4
    else:
        time_embed_dim = cfg.cond_dim
    cond_embed = layers.get_timestep_embedding(time, cfg.model_dim, dtype=jnp.float32)
    cond_embed = linear(features=time_embed_dim, name='time_dense_1')(cond_embed)
    cond_embed = activation(cond_embed)
    cond_embed = linear(features=time_embed_dim, name='time_dense_2')(cond_embed)

    if low_res_images is not None:
        print('Low res images available. Running as a superresolution network')
        if noise_aug_level is None:
            jax.debug.print('noise_aug not given but it *really* should be')
            noise_aug_level = jnp.ones_like(time) * (.25 * jnp.log(0.002)) # fallback EDM c_noise_fn on minimal noise
        aug_embed = layers.get_timestep_embedding(noise_aug_level, cfg.model_dim, dtype=jnp.float32)
        aug_embed = linear(features=time_embed_dim, name='aug_dense_1')(aug_embed)
        aug_embed = activation(aug_embed)
        aug_embed = linear(features=time_embed_dim, name='aug_dense_2')(aug_embed)

        cond_embed = cond_embed + aug_embed

        scaled_low_res = jax.image.resize(low_res_images, images.shape, "bicubic")
        images = jnp.concatenate([images, scaled_low_res], axis=-1)

    # create attn pooled text embedding and project text to cond_dim
    if cfg.text_conditionable:
        assert text_lens is not None, "text_lens cannot be None. If you're trying to null condition, pass in a 0 mask"
        assert text_enc is not None, "text_enc cannot be None. If you're trying to null condition, pass in 0s of appropriate shape. This network will add in the requisite null tokens"

        # setup null tokens
        if cfg.null_text_emb_ct > 0:
            null_text_mask = jnp.sum(text_lens, axis=1, keepdims=True)

            embedding_init = nn.initializers.variance_scaling(1.0, 'fan_in', 'normal', out_axis=0)
            null_text_embedding = param_with_axes(
                'null_text_embeddings',
                embedding_init,
                (cfg.null_text_emb_ct, text_enc.shape[-1]),
                jnp.float32,
                axes=('vocab', 'embed'))

            # first null_text_emb_ct tokens to null_text_embedding
            null_text_enc = jnp.zeros_like(text_enc[0:1]).at[:, :cfg.null_text_emb_ct].set(null_text_embedding)
            null_text_lens = jnp.zeros_like(text_lens[0:1]).at[:, :cfg.null_text_emb_ct].set(1)
            text_enc = jnp.where(jnp.expand_dims(null_text_mask, axis=-1) > 0, text_enc, null_text_enc)
            text_lens = jnp.where(null_text_mask > 0, text_lens, null_text_lens)

        # attention pooling
        if isinstance(cfg.attn_heads, Iterable):
            num_heads = text_enc.shape[-1] // cfg.mha_head_dim
        else:
            num_heads = None

        if cfg.deepfloyd_attnpooling:
            attn_pooled = LayerNorm(dtype=jnp.float32 if cfg.norm_32 else cfg.dtype, name='attn_pool_ln_0')(text_enc)
            attn_pooled = layers.DeepFloydAttentionPoolingBlock(cfg=cfg, num_heads=num_heads)(attn_pooled, text_lens)
            attn_pooled = linear(features=cfg.attn_cond_dim, name='attn_pool_dense_0')(attn_pooled)
            attn_pooled = LayerNorm(dtype=jnp.float32 if cfg.norm_32 else cfg.dtype, name='attn_pool_ln_1')(attn_pooled)
        else:
            attn_pooled = layers.AttentionPoolingBlock(cfg=cfg, num_heads=num_heads)(text_enc, text_lens)
            attn_pooled = LayerNorm(dtype=jnp.float32 if cfg.norm_32 else cfg.dtype, name='attn_pool_ln_0')(attn_pooled)
            attn_pooled = linear(features=cfg.attn_cond_dim, name='attn_pool_dense_0')(attn_pooled)
            attn_pooled = LayerNorm(dtype=jnp.float32 if cfg.norm_32 else cfg.dtype, name='attn_pool_ln_1')(attn_pooled)
            attn_pooled = linear(features=time_embed_dim, name='attn_pool_dense_1')(attn_pooled)
            attn_pooled = activation(attn_pooled)
            attn_pooled = linear(features=time_embed_dim, name='attn_pool_dense_2')(attn_pooled)

        cond_embed = attn_pooled + cond_embed # Has dimension of time_embed_dim

        # text embedding projection to cond_dim
        text_enc = linear(features=cfg.attn_cond_dim, name='text_enc_projection')(text_enc)

    # make image_channel -> model_dim convolution
    x = spatial_conv(features=cfg.model_dim * cfg.width_multipliers[0], name='unet_in_conv')(images)

    # down branch resblocks + attn on designated resolutions
    down_outputs = [x]
    for level, width_mult in enumerate(cfg.width_multipliers):
        level_channels = cfg.model_dim * width_mult
        img_res = images.shape[1] // (2 ** level)

        for res_idx in range(single_or_idx(cfg.resblocks_per_level, level)):
            x = layers.ResBlock(cfg=cfg, out_channels=level_channels, up_down_sample='none',
                                name='resblock_enc_{}_{}'.format(img_res, res_idx)) \
                                (x, cond_embed, deterministic=deterministic)
            print("Encoder ResBlock #", res_idx, " at resolution: ", img_res, " level: ", level, " width: ", level_channels)

            # attend if image is of designated resolution
            if img_res in cfg.attn_resolutions:
                attn_idx = level - (len(cfg.width_multipliers) - len(cfg.attn_resolutions))
                x = layers.ImgAttentionBlock(cfg=cfg, num_heads=single_or_idx(cfg.attn_heads, attn_idx), name='attnblock_enc_{}_{}'.format(img_res, res_idx)) \
                                            (x, text_enc, text_lens, deterministic=deterministic)
                print("SelfAttentionBlock #", res_idx, " at resolution: ", img_res, " level: ", level, " width: ", level_channels)

            down_outputs.append(x)

        # if not on the last level, downsample
        if level != len(cfg.width_multipliers) - 1:
            x = layers.ResBlock(cfg=cfg, out_channels=level_channels, up_down_sample='down',
                                name='resblock_enc_downsampling_{}_{}'.format(img_res, res_idx)) \
                                (x, cond_embed, deterministic=deterministic)
            print("Downsampling ResBlock at resolution (to half): ", img_res, " level: ", level, " width: ", level_channels)
            down_outputs.append(x)

    # middle layers
    mid_channels = cfg.model_dim * cfg.width_multipliers[-1]
    x = layers.ResBlock(cfg=cfg, out_channels=mid_channels, up_down_sample='none',
                        name='resblock_mid_1')(x, cond_embed, deterministic=deterministic)
    x = layers.ImgAttentionBlock(cfg=cfg, num_heads=single_or_idx(cfg.attn_heads, -1),name='attnblock_mid_1')(x, text_enc, text_lens, deterministic=deterministic)
    x = layers.ResBlock(cfg=cfg, out_channels=mid_channels, up_down_sample='none',
                        name='resblock_mid_2')(x, cond_embed, deterministic=deterministic)

    print('Encoder Skip Shapes: ',list(map(lambda x : x.shape, down_outputs)))
    # up branch resblocks + attn on designated resolutions + skip connections
    for level, width_mult in list(enumerate(cfg.width_multipliers))[::-1]:
        level_channels = cfg.model_dim * width_mult
        img_res = images.shape[1] // (2 ** level)

        for res_idx in range(single_or_idx(cfg.resblocks_per_level, level) + 1):
            u_skip = down_outputs.pop()
            print("Decoder ResBlock #", res_idx, " at resolution: ", img_res, " level: ", level, " width: ", level_channels, " skip shape: ", u_skip.shape)
            x = jnp.concatenate([x, u_skip], axis=-1)
            x = layers.ResBlock(cfg=cfg, out_channels=level_channels, up_down_sample='none',
                                name='resblock_dec_{}_{}'.format(img_res, res_idx)) \
                                (x, cond_embed, deterministic=deterministic)

            # attend if image is of designated resolution
            if img_res in cfg.attn_resolutions:
                print("SelfAttentionBlock #", res_idx, " at resolution: ", img_res, " level: ", level, " width: ", level_channels)
                attn_idx = level - (len(cfg.width_multipliers) - len(cfg.attn_resolutions))
                x = layers.ImgAttentionBlock(cfg=cfg, num_heads=single_or_idx(cfg.attn_heads, attn_idx), name='attnblock_dec_{}_{}'.format(img_res, res_idx))\
                                            (x, text_enc, text_lens, deterministic=deterministic)

            # upsample if on last resblock and not the highest level
            if res_idx == single_or_idx(cfg.resblocks_per_level, level) and level != 0:
                print("Upsamling ResBlock at resolution (to double): ", img_res, " level: ", level, " width: ", level_channels, " no skip")
                x = layers.ResBlock(cfg=cfg, out_channels=level_channels, up_down_sample='up',
                                    name='resblock_dec_upsampling_{}_{}'.format(img_res, res_idx)) \
                                    (x, cond_embed, deterministic=deterministic)

    # out convolution model_dim -> image_channels
    x = layers.FP32Wrap(GroupNorm(num_groups=32, name='unet_out_gn'))(x)
    x = activation(x)
    # x = spatial_conv(features=cfg.output_ch, name='unet_out_conv', kernel_init=nn.initializers.zeros, no_embed_axis=True)(x)
    x = spatial_conv(features=cfg.output_ch, name='unet_out_conv', kernel_init=nn.initializers.zeros)(x)
    return x


"""cosmian_secure_computation_client.participant.computation_owner module."""

from typing import List, Tuple
import os

import requests

from cosmian_secure_computation_client.api.provider import (create_computation,
                                                            computations)
from cosmian_secure_computation_client.api.auth import Connection
from cosmian_secure_computation_client.computations import Computation
from cosmian_secure_computation_client.log import LOGGER
from cosmian_secure_computation_client.util.mnemonic import random_words

class ComputationOwnerAPI:
    """ComputationOwnerAPI class.

    Parameters
    ----------
    token : str
        Refresh token to authenticate with Cosmian's backend.

    Attributes
    ----------
    conn : Connection
        Manage authentication to Cosmian's backend.

    """

    def __init__(self, token: str) -> None:
        """Init constructor of ComputationOwnerAPI."""
        self.conn = Connection(base_url=os.getenv(
            "COSMIAN_BASE_URL", default="https://backend.cosmian.com"),
                               refresh_token=token)

    @staticmethod
    def random_words() -> Tuple[str, str, str]:
        """Generate 3 random words to be used as pre-shared secret."""
        w1, w2, w3 = random_words()  # type: str, str, str
        LOGGER.info("Generating pre-shared secret: '%s %s %s'", w1, w2, w3)

        return w1, w2, w3

    def create_computation(self,
                           name: str,
                           code_provider_email: str,
                           data_providers_emails: List[str],
                           result_consumers_emails: List[str],
                           dev_mode: bool = False) -> Computation:
        """Invite participants to a new computation named `name`."""
        r: requests.Response = create_computation(
            conn=self.conn,
            name=name,
            cp_mail=code_provider_email,
            dps_mail=data_providers_emails,
            rcs_mail=result_consumers_emails,
            dev_mode=dev_mode)

        if not r.ok:
            raise Exception(
                f"Unexpected response ({r.status_code}): {r.content!r}")

        c: Computation = Computation.from_json_dict(r.json())
        LOGGER.info("Computation '%s' created: %s", c.name, c.uuid)

        return c

    def get_computations(self) -> List[Computation]:
        """Retriveve all computations related to your account."""
        r: requests.Response = computations(conn=self.conn)

        if not r.ok:
            raise Exception(
                f"Unexpected response ({r.status_code}): {r.content!r}")

        cs: List[Computation] = [
            Computation.from_json_dict(dct) for dct in r.json()
        ]
        LOGGER.info("Computations available: %s",
                    [(c.name, c.uuid) for c in cs])

        return cs