import cv2
import numpy as np
from skimage.morphology import skeletonize
from util import *
from branches import *
# from analysis import skeleton, multi_hit_miss
from analysis.skeleton import fast_skeletonize
from analysis.hitmiss import old_get_end_points, get_image_convolve, get_branch_point_matches, old_scan_for_end, scan_for_end, scan_for_branch

# create the membrane properties
min_membrane_threshold = 25  # the min threshold (0-255) for the membrane to be considered valid
min_membrane_length = 40  # the min membrane length
min_membrane_area = 15  # the min area of the membrane (currently not used)
max_membrane_width = 50  # the max width of the membrane (currently not used)
max_corner_edge_distance = 10  # distance for a corner to be the edge of the image
max_corner_branch_distance = 10  # distance for a corner and branch distance to be considered valid
max_corner_distance = 150  # max distance that corners can be from each other
dilate_membrane = 3
epsilon_membrane = 1
in_membrane_checks = 5

def process_membrane(layer):
    threshed = cv2.threshold(layer, min_membrane_threshold, 255, cv2.THRESH_BINARY)[1]

    """
    dilated = cv2.dilate(threshed, np.ones((dilate_membrane, dilate_membrane), np.int8), iterations=1)
    dilated = cv2.blur(dilated, (3, 3))
    dilated = cv2.medianBlur(dilated, 7)
    dilated = cv2.threshold(dilated, 5, 255, cv2.THRESH_BINARY)[1]
    # dilated = cv2.bilateralFilter(dilated, 13, 125, 125)
    # cv2.imshow('test', dilated)
    """

    skeleton = fast_skeletonize((threshed / 255).astype(np.uint8))
    branch_points = scan_for_branch(skeleton, row_first=False)
    skeleton = skeleton.astype(np.uint8) * 255

    """
    skeleton = skeletonize(threshed / 255)
    testing = multi_hit_miss(skeleton)
    branch_points = detect_branch_points(skeleton)
    skeleton = skeleton.astype(np.uint8) * 255
    """

    # destroy the branch connections
    for x, y in branch_points:
        cv2.rectangle(skeleton, (x - 3, y - 3), (x + 3, y + 3), 0, -1)

    # subdivide each skeleton contour and find the best two edges of each contour
    contours = cv2.findContours(skeleton, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
    height, width = layer.shape[:2]
    left, top, right, bottom = 0, 0, width - 1, height - 1
    corner_lines = []
    padding = 10
    for cont in contours:
        x, y, w, h = cv2.boundingRect(cont)
        single_contour = np.zeros((h + 2 * padding, w + 2 * padding, 1), np.uint8)
        offset = np.array([(int(p_x - x + padding), int(p_y - y + padding)) for p_x, p_y in cont.reshape(-1, 2)],
                          np.int32)
        cv2.drawContours(single_contour, [offset], 0, 255, 1)
        # edges = cv2.dilate(single_contour, np.ones((5, 5), np.uint8), iterations=1)

        test_ind = 0
        corners = []
        while test_ind < 3:  # test a max of 3 branches
            passed = True
            # end_points = detect_end_points((single_contour / 255).reshape(single_contour.shape[:2]).astype(np.bool))
            # corns = cv2.goodFeaturesToTrack(edges, 2 + test_ind, 0.3, 20)
            end_points = scan_for_end((single_contour / 255).reshape(single_contour.shape[:2]).astype(np.uint8), row_first=False)

            corners = []
            if end_points is not None:
                failed = 0
                for p_x, p_y in end_points:
                    # p_x, p_y = corner.ravel()
                    p_x, p_y = int(p_x + x - padding), int(p_y + y - padding)

                    """
                    # make sure it's not a branch point
                    on_edge = True
                    for branch in branch_points:
                        if point_distance((p_x, p_y), branch) < max_corner_branch_distance:
                            on_edge = False
                            failed += 1
                            break

                    if on_edge:
                    """
                    corners.append((p_x, p_y))
                if failed == test_ind + 1:
                    passed = False

            if passed:
                break

            test_ind += 1

        # we need to have two corners to continue or we're stuck in a loop
        is_loop = len(corners) < 2

        """
        if len(corners) < 2:
            continue
        """

        vectors = cont.reshape(-1, 2)

        if is_loop:
            corner_lines.append((vectors, (vectors[0], vectors[-1])))
        else:
            first = closest_to(corners[0], vectors)
            second = closest_to(corners[1], vectors)
            start = min(first, second)
            end = max(first, second)
            corner_lines.append((vectors[start:end], (vectors[start], vectors[end])))

    # revisit the lines with corners and try to attach nearby contours
    overlap_lines = []
    ind_line = 0
    connected_lines = []
    connected_corners = []
    for line, corners in corner_lines:
        c_line = list(line.reshape(-1, 2))
        for corner in corners:
            closest = sys.maxsize
            closest_point = None
            is_end = False
            for o_line, o_corners in corner_lines[ind_line + 1:]:
                for o_corner in o_corners:
                    dist = point_distance(corner, o_corner)
                    x, y = tuple(corner)
                    if x - max_corner_edge_distance <= left or x + max_corner_edge_distance > right or \
                            y - max_corner_edge_distance <= top or y + max_corner_edge_distance >= bottom:
                        continue
                    elif dist < closest and dist < max_corner_distance:
                        closest = dist
                        closest_point = (o_line, o_corner)
                        is_end = bool(tuple(o_corner) == tuple(o_corners[-1]))

            if closest_point is not None and \
                    not (tuple(corner) in connected_corners or tuple(closest_point[1]) in connected_corners):
                s_line = list(closest_point[0].reshape(-1, 2))
                is_first_end = bool(tuple(corner) == tuple(corners[-1]))

                # order the lines properly
                if is_first_end and not is_end:
                    c_line.extend(s_line)
                elif is_first_end and is_end:
                    c_line.extend(list(reversed(s_line)))
                elif not is_first_end and not is_end:
                    c_line = list(reversed(c_line))
                    c_line.extend(s_line)
                else:
                    temp = c_line[:]
                    c_line = s_line
                    c_line.extend(temp)

                # add it to the already connected corners and lines
                connected_corners.extend([tuple(corner), tuple(closest_point[1])])
                connected_lines.append((c_line, closest_point[0]))

        # process the revised line to make sure it's up to spec
        line = np.array(c_line, np.int32)
        length = cv2.arcLength(line, False)
        if length >= min_membrane_length:
            smooth_contours = cv2.approxPolyDP(line, epsilon_membrane, False).reshape(-1, 2)
            overlap_lines.append(smooth_contours)
        ind_line += 1

    """
    revised_lines = []
    # remove any overlapping or redundant connections made by the previous corner connections
    for ind, line in enumerate(overlap_lines):
        similar_lines = []
        for sub_line in overlap_lines[ind + 1:]:
            if np.isin(line, sub_line).any():
                similar_lines.append(sub_line)

        longest_line = None
        longest_length = 0
        for line in similar_lines:
            length = cv2.arcLength(line, False)
            if length > longest_length:
                longest_length = length
                longest_line = line

        revised_lines.append(line if longest_line is None else longest_line)
    """

    overlap_image = np.zeros((height, width), np.uint8)

    # draw the connected overlapping lines
    for line in overlap_lines:
        draw_lines(overlap_image, line, 255, 1, False)

    # draw small circles at the connected corners to smooth out the line
    for corner in connected_corners:
        cv2.circle(overlap_image, corner, 1, 255, -1)

    # determine the none connected corners
    nonconnected_corners = []
    for _, corners in corner_lines:
        for corner in corners:
            if tuple(corner) not in connected_corners:
                nonconnected_corners.append(tuple(corner))

    contours = cv2.findContours(overlap_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
    revised_lines = []
    lengths = []
    for cont in contours:
        vectors = cont.reshape(-1, 2)
        closest_corners = []

        for test in range(2):
            closest_corner = (0, 0)
            closest_length = sys.maxsize
            for corner in nonconnected_corners:
                if corner not in closest_corners:
                    length = point_distance(corner, vectors[closest_to(corner, vectors)])
                    if length < closest_length:
                        closest_length = length
                        closest_corner = corner
            closest_corners.append(closest_corner)

        first = closest_to(closest_corners[0], vectors)
        second = closest_to(closest_corners[1], vectors)
        start = min(first, second)
        end = max(first, second)
        line = vectors[start:end]
        revised_lines.append(line)
        lengths.append(cv2.arcLength(line, False))

    """
    # process the dilated membrane
    contours = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[1]
    height, width = layer.shape[:2]
    left, top, right, bottom = 0, 0, width - 1, height - 1
    lines = []

    lengths = []
    # process all of the lines
    for cont in contours:
        length = cv2.arcLength(cont, False) / 2
        area = cv2.contourArea(cont, False)
        if length >= min_membrane_length and area >= min_membrane_area:
            total_length += length
            cX, cY = center_mass(cont)

            # find the start and end points
            ind = 0
            cont = cont.reshape(-1, 2)
            num = cont.shape[0]
            start = cont[0]
            s_i = 0
            e_i = num - 1
            is_middle = False
            on_edge = False
            prev_rad = []
            while ind < num - 1:
                pt1 = tuple(cont[ind])
                pt2 = tuple(cont[ind + 1])
                if pt2[0] == start[0] and pt2[1] == start[1]:
                    break

                deg = point_rad(pt1, pt2)
                if (pt2[0] - 1 <= left or pt2[0] + 1 >= right) and deg < np.pi / 4:
                    if is_middle and not on_edge and (ind - s_i) > max_membrane_width:
                        e_i = ind + 1
                        break
                    else:
                        s_i = ind
                        is_middle = True
                        on_edge = True
                elif (pt2[1] - 1 <= top or pt2[1] + 1 >= bottom) and deg > np.pi / 4:
                    if is_middle and not on_edge and (ind - s_i) > max_membrane_width:
                        e_i = ind + 1
                        break
                    else:
                        s_i = ind
                        is_middle = True
                        on_edge = True
                else:
                    on_edge = False

                # check if the last
                # if len(

                ind += 1

            smooth_contours = cv2.approxPolyDP(cont[s_i:e_i], epsilon_membrane, False).reshape(-1, 2)
            lines.append(((cX, cY), length, area, smooth_contours))

    for _, corners in corner_lines:
        for x, y in corners:
            cv2.circle(skeleton, (x, y), 7, 255, -1)
    # conts = [np.array(cont, np.int32) for cont in revised_lines]
    for line in revised_lines:
        draw_lines(skeleton, line, 100, 3)
    # cv2.drawContours(skeleton, conts, -1, 100, 3)
    ilog(skeleton, delay=0)
    # exit(0)
    """

    return revised_lines, contours, lengths


# -*- coding: utf-8 -*-

from vilya.libs import api_errors
from vilya.views.api.utils import (
    RestAPIUI, http_status, api_list_user, jsonize)

_q_exports = []

@jsonize
def _q_index(request):
    if not request.user:
        return []
    following = request.user.get_following()
    return api_list_user(following)

def _q_lookup(request, username):
    return FollowUI(username)

class FollowUI(RestAPIUI):
    _q_exports = []
    _q_methods = ['get', 'put', 'delete']

    def __init__(self, username):
        if not username:
            raise api_errors.NotFoundError
        self.username = username

    def get(self, request):
        if self.user.is_following(self.username):
            request.response.set_status(204)
        else:
            request.response.set_status(404)

    @http_status(204)
    def put(self, request):
        self.user.follow(self.username)
        request.response.set_status(204)

    @http_status(204)
    def delete(self, request):
        self.user.unfollow(self.username)


# 倒序排列
'''
# inverse permutation
# 将一个数组进行倒序

n =  int(input('确定数组的长度：\n'))

a = [i for i in range(n)]
b = [0 for i in range(n)]
print(a)
for ii in range(n):
    b[n-ii-1] = a[ii]
print(b)

for i in range(n):
    if a[b[i]] == b[a[i]] == n-i-1:
        print(True)
'''

# 这个是书上的解答，有点理解不了
'''
import stdio
import sys
import stdarray

# Accept a permutation of integers from the command line and write the
# inverse permutation to standard output.

# Accept the permutation.
perm = []
for i in range(1, len(sys.argv)):
    perm += [int(sys.argv[i])]
n = len(perm)

# Make sure the permutation is valid.
exists = stdarray.create1D(n, False)
for i in range(n):
    if (perm[i] < 0) or (perm[i] >= n) or exists[perm[i]]:
        stdio.writeln("Not a permutation")
        sys.exit(0)
    exists[perm[i]] = True

# Invert the permutation.
permInverted = [0] * n
for i in range(n):
    permInverted[perm[i]] = i

# Write the inverted permutation.
for element in permInverted:
    stdio.write(str(element) + ' ')
stdio.writeln()
'''

# 哈达玛矩阵
# Hadamard matrix
# 已提取成单独文件

'''###########################################################'''

# 谣言 Rumor

# # Alice 与其他 n 个客人（包括 Bob）开一个派对，Bob 制造了一个关于 Alice 的谣言，并告诉其中的一个客人
# # 第一次听到的人会立即告诉下一个人（除 Alice 和告诉他的人之外）
# # 第二次听到的人则会停止传播这个谣言

# # 估计谣言停止传播前，除Alice之外都听到这个谣言的概率，同时估计听到这个谣言的客人预计数量

# # 类似于有放回的随机抽样

# import random

# n = int(input('参加party的人数：'))
# m = int(input('party开启的次数：'))

# # 听到谣言的客人的数量的数组
# Rumors = []

# # 执行 m 次
# for r in range(m):

    # # 构建及初始化人员数组
    # rumors = [False for i in range(n)]

    # # 随机Bob的位置，开始谣言
    # r1 = random.randrange(n)
    # rumors[r1] = True
    # # 变量说明：r1 ==> 谣言的开始的位置或者刚完成传播的位置；r2 ==> 正要传播谣言的人；r3 ==> 将被谣言传播的人
    # r2 = r1

    # # 听到谣言的客人的数量
    # Rumor = 1

    # # 构建循环
    # while True:
        # r3 = random.randrange(n)
        # if r1 != r3 and not rumors[r3]:
            # rumors[r3] = True
            # # 位置变换，要传播谣言者 晋升 为刚完成传播者，将被谣言传播者 晋升 要传播谣言者
            # r1 = r2
            # r2 = r3
            # Rumor += 1
        # # 刚完成谣言传播者与将要被谣言传播的人的情况剔除
        # elif r1 == r3:
            # continue
        # else:
            # break

    # Rumors.append(Rumor)

# # 结果计算

# # 所有人都听到谣言
# all = 0

# for RR in Rumors:
    # if  RR == n:
        # all += 1

# print(Rumors)
# print('所有人都听到谣言的概率：{}'.format(all/m))
# print('同时听到谣言的人数：{}'.format(sum(Rumors)/m))

# 总感觉自己写的程序超级长

'''#######################################################'''

# 重复值查找 Find a duplicate
# 给定一个包含 n 个元素的数组，元素值位于 1 到 n 之间
# 实现：判断数组的元素是否存在重复，要求不使用其他数组，但可改变已知数组的内容

# 创建一个数组，元素在 1 到 n 之间随机，长度为 n
# 依据要求：将数组进行排序，然后通过循环，如果 a[i] == a[i+1] 成立，则该数组存在重复的元素

# 这里就牵扯的数组排序的问题了
# 传说中的 八大排序法 ———— 有待学习研究

# 用于产生乱序序列
import random,math
# 用于测试运行的时间，主要用到其中的 datetime.datetime.now() 函数
# 通过前后时间相减，在调用 .seconds() 方法即可得到运行的时间
import datetime

# 创建一个乱序的数组
lst = [x for x in range(47, 0, -1)]
random.shuffle(lst)
lst1 = lst[:]
lst2 = lst[:]
lst3 = lst[:]

''' #### 冒泡排序法 Bubble Sort #### '''

# 思路：通过邻位比较，大的上升或者小的上升（比较双方依据规则交换位置）
# 通过双循环，就可以将数组完成升序或者降序排序
# 升序

def Bubble_Sort(lst):

    # 只需比较 len(lst) - 1 次就够了
    for i in range(len(lst) - 1):
        # 添加一个标记，如果整个循环，均没有发生位置交换，则说明已完成排序，则跳出循环（此为优化版，我借鉴的）
        Flag = True
        # 内部循环：循环截止：len(lst1) - 1 - i ，下标索引超过：len(lst1) - 1 - i 就是已经冒泡确定位置的
        for j in range(len(lst) - 1 - i):
            # 大于冒泡得到升序，小于冒泡得到降序
            if lst1[j] > lst[j + 1]:
                lst[j],lst[j + 1] = lst[j + 1],lst[j]
                Flag = False

        if Flag:
            return lst

    return lst

''' #### 选择排序（Selection sort） #### '''

# 是一种简单直观的排序算法。它的工作原理大致是将乱序的数组的元素最小（大）元素一个个取出然后按顺序放置。
# 升序

def selection_sort(lst):
    n = len(lst)
    # 外部循环，循环 n - 1 此就可以完成所有元素的比较与位置变换
    for i in range(n - 1):
        max = i
        # 内部循环：从 i + 1 位置开始，与 i 位置的元素进行比较，
        for j in range(i + 1, n):
            # 通过循环，获取最大值的索引
            if lst[max] < lst[j]:
                max = j
        # 将最大值与第 i 位置的元素进行位置调换
        lst[i],lst[max] = lst[max],lst[i]
    # 循环完成，返回结果
    return lst

''' #### 插入排序（Insertion Sort） #### ''' # 此排序方法有运行时间的比较
# 一个乱序的序列，默认第一个元素有序，将此序列分成两段，前面的有序，后面的乱序
# 将乱序的序列最后一个元素与前面有序的元素依次比较，在合适的位置插入，重复操作，即可完成排序
# 列表的元素值插入和切片操作：
    # 1、单个下标索引得到的值是一个元素，不是列表，切片操作得到的是列表，相加的时候要考虑到这一点
    # 2、切片操作的范围：包括开始位置，不包括结束位置 ==> [a,b)，需要注意结束位置的索引值
# 升序
nn0 = 0
def insertion_sort(lst,nn0):
    n = len(lst)
    # 循环 n - 1 次即可完成排序
    for i in range(n - 1):
        # 判定 lst[n - 1] 是否是已完成排序序列的最大值，是的话直接完成插入操作，重新开始排序
        if lst[n - 1] >= lst[i]:
            lst = lst[:i + 1] + [lst[n - 1]] + lst[i + 1:n - 1]
            nn0 += 1
            continue
        # 内部循环：依次比较，如果小于等于lst[j]，则进行插入操作，跳出内部循环，重新开始
        for j in range(0,i+1):
            if lst[n - 1] <= lst[j]:
                lst = lst[:j] + [lst[n - 1]] + lst[j:n - 1]
                nn0 += 1
                break

    return nn0,lst

# a = datetime.datetime.now()
# print(a)
# print(insertion_sort(lst,nn0)[0])
# b = datetime.datetime.now()
# print(b)
# print((b-a).seconds)
# print('#############################################')

#   ''' ### 上面是我自己写的，将无序序列的最后一个元素与前面的有序序列（从前向后）比较后插入正确位置 ###'''
#   ''' ### 下面是网上的思路，将无序序列的第一个元素与前面的有序序列（从后向前）比较后插入正确位置 ###'''
#   代码段稍有区别：我的是通过序列切片的方法实现，网上的是通过元素位置调换实现的（有点类似冒泡）
#   将通过一个比较大的序列排序，对比运行时间来看，那种的运行效率更高
nn1 = 0
def insertion_sort_1(lst,nn1):
    n = len(lst)
    for i in range(1,n):
        # 从后往前开始比较
        for j in range(i,0,-1):
            # 判定位置
            if lst[j] < lst[j - 1]:
                lst[j],lst[j - 1] = lst[j - 1],lst[j]
                nn1 += 1
            elif lst[j] >= lst[j - 1]:
                break
    return nn1,lst

# a1 = datetime.datetime.now()
# print(a1)
# print(insertion_sort_1(lst1,nn1)[0])
# b1 = datetime.datetime.now()
# print(b1)
# print((b1-a1).seconds)
# print('#############################################')
nn2 = 0
def insertion_sort_2(lst,nn2):
    n = len(lst)
    for i in range(1,n):
        # 判定即将开始插入的元素是否大于有序序列的最大值，不大于则开始内部循环
        if lst[i] < lst[i - 1]:
            temp = lst[i] # 保存 i 位置的值
            index = i # 保存变化的下标值
            # 从后往前开始比较，从 i - 1 开始与要插入的值比较，如果插入值要小，则进行位置变换
            # 位置变换：将大的元素往后一位保存至 j + 1 的位置，然后将空出的下标 j 保存到 index中
            for j in range(i-1,-1,-1):
                # 判定位置
                if lst[j] > temp:
                    lst[j + 1] = lst[j]
                    index = j
                    nn2 += 1
                else:
                    break
            # 内部循环结束后，将插入值 tamp 保存到空出的下标 index 当中，完成一轮插入排序
            lst[index] = temp
    return nn2,lst

# a2 = datetime.datetime.now()
# print(a2)
# print(insertion_sort_2(lst2,nn2)[0])
# b2 = datetime.datetime.now()
# print(b2)
# print((b2-a2).seconds)
# print('#############################################')
'''
经过运行时间测试，第一种的运行速度是最快的，第三种慢上几秒，第二种要比第一种慢上一倍左右
总结一下：
    1、第二种排序中用到了类似冒泡排序的方法，两两交换比较费计算
    2、第一种是通过直接找到插入的位置，通过切片的方式重新拼接得到新的序列
    3、第三种通过将插入的元素的值提取出来，变相将此位置空出来，通过循环，将大的值一位一位的往后移动，同时将空出位置的下标值保存到 index 变量中
       找到插入的位置后，该位置的值以往后移了一位，将位置空了出来，将插入值通过空白的下标保存到这个位置，完成一次循环

    由此可见：冒泡排序，两两交换，运行效率最低
    至于第一种为什么是最快的，不知道是不是走到空间换时间的路子还有待考证（我现在还是搞不清）
'''

################################################

''' #### 希尔排序（Shell sort） #### '''
# 插入排序法和冒泡排序法的结合版
# 冒泡排序法的步长是 1 ，临近的两个元素两两交换
# 希尔排序：通过一个逐渐缩小的步长来把间隔值是步长的元素的两个值进行比较和位置交换，直到步长变成 1 ，在进行冒泡排序
# 在步长变小的过程中，通过较少的比较，可以得到一个相对有序的序列，当步长为 1 时，计算量也不会很大
# 相应的，步长的选取对希尔排序的运行速度有一定的影响
# 要确保最后的步长为 1 ，无法得到想要的结果

# for 循环版
def shell_sort(lst):
    n = len(lst)
    # 确定步长
    mm = round(math.log(n,2))-1
    for m in range(mm,-1,-1):
        span = 2**m - 1
        # 根据步长，将数据分组，确定循环次数
        for i in range(span):
            # 遍历取间隔为span的元素
            for j in range(i + span,n,span):
                # 如果后面的数小于前面的数，开始循环
                if lst[j] < lst[j - span]:
                    # 计入开始循环时的初始位置的值及该位置的下标
                    index = j
                    temp = lst[j]
                    # 开始循环遍历，如果后面的数比前面的小，前面的数保存到后面位置上
                    for k in range(j - span, -1, -span):
                        if lst[k] > temp:
                            lst[k + span] = lst[k]
                            index = k
                        else:
                            break
                    lst[index] = temp

    return lst

a3 = datetime.datetime.now()
print(a3)
print(shell_sort(lst3))
b3 = datetime.datetime.now()
print(b3)
print((b3-a3).seconds)

#  while 循环版
nn4 = 0
def shell_sort_1(list,nn4):
    n = len(list)
    # 初始步长
    ii = round(math.log(n,2)) - 1
    gap = 2**ii - 1
    while gap > 0:
        for i in range(gap, n):
            # 每个步长进行插入排序
            temp = list[i]
            j = i
            # 插入排序
            while j >= gap and list[j - gap] > temp:
                list[j] = list[j - gap]
                j -= gap
                nn4 += 1
            list[j] = temp
        # 得到新的步长
        ii -= 1
        gap = 2**ii - 1
    return nn4,list

# a4 = datetime.datetime.now()
# print(a4)
# print(shell_sort_1(lst1,nn4)[0])
# print(shell_sort_1(lst1,nn4)[1])
# b4 = datetime.datetime.now()
# print(b4)
# print((b4-a4).seconds)

''' #### 归并排序（Merge sort） #### '''

# 归并排序
# 将一个无序的序列进行多次分段，小的分段进行排序后向上合并有序的序列，多次合并操作完成整个序列的排序
# 主要应用场景：将两个已排序的序列合并成一个有序的序列，此排序方法依赖归并操作
# 构建一个长度等于两个序列的的数组，依次从头开始比较，将最小（大）的提取出来，放入到已构建的数组中，被提取的数组下标加 1

# 连个有序序列归并操作
# merge_lst_a = [i for i in range(1,20,2)]
# merge_lst_b = [i for i in range(0,20,2)]
# aa = len(merge_lst_a)
# bb = len(merge_lst_b)
# cc = aa + bb
# merge_lst_c = [0 for i in range(cc)]
# print(merge_lst_a)
# print(merge_lst_b)

# j = 0
# k = 0
# for i in range(cc):
    # if j >= aa:
        # merge_lst_c[i] = merge_lst_b[k]
        # k += 1
    # elif k >= bb:
        # merge_lst_c[i] = merge_lst_a[j]
        # j += 1
    # elif merge_lst_a[j] <= merge_lst_b[k]:
        # merge_lst_c[i] = merge_lst_a[j]
        # j += 1
    # elif merge_lst_a[j] > merge_lst_b[k]:
        # merge_lst_c[i] = merge_lst_b[k]
        # k += 1

# print(merge_lst_c)
######################################################
# 合并
def merge1(l_lst,r_lst):
    result = []
    if n == 1:
        return lst
    l,r = 0,0
    while l < len(l_lst) and r < len(r_lst):
        if l_lst[l] <= r_lst[r]:
            result.append(l_lst[l])
            l += 1
        else:
            result.append(r_lst[r])
            r += 1
    result += l_lst[l:]
    result += r_lst[r:]

    return result

# 分组
def merge_sort1(lst):
    n = len(lst)
    steps = 2
    while steps < n:
        for i in range(0,n,steps):
            if i + steps <= n:
                lst[i:i + steps] =  merge(lst[i:i + steps])
            else:
                lst[i:] = merge(lst[i:])
        steps *= 2
    return lst

# print(lst)
# print(merge_sort(lst))

########################################
'''归并排序中用到的递归，需要好好的学习一下，目前不是很清楚'''
########################################

def merge_sort(list):
    # 认为长度不大于1的数列是有序的
    if len(list) <= 1:
        return list
    # 二分列表
    middle = int(len(list) // 2)
    left = merge_sort(list[:middle])   # 递归#######################
    right = merge_sort(list[middle:])  # 递归#######################
    # 最后一次合并
    return merge(left, right)
# 合并
def merge(left, right):
    l,r=0,0
    result=[]
    while l < len(left) and r < len(right):
        if left[l] < right[r]:
            result.append(left[l])
            l+=1
        else:
            result.append(right[r])
            r +=1
    result += left[l:]
    result += right[r:]
    return result

a5 = datetime.datetime.now()
print(a5)
print(merge_sort(lst2))
b5 = datetime.datetime.now()
print(b5)
print((b5-a5).seconds)

## 运行结果表明：在此乱序序列的排序中，归并排序 速度快于 希尔排序


#!/usr/bin/env python3

import sys
import math
import argparse

def print_usage(name):
    print("python3 {} <input file>".format(name))

def compute_module_fuel(mass):
    fuel = math.floor(mass/3) - 2;
    if fuel < 0:
        fuel = 0

    return fuel

def compute_module_and_fuel(mass):
    fuel = compute_module_fuel(mass)

    additional_fuel = compute_module_fuel(fuel)

    while additional_fuel > 0:
        #print(f'additional_fuel is {additional_fuel}')
        fuel += additional_fuel
        additional_fuel = compute_module_fuel(additional_fuel)

    return fuel

def compute_total_fuel(input_file,name, modules_and_fuel):
    total_fuel = 0
    for module in input_file:
        if modules_and_fuel is True:
            total_fuel += compute_module_and_fuel(int(module))
        else:
            total_fuel += compute_module_fuel(int(module))

    return total_fuel

def main():
    parser = argparse.ArgumentParser(description='Compute required fuel for modules, or modules+fuel')
    parser.add_argument('file', type=argparse.FileType('r'))
    parser.add_argument('--modules-and-fuel', action='store_true', default=False, help='Compute fuel for modules plus the loaded fuel.')

    args = parser.parse_args()

    if (len(sys.argv) > 1):
        with args.file as input_file:
            total_fuel = compute_total_fuel(input_file,sys.argv[1], args.modules_and_fuel)
            print(f'Total fuel required = {total_fuel}')
    else:
        print_usage(sys.argv[0])

if __name__ == "__main__":
    main()


from copy import copy
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, DEFAULT_FONT

# модуль для переноса значений и некоторых свойств ячеек из одного файла в другой.
# шрифт по умолчанию для всего документа задается отдельно в строчках 17-18

file_in = 'Расписание весна 21-22 v2.xlsx'
file_out = 'result.xlsx'

wb_from = load_workbook(file_in)
ws_from = wb_from.active

wb_to = Workbook()
ws_to = wb_to.active
_font = Font(name="Times New Roman", sz=14, b=False)
{k: setattr(DEFAULT_FONT, k, v) for k, v in _font.__dict__.items()}

for row in ws_from.rows:
    for cell in row:
        ws_to.cell(cell.row, cell.column).value = copy(cell.value)
        ws_to.cell(cell.row, cell.column).font = ws_to.cell(cell.row, cell.column).font + Font(bold=cell.font.b)
        ws_to.cell(cell.row, cell.column).fill = copy(cell.fill)

wb_to.save(file_out)

Excel/перенос форматирования/borrow_cells.py


class Node:
    def __init__(self,value):
        self.value = value
        self.left = None
        self.right = None

# IT is very important to write return in line 17 return FindTheClosestValueHelper(node.left,closestValue,value) if not it will return None

# def findClosestValueInBst(root,value):
#     return FindTheClosestValueHelper(root,float('inf'),value)
# def FindTheClosestValueHelper(node,closestValue,value):
#     if node is None:
#         return closestValue
#     if abs(node.value-closestValue)>abs(node.value-value):
#         closestValue = node.value
#     if node.value>value:
#         return FindTheClosestValueHelper(node.left,closestValue,value)
#     elif node.value<value:
#         return FindTheClosestValueHelper(node.right,closestValue,value)
#     else:
#         return closestValue

#algoexpert code ❤💕 Recursive Way

# def findClosestValueInBst(tree,target):
#     return findClosestValueInBstHelper(tree,target,float("inf"))
# def findClosestValueInBstHelper(tree,target,closest):
#     if tree is None:
#         return closest
#     if abs(target-closest) > abs(target-tree.value):
#         closest = tree.value
#     if target  < tree.value:
#         return findClosestValueInBstHelper(tree.left,target,closest)
#     elif target > tree.value:
#         return findClosestValueInBstHelper(tree.right,target,closest)
#     else:
#         return closest

# algoexpert code ❤💕 Iterative way
def findClosestValueInBst(tree,target):
    return findClosestValueInBstHelper(tree,target,float("inf"))
def findClosestValueInBstHelper(tree,target,closest):
    currentNode = tree
    while currentNode is not None:
        if abs(target-closest) > abs(target-currentNode.value):
            closest = currentNode.value
        if target  < currentNode.value:
            currentNode = currentNode.left
        elif target > currentNode.value:
            currentNode = currentNode.right
        else:
            break
    return closest

if __name__ == "__main__":
    binaryTree = Node(10)
    binaryTree.left = Node(5)
    binaryTree.left.left = Node(2)
    binaryTree.left.left.left = Node(1)
    binaryTree.left.right = Node(5)
    binaryTree.right = Node(15)
    binaryTree.right.left = Node(13)
    binaryTree.right.right = Node(22)
    binaryTree.right.left.right = Node(14)
    print(findClosestValueInBst(binaryTree,12))


import streamlit as st
from PIL import Image

import cv2
import numpy as np

import tempfile

#適応的2値化処理
def threshold(src, ksize=3, c=2):

    # 局所領域の幅
    d = int((ksize-1)/2)

    # 画像の高さと幅
    h, w = src.shape[0], src.shape[1]

    # 出力画像用の配列（要素は全て255）
    dst = np.empty((h,w))
    dst.fill(255)

    # 局所領域の画素数
    N = ksize**2

    for y in range(0, h):
        for x in range(0, w):
            # 局所領域内の画素値の平均を計算し、閾値に設定
            t = np.sum(src[y-d:y+d+1, x-d:x+d+1]) / N

            # 求めた閾値で二値化処理
            if(src[y][x] < t - c): dst[y][x] = 0
            else: dst[y][x] = 255

    return dst

st.title('スマホで撮影した書類写真をくっきりと白黒化するWebアプリ！')
'''
## 影がかかっている写真であってもクッキリとした白黒画像に変換できる

スマホで書類の写真を撮影する際に、影がかかってしまうことがある。
通常の白黒化処理では特定の画素が「この閾値より黒っぽかったら黒！」と決め打ちするため、影のかかった部分は黒として判定されてしまい、下の添付画像のように汚くなってしまうことが頻繁にある。
そのような写真であっても、適応的二値化処理を用いることで、影を取り除いたクッキリとした白黒画像が生成される。

適応的二値化処理（AdaptiveThreshold）とは白か黒かの閾値を固定せず、画素ごとに自分の周囲の画素を参考にして白か黒かを判断する二値化処理のことで、陰影を取り除くのに適している。
'''
st.image("siroku.jpg",caption ="一般的な白黒化",use_column_width=True)
st.image("sirokuro.jpg",caption ="適応的2値化処理を用いた白黒化",use_column_width=True)

uploaded_file = st.file_uploader("jpg画像を選択してください",type = "jpg")
if uploaded_file is not None:
    #img = Image.open(uploaded_file)#imgはPillow型
    #uploaded_fileをcv2.imreadで読み取れるようにする処理
    tfile = tempfile.NamedTemporaryFile(delete=False)
    tfile.write(uploaded_file.read())
    #検索の受け売りなので、どうしてtempfileを使うとuploaded_fileをcv2.imreadしたときにエラーがでなくなるのかわからない
    img = cv2.imread(tfile.name)
    #一度cv2.imwriteを使わないと、st.imageしたときにエラーが出る
    cv2.imwrite('temp.jpg',img)
    st.image('temp.jpg',caption ="アップロードされた画像",use_column_width=True)
    #これも検索の受け売り。なぜcv2.imwriteしてから指定した'temp.jpg'をst.imageするとうまくいくのかわからない
    st.title("↓に白黒化画像が表示されます")
    # グレースケール変換
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)#grayはopenCV型
    # 方法1
    dst = threshold(gray, ksize=11, c=13)
    cv2.imwrite('temporary.jpg', dst)
    st.image('temporary.jpg',caption ="適応的2値化処理で白黒化された画像",use_column_width=True)


from absl.testing import parameterized
import numpy as np

from tensorflow.python.eager import context
from tensorflow.python.eager.polymorphic_function import polymorphic_function
from tensorflow.python.framework import constant_op
from tensorflow.python.framework import dtypes
from tensorflow.python.framework import ops
from tensorflow.python.framework import random_seed as random_seed_lib
from tensorflow.python.framework import test_util
from tensorflow.python.ops import array_ops
from tensorflow.python.ops import gradient_checker
from tensorflow.python.ops import gradient_checker_v2
from tensorflow.python.ops import variables
from tensorflow.python.platform import test

class ExtractImagePatchesGradTest(test.TestCase, parameterized.TestCase):
  """Gradient-checking for ExtractImagePatches op."""

  _TEST_CASES = [
      {
          'in_shape': [2, 5, 5, 3],
          'ksizes': [1, 1, 1, 1],
          'strides': [1, 2, 3, 1],
          'rates': [1, 1, 1, 1],
      },
      {
          'in_shape': [2, 7, 7, 3],
          'ksizes': [1, 3, 3, 1],
          'strides': [1, 1, 1, 1],
          'rates': [1, 1, 1, 1],
      },
      {
          'in_shape': [2, 8, 7, 3],
          'ksizes': [1, 2, 2, 1],
          'strides': [1, 1, 1, 1],
          'rates': [1, 1, 1, 1],
      },
      {
          'in_shape': [2, 7, 8, 3],
          'ksizes': [1, 3, 2, 1],
          'strides': [1, 4, 3, 1],
          'rates': [1, 1, 1, 1],
      },
      {
          'in_shape': [1, 15, 20, 3],
          'ksizes': [1, 4, 3, 1],
          'strides': [1, 1, 1, 1],
          'rates': [1, 2, 4, 1],
      },
      {
          'in_shape': [2, 7, 8, 1],
          'ksizes': [1, 3, 2, 1],
          'strides': [1, 3, 2, 1],
          'rates': [1, 2, 2, 1],
      },
      {
          'in_shape': [2, 8, 9, 4],
          'ksizes': [1, 2, 2, 1],
          'strides': [1, 4, 2, 1],
          'rates': [1, 3, 2, 1],
      },
  ]

  def testGradient(self):
    # Set graph seed for determinism.
    random_seed = 42
    random_seed_lib.set_random_seed(random_seed)

    with self.cached_session():
      for test_case in self._TEST_CASES:
        np.random.seed(random_seed)
        in_shape = test_case['in_shape']
        in_val = constant_op.constant(
            np.random.random(in_shape), dtype=dtypes.float32)
        # Avoid `dangerous-default-value` pylint error by creating default
        # args to `extract` as tuples.
        ksizes = tuple(test_case['ksizes'])
        strides = tuple(test_case['strides'])
        rates = tuple(test_case['rates'])

        for padding in ['VALID', 'SAME']:

          def extract(in_val,
                      ksizes=ksizes,
                      strides=strides,
                      rates=rates,
                      padding=padding):
            return array_ops.extract_image_patches(in_val, ksizes, strides,
                                                   rates, padding)

          err = gradient_checker_v2.max_error(
              *gradient_checker_v2.compute_gradient(extract, [in_val]))
          self.assertLess(err, 1e-4)

  @parameterized.parameters(set((True, context.executing_eagerly())))
  def testConstructGradientWithLargeImages(self, use_tape):
    with test_util.AbstractGradientTape(use_tape=use_tape) as tape:
      batch_size = 4
      # Prevent OOM by setting reasonably large image size (b/171808681).
      height = 512
      width = 512
      ksize = 5
      shape = (batch_size, height, width, 1)
      images = variables.Variable(
          np.random.uniform(size=np.prod(shape)).reshape(shape), name='inputs')
      tape.watch(images)
      patches = array_ops.extract_image_patches(images,
                                                ksizes=[1, ksize, ksize, 1],
                                                strides=[1, 1, 1, 1],
                                                rates=[1, 1, 1, 1],
                                                padding='SAME')
      # Github issue: #20146
      # tf.image.extract_image_patches() gradient very slow at graph
      # construction time.
      gradients = tape.gradient(patches, images)
      # Won't time out.
      self.assertIsNotNone(gradients)

  def _VariableShapeGradient(self, test_shape_pattern):
    """Use test_shape_pattern to infer which dimensions are of

    variable size.
    """
    # Testing shape gradient requires graph mode.
    with ops.Graph().as_default():
      # Set graph seed for determinism.
      random_seed = 42
      random_seed_lib.set_random_seed(random_seed)

      with self.test_session():
        for test_case in self._TEST_CASES:
          np.random.seed(random_seed)
          in_shape = test_case['in_shape']
          test_shape = [
              x if x is None else y
              for x, y in zip(test_shape_pattern, in_shape)
          ]
          in_val = array_ops.placeholder(shape=test_shape, dtype=dtypes.float32)

          feed_dict = {in_val: np.random.random(in_shape)}
          for padding in ['VALID', 'SAME']:
            out_val = array_ops.extract_image_patches(in_val,
                                                      test_case['ksizes'],
                                                      test_case['strides'],
                                                      test_case['rates'],
                                                      padding)
            out_val_tmp = out_val.eval(feed_dict=feed_dict)
            out_shape = out_val_tmp.shape

            err = gradient_checker.compute_gradient_error(
                in_val, in_shape, out_val, out_shape)
            self.assertLess(err, 1e-4)

  def test_BxxC_Gradient(self):
    self._VariableShapeGradient([-1, None, None, -1])

  def test_xHWx_Gradient(self):
    self._VariableShapeGradient([None, -1, -1, None])

  def test_BHWC_Gradient(self):
    self._VariableShapeGradient([-1, -1, -1, -1])

  def test_AllNone_Gradient(self):
    self._VariableShapeGradient([None, None, None, None])

  def testJitCompile(self):
    with test_util.AbstractGradientTape(use_tape=True) as tape:
      shape = (4, 512, 512, 1)
      ksize = 5

      images = variables.Variable(np.random.uniform(size=shape), name='inputs')
      tape.watch(images)

      # Github issues: #59058, #59061
      # tf.image.extract_image_patches() does not support backward pass
      # when compiled with XLA.
      extract_image_patches_jit = polymorphic_function.function(
          array_ops.extract_image_patches, jit_compile=True
      )
      patches = extract_image_patches_jit(
          images,
          ksizes=[1, ksize, ksize, 1],
          strides=[1] * 4,
          rates=[1] * 4,
          padding='SAME',
      )

      gradients = tape.gradient(patches, images)
      self.assertIsNotNone(gradients)

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


#hangman but wont bother making shapes so its all written
import random
import time

words = [
    "apple",
    "orange",
    "banana",
    "peach",
    "melon",
    "fruit",
    "tomato",
    "potato",
    "carrot",
    "grapes",
    "garlic",
    "ginger",
    "onion",
    "pumpkin",
    "lettuce",
    "cabbage",
    "avocado",
    "beans",
    "lemon",
    "spinach",
    "cherry",
    "wheat",
    "walnut",
    "almond",
    "coconut",
    "lentil",
    "leeks",
    "apricot",
    "olives",
    "oregano",
    "pepper",
    "papaya",
    "radish",
    "mango",
    "plums"
]
usedltrs = []

w = random.choice(words)
class A:
    done = False
def lose():
    y = 0
    for l in usedltrs:
        if l in w:
            y += 0
        else:
            y += 1
    print(f"You have {10 - y} turns left")
    if y == 10:
        A.done = True
def word():
    lw = []
    for c in w:
        if c in usedltrs:
            lw.append(c)
        else:
            lw.append("_")
    print(*lw)
word()
def ask():
    global r
    r = input("Guess a letter or the whole word\n").lower()
def add():
    if r not in usedltrs:
        usedltrs.append(r)
    else:
        return
def winning():
    x = 0
    for c in w:
        if c in usedltrs:
            x += 1
        else:
            x += 0
    if x == len(w):
        print("Congrats! You found the hidden word!")
    else:
        return

while A.done == False:
    ask()
    if len(r) == 0:
        print("Please enter an input")
    elif len(r) == 1:
        if r in w:
            print("You are right!")
            add()
            word()
            print(f"Used letters are {usedltrs}")
        else:
            print("You are wrong!")
            add()
            print(f"Used letters are {usedltrs}")
            lose()
            word()
    elif len(r) == len(w):
        if r == w:
            print("Congrats! You found the hidden word!")
            break
        else:
            print("You are wrong! Try again")
            lose()
            word()
    else:
        print("Please respect the instructions and play fairly")
    if A.done == True:
        print("You lost!")
        break
    x = 0
    for c in w:
        if c in usedltrs:
            x += 1
        else:
            x += 0
    if x == len(w):
        print("Congrats! You found the hidden word!")
        break

del usedltrs
print("Thanks for playing!")
time.sleep(3)


import os
import pickle
import chess
from chess.pgn import read_game
from copy import deepcopy
import numpy as np

piece_map = {
    'p' : [1,0,0,0,0,0,0,0,0,0,0,0,0],
    'P' : [0,0,0,0,0,0,1,0,0,0,0,0,0],
    'n' : [0,1,0,0,0,0,0,0,0,0,0,0,0],
    'N' : [0,0,0,0,0,0,0,1,0,0,0,0,0],
    'b' : [0,0,1,0,0,0,0,0,0,0,0,0,0],
    'B' : [0,0,0,0,0,0,0,0,1,0,0,0,0],
    'r' : [0,0,0,1,0,0,0,0,0,0,0,0,0],
    'R' : [0,0,0,0,0,0,0,0,0,1,0,0,0],
    'q' : [0,0,0,0,1,0,0,0,0,0,0,0,0],
    'Q' : [0,0,0,0,0,0,0,0,0,0,1,0,0],
    'k' : [0,0,0,0,0,1,0,0,0,0,0,0,0],
    'K' : [0,0,0,0,0,0,0,0,0,0,0,1,0],
    '.' : [0,0,0,0,0,0,0,0,0,0,0,0,1],
}

column_map = {
    'a' : [1,0,0,0,0,0,0,0,0,0,0,0,0],
    'b' : [0,1,0,0,0,0,0,0,0,0,0,0,0],
    'c' : [0,0,1,0,0,0,0,0,0,0,0,0,0],
    'd' : [0,0,0,1,0,0,0,0,0,0,0,0,0],
    'e' : [0,0,0,0,1,0,0,0,0,0,0,0,0],
    'f' : [0,0,0,0,0,1,0,0,0,0,0,0,0],
    'g' : [0,0,0,0,0,0,1,0,0,0,0,0,0],
    'h' : [0,0,0,0,0,0,0,1,0,0,0,0,0],
}

row_map = {
    '1' : [1,0,0,0,0,0,0,0,0,0,0,0,0],
    '2' : [0,1,0,0,0,0,0,0,0,0,0,0,0],
    '3' : [0,0,1,0,0,0,0,0,0,0,0,0,0],
    '4' : [0,0,0,1,0,0,0,0,0,0,0,0,0],
    '5' : [0,0,0,0,1,0,0,0,0,0,0,0,0],
    '6' : [0,0,0,0,0,1,0,0,0,0,0,0,0],
    '7' : [0,0,0,0,0,0,1,0,0,0,0,0,0],
    '8' : [0,0,0,0,0,0,0,1,0,0,0,0,0],
}

# this character is appended to the end of the move if a piece is being promoted to the piece denoted by the letter
promotion_map = {
    'n' : [0,0,0,0,0,0,0,0,1,0,0,0,0],
    'b' : [0,0,0,0,0,0,0,0,0,1,0,0,0],
    'r' : [0,0,0,0,0,0,0,0,0,0,1,0,0],
    'q' : [0,0,0,0,0,0,0,0,0,0,0,1,0],
    '.' : [0,0,0,0,0,0,0,0,0,0,0,0,1],
}

turn_map = {
    chess.WHITE: [1,1,1,1,1,1,0,0,0,0,0,0,0],
    chess.BLACK: [0,0,0,0,0,0,1,1,1,1,1,1,0],
    'b': [0,0,0,0,0,0,1,1,1,1,1,1,0],
    'w': [1,1,1,1,1,1,0,0,0,0,0,0,0],
}

class DataOrganization:
    MAX_MOVES = 100
    GAME_COUNT = 200
    def __init__(self, path=''):
        self.path = path
        self.x1 = []
        self.x2 = []
        self.y = []

    def create_pickle(self, name, obj):
        out = open(os.path.join(os.getcwd(), name), 'wb')
        pickle.dump(obj, out)
        out.close()
        return obj

    def depickle(self, name):
        with open(os.path.join(os.getcwd(), name), 'rb') as pick:
            tree = pickle.load(pick)
        return tree

    def gather_data(self):
        for file in os.listdir(self.path):
            print('reading ' + file)
            games = 0
            if (file.endswith('pgn')):
                pgn = open(os.path.join(self.path, file))
                game = read_game(pgn)
                while game is not None and games < self.GAME_COUNT:
                    games += 1
                    result = game.headers['Result'].strip()
                    if result == '1-0':
                        self.get_game_data_v2(game, True, games)
                    elif result == '0-1':
                        self.get_game_data_v2(game, False, games)
                    else:
                        self.get_game_data_v2(game, False, games)
                        self.get_game_data_v2(game, True, games)
                    # the chess package can sometimes be finicky about which games it wants to read. This prevents any unnecessary breakdowns
                    try:
                        game = read_game(pgn)
                    except:
                        game = read_game(pgn)
        self.x1 = np.asarray(self.x1)
        self.x2 = np.asarray(self.x2)
        self.y = np.asarray(self.y)
        print(self.x2.shape)
        print(self.x1.shape)
        print(self.y.shape)

    def check(self):
        for i in range(len(self.x1)):
            print(self.x1.shape)
            print(self.get_board_from_binary(self.x1[i]))
            print(self.convert_binary_to_move(self.x1[i]))
            print('white' if self.find_key(self.x1[i][7][8], turn_map) == chess.WHITE else 'black')
            print(self.y[i])

    def check_input(self, x):
        print(self.get_board_from_binary(x[0]))
        print(self.convert_binary_to_move(x[0]))
        print('white' if self.find_key(x[0][7][8], turn_map) == chess.WHITE else 'black')

    def get_game_data(self, game, is_white, games):
        iter = 0
        board = chess.Board()
        for move in game.mainline_moves():
            # we dont want white's moves if we're black and vice versa and we dont want to overload the model with opening knowledge
            if (iter % 2 != (0 if is_white else 1)) or (games % 5 != 0 and iter < 15):
                iter += 1
                board.push(move)
                continue
            move_uci = chess.Move.uci(move)
            input_board = self.get_binary_board(board, is_white)
            legal_moves = board.legal_moves
            num_moves_taken = np.random.randint(1, 5)

            if legal_moves.count() < num_moves_taken:
                board.push(move)
                iter += 1
                continue
            # we want the model to see more bad moves than good moves but we also dont want it to adapt to a certain probability
            # (i.e. just guessing that 3/4 of moves will be 0 and 1/4 will be one and outputting the same value for everything)
            # even if this skews its binary accuracy to be low
            # in practice, it will see all legal moves and only a handful will be good
            legal_moves = np.random.choice(list(legal_moves), num_moves_taken)
            legal_moves[num_moves_taken - 1] = move
            for legal_move in legal_moves:
                legal_move_uci = chess.Move.uci(legal_move)
                board_copy = self.append_binary_move(deepcopy(input_board), legal_move_uci)
                self.y.append(1 if move_uci == legal_move_uci else 0)
                self.x1.append(board_copy)
            board.push(move)
            iter += 1

    def append_binary_move(self, board, move):
        binary_move = self.get_binary_move(move)
        for i in range(5):
            board[i][8] = binary_move[i]
        return board

    def get_game_data_v2(self, game, is_white, games):
        board = chess.Board()
        for iterations, move in enumerate(game.mainline_moves()):
            # we dont want white's moves if we're black and vice versa and we dont want to overload the model with opening knowledge
            if (iterations % 2 != (0 if is_white else 1)) or (games % 10 != 0 and iterations < 15):
                board.push(move)
                continue
            move_uci = chess.Move.uci(move)
            x1_i = self.get_binary_board_v2(board)

            x2_i, y_i = self.get_x2_y(board, move_uci)
            x2_i[self.MAX_MOVES - 1] = np.ones(shape=(5, 13)) if is_white else  x2_i[self.MAX_MOVES - 1]
            self.x1.append(x1_i)
            self.x2.append(x2_i)
            self.y.append(y_i)
            board.push(move)

    def get_binary_board(self, board: chess.Board, is_single_batch = False):
        map = board.piece_map()
        output_board = np.zeros(shape=(8, 9, 13))
        iter = 0
        for i in range(8):
            row = np.zeros(shape=(9, 13))
            for j in range(8):
                row[j] = piece_map['.'] if iter not in map else piece_map[map[iter].symbol()]
                iter += 1
            output_board[i] = row
        output_board[7][8] = turn_map[board.turn]
        return output_board if not is_single_batch else np.asarray([output_board])

    '''
    this somewhat non pythonic method does what the above does without the middle man of the chess package.
    much faster when caller only has fen string to work with
    '''
    def get_binary_board_from_fen(self, fen: str):
        output_board = np.zeros(shape=(8, 9, 13))
        fen_idx = 0
        for i in range(8):
            row = np.zeros(shape=(9, 13))
            j = 0
            while j < 8:
                if fen[fen_idx] in piece_map:
                    row[j] = piece_map[fen[fen_idx]]
                    j += 1
                else:
                    for k in range(int(fen[fen_idx])):
                        row[j] = piece_map['.']
                        j += 1
                fen_idx += 1
            fen_idx += 1 # for / character
            output_board[7-i] = row
        output_board[7][8] = turn_map[fen[fen_idx]]
        return output_board

    def get_binary_board_v2(self, board):
        map = board.piece_map()
        output_board = np.zeros(shape=(8, 8, 13))
        iter = 0
        for i in range(8):
            row = np.zeros(shape=(8, 13))
            for j in range(8):
                row[j] = piece_map['.'] if iter not in map else piece_map[map[iter].symbol()]
                iter += 1
            output_board[7-i] = row
        return output_board

    def get_x2_y(self, board: chess.Board, move):
        y_i = np.zeros(shape=(self.MAX_MOVES))
        x2_i = np.zeros(shape=(self.MAX_MOVES, 5, 13))
        for idx, legal_move in enumerate(board.legal_moves()):
            legal_move_uci = chess.Move.uci(legal_move)
            y_i[idx] = 1 if move == legal_move_uci else 0
            x2_i[idx] = self.get_binary_move(legal_move_uci)
        return x2_i, y_i

    '''
    Converts moves to binary representations in constant time using the global maps
    This can either be done to create probability vector training outputs or inputs when assigning probabilities to legal moves
    '''
    def get_binary_move(self, move):
        arr = np.zeros(shape=(5, 13))
        arr[0] = column_map[move[0]]
        arr[1] = row_map[move[1]]
        arr[2] = column_map[move[2]]
        arr[3] = row_map[move[3]]

        arr[4] = promotion_map[move[4]] if len(move) == 5 else promotion_map['.']
        return arr

    def prepare_input(self, board: chess.Board, move: str, is_batch=False):
        board = self.get_binary_board(board, board.turn)
        a = self.append_binary_move(board, move)
        return np.asarray([self.append_binary_move(board, move)] if not is_batch else self.append_binary_move(board, move))

    def prepare_input_v2(self, board: chess.Board, is_batch=False):
        binary_moves, uci_moves = self.get_move_input_v2(board)
        return self.get_binary_board_v2(board), binary_moves, uci_moves

    def prepare_graph_train_data(self, board):
        return self.get_binary_board_v2(board),

    def get_move_input_v2(self, board: chess.Board):
        binary_moves = np.zeros(shape=(self.MAX_MOVES, 5, 13))
        uci_moves = []
        idx = 0
        for idx, move in enumerate(board.generate_legal_moves()):
            uci = chess.Move.uci(move)
            binary_moves[idx] = self.get_binary_move(uci)
            uci_moves.append(uci)

        if board.turn:
            binary_moves[idx + 1] = np.ones(shape=(5, 13))
        return binary_moves, uci_moves
    '''
    Mostly for debug, used to ensure binary representaitons of moves look the way they're supposed to
    '''
    def convert_binary_to_move(self, move):
        try:
            toRet = self.find_key(move[0], column_map)
            toRet += self.find_key(move[1], row_map)
            toRet += self.find_key(move[2], column_map)
            toRet += self.find_key(move[3], row_map)
            toRet += self.find_key(move[4], promotion_map)
        except:
            print(np.zeros(shape=(5, 13)))
            print(move)

        return toRet

    '''
    Mostly for debug, used to ensure boards look the way they're supposed to by converting binary boards into human readable character representations
    This is very slow, I would not recommend using this for large batches of data
    '''
    def get_board_from_binary(self, board):
        to_ret = np.zeros(shape=(8, 8), dtype=str)
        for i in range(8):
            for j in range(8):
                for piece in piece_map:
                    if np.allclose(np.asarray(piece_map[piece]), np.asarray(board[i][j])):
                        to_ret[i][j] = piece
                        break
        return to_ret

    def find_key(self, val, dict):
        for i in dict.keys():
            if np.allclose(np.asarray(dict[i]), val):
                return i

    '''
    it's necessary to 'clean' the fen because we don't want the same position represented multiple times through the move counters at the end of the fen
    '''
    @staticmethod
    def clean_fen(fen: str, start=''):
        if fen is not None and ' ' in fen:
            for i in (fen.split(' ')[0:4]):
                start += i
            return start
        return fen

    @staticmethod
    def dirty_fen(clean_fen: str):
        out_fen = ''
        board_idx = 0
        for idx, c in enumerate(clean_fen):
            if board_idx == 64:
                out_fen += ' ' + c + ' '
            elif board_idx > 64 and c not in ['K', 'Q', 'k', 'q']:
                if c == '-':
                    out_fen += c + ' ' if out_fen[len(out_fen)-1] == ' ' else ' ' + c + ' '
                else:
                    out_fen += ' ' + clean_fen[idx:len(clean_fen)] + ' '
                    break
            else:
                out_fen += c
            board_idx += int(c) if c.isnumeric() else 1 if c != '/' else 0

        return out_fen + '20 21'


import numpy as np

from dolfin import *
from fenics_shells import *

def test_assembler_reissner_mindlin(space=DuranLibermanSpace):
    """This test checks that the linear algebra objects produced by the
    built-in FEniCS assembler and the fenics-shells projected assembler induce the
    same (natural, energy) norm for the Reissner-Mindlin problem.
    """
    # First of all we setup everything on the full space
    # as usual.
    mesh = UnitSquareMesh(32, 32, "crossed")

    E = Constant(10920.0)
    nu = Constant(0.3)
    t = Constant(1E-2)
    kappa = Constant(5.0/6.0)

    U = space(mesh)
    U_F = U.full_space
    U_P = U.projected_space

    u_ = Function(U_F)
    theta_, w_, R_gamma_, p_ = split(u_)
    u = TrialFunction(U_F)
    u_t = TestFunction(U_F)

    # Elastic energy density
    psi = psi_M(k(theta_), E=E, nu=nu, t=t) \
        + psi_T(R_gamma_, E=E, nu=nu, t=t, kappa=kappa) \
    # Elastic energy
    L_el = psi*dx

    # External work
    W_ext = inner(Constant(1.0), w_)*dx

    # Reduction operator
    L_R = inner_e(gamma(theta_, w_) - R_gamma_, p_)

    L = L_el + L_R - W_ext
    F = derivative(L, u_, u_t)
    J = derivative(F, u_, u)

    # Operators on full space
    A_f = assemble(J)
    F_f = assemble(F)

    # Operators on projected space
    A_p, F_p = assemble(U_P, J, F)

    # Initialise Functions on U_F and U_P  with 1.0 everywhere. These are used
    # to calculate the inner product induced by the above forms.
    u_p = interpolate(Constant((1.0, 1.0, 1.0)), U_P)
    u_f = Function(U_F)
    # Generate compatible full solution
    reconstruct_full_space(u_f, u_p, J, F)

    # Tests
    from numpy.testing import assert_approx_equal
    # inner product induced by A_f and A_p
    assert_approx_equal(u_f.vector().inner(A_f*u_f.vector()),
                        u_p.vector().inner(A_p*u_p.vector()))
    # inner product induced by F_p and F_f
    assert_approx_equal(F_f.inner(u_f.vector()),
                        F_p.inner(u_p.vector()))


from django.shortcuts import render
import razorpay

from django.views.decorators.csrf import csrf_exempt

from razorpay_second.settings import (Raz_Public_Key, Raz_Secret_Key)

from .models import Coffee

# Create your views here.

def home(request):
    if request.method == "POST":
        name = request.POST.get("name")
        amount = int(request.POST.get("amount")) * 100
        client = razorpay.Client(auth=(Raz_Public_Key, Raz_Secret_Key))
        payment = client.order.create(
            {
                'amount': amount,
                'currency': 'INR',
                'payment_capture': '1'
            }
        )
        print('payment: ', payment)

        coffee = Coffee(name=name, amount=amount, payment_id=payment['id'])
        coffee.save()
        return render(request, "index.html", {'payment': payment})

    return render(request, "index.html")

@csrf_exempt
def success(request):
    if request.method == "POST":
        a = request.POST
        print('a: ', a)
    return render(request, "success.html")


from typing import List, Optional

class ListingFile:
    def __init__(self, data: Optional[str] = None):
        self.data: Optional[str] = data
        self.releases: List[str] = []

        self.parse()

    def get_releases(self) -> List[str]:
        return self.releases

    def parse(self) -> None:
        if not self.data:
            return

        lines: List[str] = self.data.split("\n")

        for line in lines:
            line = line.strip()

            # empty
            if not line:
                continue

            # ignore comments
            if line and line[0] == "#":
                continue

            self.releases.append(line)

        self.releases.sort()


"""Define taskmanager commands tests."""

from io import StringIO

from django.core.management import call_command
from django.test import TestCase

from taskmanager.models import AppCommand

class CollectTaskCommandTest(TestCase):
    """A set of tests for collect task command."""

    def test_command_output(self):
        """Test the command output."""
        out = StringIO()
        call_command("collectcommands", stdout=out)
        self.assertIn("migrate", out.getvalue())

    def test_command_output_no_djangocore(self):
        """Test the command output invoked with excludecodre argument."""
        out = StringIO()
        call_command("collectcommands", "--excludecore", stdout=out)
        self.assertNotIn("migrate", out.getvalue())

    def test_command_creation(self):
        """Test the commands creation."""
        self.assertEqual(AppCommand.objects.all().count(), 0)
        out = StringIO()
        call_command("collectcommands", stdout=out)
        self.assertNotEqual(AppCommand.objects.all().count(), 0)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon Apr  4 11:26:57 2022

@author: minhpham1606
"""
import math

def shortest_route_len(G, s, t):
    if s == t:
        return 0
    if G[s] == []:
        return math.inf
    if t in G[s]:
        return 1
    visited = {s}
    aout = [math.inf]*(len(G))
    aout[s] = 0
    queue = []
    current = s
    while len(visited) != len(G):
        for i in G[current]:
            if i not in visited:
                visited.add(i)
                queue.append(i)
                aout[i] = G[s] + 1

def shortest_route(G, s, t, cache = None):
    cache = {s} if cache is None else cache
    if s == t:
        return 0
    if G[s] == []:
        return math.inf
    if t in G[s]:
        return 1
    check = []
    for l in G[s]:
        if l not in cache:
            cache.add(l)
            check.append(l)
    out = []
    for l in check:
        out.append(shortest_route_len(G, l, t, cache))
    if out == []:
        return 1
    return 1 + min(out)


DASH_EVENTS = [
    'calendar purchase',
    'calendar add',
    'document purchase',
    'document add',
    'other class join',
    'class join',
    'subscription',
]
DASH_EVENT_LIST = list(zip(range(100), DASH_EVENTS))

WEATHER_ICONS = {
    # t-storms late
    4: 'wi wi-storm-showers',

    # light drizzle
    9: 'wi wi-night-alt-sprinkle',

    # n/d showers
    11: 'wi wi-showers',

    # n/d: rain
    12: 'wi wi-rain',

    # n/d: drifting snow / windy
    15: 'wi wi-snow-wind',

    # n: haze
    21: 'wi wi-fog',

    # d: partly cloudy / windy
    24: 'wi wi-cloudy-windy',

    # moon: waning crescent
    25: 'wi wi-moon-waning-crescent',

    # cloudy
    26: 'wi wi-cloudy',

    # n: mostly cloudy
    27: 'wi wi-cloudy',

    # d: mostly cloudy
    28: 'wi wi-cloudy',

    # n: partly cloudy
    29: 'wi wi-night-cloudy',

    # d: partly couldy
    30: 'wi wi-cloudy',

    # n: clear
    31: 'wi wi-night-clear',

    # d: sunny
    32: 'wi wi-day-sunny',

    # n: mostly clear / fair
    33: 'wi wi-night-clear',

    # d: mostly sunny / fair
    34: 'wi wi-day-sunny',

    # d: scattered T-storms
    38: 'wi wi-storm-showers',

    # d: AM showers
    39: 'wi wi-day-showers',

    # heavy rain
    40: 'wi wi-rain',

    # # n: showers late
    # 45: 'wi wi-night-alt-showers',

    # # d: showers early
    # 45: 'wi wi-day-showers',

    # n: snow-showers
    46: 'wi wi-rain-mix',

    # # d: t-storms early
    # 47: 'wi wi-day-thunderstorm',

    # n: scattered t-storms
    47: 'wi wi-thunderstorm',

}


import math
def get_jie(a, b, c):
    delta = b**2-4*a*c
    if delta < 0:
        return []
    else:
        x1 = (-b+math.sqrt(delta))/(2*a)
        x2 = (-b-math.sqrt(delta))/(2*a)
        if x1 == x2:
            return [x1]
        else:
            return sorted([x1, x2])
def get_res(x, param):
    res = 0
    exp = len(param)-1
    for idx, p in enumerate(param):
        res += p * x ** (exp-idx)
    return res

def get_gen(pos, param):
    pos = [-10000000000] + pos +[10000000000]
    jie = []
    for i in range(len(pos)-1):
        x1 = get_res(pos[i], param)
        x2 = get_res(pos[i+1], param)
        if x1 == 0:
            jie.append(pos[i])
            continue
        if x1 < 0 and x2 <= 0 or x1 > 0 and x2 >= 0:
            continue
        else:
            p1, p2 = pos[i], pos[i+1]
            while abs(p1-p2) > 0.001:
                mid = (p1+p2)/2
                x = get_res(mid, param)
                if x1 * x > 0:
                    p1 = mid
                else:
                    p2 = mid
            jie.append(p1)
    return jie

if __name__ == '__main__':
    n = int(input())
    a = list(map(int, input().split()))
    while a[0] == 0:
        a.pop(0)
        n -= 1
    p = n
    dif = a.copy()
    while p > 2:
        for i in range(p):
            dif[i] = dif[i] * (p-i)
        dif = dif[:-1]
        p -= 1
    res = get_jie(dif[0], dif[1], dif[2])
    m = 2
    while m < n:
        param = a.copy()
        q = n
        while q > m+1:
            for i in range(q):
                param[i] = param[i] * (q - i)
            param = param[:-1]
            q -= 1
        res = get_gen(res, param)
        m += 1
    # print(res)
    if not res:
        print("No")
    else:
        new_res = []
        for r in res:
            if abs(r-0) < 0.001:
                new_res.append(0)
            else:
                new_res.append(r)
        r = ["{:.2f}".format(x) for x in new_res]
        s = " ".join(r)
        print(s)


import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

def F32005 (X):
    '''F3_2005绘图函数'''
    dim = X.shape[0]
    f_bias_3 = -450

    # np.dot : np.dot()函数主要有两个功能，向量点积和矩阵乘
    result = 0
    for i in range(dim):
        Z = X
        # print(Z)
        result =  result + ((1000000)**(i/dim-1)) * Z[i]**2
        # print( result)
    return  result + f_bias_3

def F3Plot():
    fig = plt.figure(1) #定义figure
    ax = Axes3D(fig) #将figure变为3d
    # 遍历解空间
    x1=np.arange(-100,100,2) #定义x1，范围为[-100,100],间隔为2
    x2=np.arange(-100,100,2) #定义x2，范围为[-100,100],间隔为2
    X1,X2=np.meshgrid(x1,x2) #生成网格

    nSize = x1.shape[0]
    # 初始化空间
    Z=np.zeros([nSize,nSize])

    for i in range(nSize):
        for j in range(nSize):
            #构造F1输入
            X=[X1[i,j],X2[i,j]]
            #将格式由list转换为np.array
            X=np.array(X)
            # 计算F1的值
            Z[i, j] = F32005(X)
    #绘制3D曲面
    # rstride:行之间的跨度  cstride:列之间的跨度
    # rstride:行之间的跨度  cstride:列之间的跨度
    # cmap参数可以控制三维曲面的颜色组合
    ax.plot_surface(X1, X2, Z, rstride = 1, cstride = 1, cmap = plt.get_cmap('rainbow'))
    ax.contour(X1, X2, Z, zdir='z', offset=0)#绘制等高线
    ax.set_xlabel('X1')#x轴说明
    ax.set_ylabel('X2')#y轴说明
    ax.set_zlabel('Z')#z轴说明
    ax.set_title('F1_space')
    plt.show()

F3Plot()


import numpy as np
import csv
from pymetis import part_graph

# Set random seed
seed = 0
np.random.seed(seed)

def partition(adj_raw, n):
    node_num = len(set(adj_raw[0])) + len(set(adj_raw[1]))
    print(node_num)
    adj_list = [[] for _ in range(node_num)]
    for i, j in zip(adj_raw[0], adj_raw[1]):
        if i == j:
            continue
        adj_list[i].append(j)
        adj_list[j].append(i)

    _, ss_labels = part_graph(nparts=n, adjacency=adj_list)

    return ss_labels

# Load data
print("Loading dataset")
# load adjacency matrix and the ground_truth

net = []
with open('amazon_network.csv', 'r') as f:
    reader = csv.reader(f)
    data = list(reader)
    ttt = 0
    for d in data:
        print(ttt / len(data))
        ttt += 1
        #if d[0] in uu_final:
        net.append([d[0], d[1]])

productID = {}
userID = {}
for key_word in net:
    if key_word[0] not in userID:
        userID[key_word[0]] = len(userID.keys())
    if key_word[1] not in productID:
        productID[key_word[1]] = len(productID.keys())

G = {}
for key_word in net:
    if (userID[key_word[0]], productID[key_word[1]]) not in G.keys():
        G[(userID[key_word[0]], productID[key_word[1]])] = 1
    else:
        G[(userID[key_word[0]], productID[key_word[1]])] += 1

f = open('tmp_Incons.txt','a')
for key in G.keys():
    f.write(str(key[0])+' '+str(key[1])+'\n')
f.close()

adj = np.loadtxt('tmp_Incons.txt')
adj = adj[:, 0: 2]
num_user = len(set(adj[:, 0]))
num_object = len(set(adj[:, 1]))
adj[:, 1] += (np.max(adj[:, 0])+1)
adj = adj.astype('int')
edge_index = adj.T
ss_label = partition(edge_index, 20)
ss_label = np.array(ss_label)

sampled_node1 = np.where(ss_label==0)[0]
sampled_node2 = np.where(ss_label==1)[0]
#sampled_node3 = np.where(ss_label==2)[0]
#sampled_node4 = np.where(ss_label==3)[0]
#sampled_node5 = np.where(ss_label==4)[0]
#sampled_node6 = np.where(ss_label==5)[0]
sampled_node = list(set(list(sampled_node1)+list(sampled_node2)))#+list(sampled_node3)+list(sampled_node4)+list(sampled_node5)+list(sampled_node6)))
sampled_node = np.array(sampled_node)
print(len(sampled_node))

user_dic = {}
prod_dic = {}
f = open('amazonInCons.txt','a')
for i in range(edge_index.shape[1]):
    if (edge_index[0, i] in sampled_node) and (edge_index[1, i] in sampled_node):
        if edge_index[0, i] not in user_dic.keys():
            user_dic[edge_index[0, i]] = len(user_dic.keys())
        if edge_index[1, i] not in prod_dic.keys():
            prod_dic[edge_index[1, i]] = len(prod_dic.keys())
        f.write(str(user_dic[edge_index[0, i]])+' '+str(prod_dic[edge_index[1, i]])+'\n')
f.close()

label = []
tmp_id = []
with open('amazon_gt.csv', 'r') as f:
    reader = csv.reader(f)
    data = list(reader)
    for d in data:
        if (d[0] in userID.keys()) and (userID[d[0]] in user_dic.keys()) and (d[0] not in tmp_id):
            tmp_id.append(d[0])
            if d[1] == '-1':
                label.append([user_dic[userID[d[0]]], 1])
            else:
                label.append([user_dic[userID[d[0]]], 0])
print(len(label), np.sum(np.array(label)[:, 1]))
np.savetxt('amazon_label.txt', label, fmt="%d")

adj = np.loadtxt('amazonInCons.txt')
adj = adj[:, 0: 2]
num_user = len(set(adj[:, 0]))
num_object = len(set(adj[:, 1]))
adj[:, 1] += num_user
adj = adj.astype('int')
np.savetxt('amazon.txt', adj, fmt="%d")


from collections import namedtuple

from django.conf import ImproperlyConfigured, settings
from django.contrib.admindocs.views import simplify_regex
from django.core.cache import cache
from django.urls.resolvers import RegexPattern, RoutePattern, URLPattern, URLResolver
from django.utils.module_loading import import_string

from . import defaults

def _get_setting(name):
    return getattr(settings, name, getattr(defaults, name))

def _get_blacklist(name):
    blacklist = _get_setting('PERMISSIONS_AUDITOR_BLACKLIST')

    # Fall back to the defauls if the user does not provide the specific
    # blacklist in their settings.
    if name not in blacklist:
        blacklist = getattr(defaults, 'PERMISSIONS_AUDITOR_BLACKLIST')

    return blacklist[name]

NAMESPACE_BLACKLIST = tuple(_get_blacklist('namespaces'))
VIEW_BLACKLIST = tuple(_get_blacklist('view_names'))
MODULE_BLACKLIST = tuple(_get_blacklist('modules'))

ViewDetails = namedtuple('ViewDetails', [
    'module', 'name', 'url', 'permissions', 'login_required', 'docstring'
])

class ViewParser:

    def __init__(self):
        self.load_processors()

    def load_processors(self):
        self._processors = []

        for processor_path in _get_setting('PERMISSIONS_AUDITOR_PROCESSORS'):

            try:
                processor = import_string(processor_path)
                self._processors.append(processor())
            except (ImportError, TypeError) as ex:
                raise ImproperlyConfigured(
                    '{} is not a valid permissions processor.'.format(processor_path)
                ) from ex

    def parse(self, view):
        """
        Process a view.

        Returns a tuple containing:
        permissions (list), login_required (boolean or None), docstring (str)
        """
        permissions = []
        login_required = False
        docstrings = []

        for processor in self._processors:
            if processor.can_process(view):
                permissions.extend(processor.get_permission_required(view))

                login_required_result = processor.get_login_required(view)
                if login_required_result is None and not login_required:
                    login_required = login_required_result
                else:
                    login_required = login_required_result or login_required

                docstrings.append(processor.get_docstring(view))

        return (
            sorted(set(permissions)),
            login_required,
            '\n'.join(list(set(filter(None, docstrings))))
        )

def _get_views(urlpatterns=None, base_url=''):
    """
    Recursively fetch all views in the specified urlpatterns.

    If urlpatterns is not specified, uses the `PERMISSIONS_AUDITOR_ROOT_URLCONF`
    setting, which by default is the value of `ROOT_URLCONF` in your project settings.

    Returns a list of `View` namedtuples.
    """
    views = []

    if urlpatterns is None:
        root_urlconf = import_string(_get_setting('PERMISSIONS_AUDITOR_ROOT_URLCONF'))
        urlpatterns = root_urlconf.urlpatterns

    parser = ViewParser()

    for pattern in urlpatterns:
        if isinstance(pattern, RoutePattern) or isinstance(pattern, URLResolver):

            if pattern.namespace in NAMESPACE_BLACKLIST:
                continue

            # Recursively fetch patterns
            views.extend(_get_views(pattern.url_patterns, base_url + str(pattern.pattern)))

        elif isinstance(pattern, URLPattern) or isinstance(pattern, RegexPattern):
            view = pattern.callback

            # If this is a CBV, use the actual class instead of the as_view() classmethod.
            view = getattr(view, 'view_class', view)
            view = getattr(view, 'cls', view)

            full_view_path = '{}.{}'.format(view.__module__, view.__name__)
            if full_view_path in VIEW_BLACKLIST or view.__module__ in MODULE_BLACKLIST:
                continue

            permissions, login_required, docstring = parser.parse(view)

            views.append(ViewDetails._make([
                view.__module__,
                view.__name__,
                simplify_regex(base_url + str(pattern.pattern)),
                permissions,
                login_required,
                docstring
            ]))

    return views

def get_views(urlpatterns=None, base_url=''):
    """
    Wrapper for caching _get_views().
    """
    cache_key = _get_setting('PERMISSIONS_AUDITOR_CACHE_KEY')
    cache_base_url_key = cache_key + '_BASE_URL'
    cache_timeout = _get_setting('PERMISSIONS_AUDITOR_CACHE_TIMEOUT')

    cache_content = cache.get_many([cache_key, cache_base_url_key])
    views = cache_content.get(cache_key, None)
    cached_base_url = cache_content.get(cache_base_url_key, None)

    if views is None or cached_base_url != base_url:
        views = _get_views(urlpatterns, base_url)
        cache.set_many({
            cache_key: views,
            cache_base_url_key: base_url
        }, timeout=cache_timeout)

    return views


# -*- coding: utf-8 -*-
"""
Created on Sun Jan 16 20:24:40 2022

@author: MC
"""

import pandas as pd
import ELO_Functions as elo
import streamlit as st
import altair as alt

header = st.container()
inputs = st.container()
graph = st.container()
footer = st.container()

with header:
    st.title('The Vaz Brothers Fifa Rankings!')
    st.text('')
    st.text('This project uses a custom ELO formula that takes into account team ratings')
    st.text('This custom formula uses a different k-factor depending on team ratings')
    st.text('The purpose is to determine which brother is the best at FIFA')
    st.text('')
    st.text('Instructions:')
    st.text('1. Select the Winner')
    st.text('2. Select the Loser')
    st.text('3. Team Rankings (stars)')
    st.text('4. Hit the "Calculate" button')

with inputs:

    st.title('Inputs for calculation')
    col1, col2, col3, col4 = st.columns((3,1,3,1))

    Players_List = ['MC','Austin','Liam','Donovan']
    Ratings_List = [5,4.5,4,3.5,3,2.5,2,1.5,1,0.5]

    with col1:
        Won = st.selectbox('Winner', Players_List)
        WTR = st.selectbox('Winner Team Rating',Ratings_List)
    with col3:
        Lost = st.selectbox('Loser', Players_List)
        LTR = st.selectbox('Loser Team Rating',Ratings_List)

    calculate = st.button('Calculate')

    Player_Data = pd.read_csv('ELO_Rankings')

    melted_df = Player_Data.melt(id_vars = ['Date'],
                                 value_vars = ['Austin','MC','Donovan','Liam'],
                                 var_name = 'Player',
                                 value_name = 'ELO')

    Chart = (alt.Chart(melted_df, width =700, height = 600)
             .mark_line()
             .configure_title(fontSize = 24)
             .configure_axis(titleFontSize = 20)
             .encode(x=alt.X("Date:T", title = 'Date'),
                     y= alt.Y("ELO:Q",title = 'ELO Rating',scale = alt.Scale(domain=(1200, 1700))),
                     color = 'Player')
             .properties(title = "Ranking over Time"))

if calculate:

    result = elo.play_a_game(Won, Lost, WTR, LTR, Player_Data)

    result.to_csv('ELO_Rankings')

    with graph:

        st.dataframe(result.drop(columns = 'Date').tail(1))

        #st.text('This graph shows our ELO scores over time!')

        #st.altair_chart(Chart)


import pandas as pd
import numpy as np
import re

import matplotlib.pyplot as plt
import sklearn.metrics as metrics

from vowpalwabbit import pyvw

from gensim.parsing import preprocessing as prep
from collections import defaultdict
from sklearn.model_selection import train_test_split
train = pd.read_csv('../input/train.csv')
train.head()
plt.hist(train['target']);
class Tokenizer(object):
    def __call__(self, doc):
        striped = prep.strip_punctuation(doc)
        striped = prep.strip_tags(striped)
        striped = prep.strip_multiple_whitespaces(striped).lower()
        return striped
class FilterRareWords(object):
    def __init__(self):
        self.cv = defaultdict(int)
    def fit(self, texts):
        for text in texts:
            for word in text.split():
                self.cv[word] += 1
    def __call__(self, text):
        return ' '.join([self.filter_word(word) for word in text.split()])
    def filter_word(self, word):
        return '' if self.cv[word] < 2 else word
tokenizer = Tokenizer()
filter_words = FilterRareWords()
train[train['target'] == 1].head()
train['question_text'] = train['question_text'].apply(tokenizer)

filter_words.fit(train['question_text'])
train['question_text'] = train['question_text'].apply(filter_words)
pos_weight = train['target'].sum() / train.shape[0]
def make_vw_feature_line(label, importance, text):
    return '{} {} |text {}'.format(label, importance, text)

def make_vw_corpus(texts, labels):
    for text, label in zip(texts, labels):
        if label == 1.0:
            cur_feautre = make_vw_feature_line('1', 1 - pos_weight, text)
        else:
            cur_feautre = make_vw_feature_line('-1', pos_weight, text)
        yield cur_feautre
X_train, X_test = train_test_split(train, test_size=0.1, shuffle=True, random_state=42)
vw = pyvw.vw(
    quiet=True,
    loss_function='logistic',
    link='logistic',
    b=29,
    ngram=2,
    skips=1,
    random_seed=42,
    l1=3.4742122764e-09,
    l2=1.24232077629e-11,
    learning_rate=0.751849318433,
)
def get_pred(feature):
    ex = vw.example(feature)
    pred = vw.predict(ex)
    ex.finish()
    return pred
for fit_iter in range(3):
    for num, feature in enumerate(make_vw_corpus(X_train['question_text'], X_train['target'])):
        ex = vw.example(feature)
        vw.learn(ex)
        ex.finish()

    print('pass num {} done'.format(fit_iter))
pred = np.array([get_pred(x) for x in make_vw_corpus(X_test['question_text'], X_test['target'])])
thresholds = np.linspace(0, 1, 100)
f1_scores = [metrics.f1_score(X_test['target'], pred > threshold) for threshold in thresholds]
plt.plot(thresholds, f1_scores)
plt.grid(True)
plt.show()
print('best f1 score is {} with threshold {}'.format(np.max(f1_scores), thresholds[np.argmax(f1_scores)]))
test = pd.read_csv('../input/test.csv')

test['question_text'] = test['question_text'].apply(tokenizer)
test['question_text'] = test['question_text'].apply(filter_words)

pred = np.array([get_pred(x) for x in make_vw_corpus(test['question_text'], [1] * len(test))])

example = pd.read_csv('../input/sample_submission.csv')
example['prediction'] = (pred > thresholds[np.argmax(f1_scores)]).astype(int)
example.to_csv('submission.csv', index=False)
plt.hist(example['prediction']);


import os

# os.system('cd ..')
exp = 'EXP20221219_3'

# for cp in ['epoch-best.pth', 'epoch-last.pth'] + [f'epoch-{x}.pth' for x in range(300, 4000, 300)]:
for cp in ['epoch-best.pth', 'epoch-last.pth']:
# for cp in ['epoch-last.pth']:
# for cp in ['epoch-best.pth']:
# for cp in ['epoch-300.pth']:
    for scale_ratio in [2, 2.5, 3, 3.5, 4.0, 6, 8, 10]:
    # for scale_ratio in [4]:
        print(cp, '   ', scale_ratio)

        # os.system(f'CUDA_DEVICES_VISIBLE=0 python test_interpolate_sr.py '
        #           f'--config configs/test_interpolate.yaml '
        #           f'--scale_ratio {scale_ratio}')

        # os.system(f'CUDA_VISIBLE_DEVICES=1 python test_inr_liif_metasr_aliif.py '
        #           f'--config configs/baselines/test_INR_liif_metasr_aliif.yaml '
        #           f'--model checkpoints/{exp}/{cp} '
        #           f'--scale_ratio {scale_ratio}')

        # os.system(f'CUDA_VISIBLE_DEVICES=7 python test_inr_mysr.py '
        #           f'--config configs/test_UC_INR_mysr.yaml '
        #           f'--model checkpoints/{exp}/{cp} '
        #           f'--scale_ratio {scale_ratio}')

        os.system(f'CUDA_VISIBLE_DEVICES=1 python test_inr_diinn_arbrcan_sadnarc_funsr_overnet.py '
              f'--config configs/test_INR_diinn_arbrcan_funsr_overnet.yaml '
              f'--model checkpoints/{exp}/{cp} '
              f'--scale_ratio {scale_ratio} '
              f'--dataset_name AID')

        # os.system(f'CUDA_DEVICES_VISIBLE=0 python test_cnn_sr.py '
        #       f'--config configs/test_CNN.yaml '
        #       f'--model checkpoints/{exp}/{cp} '
        #       f'--scale_ratio {scale_ratio}')

        print('*' * 30)


from pydantic import ValidationError, validator
from sqlalchemy.orm import validates
from dtos.user_base import UserRegister

#@validator('username')
def validate_user_registration(user_data : UserRegister):
    username = user_data.username
    email = user_data.email

    if ' ' in username:
        raise ValueError('username must not contain a space')

    #Email logic defined here
    if  email.endswith('@example.com'):
        raise ValueError("Invalid email domain")

    return True


import argparse
import numpy as np

parser = argparse.ArgumentParser("Find the submarine location")
parser.add_argument('--filename', dest='filename', default='input')
args = parser.parse_args()

with open(args.filename, 'r') as f:
    lines = f.readlines()

num_drawns = [int(x) for x in lines[0].split(',')]

grids = []

def read_one_grid(grid_text):
    grid = []
    for l, vals in enumerate(grid_text):
        grid.append([int(x) for x in vals.split()])
    return grid

end_of_grids = False
nb_grids = 0
while(not end_of_grids):
    current_index = nb_grids * 6 + 2
    if current_index >= len(lines):
        break
    grids.append(read_one_grid(lines[current_index : current_index + 5]))
    nb_grids += 1

check_grid = np.zeros((len(grids),5,5))
grids = np.asarray(grids)

for num in num_drawns:
    check_grid[grids == num] = 1
    good_line = np.nonzero(check_grid.all(axis=2))
    good_col = np.nonzero(check_grid.all(axis=1))
    if len(good_line[0]):
        winner_grid = good_line[0]
        break
    elif len(good_col[0]):
        winner_grid = good_col[0]
        break

non_zero_tot = grids[winner_grid][(check_grid[winner_grid] == 0).nonzero()].sum()
print('non_zero_tot :', non_zero_tot, 'product :', non_zero_tot * num)


#!/usr/bin/python3

'''
a = (1,4,5,6,7)

#判断元素4是否在元组里
if 4 in a:
    print("在")
else:
    print("不再")

#把元素5修改成8
print(a)
b = list(a)
b[b.index(5)] = 8
a = tuple(b)
print(a)

'''

'''
#将a字符串的数字取出，并输出成一个新的字符串
a = input("请输入一个字符串\n")

b = "".join(x for x in a if x.isdigit())

print(a)
print(b)

'''

'''
#统计a字符串出现的每个字母的出现次数
a = "absdDababsbasba"
#a1 = ""
#for x in a:
#    if x >= 'A' and x <= 'Z':
#        x = x.swapcase()
#    a1 += x
a1 = a.lower()
b = {x:a1.count(x) for x in set(a1)}
print(a)
print(b)

'''

'''
#字符串多次出现的字母，仅留最先出现的一个

a = "acdacddddffa"
print(a)
print(''.join(x for x in set(a)))

'''

'''

#将a字符串反转并输出
a = "asdfgh"

print(a[::-1])
'''

'''
#字典练习

ainfo = {'ab':'liming','ac':20}

#添加
ainfo['sex'] = 'man'
ainfo.update(dict(age=20))

print(ainfo)

#输出结果：['ab','ac']

b = [x for x in ainfo.keys() if len(x) < 3]
print(b)

#输出结果：['liming',20]

c = [ainfo[y] for y in [x for x in ainfo.keys() if len(x) < 3]]
print (c)

#返回键名ab对应的值

print(ainfo['ab'])
print(ainfo.get('ab'))

#删除键名ac对应的值

print(ainfo.pop('ac'))

#del ainfo['ac']

print(ainfo)

'''

'''

#元组

a = (1,2,3)

#实现(5,2,3)
b = list(a)
b[0] = 5
a = tuple(b)

print(a)

#判断2是否在元组里

if 2 in a:
    print("在")
else:
    print("不再")

'''

'''
#集合

a = set(['a','b','c'])
b = set(['b','e','f','g'])
a.add('jay')

print(a)

#for x in b:
#    a.add(x)

a = set(list(a)+list(b))

print(a)

'''

'''
#输出结果：[1 love python,2 love python,3 love python,.... 10 love python]

a = [str(x) + ' love python' for x in range(1,11)]

print(a)

#输出结果：[(0,0),(0,2),(2,0),(2,2)]

b = [(x,y) for x in (0,2) for y in (0,2)]
print(b)

'''

a = [1,2,3]
b = a[:]

print(b)

del a
print(b)


from post.models import Post, Tag
from rest_framework import serializers
from .constants import constant

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ('id', 'name')

class PostSerializer(serializers.ModelSerializer):

    class Meta:
        model = Post
        fields = '__all__'
        read_only_fields = ('created', 'tags')

    # def get_validation_exclusions(self, *args, **kwargs):
    #     exclusions = super(PostSerializer, self).get_validation_exclusions()
    #
    #     return exclusions + ['test']

    def create(self, validated_data):
        print("validated_data", validated_data)
        str_tags = self.initial_data['tags']

        tag_list = str_tags.split(",")

        instance = Post.objects.create(**validated_data)

        tags = Tag.objects.filter(id__in=tag_list)
        for tag in tags:
            instance.tags.add(tag)

        return instance

class PostObjSerializer():
    def __init__(self, post_obj):
        self.obj = {
            "pk": post_obj.pk,
            "title": post_obj.title,
            "post_url": post_obj.post_url,
            "desc": post_obj.desc,
            "thumbnail_link": post_obj.thumbnail_link,
            "url": constant["url_post"]+str(post_obj.id),
            "tags": []
        }

        tags = post_obj.tags.all()
        if tags:
            self.obj["tags"] = [{"name": entry.name, "id": entry.id, "url": constant["url_tag"]+str(entry.id)}
                                for entry in tags]

    def run(self):
        return self.obj


"""
Get coordinates from previous day to form new sheet
"""
import csv
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import math

dire='C:/Users/ferad/OneDrive/Escritorio/hybridZone/WorkField/SheetsData/'
ids=pd.read_csv(dire+'day60.csv') #ñprevious day file
ids=ids['ID'].tolist()
veg=pd.read_csv(dire+'2022_veg_trait_data_new_coords_habitat.csv')

x=[]
y=[]
h=[]
missing=[]
dis=[]
prev=0
for i in ids:
    try:
        new=float(veg.loc[veg['ID']==i]['x'])
        x.append(new)
        dis.append(round(abs(new-prev),2))
        prev=new
        # y.append(float(veg.loc[veg['ID']==i]['y']))
        # h.append(float(veg.loc[veg['ID']==i]['h']))
    except:
        x.append(' ')
        dis.append(' ')
        missing.append(i)
        # y.append('missing')
        # h.append('missing')
        # print(veg['ID']==i)
        # print(veg.loc[veg['ID']==i]['x'])

notSheet=[]
for i in veg['ID']:
    if not i in ids:
        notSheet.append(i)

dictionary={'ID':ids,'x':dis}
# dictionary={'ID':ids,'x':x,'y':y,'h':h}
dataframe=pd.DataFrame(dictionary)
dataframe.to_csv('IDsCoordinates.csv')


# By using two for loops cur and runner we can find the max sub arr with runtime of O(n**2)

# Kadane's algorithm find the maximum sum of a contiguous subarray in an array with a runtime of O(n).

# https://favtutor.com/blogs/kadanes-algorithm-python

def max_continous_sum(arr):
	current_max = 0
	max_sum = 0

	for i in range(len(arr)):
		current_max += arr[i]

		if current_max < 0:
			current_max = 0

		if current_max > max_sum:
			max_sum = current_max

	return max_sum

# if the arry is circular, we will track both maximin positive and maximin negative as well as the array sum and return the maximm of either maximin positive or difference of array sum and maximun negative

def max_continous_circular_arr(arr):
	curr_max = curr_min = total_max = 0
	pos_max = float('-inf')
	min_max = float('inf')

	for i in range(len(arr)):
		total_max += arr[i]

		curr_max += arr[i]

		if curr_max > pos_max:
			pos_max = curr_max

		if curr_max < 0:
			curr_max = 0

		curr_min += arr[i]
		if curr_min < min_max:
			min_max = curr_min

		if curr_min > 0:
			curr_min = 0

	print('Total max',total_max)
	print('Minimun max',min_max)
	print('positive max', pos_max)

	if total_max == min_max:
		return pos_max

	return max(pos_max, (total_max - min_max))

def main():
	arr = [1, 4, 5, 6, -2, -6, -9, 0, 1, 2]
	arr2 = [-1, -3, -2, 6, -1 ,4]
	# print('the maximum sub array is: ', end='')
	# print(max_continous_sum(arr))
	# print("max Continous Sum: ", end='')
	print(max_continous_circular_arr(arr2))
if __name__ == '__main__':
	main()


from dcgan import *

# Learning Parameters
CRITERION = nn.BCEWithLogitsLoss()
N_EPOCHS = 50
Z_DIM = 64
DISPLAY_STEP = 500
BATCH_SIZE = 128
LR = 0.0002
DEVICE = 'cuda'
DOWNLOAD_DATA = True

# Optimization-Momentur Parameters
BETA_1 = 0.5
BETA_2 = 0.999

# Normalize images - values between -1 & 1
transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=(0.5,), std=(0.5,)),
])
# Data loader object
dataloader = DataLoader(
    MNIST('.', download=DOWNLOAD_DATA, transform=transform),
        batch_size=BATCH_SIZE, shuffle=True)

# Instantiate Generator & Discriminator
gen = Generator(Z_DIM).to(DEVICE)
gen_opt = torch.optim.Adam(gen.parameters(), lr=LR, betas=(BETA_1, BETA_2))
disc = Discriminator().to(DEVICE)
disc_opt = torch.optim.Adam(disc.parameters(), lr=LR, betas=(BETA_1, BETA_2))

# Initialize wieghts to the normal distribution
# with mean 0 and standard deviation 0.02
def weights_init(m):
    if isinstance(m, nn.Conv2d) or isinstance(m, nn.ConvTranspose2d):
        torch.nn.init.normal_(m.weight, mean=0.0, std=0.02)
    if isinstance(m, nn.BatchNorm2d):
        torch.nn.init.normal_(m.weight, mean=0.0, std=0.02)
        torch.nn.init.constant_(m.bias, 0)

gen = gen.apply(weights_init)
disc = disc.apply(weights_init)

def run_neural_network():
    cur_step = 0
    mean_generator_loss = 0
    mean_discriminator_loss = 0
    for epoch in range(N_EPOCHS):
        # Dataloader returns the batches
        for real, _ in tqdm(dataloader):
            cur_batch_size = len(real)
            real = real.to(DEVICE)

            ## Update Discriminator
            disc_opt.zero_grad()
            fake_noise = get_noise(cur_batch_size, Z_DIM, DEVICE)
            fake = gen(fake_noise).detach()
            disc_fake_pred = disc(fake)
            disc_fake_loss = CRITERION(disc_fake_pred, torch.zeros_like(disc_fake_pred))
            real_disc_pred = disc(real)
            real_disc_loss = CRITERION(real_disc_pred, torch.ones_like(real_disc_pred))
            disc_loss = (disc_fake_loss + real_disc_loss) / 2
            # Update Gradients
            disc_loss.backward(retain_graph=True)
            # Update Optimizer
            disc_opt.step()
            # Keep track of the average discriminator loss
            mean_discriminator_loss += disc_loss / DISPLAY_STEP

            ## Update Generator
            gen_opt.zero_grad()
            fake_noise_2 = get_noise(cur_batch_size, Z_DIM, DEVICE)
            fake_2 = gen(fake_noise_2)
            disc_fake_2_pred = disc(fake_2)
            gen_loss = CRITERION(disc_fake_2_pred, torch.ones_like(disc_fake_2_pred))
            # Update gradients
            gen_loss.backward()
            # Update optimizer
            gen_opt.step()
            # Keep track of the average generator loss
            mean_generator_loss += gen_loss.item() / DISPLAY_STEP

            ## Visualizing
            if (cur_step % DISPLAY_STEP) == 0 and (cur_step > 0):
                print(f"Step: {cur_step}  Generator loss: {mean_generator_loss}  Discriminator loss: {mean_discriminator_loss}")
                show_tensor_images(fake)
                show_tensor_images(real)
                mean_generator_loss = 0
                mean_discriminator_loss = 0

            cur_step += 1


### 메인 함수 있는 곳

# --------------------------------------------

import streamlit as st

# 다른 파이썬 파일 임포트
from app_image import run_app_image
from app_csv import run_app_csv
from app_about import run_app_about
# ----------------------------------------------

def main():
    st.title('내 앱 대시보드')

    ### 누르면 왼쪽에 메뉴 나오게 하기
    menu = ['이미지업로드', 'csv업로드', 'About']
    # ('메뉴'-> 유저에게 보여지는거, menu -> 여기서 가져와라)
    # st.sidebar.selectbox('메뉴', menu)  # 화면에 보여주기만 하는것

    ## 선택한 메뉴 페이지로 이동하기
    choice = st.sidebar.selectbox('메뉴', menu)
    # print(choice)
    # if choice == '이미지업로드': # 라고 해도 되지만 메뉴 이름 자동변환위해

    if choice == menu[0] :
        run_app_image()

    elif choice == menu[1] :  # ------------------------------------
        run_app_csv()

    else : # -------------------------------------------------------
        run_app_about()

if __name__ == '__main__':
    main()


# coding=utf-8

from odoo import api, fields, models
from odoo.addons import decimal_precision as dp

class PurchaseOrderLine(models.Model):
    _inherit = "purchase.order.line"

    qty_unship = fields.Float(compute='_compute_qty_unship', string="unship Qty",
                              digits=dp.get_precision('Product Unit of Measure'), store=True)

    @api.depends('order_id.state', 'move_ids.state', 'move_ids.product_uom_qty')
    def _compute_qty_unship(self):
        for line in self:
            if line.order_id.state not in ['purchase', 'done']:
                continue
            if line.product_id.type not in ['consu', 'product']:
                continue
            received = 0.0
            for move in line.move_ids:
                if move.state == 'assigned':
                    received += move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
                if move.state == 'done':
                    if move.location_dest_id.usage == "supplier":
                        if move.to_refund:
                            received -= move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
                    else:
                        received += move.product_uom._compute_quantity(move.product_uom_qty, line.product_uom)
            line.qty_unship = line.product_qty - received

    @api.multi
    def _prepare_stock_moves(self, picking, count=None):
        res = super(PurchaseOrderLine, self)._prepare_stock_moves(picking)
        if not res or count is None:
            return res

        res[0]['product_uom_qty'] = count
        res[0]['quantity_done'] = count
        return res

    @api.multi
    def _create_stock_moves(self, picking, stock_count=None):
        """
        :param picking:
        :param dict stock_count: {line_id: count}
        :return:
        """
        if stock_count is None:
            return super(PurchaseOrderLine, self)._create_stock_moves(picking)

        moves = self.env['stock.move']
        done = self.env['stock.move'].browse()
        for line in self:
            count = stock_count.get(line.id, 0)
            if count == 0:
                continue
            for val in line._prepare_stock_moves(picking, count):
                new_move = moves.create(val)
                new_move.ordered_qty = line.product_qty
                done += new_move
        return done


import argparse

try:
    from waymo_open_dataset import dataset_pb2
except ImportError:
    raise ImportError(
        'Please run "pip install waymo-open-dataset-tf-2-1-0==1.2.0" '
        'to install the official devkit first.')

from glob import glob
from os.path import join

import mmcv
import tensorflow as tf
from waymo_open_dataset.protos import metrics_pb2

def save_label(frame, objects, version='multi-view', cam_sync=True):
    """Parse and save gt bin file for camera-only 3D detection on Waymo.

    Args:
        frame (:obj:`Frame`): Open dataset frame proto.
        objects (:obj:`Object`): Ground truths in waymo dataset Object proto.
        version (str): Version of gt bin file. Choices include 'multi-view'
            and 'front-view'. Defaults to 'multi-view'.
        cam_sync (bool): Whether to generate camera synced gt bin. Defaults to
            True.
    """
    id_to_bbox = dict()
    id_to_name = dict()
    for labels in frame.projected_lidar_labels:
        name = labels.name  # 0 unknown, 1-5 corresponds to 5 cameras
        for label in labels.labels:
            # TODO: need a workaround as bbox may not belong to front cam
            bbox = [
                label.box.center_x - label.box.length / 2,
                label.box.center_y - label.box.width / 2,
                label.box.center_x + label.box.length / 2,
                label.box.center_y + label.box.width / 2
            ]
            # object id in one frame
            id_to_bbox[label.id] = bbox
            id_to_name[label.id] = name - 1
    if version == 'multi-view':
        cam_list = [
            '_FRONT', '_FRONT_LEFT', '_FRONT_RIGHT', '_SIDE_LEFT',
            '_SIDE_RIGHT'
        ]
    elif version == 'front-view':
        cam_list = ['_FRONT']
    else:
        raise NotImplementedError
    for obj in frame.laser_labels:
        bounding_box = None
        name = None
        id = obj.id
        for cam in cam_list:
            if id + cam in id_to_bbox:
                bounding_box = id_to_bbox.get(id + cam)
                name = str(id_to_name.get(id + cam))
                break
        num_pts = obj.num_lidar_points_in_box

        if cam_sync:
            if obj.most_visible_camera_name:
                box3d = obj.camera_synced_box
            else:
                continue
        else:
            box3d = obj.box

        if bounding_box is not None and obj.type > 0 and num_pts >= 1:
            o = metrics_pb2.Object()
            o.context_name = frame.context.name
            o.frame_timestamp_micros = frame.timestamp_micros
            o.score = 0.5
            o.object.CopyFrom(obj)
            o.object.box.CopyFrom(box3d)
            objects.objects.append(o)

parser = argparse.ArgumentParser(description='Waymo GT Generator arg parser')
parser.add_argument(
    '--root-path',
    type=str,
    default='data/waymo/waymo_format/validation',
    help='specify the root path of dataset')
parser.add_argument(
    '--version',
    type=str,
    default='multi-view',
    required=False,
    help='specify the gt version')
parser.add_argument(
    '--out-dir',
    type=str,
    default='data/waymo/waymo_format/',
    required=False,
    help='name of info pkl')
parser.add_argument(
    '--backend',
    type=str,
    default='disk',
    required=False,
    help='file backend for data loading')
args = parser.parse_args()

if __name__ == '__main__':
    load_dir = args.root_path
    version = args.version
    out_dir = args.out_dir
    if args.backend == 'disk':
        file_client_args = dict(backend='disk')
    elif args.backend == 'petrel':
        file_client_args = dict(
            backend='petrel',
            path_mapping=dict({
                './data/waymo/':
                's3://openmmlab/datasets/detection3d/waymo-v1.3.1/',
                'data/waymo/':
                's3://openmmlab/datasets/detection3d/waymo-v1.3.1/'
            }))
    tfrecord_pathnames = glob(join(load_dir, '*.tfrecord'))
    if file_client_args['backend'] == 'disk':
        tfrecord_pathnames = sorted(glob(join(load_dir, '*.tfrecord')))
    else:
        file_client = mmcv.FileClient(**file_client_args)
        load_dir = file_client.client._map_path(load_dir)
        from petrel_client.client import Client
        client = Client()
        contents = client.list(load_dir)
        tfrecord_pathnames = list()
        for content in sorted(list(contents)):
            if content.endswith('tfrecord'):
                tfrecord_pathnames.append(join(load_dir, content))

    objects = metrics_pb2.Objects()
    progress_bar = mmcv.ProgressBar(len(tfrecord_pathnames))
    for i in range(len(tfrecord_pathnames)):
        pathname = tfrecord_pathnames[i]
        segment_filename = pathname.split('/')[-1]
        context_name = segment_filename[8:-28]
        dataset = tf.data.TFRecordDataset(pathname, compression_type='')
        for frame_idx, data in enumerate(dataset):
            frame = dataset_pb2.Frame()
            frame.ParseFromString(bytearray(data.numpy()))
            save_label(frame, objects, version)
        progress_bar.update()

    # Write objects to a file.
    f = open(join(out_dir, 'cam_gt.bin'), 'wb')
    f.write(objects.SerializeToString())
    f.close()