import sys
from threading import Lock
from enum import Enum
from heapq import *
from functools import reduce

# if __name__ == "__main__":
#     s = Solution()
#     image = [[1,1,1],[1,1,0],[1,0,1]]
#     s.floodFill(image,1,1,2)

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None

class Solution_697(object):
    def findShortestSubArray(self, nums) -> int:
        dict = {}
        for i in nums:
            if i in dict:
                dict[i] += 1
            else:
                dict[i] = 1
        max_occurs_ele = -1
        max_occurs_count = 0
        for k,v in dict.items():
            if v > max_occurs_count:
                max_occurs_count = v
                max_occurs_ele = k
        res = []
        for k,v in dict.items():
            if v == max_occurs_count:
                res.append(k)
        degree = len(nums)
        for e in res:
            j = len(nums) - 1
            end = j
            start = nums.index(e)
            while j > 0:
                if nums[j] == e:
                    end = j
                    break
                else:
                    j -= 1
            if (end - start + 1) <= degree:
                degree = end - start + 1
        return degree

class Solution_860:
    def lemonadeChange(self, bills) -> bool:
        change = {}
        for pay in bills:
            if pay == 5:
                if pay in change:
                    change[pay] += 1
                else:
                    change[pay] = 1
            elif pay == 10:
                if 5 not in change or change[5] <= 0:
                    return False
                else:
                    change[5] -= 1
                if pay in change:
                    change[pay] += 1
                else:
                    change[pay] = 1
            elif pay == 20:
                if 5 not in change or change[5] <= 0:
                    return False
                if 10 in change and change[10] > 0:
                    change[10] -=1
                    change[5] -= 1
                elif change[5] >= 3:
                    change[5] -= 3
                else:
                    return False
        return True

class Solution_455:
    def findContentChildren(self, g, s) -> int:
        g = sorted(g)
        s = sorted(s)
        i = 0
        j = 0
        while i < len(g) and j < len(s):
            if s[j] >= g[i]:
                i += 1
            j += 1
        return i

class Solution_1071:
    def gcdOfStrings(self, str1: str, str2: str) -> str:
        res = ""
        if str1 == str2:
            return str1
        short_str = str1 if len(str1) < len(str2) else str2
        long_str = str1 if len(str1) >= len(str2) else str2
        pos = long_str.find(short_str,0)
        if pos == -1:
            return res
        rest = long_str[len(short_str):]
        return self.gcdOfStrings(rest,short_str)

class Employee:
    def __init__(self, id, importance, subordinates):
        # It's the unique id of each node.
        # unique id of this employee
        self.id = id
        # the importance value of this employee
        self.importance = importance
        # the id of direct subordinates
        self.subordinates = subordinates

"""
# Employee info
class Employee:
    def __init__(self, id, importance, subordinates):
        # It's the unique id of each node.
        # unique id of this employee
        self.id = id
        # the importance value of this employee
        self.importance = importance
        # the id of direct subordinates
        self.subordinates = subordinates
"""
#[[1,5,[2,3]],[2,3,[]],[3,3,[]]]
#[[1,5,[2,3]],[2,3,[4]],[3,4,[]],[4,1,[]]]
importance_map = {}
class Solution_690:
    def get_importance(self,employee):
        res = 0
        res += employee.importance
        for id in employee.subordinates:
            res += self.get_importance(importance_map[id])
        return res

    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        global importance_map
        for p in employees:
            importance_map[p.id] = p
            if p.id == id:
                root_people = p
        total = 0
        total += self.get_importance(root_people)
        return total

class Solution_1018:
    def prefixesDivBy5(self, A):
        res = []
        val = -1
        for i in range(len(A)):
            if val == -1:
                val = A[i]
            else:
                val = val * 2 + A[i]
            res.append(val%5==0)
        return res

class Solution_720:
    def longestWord(self, words) -> str:
        if len(words) == 1:
            return words[0]
        new_words = sorted(words)
        dict = set()
        res = ""
        for w in new_words:
            if len(w) > len(res):
                exist = True
                i = 1
                while i < len(w):
                    if w[:i] not in dict:
                        exist = False
                        break
                    i += 1
                if exist:
                    res = w
            dict.add(w)
        return res

#[8,7,3,5,3,6,1,4])
class Solution_645:
    def findErrorNums(self, nums):
        res = []
        dict = {}
        for num in nums:
            if num not in dict:
                dict[num] = 1
            else:
                res.append(num)
        i = 1
        while i < len(nums):
            if i not in dict:
                res.append(i)
                break
            i += 1
        return res

def get_value(n):
    if n == 0:
        return 1
    elif n == 1:
        return n
    else:
        return n * get_value(n - 1)

def gen_last_value(n, m):
    first = get_value(n)
    second = get_value(m)
    third = get_value((n - m))
    return first / (second * third)

class Solution_1128:
    def numEquivDominoPairs(self, dominoes):
        res = 0
        dict = {}
        for ele in dominoes:
            min = ele[0] if ele[0] < ele[1] else ele[1]
            max = ele[0] if ele[0] > ele[1] else ele[1]
            if (min,max) in dict:
                #res += dict[(min,max)]
                dict[(min, max)] += 1
            else:
                dict[(min,max)] = 1

        for k,v in dict.items():
            if v >= 2:
                res += gen_last_value(v,2)

        return res

class Solution_438:
    def findAnagrams(self, s: str, p: str):
        res = []
        len_p = len(p)
        record = [-1] * 26
        for c in p:
            i = ord(c)-ord('a')
            if record[i] == -1:
                record[i] = 1
            else:
                record[i] += 1
        start = 0
        end = 0
        match_cnt = 0
        while end < len(s):
            if record[ord(s[end])-ord('a')] > 0:
                match_cnt += 1
            record[ord(s[end])-ord('a')] -= 1

            if end - start + 1 == len_p:
                if match_cnt == len_p:
                    res.append(start)
#开始新的搜索
                if record[ord(s[start])-ord('a')] >= 0:
                    match_cnt -= 1
#还原之前减去的
                record[ord(s[start])-ord('a')] += 1
                start += 1
            end += 1

        return res

class Solution_172:
    def trailingZeroes(self, n: int) -> int:
        res = 0
        sum = 1
        for i in range(1,n+1):
            sum *= i

        s = str(sum)[::-1]
        for c in s:
            if c == '0':
                res += 1
            else:
                break
        return res

class Solution_219:
    def containsNearbyDuplicate(self, nums, k) -> bool:
        record = {}
        for index in range(0,len(nums)):
            if nums[index] in record:
                if index - record[nums[index]] <= k:
                    return True
                else:
                    record[nums[index]] = index
            else:
                record[nums[index]] = index
        return False

#69. Sqrt(x)
class Solution_69:
    def mySqrt(self, x: int) -> int:
        if x == 0:
            return 0
        low = 1
        high = x
        while low <= high:
            mid = low + (high-low)//2
            val = mid * mid
            if val == x:
                return mid
            elif val < x:
                low = mid + 1
            else:
                high = mid - 1
        return high

class Solution_605:
    def canPlaceFlowers(self, flowerbed: [int], n: int) -> bool:
        if n == 0:
            return True
        flowerbed.insert(0,0)
        flowerbed.append(0)
        l = len(flowerbed)
        index = 0
        total = 0
        start_count = False
        temp_cnt = 0
        while index < l:
            if flowerbed[index] == 0:
                temp_cnt += 1
                start_count = True
            else:
                if start_count:
                    total += (temp_cnt - 1) // 2
                start_count = False
                temp_cnt = 0
            index += 1

        if start_count:
            total += (temp_cnt - 1) / 2
        return total >= n

import math

class Solution_686:
    def repeatedStringMatch(self, A: str, B: str) -> int:
        b_map = {}
        a_map = {}
        for b_e in B:
            if b_e in b_map:
                b_map[b_e] += 1
            else:
                b_map[b_e] = 1
        for a_e in A:
            if a_e in a_map:
                a_map[a_e] += 1
            else:
                a_map[a_e] = 1
        res = - 1
        prev = -1
        for k,v in b_map.items():
            if k not in a_map:
                return -1
            if prev == -1:
                prev = a_map[k]/v
                continue
            times = a_map[k]/v
            if times != prev:
                return -1
        if prev > 1:
            return 1
        else:
            res = 1/prev
            if res - (int(res)) == 0:
                return res + 1
            else:
                return math.ceil(1/prev)

class Solution_754:
    def reachNumber(self, target: int) -> int:

        pass

cnt = 0
l = []
class Solution_894:
    def allPossibleFBT(self, N: int):
        t = TreeNode(0)
        global cnt
        cnt += 1
        return l
        pass

    def recrusive(self,parent:TreeNode,cur_num,N :int,record):
        if cur_num > N - 2:
            return

        left = TreeNode(0)
        right = TreeNode(0)
        parent.left = left
        parent.right = right
        self.recrusive(left,cur_num + 2,N)
        self.recrusive(right,cur_num + 2, N)
        pass

class Solution_1200:
    def minimumAbsDifference(self, arr):
        s = sorted(arr)
        min_distinct = s[-1] - s[0]
        res = []
        for i in range(0,len(s) - 1):
            if (s[i+1] - s[i]) < min_distinct:
                min_distinct = s[i+1] - s[i]

        for i in range(0, len(s) - 1):
            if (s[i+1] - s[i]) == min_distinct:
                couple = [s[i],s[i+1]]
                res.append(couple)

        return res

import time
class FizzBuzz_1195:
    def __init__(self, n: int):
        self.n = n
        self.cur = 1
        self.fizzlock = Lock()
        self.buzzlock = Lock()
        self.fizzbuzzlock = Lock()
        self.numberlock = Lock()

    # printFizz() outputs "fizz"
    def fizz(self, printFizz: 'Callable[[], None]') -> None:
        while True:
            self.fizzlock.acquire()
            self.fizzbuzzlock.acquire()
            if self.cur % 3 == 0 and self.cur % 5 != 0:
                printFizz()
                self.cur += 1
            self.fizzlock.release()
            self.fizzbuzzlock.release()
            if self.cur >= self.n:
                break
        pass

    # printBuzz() outputs "buzz"
    def buzz(self, printBuzz: 'Callable[[], None]') -> None:
        while True:
            self.buzzlock.acquire()
            self.fizzbuzzlock.acquire()
            if self.cur % 5 == 0 and self.cur % 3 != 0:
                print("buzz " + self.cur)
                printBuzz()
                self.cur += 1
            self.buzzlock.release()
            self.fizzbuzzlock.release()
            if self.cur >= self.n:
                break
        pass

    # printFizzBuzz() outputs "fizzbuzz"
    def fizzbuzz(self, printFizzBuzz: 'Callable[[], None]') -> None:
        while True:
            self.lock.acquire()
            if self.n % 5 == 0 and self.n % 3 == 0:
                print("fizzbuzz " + self.cur)
                printFizzBuzz()
                self.cur += 1
            self.lock.release()
            if self.cur >= self.n:
                break
        pass

    # printNumber(x) outputs "x", where x is an integer.
    def number(self, printNumber: 'Callable[[int], None]') -> None:
        while True:
            self.lock.acquire()
            if self.cur % 5 != 0 and self.cur % 3 != 0:
                print("number " + self.cur)
                printNumber(self.cur)
                self.cur += 1
            self.lock.release()
            if self.cur >= self.n:
                break
        pass

class Solution_1190:
    def reverseParentheses(self, s: str) -> str:

        pass

class Solution_79:
    def dfs(self,board,word,cur_pos,row,col):
        if cur_pos >= len(word):
            return True
        if row < 0 or row >= len(board) or col < 0 or col >= len(board[0]) or board[row][col] == "." :
            return False
        if board[row][col] != word[cur_pos]:
            return False
        tmp = board[row][col]
        board[row][col] = '.'
        cur_pos += 1
        ret = self.dfs(board, word, cur_pos, row - 1, col) or self.dfs(board, word, cur_pos, row + 1, col) or \
               self.dfs(board, word, cur_pos, row, col - 1) or self.dfs(board, word, cur_pos, row, col + 1)
        board[row][col] = tmp
        return ret

    def exist(self, board, word: str) -> bool:
        for i in range(len(board)):
            for j in range(len(board[i])):
                ret = self.dfs(board,word,0,i,j)
                if ret:
                    return ret
                pass
        return False

# Input: nums =
# [
#   [9,9,4],
#   [6,6,8],
#   [2,1,1]
# ]
# Output: 4

class Num_State(Enum):
    Undefined = 0
    Increase = 1
    Decrease = 2

class Solution_329:
    def dfs(self,matrix,row,col,pre_num,is_increase,record,trace):
        k = str(row) + "," + str(col)
        if row < 0 or row >= len(matrix) or col < 0 or col >= len(matrix[0]) or trace.get(k):
            return 0

        if is_increase:
            if matrix[row][col] <= pre_num:
                return 0
        else:
            if matrix[row][col] >= pre_num:
                return 0
        if k in trace:
            return cnt

        trace[k] = 1
        if k in record:
             return record[k]
        ret = 1 + max(self.dfs(matrix,row - 1,col,matrix[row][col],is_increase,record,trace),self.dfs(matrix,row + 1,col,matrix[row][col],is_increase,record,trace),
        self.dfs(matrix, row, col - 1, matrix[row][col], is_increase,record,trace),self.dfs(matrix,row,col + 1,matrix[row][col],is_increase,record,trace))
        del trace[k]
        record[k] = ret
        return ret

    def longestIncreasingPath(self, matrix) -> int:
        max_increase_cnt = 0
        max_decrease_cnt = 0
        increase_record = {}
        decrease_record = {}
        for i in range(len(matrix)):
            for j in range(len(matrix[i])):
                trace1 = {}
                max_increase_cnt = max(self.dfs(matrix,i,j, sys.maxsize,False,increase_record,trace1),max_increase_cnt)
                trace2 = {}
                max_decrease_cnt = max(self.dfs(matrix, i, j,-sys.maxsize,True,decrease_record,trace2), max_decrease_cnt)
        return max(max_increase_cnt,max_decrease_cnt)

#Input: s = "10#11#12"
#Output: "jkab"
#Explanation: "j" -> "10#" , "k" -> "11#" , "a" -> "1" , "b" -> "2".
class Solution_1309:
    def freqAlphabets(self, s: str) -> str:
        i = len(s) - 1
        res = ""
        while i >= 0:
            if s[i] == "#":
                r = chr(int(s[i-2:i]) - 1 + ord("a"))
                res = r + res
                i = i - 3
            else:
                r = chr(ord(s[i]) - ord("1") + ord("a"))
                res = r + res
                i = i - 1
        return res

#Input: nums = [1,3,-1,-3,5,3,6,7], and k = 3
# Output: [3,3,5,5,6,7]
# Explanation:
#
# Window position                Max
# ---------------               -----
# [1  3  -1] -3  5  3  6  7       3
#  1 [3  -1  -3] 5  3  6  7       3
#  1  3 [-1  -3  5] 3  6  7       5
#  1  3  -1 [-3  5  3] 6  7       5
#  1  3  -1  -3 [5  3  6] 7       6
#  1  3  -1  -3  5 [3  6  7]      7
class Solution_239:
    def maxSlidingWindow(self, nums, k: int):
        heap = []

        heappush(heap, 2)
        heappush(heap, 3)
        heappush(heap, 3)
        heappush(heap,1)
        heappush(heap, 1)
        n = nlargest(1,heap)
        a = []
        heappop(heap)
        heapify(heap)
        return nums

# Input: "babad"
# Output: "bab"
# Note: "aba" is also a valid answer.
class Solution_5:
    def longestPalindrome(self, s: str) -> str:
        l = len(s)
        if l <= 1:
            return s
        dp = [] # dp[i][j] = 1 means from i to j is palindrome
        for i in range(l):
            dp.append([])
            for j in range(l):
                if i == j:
                    dp[i].append(1)
                else:
                    dp[i].append(0)
        end = 1
        max_len = 0
        res = ""
        while end < l:
            begin = end
            while begin >= 0:
                if s[begin] == s[end]:
                    if (end - begin) < 3 or dp[begin+1][end-1] == 1:
                        dp[begin][end] = 1
                        if (end - begin + 1) > max_len:
                            max_len = end - begin + 1
                            res = s[begin:end + 1]
                begin -= 1
            end += 1
        return res

# Given arraytype nums = [-1, 0, 1, 2, -1, -4],
# A solution set is:
# [
#   [-1, 0, 1],
#   [-1, -1, 2]
# ]
class Solution_15:
    def threeSum(self, nums):
        res = []
        l = len(nums)
        if l < 3:
            return res
        record = {}
        nums = sorted(nums)
        for i in range(len(nums)):
            if nums[i] in record:
                record[nums[i]].append(i)
            else:
                record[nums[i]] = [i]
        res_record = {}
        slow = 0
        while slow < l:
            fast = slow + 1
            if nums[slow] > 0:
                break
            while fast < l:
                #s = ''.join(str(i) for i in sorted([nums[slow], nums[fast], find]))
                if nums[slow] + nums[fast] > 0:
                    break
                k = str(nums[slow]) + str(nums[fast])
                if k in res_record:
                    fast += 1
                    continue
                find = -(nums[slow] + nums[fast])
                if find in record:
                    pos_list = record[find]
                    dup = True
                    find_pos = -1
                    for pos in pos_list:
                        if pos != slow and pos != fast:
                            dup = False
                            find_pos = pos
                            break
                    if dup:
                        fast += 1
                        continue
                    res.append([nums[slow],nums[fast],find])
                    res_record[str(nums[slow]) + str(nums[fast])] = True
                    res_record[str(nums[fast]) + str(nums[slow])] = True
                    res_record[str(nums[slow]) + str(nums[find])] = True
                    res_record[str(nums[find]) + str(nums[slow])] = True
                    res_record[str(nums[fast]) + str(nums[find])] = True
                    res_record[str(nums[find]) + str(nums[fast])] = True
                fast += 1
            slow += 1
        return res

class Solution_15ex:
    def threeSum(self, nums):
        res = []
        l = len(nums)
        if l < 3:
            return res
        nums = sorted(nums)
        head = 0
        end = l - 1
        last_head = 2e31
        while head <= end:
            mid = head + 1
            end = l - 1
            if head <= end and nums[head] == last_head:
                head += 1
                continue
            last_head = nums[head]
            while mid < end:
                last_end = nums[end]
                if nums[end] < 0:
                    break
                if nums[head] + nums[mid] + nums[end] < 0:
                    mid += 1
                elif nums[head] + nums[mid] + nums[end] > 0:
                    end -= 1
                    while end >= head and nums[end] == last_end:
                        end -= 1
                        continue
                else:
                    res.append([nums[head],nums[mid],nums[end]])
                    mid += 1
                    end -= 1
                    while end >= head and nums[end] == last_end:
                        end -= 1
                        continue
            head += 1
        return res

# Given arraytype nums = [-1, 2, 1, -4], and target = 1.
# The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
class Solution_16:
    def threeSumClosest(self, nums, target: int) -> int:
        diff = 2e31
        nums = sorted(nums)
        head = 0
        l = len(nums)
        end = l - 1
        sum = 0
        while head < end:
            last_head = nums[head]
            mid = head + 1
            end = l - 1
            while mid < end:
                last_end = nums[end]
                if abs(nums[head] + nums[mid] + nums[end] - target) < diff:
                    diff = abs(nums[head] + nums[mid] + nums[end] - target)
                    sum = nums[head] + nums[mid] + nums[end]
                if nums[head] + nums[mid] + nums[end] < target:
                    mid += 1
                elif nums[head] + nums[mid] + nums[end] > target:
                    end -= 1
                    while end >= 0 and last_end == nums[end]:
                        end -= 1
                        continue
                else:
                    return sum
            head += 1
            while head < l and last_head == nums[head]:
                head += 1
                continue
        return sum

#1310
# Input: arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
# Output: [2,7,14,8]
class Solution_1310:
    #def xorQueries(self, arr: List[int], queries: List[List[int]]) -> List[int]:
    def xorQueries(self, arr, queries):
        # res = []
        # for ele in [arr[q[0]:q[1]+1] for q in queries]:
        #     res.append(reduce(lambda x,y:x^y,ele))
        # return res

        l = len(arr)
        i = 1
        record = [0] * l
        record[0] = arr[0]
        while i < l:
            record[i] = record[i-1] ^ arr[i]
            i += 1

        res = []
        for q in queries:
            if q[0] - 1 < 0:
                res.append(record[q[1]] ^ 0)
            else:
                res.append(record[q[1]] ^ record[q[0] - 1])
        return res

# Input: ")()())"
# Output: 4
# Explanation: The longest valid parentheses substring is "()()"
class Solution_32:
    def longestValidParentheses(self, s: str) -> int:
        pass

# Input: candidates = [10,1,2,7,6,1,5], target = 8,
# A solution set is:
# [
#   [1, 7],
#   [1, 2, 5],
#   [2, 6],
#   [1, 1, 6]
# ]
class Solution_40:
    def combine(self,candidates,cur_pos,cur_sum,target_num,cur_list,res,dup_record):
        if cur_sum > target_num:
            return
        if cur_sum == target_num:
            k = ''.join(str(i) for i in cur_list)
            if k not in dup_record:
                dup_record[k] = True
                res.append(cur_list.copy())
            return
        else:
            i = cur_pos
            while i < len(candidates):
                if (cur_sum + candidates[i]) > target_num:
                    break
                if i > cur_pos and candidates[i] == candidates[i-1]:
                    i += 1
                    continue
                cur_list.append(candidates[i])
                self.combine(candidates,i+1,cur_sum + candidates[i],target_num,cur_list,res,dup_record)
                del (cur_list[-1])
                #self.combine(candidates, i+1,cur_sum, target_num, cur_list, res,dup_record)
                i += 1

    def combinationSum2(self, candidates, target: int):
        candidates = sorted(candidates)
        dup_record = {}
        res = []
        self.combine(candidates,0,0,target,[],res,dup_record)
        return res

class Solution_1184:
    #def distanceBetweenBusStops(self, distance: List[int], start: int, destination: int) -> int:
    def distanceBetweenBusStops(self, distance, start: int, destination: int) -> int:
        l = len(distance)
        clockwise_disatance = 0
        i = start
        while i != destination:
            clockwise_disatance += distance[i]
            i = (i + 1) % l
        counterclockwise_distance = 0
        j = destination
        while j != start:
            counterclockwise_distance += distance[j]
            j = (j + 1) % l
        return min(clockwise_disatance,counterclockwise_distance)

class Solution_90:
    def dfs(self,cur_pos,target_len,nums,cur_list,res):
        if len(cur_list) > target_len or cur_pos > len(nums):
            return
        if len(cur_list) == target_len:
            res.append(cur_list)
            return
        for i in range(cur_pos,len(nums)):
            if (len(cur_list) + len(nums) - i) < target_len:
                break
            if i > cur_pos:
                if nums[i] == nums[i-1]:
                    continue
            self.dfs(i + 1,target_len,nums,cur_list + [nums[i]] ,res)
            i += 1

    def subsetsWithDup(self, nums):
        res = []
        nums = sorted(nums)
        for i in range(len(nums)+1):
            self.dfs(0,i,nums,[],res)
        return res

# input
# [0,0,0,0,0,1,1,1,2,2,3,3,5,5,6]
# Expected
# [0,0,1,1,2,2,3,3,5,5,6]
class Solution_80:
    def removeDuplicates(self, nums) -> int:
        l = len(nums)
        if l <= 2:
            return l
        tag = nums[0] - 1
        dup_cnt = 0
        pos = 1
        while pos < l - 1:
            if nums[pos-1] == nums[pos] and nums[pos] == nums[pos+1]:
                dup_cnt += 1
                nums[pos-1] = tag
            pos += 1
        res = l - dup_cnt
        slow = 0
        fast = 1
        while slow < res and fast < l:
            if nums[slow] != tag:
                slow += 1
            else:
                if fast <= slow:
                    fast = slow + 1
                while fast < l and nums[fast] == tag:
                    fast += 1
                if fast < l:
                    nums[slow],nums[fast] = nums[fast],nums[slow]
                    fast += 1
                slow += 1
        return res

# Input: n = 4, k = 2
# Output:
# [
#   [2,4],
#   [3,4],
#   [2,3],
#   [1,2],
#   [1,3],
#   [1,4],
# ]
class Solution_77:
    def dfs(self,start,k,max_num,sub,res):
        cur_len = len(sub)
        if cur_len == k:
            res.append(sub)
            return

        for i in range(start,max_num):
            self.dfs(i + 1,k,max_num,sub + [i],res)

    def combine(self, n: int, k: int):
        res = []
        self.dfs(1,k,n+1,[],res)
        return res

class Solution_74:
    def dfs(self,matrix,cur_row,cur_col,rows,columns,target):
        if cur_row >= rows or cur_col >= columns:
            return False
        if target == matrix[cur_row][cur_col]:
            return True
        if target < matrix[cur_row][cur_col]:
            return False
        if (cur_row + 1) < rows:
            if target >= matrix[cur_row+1][cur_col]:
                return self.dfs(matrix,cur_row + 1,cur_col,rows,columns,target)
            else:
                return self.dfs(matrix, cur_row,cur_col + 1, rows, columns,target)
        else:
            return self.dfs(matrix, cur_row,cur_col + 1, rows, columns,target)

    def searchMatrix(self, matrix, target: int) -> bool:
        rows = len(matrix)
        if rows == 0:
            return False
        columns = len(matrix[0])
        if columns == 0:
            return False
        if target > matrix[rows-1][columns-1]:
            return False
        return self.dfs(matrix,0,0,rows,columns,target)

# Input: n = 3, k = 3
# Output: "213"
# "123"
# "132"
# "213"
# "231"
# "312"
# "321"
class Solution_60:
    def dfs(self,begin,end,nums,k,res):
        if len(res) >= k:
            return True
        if begin == end:
            res.append(nums.copy())
            return False
        for i in range(begin,end):
            #nums[begin],nums[i] = nums[i],nums[begin]
            tmp = nums[i]
            nums[begin+1:i+1] = nums[begin:i]
            nums[begin] = tmp
            if self.dfs(begin+1,end,nums,k,res):
                return True
            tmp = nums[begin]
            nums[begin:i] = nums[begin+1:i+1]
            nums[i] = tmp
            #nums[begin], nums[i] = nums[i], nums[begin]
        return False

    def getPermutation(self, n: int, k: int) -> str:
        res = []
        nums = []
        for i in range(1,n+1):
            nums.append(i)

        self.dfs(0,len(nums),nums,k,res)
        if len(res) == k:
            return ''.join(str(i) for i in res[k-1])
        return ""
#[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 2, 1], [3, 1, 2]]

# Input: 3
# Output:
# [
#  [ 1, 2, 3 ],
#  [ 8, 9, 4 ],
#  [ 7, 6, 5 ]
# ]
class Solution_59:
    def generateMatrix(self, n: int):
        res = []
        for i in range(n):
            res.append([0] * n)
        cur_num = 1
        init_pos = 0
        for edge_len in range(n,0,-2):
            row = init_pos
            col = init_pos
            res[row][col] = cur_num
            cur_num += 1
            col += 1
            while col < init_pos + edge_len:
                res[row][col] = cur_num
                col += 1
                cur_num += 1
            col -= 1
            row += 1
            while row < init_pos + edge_len:
                res[row][col] = cur_num
                row += 1
                cur_num += 1
            row -= 1
            col -= 1
            while col >= init_pos:
                res[row][col] = cur_num
                col -= 1
                cur_num += 1
            row -= 1
            col += 1
            while row > init_pos:
                res[row][col] = cur_num
                row -= 1
                cur_num += 1
            init_pos += 1
        return res

# Input:
# [
#  [ 1, 2, 3 ],
#  [ 4, 5, 6 ],
#  [ 7, 8, 9 ]
# ]
# Output: [1,2,3,6,9,8,7,4,5]
class Solution_54:
    def spiralOrder(self, matrix):
        res = []
        h = len(matrix)
        if h == 0:
            return res
        w = len(matrix[0])
        min_len = min(w,h)
        start_pos = 0
        while w > 0 and h > 0:
            if start_pos > min_len // 2:
                break
            row = start_pos
            col = start_pos
            if w == 1:
                while row < start_pos + h:
                    res.append(matrix[row][col])
                    row += 1
                break
            if h == 1:
                while col < start_pos + w:
                    res.append(matrix[row][col])
                    col += 1
                break
            while col < start_pos + w - 1:
                res.append(matrix[row][col])
                col += 1
            while row < start_pos + h - 1:
                res.append(matrix[row][col])
                row += 1
            while col > start_pos:
                res.append(matrix[row][col])
                col -= 1
            while row > start_pos:
                res.append(matrix[row][col])
                row -= 1
            start_pos += 1
            w -= 2
            h -= 2
        return res

class Solution_63:
    def dfs(self,matrix,row,column,target_row,target_col,dp):
        if row == target_row and column == target_col:
            return 1
        if row > target_row or column > target_col:
            return 0
        if matrix[row][column] == 1:
            return 0
        k = str(row)+","+ str(column)
        if k in dp:
            return dp[k]
        dp[k] = self.dfs(matrix,row + 1,column,target_row,target_col,dp) + self.dfs(matrix,row,column + 1,target_row,target_col,dp)
        return dp[k]

    def uniquePathsWithObstacles(self, obstacleGrid) -> int:
        if len(obstacleGrid[0]) == 0:
            return 1
        if obstacleGrid[0][0] == 1 or obstacleGrid[len(obstacleGrid) - 1][len(obstacleGrid[0]) - 1]:
            return 0
        dp = {}
        return self.dfs(obstacleGrid,0,0,len(obstacleGrid) - 1,len(obstacleGrid[0]) - 1,dp)

    def uniquePathsWithObstacles2(self, obstacleGrid) -> int:
        if len(obstacleGrid[0]) == 0:
            return 1
        if obstacleGrid[0][0] == 1 or obstacleGrid[len(obstacleGrid) - 1][len(obstacleGrid[0]) - 1]:
            return 0
        dp = []
        for i in range(len(obstacleGrid)):
            dp.append([0] * len(obstacleGrid[0]))

        dp[len(obstacleGrid) - 1][len(obstacleGrid[0])-1] = 1
        for row in range(len(obstacleGrid) - 1, - 1,-1):
            for col in range(len(obstacleGrid[0]) - 1, - 1,-1):
                if obstacleGrid[row][col] == 1:
                    dp[row][col] = 0
                else:
                    if col + 1 < len(obstacleGrid[0]):
                        dp[row][col] += dp[row][col + 1]
                    if row + 1 < len(obstacleGrid):
                        dp[row][col] +=  dp[row+1][col]
        return dp[0][0]

class Solution_1331:
    def arrayRankTransform(self, arr):
        record = {}
        for i in range(len(arr)):
            if arr[i] not in record:
                record[arr[i]] = [i]
            else:
                record[arr[i]].append(i)
        keys = record.keys()
        keys = sorted(keys)
        res = [0] * len(arr)
        i = 1
        for key in keys:
            for pos in record[key]:
                res[pos] = i
            i += 1
        return res
        #return [dict[key] for key in keys]

class Solution_443:
    def compress(self, chars) -> int:
        l = len(chars)
        if l == 1:
            return 1
        begin = 0
        end = begin + 1
        input_pos = begin
        while end <= l:
            if end == l or chars[begin] != chars[end]:
                gap = end - begin
                if gap >= 2:
                    input = []
                    while gap > 0:
                        input.append( gap % 10)
                        gap = gap // 10
                    input = input[::-1]
                    chars[input_pos] = chars[begin]
                    input_pos += 1
                    for v in input:
                        chars[input_pos] = str(v)
                        input_pos += 1
                else:
                    chars[input_pos] = chars[begin]
                    input_pos += 1
                begin = end
            end += 1
        chars[0:] = chars[0:input_pos]
        return len(chars)

class Solution_1342:
    def numberOfSteps (self, num: int) -> int:
        digits = f'{num:b}'
        return digits.count('1') - 1 + len(digits)


# Advent of Code: Day 17
__author__ = "Matteo Golin"

from typing import Literal, TypeAlias, Iterable

# All rocks relative to bottom leftmost edge
Coordinate: TypeAlias = tuple[int, int]
Rock: TypeAlias = set[Coordinate]
JetStream: TypeAlias = list[Literal[1, -1]]

HORIZONTAL: Rock = {(0, 0), (1, 0), (2, 0), (3, 0)}
PLUS: Rock = {(0, 1), (1, 0), (1, 1), (1, 2), (2, 1)}
L: Rock = {(0, 0), (1, 0), (2, 0), (2, 1), (2, 2)}
VERTICAL: Rock = {(0, 0), (0, 1), (0, 2), (0, 3)}
CUBE: Rock = {(0, 0), (0, 1), (1, 0), (1, 1)}
ROCKS: list[Rock] = [HORIZONTAL, PLUS, L, VERTICAL, CUBE]

CHAMBER_WIDTH: int = 7
LFT_OFF: int = 2
BTM_OFF: int = 3
ROCKS_TO_FALL_1: int = 2022
ROCKS_TO_FALL_2: int = 1000000000000

def translate_coord(coord: Coordinate, offset: Coordinate) -> Coordinate:
    """Returns the translated coordinate."""
    return (coord[0] + offset[0], coord[1] + offset[1])

def translate(rock: Iterable[Coordinate], offset: Coordinate) -> Rock:
    """Returns the translated rock."""
    return set(translate_coord(c, offset) for c in rock)

def height(occupied: set[Coordinate]) -> int:
    """Returns the height of the rock tower so far."""
    return max(occupied, key=lambda x: x[1])[1]

def drop_rock(
    cur_rock: int, cur_jet: int, jet_stream: JetStream, occupied: set[Coordinate], fallen: dict[str, int]
) -> int:
    """
    Does one dropped rock cycle and returns the current jet index. If a cycle is detected, then -1 is returned.
    """

    # Translate rock away from side and highest rock to start
    rock = translate(ROCKS[cur_rock % len(ROCKS)], (LFT_OFF, height(occupied) + BTM_OFF + 1))
    fall_pattern = f"{cur_rock % len(ROCKS)}"
    while True:
        # Push rock first
        push = jet_stream[cur_jet]
        translated_rock = translate(rock, (push, 0))

        # Only push rock if it does not hit another rock and does not exceed walls
        if not occupied & translated_rock and all(0 <= x < CHAMBER_WIDTH for x, _ in translated_rock):
            fall_pattern += ">" if push == 1 else "<"
            rock = translated_rock
        else:
            fall_pattern += "x"

        # Translate rock downward
        translated_rock = translate(rock, (0, -1))
        if occupied & translated_rock:  # If the rock will intersect with another...
            occupied.update(rock)  # Record rock spaces as occupied
            if fall_pattern in fallen:
                print(fall_pattern)
                fallen["cycle start"] = fallen[fall_pattern]
                return -1

            fallen[fall_pattern] = cur_rock
            return (cur_jet + 1) % len(jet_stream)  # Return next jet

        fall_pattern += "v"
        rock = translated_rock

        cur_jet = (cur_jet + 1) % len(jet_stream)

def draw_image(occupied: set[Coordinate]) -> None:
    """Prints out a visualization of the rock tower."""
    max_height = height(occupied)
    image = [["." for _ in range(CHAMBER_WIDTH)] for _ in range(max_height + BTM_OFF)]

    for x, y in occupied:
        image[y][x] = "#"

    print("-" * (CHAMBER_WIDTH + 2))
    for row in reversed(image):
        print("|", end="")
        for col in row:
            print(col, end="")
        print("|", end="")
        print()
    print("-" * (CHAMBER_WIDTH + 2))

def height_after(rocks: int) -> int:
    """Returns the height of the rock tower after the passed number of rocks have fallen."""
    cur_jet = 0
    total_rocks = 0
    occupied: set[Coordinate] = set((_, 0) for _ in range(CHAMBER_WIDTH))
    fall_patterns = dict()

    while total_rocks < rocks:
        cur_jet = drop_rock(total_rocks, cur_jet, jet_stream, occupied, fall_patterns)
        if cur_jet == -1:  # Cycle detected
            break
        total_rocks += 1

    if rocks == 5 or rocks == 20:
        draw_image(occupied)

    if cur_jet == -1:
        period_len = total_rocks - fall_patterns["cycle start"]
        print(f"Cycle detected from rock {fall_patterns['cycle start']} to rock {total_rocks}.")
        height_after(fall_patterns["cycle start"])
        height_after(total_rocks)
        print(f"Cycle has period of {period_len}")
        current_height = height(occupied)
        print(f"The current height is {current_height}")
        period_height = current_height - height_after(fall_patterns["cycle start"])
        print(f"The height of each period is {period_height}")
        periods, remainder = divmod(rocks - total_rocks, period_len)

        print(periods, remainder)
        return current_height + (periods * period_height) + height_after(remainder)

    return height(occupied)

# Main
if __name__ == "__main__":
    # Parse input
    jet_stream: JetStream = []
    with open("./example.txt") as file:
        jet_stream = list(map(lambda x: 1 if x == ">" else -1, file.read().strip()))

    # Part 1: How tall is the tower after 2022 rocks have fallen?
    h = height_after(ROCKS_TO_FALL_1)
    print(f"The tower of rocks will be {h} units tall after {ROCKS_TO_FALL_1} rocks have stopped falling.")

    # Part 2: How tall is the tower after 1000000000000 rocks have fallen.
    print(f"The tower of rocks will be {h} units tall after {ROCKS_TO_FALL_2} rocks have stopped falling.")


import sys
import os
import importlib

import bpy

from .. import blender_time as b_time
from .. import caption as c
importlib.reload(b_time)
importlib.reload(c)

def import_cc(context, text, accent, pitch, language):
    print(".txt file detected")
    captions = []
    line_counter = 0
    cc_text = ""
    cc_type = 1

    for line in text:
        if len(line) > 0:
            if line[0:2].find('>>') != -1: # person
                cc_type = 1
                cc_name = line[2:len(line)].split(":")[0]
                text_tmp = line[2:len(line)].split(":")[1]
                cc_text = text_tmp[1:len(text_tmp)]

            elif line[0] == '[': # event
                cc_type = 2
                cc_name = ''
                cc_text = line.split('[')[1].split(']')[0]

            else: # plain text line

                if len(cc_text) == 0: # no previous line
                    cc_name = "noname"
                    cc_type = 0
                    cc_text = line

                else: # second line
                    cc_text += " " + line

        else: # len(line == 0) equivalent of '\n'
            captions.append(c.Caption(context, cc_type, cc_name, cc_text, b_time.Time(-1, -1, -1, -1), b_time.Time(-1, -1, -1, -1), accent, 1, pitch, language))
            cc_text = ""

        line_counter += 1
        if line_counter == len(text): # on exit
            if len(cc_text) > 0:
                captions.append(c.Caption(context, cc_type, cc_name, cc_text, b_time.Time(-1, -1, -1, -1), b_time.Time(-1, -1, -1, -1), accent, 1, pitch, language))

    return(captions)


# -*- coding: utf-8 -*-
### 爆后台路径补充版：通过yourdomain/data/mysql_error_trace.inc猜测类似后台地址。
import re
import os
import requests
from common import utils

is_ip = False
interval = 3600

def my_requests(url, method='get', timeout=15, try_count=3, **args):
    for n in range(try_count):
        try:
            global is_ip, proxies
            if (is_ip):
                response = requests.request(method=method, url=url, headers=utils.get_headers(), proxies=proxies,timeout=timeout,**args)
            else:
                response = requests.request(method=method, url=url, headers=utils.get_headers(), timeout=timeout, **args)
            response.encoding = 'utf-8'
            if response.status_code == 200:
                if "antispider" in response.url:
                    #is_ip = True
                    proxies = getip()
                    print("需要切换IP自动验证:",proxies)
                    continue
                if "passport" in response.url:
                    #baidu_img.识别百度验证码()
                    continue
                return response
            else:
                print(url+'---request err:'+ str(response.status_code))
                return None
        except Exception as e:
            print(e)
            #is_ip = True
            proxies = getip()
            print("IP自动验证:", proxies)
            continue
        print("请求url:%s失败，剩余重试次数：%d" % (url, n))

def getip(method='get', timeout=15, try_count=3, **args):
    url = ""
    response = requests.request(method=method, url=url, headers=utils.get_headers(), timeout=timeout, **args)
    if response.status_code == 200:
        proxies = {'https': response.text.replace('\r\n', '')}
        return proxies

class Unit(object):
    def getfilelist(self, filepath):
        try:
            #parentDirPath = os.path.abspath(os.path.dirname(os.path.split(os.path.realpath(__file__))[0]))
            #path = parentDirPath + filepath
            with open(filepath, "r", encoding='UTF-8') as f:  # 打开文件
                data = f.read().split('\n')
                if len(data) > 0:
                    print('导入数据:'+str(len(data)))
                    return data
                else:
                    print('load txt err')
                    return None
        except Exception as e:
            print('not fond file or err')
            return None

    def create_str_to_txt(self,date, str_data):
        try:
            path_file_name = date
            if not os.path.exists(path_file_name):
                with open(path_file_name, "w") as f:
                    print(f)
            with open(path_file_name, "a") as f:
                f.write(str_data)
        except:
            print('e')

if __name__ == '__main__':
    try:
        filename = "注册扫描结果"
        WordList = Unit().getfilelist('./res/' + filename)
        for txt in WordList:
            try:
                arrary =[]
                words = ['member','plus','m']
                domain_url = txt.replace('\r','')
                select_url = domain_url+"/data/mysql_error_trace.inc"
                response = my_requests(url=select_url)
                if response:
                    response_txt = response.text
                    utl_list = re.findall('(?=Page:).*', response_txt)
                    for last_url in utl_list:
                        last_url = last_url.replace('\r','').replace('Page:','').replace(' ','')
                        last_url = last_url[0:last_url.rfind('?')]
                        if last_url.count('/') >= 2:
                            s = last_url.split('/')[1]
                            if s not in words and s not in arrary and s !='':
                                arrary.append(s)
                                s_url = domain_url + '/' + s + '/'
                                print('try:'+ s_url)
                                response2 = my_requests(url=s_url)
                                if response2:
                                    try:
                                        response2.encoding = response2.apparent_encoding
                                        response2_txt = response2.text
                                        title = re.findall('<title>.*</title>', response2_txt)[0]
                                        if '页面未找到' in title:
                                            continue
                                        Unit().create_str_to_txt('./res/批量爆破织梦后台_成功_补充版.txt',domain_url + '\n' + s_url + '\n'+title + '\n\n')
                                        print(title+'  :  '+ s_url)
                                    except:
                                        continue
                    if len(arrary) == 0:
                        print(domain_url + '未找到相对于目录')
            except:
                continue

    except Exception as e:
        print(e)
        pass

织梦/爆路径补充版.py


import functools
from typing import List

def largestNumber(nums: List[int]) -> str:
    def sort_relu(a, b):
        x, y = a + b, b + a
        if x > y: return 1
        elif x < y: return -1
        else: return 0

    nums = [str(num) for num in nums]
    nums = sorted(nums, key=functools.cmp_to_key(sort_relu))
    return "".join(nums)


import requests
import re
import json
from github import Github

def get_browser_download_url(assets, ending):
    for a in assets:
        if a.name.endswith(ending):
            return a.browser_download_url

    raise ValueError("Could not find asset with ending '{}'.".format(ending))

def get_sig(assets, ending):
    for a in assets:
        if a.name.endswith(ending + ".sig"):
            resp = requests.get(a.browser_download_url)
            resp.raise_for_status()
            return resp.text

    raise ValueError("Could not find asset with ending '{}.sig'.".format(ending))

if __name__ == '__main__':
    repo = Github().get_repo("trawls-app/trawls")
    release = repo.get_latest_release()
    version_str = re.search(r"\d+\.\d+\.\d+.*", release.tag_name).group()

    if release.draft:
        raise Exception("Release is still a draft")

    release_assets = release.get_assets()
    data = {
        "name": version_str,
        "notes": release.body,
        "pub_date": release.published_at.isoformat() + "Z",
        "platforms": {
            "darwin-universal": {
                "signature": get_sig(release_assets, ".app.tar.gz"),
                "url": get_browser_download_url(release_assets, ".app.tar.gz")
            },
            "linux-x86_64": {
                "signature": get_sig(release_assets, ".AppImage.tar.gz"),
                "url": get_browser_download_url(release_assets, ".AppImage.tar.gz")
            },
            "windows-x86_64": {
                "signature": get_sig(release_assets, ".msi.zip"),
                "url": get_browser_download_url(release_assets, ".msi.zip")
            }
        }
    }

    with open("../static_api/releases/current.json", "w") as fp:
        json.dump(data, fp, indent=4)


"""Information that should be available to the python library.
"""
from os import environ
from pathlib import Path

# The root of the qmk_firmware tree.
QMK_FIRMWARE = Path.cwd()

# This is the number of directories under `qmk_firmware/keyboards` that will be traversed. This is currently a limitation of our make system.
MAX_KEYBOARD_SUBFOLDERS = 5

# Supported processor types
CHIBIOS_PROCESSORS = 'cortex-m0', 'cortex-m0plus', 'cortex-m3', 'cortex-m4', 'MKL26Z64', 'MK20DX128', 'MK20DX256', 'STM32F042', 'STM32F072', 'STM32F103', 'STM32F303', 'STM32F401', 'STM32F411', 'STM32G431', 'STM32G474'
LUFA_PROCESSORS = 'at90usb162', 'atmega16u2', 'atmega32u2', 'atmega16u4', 'atmega32u4', 'at90usb646', 'at90usb647', 'at90usb1286', 'at90usb1287', None
VUSB_PROCESSORS = 'atmega32a', 'atmega328p', 'atmega328', 'attiny85'

# Common format strings
DATE_FORMAT = '%Y-%m-%d'
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S %Z'
TIME_FORMAT = '%H:%M:%S'

# Used when generating matrix locations
COL_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijilmnopqrstuvwxyz'
ROW_LETTERS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnop'

# Mapping between info.json and config.h keys
LED_INDICATORS = {
    'caps_lock': 'LED_CAPS_LOCK_PIN',
    'num_lock': 'LED_NUM_LOCK_PIN',
    'scroll_lock': 'LED_SCROLL_LOCK_PIN',
}

# Constants that should match their counterparts in make
BUILD_DIR = environ.get('BUILD_DIR', '.build')
KEYBOARD_OUTPUT_PREFIX = f'{BUILD_DIR}/obj_'


from django import forms
from django.core.exceptions import ValidationError

class FeedForm(forms.Form):
    CHOICES = [
        ('All','ALL'),
        ('sku_id','Sku id'),
        ('product_id','Product Id'),
        ("sku_name","Sku name"),
                ('manufacturer_name','Manufacturer name'),
                ('salt_name', 'Salt name'),
                ('drug_form', 'Drug form'),
                ('pack_size','Pack size'),
                ('strength','Strength'),

    ]
    qry = forms.CharField(required=True,  widget=forms.TextInput(attrs={'placeholder': 'Search'}))
    choice = forms.MultipleChoiceField(choices=CHOICES, required=True)#,widget=forms.SelectMultiple())

   # def clean(self):
    #    if not (self.sku_id or self.product_id or self.sku_name or self.price or self.manufacturer_name or self.salt_name or self.pack_size or self.strength):
     #       raise ValidationError("You must specify either email or telephone")


import matplotlib.pyplot as plt
import numpy as np
import warnings
from scipy.interpolate import interp1d
from scipy.optimize import curve_fit
from scipy.special import lambertw
from abc import ABC, abstractclassmethod, abstractmethod

def exponential(x, a, b):

    # log_y = np.log(a) + b * x
    # y = np.exp(log_y)
    y = a * np.exp(b * x)

    return y

class LightSource(ABC):

    def __init__(self, x, y, y_err=None):

        self.x = x
        self.y = y
        self.y_err = y_err
        self._interpolator = self._interpolate()

    def __call__(self, x, *args, **kwargs):

        y_interpolated = self._interpolator(x, *args, **kwargs)

        return y_interpolated

    def __getitem__(self, item):

        return self.__class__(x=self.x, y=self.y[item],
                              y_err=self.y_err[item])

    @abstractclassmethod
    def load(cls, filename):

        pass

    @abstractmethod
    def save(self, filename):

        pass

    def plot(self, axes=None, pixel=0, **kwargs):

        if axes is None:
            fig = plt.figure()
            axes = fig.add_subplot(111)

        x_fit = np.arange(1000)
        y_fit = self(x_fit, pixel=pixel)

        mask = (y_fit > 0) * (y_fit <= 2000)
        x_fit = x_fit[mask]
        y_fit = y_fit[mask]

        if self.photo_electrons_err is not None:

            y_err = self.photo_electrons_err[:, pixel]
        else:

            y_err = None

        axes.errorbar(self.ac_level, self.photo_electrons[:, pixel],
                      yerr=y_err,
                      label='Data points, pixel : {}'.format(pixel),
                      linestyle='None', marker='o', color='k', **kwargs)
        axes.plot(x_fit, y_fit, label='Interpolated data', color='r')
        axes.set_xlabel('AC DAC level')
        axes.set_ylabel('Number of p.e.')
        axes.set_yscale('log')
        axes.legend(loc='best')

        return axes

class ACLED(LightSource):

    def __init__(self, ac_level, photo_electrons, photo_electrons_err=None,
                 saturation_threshold=300):

        self.ac_level = ac_level - ac_level[0]
        self.photo_electrons = photo_electrons
        self.photo_electrons_err = photo_electrons_err
        self.saturation_threshold = saturation_threshold  # in p.e.
        self._interpolate()
        self._extrapolate()
        self._extrapolate_exponential()

    def __call__(self, ac_level, pixel=None):

        y = self.func_exponential(ac_level)
        y_shape = y.shape
        y = y.ravel()
        y_spline = self.func_spline(ac_level).ravel()
        y_poly = self.func_polynomial(ac_level).ravel()

        start_values = (y < 5)
        end_values = (y > self.saturation_threshold)

        y[~start_values] = y_spline[~start_values]
        y[end_values] = y_poly[end_values]
        y = y.reshape(y_shape)

        if pixel is not None:

            y = y[pixel]

        # mask = np.isfinite(y)
        # assert (np.diff(y[mask]) > 0).all()

        return y

    def __getitem__(self, item):

        return ACLED(ac_level=self.ac_level,
                     photo_electrons=self.photo_electrons[item])

    @classmethod
    def load(cls, filename):

        raise NotImplementedError

    def _extrapolate(self):

        pes = self.photo_electrons.copy()
        params = []
        deg = 4

        for i, pe in enumerate(pes.T):

            ac_level = self.ac_level.copy()
            mask = (pe > 50) * (pe < self.saturation_threshold) * np.isfinite(pe)

            err = None
            if self.photo_electrons_err is not None:
                err = self.photo_electrons_err[:, i]
                mask = mask * (np.isfinite(err))
                err = err[mask]
                err = 1 / err

            pe = pe[mask]
            ac_level = ac_level[mask]

            err = None

            if len(pe) <= 1:

                param = [np.nan] * (deg + 1)

                warnings.warn('Could not interpolate pixel {}'.format(i),
                              UserWarning)

            else:
                param = np.polyfit(ac_level, pe, deg=deg, w=err)

            params.append(param)

        params = np.array(params)
        self._params = params

    def _extrapolate_exponential(self):

        pes = self.photo_electrons.copy()
        params = []

        for i, pe in enumerate(pes.T):

            ac_level = self.ac_level.copy()
            mask = (pe > 0) * (pe < 100) * np.isfinite(pe) * (ac_level >= 0)

            if self.photo_electrons_err is not None:
                err = self.photo_electrons_err[:, i]
                mask = mask * (np.isfinite(err))
                err = err[mask]

            else:

                err = None

            pe = pe[mask]
            ac_level = ac_level[mask]

            if len(pe) <= 5:

                param = [np.nan] * 2

                warnings.warn('Could not interpolate pixel {}'.format(i),
                              UserWarning)

            else:

                try:

                    intercept = np.where(ac_level == np.min(ac_level))[0][0]
                    intercept = pe[intercept]

                    slope = np.log(pe)
                    slope = np.diff(slope) / np.diff(ac_level)
                    slope = np.mean(slope)

                    p0 = np.array([intercept, slope])

                    param = curve_fit(exponential, ac_level,
                                              pe, maxfev=10000, sigma=err,
                                      p0=p0)[0]

                except RuntimeError:

                    param = [np.nan] * 2

                    warnings.warn('Could not interpolate pixel {}'.format(i),
                                  UserWarning)

            params.append(param)

        params = np.array(params)
        self._params_exponential = params

    def func_exponential(self, x):

        y = np.zeros((self.photo_electrons.shape[1], len(x)))

        for i in range(len(y)):
            y[i] = exponential(x, self._params_exponential[i][0],
                               self._params_exponential[i][1])

        return y

    def func_spline(self, x):

        y = np.zeros((self.photo_electrons.shape[1], len(x)))

        for i in range(len(y)):
            y[i] = self._spline[i](x)

        return y

    def func_polynomial(self, x):

        y = np.zeros((self.photo_electrons.shape[1], len(x)))

        for i in range(len(y)):
            y[i] = np.polyval(self._params[i], x).T

        return y

    def _interpolate(self):

        pes = self.photo_electrons.copy().T
        cubic_spline = []

        for pe in pes:

            mask = np.isfinite(pe) # * (pe > 5)
            x = self.ac_level[mask]
            y = pe[mask]

            if not len(x):

                x = self.ac_level
                y = pe

            spline = interp1d(x, y,
                          kind='quadratic',
                          bounds_error=False,
                              fill_value=np.nan)

            cubic_spline.append(spline)

        # mask = np.isfinite(pes)
        # pes[~mask] = 0
        # w = np.ones(pes.shape)
        # w[~mask] = 0
        # w = np.sum(w, axis=0)
        # w[w>0] = 1
        #
        # print(pes.shape, w.shape, self.ac_level.shape)
        # cubic_spline = splprep(pes.T, w=w.T, u=self.ac_level)
        #
        # # cubic_spline = interp1d(self.ac_level, pes.T,
         #                       kind='slinear',
         #                       bounds_error=None,
         #                       fill_value='extrapolate')

        self._spline = cubic_spline

    def save(self, filename):

        pass

    def plot(self, axes=None, pixel=0, y_lim=(0, 2000), **kwargs):

        if axes is None:
            fig = plt.figure()
            axes = fig.add_subplot(111)

        x_fit = np.arange(1000)
        y_fit = self(x_fit, pixel=pixel)

        mask = (y_fit > y_lim[0]) * (y_fit <= y_lim[1])
        x_fit = x_fit[mask]
        y_fit = y_fit[mask]

        if self.photo_electrons_err is not None:

            y_err = self.photo_electrons_err[:, pixel]
        else:

            y_err = None

        axes.errorbar(self.ac_level, self.photo_electrons[:, pixel],
                      yerr=y_err, label='Data points, pixel : {}'.format(pixel),
                      linestyle='None', marker='o', color='k', **kwargs)
        axes.plot(x_fit, y_fit, label='Interpolated data', color='r')
        axes.plot(x_fit, self.func_spline(x_fit)[pixel], label='Spline')
        axes.plot(x_fit, self.func_polynomial(x_fit)[pixel], label='Polynomial')
        axes.plot(x_fit, self.func_exponential(x_fit)[pixel], label='Exponential')
        axes.set_xlabel('AC DAC level')
        axes.set_ylabel('Number of p.e.')
        axes.set_yscale('log')
        axes.legend(loc='best')

        return axes

class DCLED(LightSource):

    def __init__(self, dc_level, nsb_rate, nsb_rate_error=None):

        self.dc_level = dc_level
        self.nsb_rate = nsb_rate
        self.nsb_rate_error = nsb_rate_error
        self._interpolate()

    def __call__(self, *args, **kwargs):

        pass

    def __getitem__(self, item):

        return DCLED(dc_level=self.dc_level, nsb_rate=self.nsb_rate[item],
                     nsb_rate_error=self.nsb_rate_error[item])

    def load(cls, filename):

        pass

    def save(self, filename):

        pass

    def plot(self):

        plt.figure()

if __name__ == '__main__':

    # data = np.load('/home/alispach/Documents/PhD/ctasoft/digicampipe/charge_linearity_final.npz')
    ac_leds = np.load('/sst1m/analyzed/calib/mpe/mpe_fit_results_combined.npz')

    ac_levels = ac_leds['ac_levels'][:, 0]
    pe = ac_leds['mu']
    pe_err = ac_leds['mu_error']

    test = ACLED(ac_levels, pe, pe_err)

    x = np.linspace(-100, 10000, num=1E3)
    # X = np.zeros((1296, len(x)))
    # X[:] = x
    print(test(x))

    test.plot(pixel=0, y_lim=(0, 1E4))

    plt.show()


from django.urls import path
from app1  import views
from . import views

urlpatterns = [
   # path('app1/', views.app1, name='app1'),
     path('',views.login,name='login'),
     path('reg/',views.register,name='reg'),
     path('home/',views.home,name='home'),
     path('logout/',views.logoutpage,name='logout'),
     path('forgot/',views.forgot,name="forgot"),
     path('home/profile/', views.user_profile, name='user_profile'),
     path('updateprofile/',views.update_profile, name='updateprofile'),

]


from django.conf.urls import url
from apps.crud_perins.views import periodoCreate, periodoList, periodoDelete, periodoUpdate, periodoShow, search, \
    inscripCreate, inscripList, inscripDelete, inscripUpdate, inscripShow, searchT

from apps.crud_perins.views import alumnosCreate, alumnosList, alumnosDelete, alumnosUpdate, alumnoShow, searchI, \
    estadoCreate,estadoDelete,estadoList,estadoShow,estadoUpdate, search_I

from apps.crud_perins.views import usuarioCreate, usuarioList, usuarioDelete, usuarioUpdate, usuarioShow, searchJ, \
    areaCreate,areaList,areaDelete,areaUpdate,areaShow, search_J

from apps.crud_perins.views import organigramaCreate, organigramaList, organigrmaDelete, organigramaUpdate, organigramaShow, searchV, \
    puestoCreate, puestoList, puestoDelete, puestoUpdate, puestoShow, search_V

from apps.crud_perins.views import grupoCreate, grupoList, grupoDelete, grupoUpdate, grupoShow, gruposearch, \
    muniCreate, muniList, muniDelete, muniUpdate, muniShow, munisearch

from apps.crud_perins.views import actividadCreate, actividadList, actividadDelete, actividadUpdate, actividadShow, \
    rolCreate, rolList, rolDelete, rolUpdate, rolShow, searchL, search_L

from apps.crud_perins.views import carreraCreate, carreraList, carreraDelete, carreraUpdate, carreraShow, searchM, \
    localidadCreate, localidadList, localidadDelete, localidadShow, localidadUpdate, buscarM

from apps.crud_perins.views import coordinadorCreate, coordinadorList, coordinadorDelete, coordinadorUpdate, coordinadorShow, \
    search_c, instructorCreate, instructorList, instructorDelete, instructorUpdate, instructorShow, search_i
urlpatterns = [
#-----------------------------tablas de joan-------------------------------------------
    url(r'^nuevo/', periodoCreate.as_view(), name='periodo_crear'),
    url(r'^listar/', periodoList.as_view(), name='periodos_listar'),
    url(r'^eliminar/(?P<pk>\d+)/$', periodoDelete.as_view(), name='periodo_eliminar'),
    url(r'^editar/(?P<pk>\d+)/$', periodoUpdate.as_view(), name='periodo_editar'),
    url(r'^mostrar/(?P<pk>\d+)/$', periodoShow.as_view(), name='periodo_mostrar'),
    url(r'^buscar/$', search, name='periodo_buscar'),

    url(r'^Nuevo/', inscripCreate.as_view(), name='inscrip_Crear'),
    url(r'^Listar/', inscripList.as_view(), name='inscrips_Listar'),
    url(r'^Eliminar/(?P<pk>\d+)/$', inscripDelete.as_view(), name='inscrip_Eliminar'),
    url(r'^Editar/(?P<pk>\d+)/$', inscripUpdate.as_view(), name='inscrip_Editar'),
    url(r'^Mostrar/(?P<pk>\d+)/$', inscripShow.as_view(), name='inscrip_Mostrar'),
    url(r'^Buscar/$', searchT, name='inscrip_Buscar'),
#--------------------------Tablas de Ismael--------------------------------------------
    url(r'^nuevoI/', alumnosCreate.as_view(), name='alumno_crear'),
    url(r'^listarI/', alumnosList.as_view(), name='alumnos_listar'),
    url(r'^eliminarI/(?P<pk>\d+)/$', alumnosDelete.as_view(), name='alumno_eliminar'),
    url(r'^modificarI/(?P<pk>\d+)/$', alumnosUpdate.as_view(), name='alumno_editar'),
    url(r'^mostrarI/(?P<pk>\d+)/$', alumnoShow.as_view(), name='alumno_mostrar'),
    url(r'^buscarI/$', searchI, name='alumno_buscar'),
    #aqui inician las urls de estado
    url(r'^nuevo_e/', estadoCreate.as_view(), name='estado_crea'),
    url(r'^listar_e/', estadoList.as_view(), name='estado_lista'),
    url(r'^editar_e/(?P<pk>\d+)/$', estadoUpdate.as_view(), name='estado_edita'),
    url(r'^borrar_e/(?P<pk>\d+)/$', estadoDelete.as_view(), name='estado_borrar'),
    url(r'^ver_e/(?P<pk>\d+)/$', estadoShow.as_view(), name='estado_ver'),
    url(r'^buscar_e/$', search_I, name='estado_busca'),
#----------------------url javier-----------------------------------------------------
    url(r'^nuevoJ/', usuarioCreate.as_view(), name='usuario_crear'),
    url(r'^listarJ/', usuarioList.as_view(), name='usuario_listar'),
    url(r'^eliminarJ/(?P<pk>\d+)/$', usuarioDelete.as_view(), name='usuario_eliminar'),
    url(r'^editarJ/(?P<pk>\d+)/$', usuarioUpdate.as_view(), name='usuario_editar'),
    url(r'^mostrarJ/(?P<pk>\d+)/$', usuarioShow.as_view(), name='usuario_mostrar'),
    url(r'^buscarJ/$', searchJ, name='usuario_buscar'),

    url(r'^nuevos_J/', areaCreate.as_view(), name='area_crea'),
    url(r'^lista_J/', areaList.as_view(), name='area_lista'),
    url(r'^elimina_J/(?P<pk>\d+)/$', areaDelete.as_view(), name='area_elimina'),
    url(r'^edita_J/(?P<pk>\d+)/$', areaUpdate.as_view(), name='area_edita'),
    url(r'^muestra_J/(?P<pk>\d+)/$', areaShow.as_view(), name='area_muestra'),
    url(r'^buscador_J/$', search_J, name='area_busca'),

#------------------------url de ivan--------------------------------
    url(r'^nuevoV/', organigramaCreate.as_view(), name='organigrama_crear'),
    url(r'^listarV/', organigramaList.as_view(), name='organigrama_listar'),
    url(r'^eliminarV/(?P<pk>\d+)/$', organigrmaDelete.as_view(), name='organigrama_eliminar'),
    url(r'^modificarV/(?P<pk>\d+)/$', organigramaUpdate.as_view(), name='organigrama_editar'),
    url(r'^mostrarV/(?P<pk>\d+)/$', organigramaShow.as_view(), name='organigrama_mostrar'),
    url(r'^buscarV/', searchV, name='organigrama_buscar'),

    url(r'^nuevos_V/', puestoCreate.as_view(), name='puesto_crear'),
    url(r'^listarr_V/', puestoList.as_view(), name='puesto_listar'),
    url(r'^eliminarr_V/(?P<pk>\d+)/$', puestoDelete.as_view(), name='puesto_eliminar'),
    url(r'^modificarr_V/(?P<pk>\d+)/$', puestoUpdate.as_view(), name='puesto_editar'),
    url(r'^mostrarr_V/(?P<pk>\d+)/$', puestoShow.as_view(), name='puesto_mostrar'),
    url(r'^search_V/$', search_V, name='puesto_search'),

#-------------------------url karyn-----------------------------------------
    url(r'^nuevok/', grupoCreate.as_view(), name='grupo_crear'),
    url(r'^listark/', grupoList.as_view(), name='grupo_listar'),
    url(r'^eliminark/(?P<pk>\d+)/$', grupoDelete.as_view(), name='grupo_eliminar'),
    url(r'^editark/(?P<pk>\d+)/$', grupoUpdate.as_view(), name='grupo_editar'),
    url(r'^mostrark/(?P<pk>\d+)/$', grupoShow.as_view(), name='grupo_mostrar'),
    url(r'^buscark/$', gruposearch, name='grupo_buscar'),

    url(r'^Nuevo_k/', muniCreate.as_view(), name='muni_crear'),
    url(r'^Listar_k/', muniList.as_view(), name='muni_listar'),
    url(r'^Eliminar_k/(?P<pk>\d+)/$', muniDelete.as_view(), name='muni_eliminar'),
    url(r'^Editar_k/(?P<pk>\d+)/$', muniUpdate.as_view(), name='muni_editar'),
    url(r'^Mostrar_k/(?P<pk>\d+)/$', muniShow.as_view(), name='muni_mostrar'),
    url(r'^Buscar_k/$', munisearch, name='muni_buscar'),

#--------------------url litzy---------------------------------------------
    url(r'^nuevoL/', actividadCreate.as_view(), name='actividad_crear'),
    url(r'^listarL/', actividadList.as_view(), name='actividad_listar'),
    url(r'^eliminarL/(?P<pk>\d+)/$', actividadDelete.as_view(), name='actividad_eliminar'),
    url(r'^modificarL/(?P<pk>\d+)/$', actividadUpdate.as_view(), name='actividad_editar'),
    url(r'^mostrarL/(?P<pk>\d+)/$', actividadShow.as_view(), name='actividad_mostrar'),
    url(r'^buscarL/', searchL, name='actividad_buscar'),

    url(r'^nuevos_L/', rolCreate.as_view(), name='rol_crear'),
    url(r'^listarr_L/', rolList.as_view(), name='rol_listar'),
    url(r'^eliminarr_L/(?P<pk>\d+)/$', rolDelete.as_view(), name='rol_eliminar'),
    url(r'^modificarr_L/(?P<pk>\d+)/$', rolUpdate.as_view(), name='rol_editar'),
    url(r'^mostrarr_L/(?P<pk>\d+)/$', rolShow.as_view(), name='rol_mostrar'),
    url(r'^search_L/$', search_L, name='rol_search'),

#--------------------url may----------------------------
    url(r'^nuevoM/', carreraCreate.as_view(), name='carrera_crear'),
    url(r'^listarM/', carreraList.as_view(), name='carrera_listar'),
    url(r'^eliminarM/(?P<pk>\d+)/$', carreraDelete.as_view(), name='carrera_eliminar'),
    url(r'^modificarM/(?P<pk>\d+)/$', carreraUpdate.as_view(), name='carrera_editar'),
    url(r'^mostrarM/(?P<pk>\d+)/$', carreraShow.as_view(), name='carrera_mostrar'),
    url(r'^searchM/$', searchM, name='carrera_buscar'),

    url(r'^nuevosM/', localidadCreate.as_view(), name='localidad_crear'),
    url(r'^listasM/', localidadList.as_view(), name='localidad_listar'),
    url(r'^eliminasM/(?P<pk>\d+)/$', localidadDelete.as_view(), name='localidad_eliminar'),
    url(r'^modificasM/(?P<pk>\d+)/$', localidadUpdate.as_view(), name='localidad_editar'),
    url(r'^muestrasM/(?P<pk>\d+)/$', localidadShow.as_view(), name='localidad_mostrar'),
    url(r'^buscasM/$', buscarM, name='localidad_buscar'),

#--------------------url nubia-------------------------------
  url(r'^nuevoN/', coordinadorCreate.as_view(), name='coordina_crear'),
    url(r'^listarN/', coordinadorList.as_view(), name='coordinar_listar'),
    url(r'^eliminarN/(?P<pk>\d+)/$', coordinadorDelete.as_view(), name='coordina_eliminar'),
    url(r'^editarN/(?P<pk>\d+)/$', coordinadorUpdate.as_view(), name='coordina_editar'),
    url(r'^mostrarN/(?P<pk>\d+)/$', coordinadorShow.as_view(), name='coordina_mostrar'),
    url (r'^buscarN/$', search_c, name='coordina_buscar'),
#aqui inician las urls del crud instructor
    url(r'^nuevosN/', instructorCreate.as_view(), name='instruccion_crear'),
    url(r'^listaN/', instructorList.as_view(), name='instrucciones_listar'),
    url(r'^eliminaN/(?P<pk>\d+)/$', instructorDelete.as_view(), name='instruccion_eliminar'),
    url(r'^editaN/(?P<pk>\d+)/$', instructorUpdate.as_view(), name='instruccion_editar'),
    url(r'^verN/(?P<pk>\d+)/$', instructorShow.as_view(), name='instruccion_mostrar'),
    url(r'^buscaN/$', search_i, name='instruccion_buscar'),
]


# coding: utf-8

# In[29]:

import sys,math
from collections import defaultdict
from pprint import pprint

# In[108]:

def sign(number):
    if number>=0:
        return 1
    else:
        return -1

# In[116]:

class SGD():
    def __init__(self, f_name, iter_times_training=10):
        labels = []
        lines = []
        self.ws = defaultdict(int)

        # read lines and labels
        for line in open(f_name, "r", encoding="utf-8"):
            label, line_ = line.split("\t")
            labels.append(label)
            lines.append(line_)
            for w in line_.split():
                self.ws[w] = 0
        #pprint(self.ws)

        # train the model: update the weights
        for iter_ in range(iter_times_training):
            for label, line in zip(labels, lines):
                #print(label,line)
                phi_dict=self.phi(line)
                val=abs(self.sum_prod(phi_dict))
                if val<=10:
                    self.update_weight(label, phi_dict)

        # generate string showing the predicted value of line
        self.str = ""
        for line in lines:
            label = self.predict_one_line(line)
            predicted_line = "{label}\t{sentence}\n".format(
                label=label, sentence=line)
            self.str += predicted_line

    def predict_one_line(self, line):
        phi_dict = self.phi(line)
        sum_product= self.sum_prod(phi_dict)
        output=(math.e**sum_product)/float((1+math.e)**sum_product)
        print(sum_product,output)
        return sum_product

    def __str__(self):
        return self.str

    def update_weight(self, label, phi_dict, c=0.1,alpha=0.01):
        #phi_dict = self.phi(line)
        # print(phi_dict)
        for w in phi_dict:
            if abs(self.ws[w])<c:
                self.ws[w]=0
            else:
                self.ws[w]-=sign(self.ws[w])*c
        w__phi_x = self.sum_prod(phi_dict)
        coeff_phi = alpha * self.grad_P_coeff_phi(label, phi_dict)
        for w in phi_dict:
            self.ws[w] += coeff_phi * phi_dict[w]
            #print("coeff phi:\t{coeff}\n{weight}".format(coeff=coeff_phi,weight=self.ws[w]))
            #input()

    def grad_P_coeff_phi(self, label, phi_dict):
        #print(label,phi_dict,sep="\n")
        label=int(label)
        coeff = 0
        sum_prod = self.sum_prod(phi_dict)
        #print(sum_prod)
        if label == -1:
            coeff = -math.e**(sum_prod) / ((float(1 + math.e**(sum_prod)))**2)
        elif label == 1:
            coeff = math.e**(sum_prod) / ((float(1 + math.e**(sum_prod)))**2)
        #print(coeff)
        #input()
        return coeff

    def phi(self, line):
        phi_dict = defaultdict(int)
        for w in line.split():
            phi_dict[w] += 1
        return phi_dict

    def sum_prod(self, phi_dict):
        #print(phi_dict)
        output = 0
        for w in phi_dict:
            output += self.ws[w] * phi_dict[w]
        #input(output)
        return output

# In[117]:

training_file_path="../../data/titles-en-train.labeled"

# In[118]:

if __name__=="__main__":
    sgd=SGD(training_file_path)

# In[119]:

print(sgd)

# In[59]:

math.e**0

# In[ ]:


# -*- coding: utf-8 -*-
"""
Created on Sun Jun 20 10:13:03 2021

@author: staar
"""

#%%
#%%
# 6. You can use "json.dumps()" to pretty-print Python dicts
#    as an alternative to the "pprint" module

# The standard string repr for dicts is hard to read:
my_mapping = {'a': 23, 'b': 42, 'c': 0xc0ffee}
my_mapping
# {'b': 42, 'c': 12648430. 'a': 23}  #

# The "json" module can do a much better job:
import json
print(json.dumps(my_mapping, indent=4, sort_keys=True))
#{
#    "a": 23,
#    "b": 42,
#    "c": 12648430
#}

# Note this only works with dicts containing primitive types (check out the "pprint" module):
json.dumps({all: 'yup'}) #!!! TypeError: keys must be a string

## WHAT'S all TYPE ???

#%%
# In most cases I'd stick to the built-in "pprint" module though :-)
# https://pymotw.com/3/pprint/index.html
import pprint as pp

pp.pprint(my_mapping)
pp.pprint(my_mapping, indent=4, depth=1)  # ?
pp.pformat(my_mapping)  # ?

#%%
data = [
    (1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}),
    (2, {'e': 'E', 'f': 'F', 'g': 'G', 'h': 'H',
         'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L'}),
    (3, ['m', 'n']),
    (4, ['o', 'p', 'q']),
    (5, ['r', 's', 't''u', 'v', 'x', 'y', 'z']),
]

pp.pprint(data)  # what the hell... ???!!!
pp.pprint(data, indent=4)

#%% 25. Palindrome

def palindrome(a):
    return a == a[::-1]

palindrome('mom')
palindrome('mama')
palindrome('kobylamamalybok')

#%% 2. Anagrams
"""
This method can be used to CHECK IF two strings are anagrams.
An anagram is a word or phrase formed by rearranging the letters
of a different word or phrase, typically using all the original letters
exactly once.
"""

from collections import Counter    #!!!

Counter("aabbbcddeeee")
Counter([1, 2, 1, 3, 2, 4, 3, 2, 1])

def anagram(first, second):
    return Counter(first) == Counter(second)

anagram("abcd3", "3acdb")
anagram("abcd3", "3acd")

#%%
#%% 5. Print a string N times without using loop

print("string"*2)

#%% 6. Capitalize first letters of every word

print("what the hell...!".title())

#%% 13. Decapitalize
"""
This method can be used to turn the first letter of the given string into lowercase.
"""
def decapitalize(ss):
    return ss[:1].lower() + ss[1:]

decapitalize('FooBar')

'FooBar'.lower()  # not the same!
'Foo Bar'.lower()
'Foo BAR'.lower()

#%% 11. Comma-separated
hobbies = ["basketball", "football", "swimming"]
print("My hobbies are:")
print(", ".join(hobbies))

#%% 12. Count vowels

import re  #!!!

def count_vowels(ss):
    return len(re.findall(r'[aeiouy]', ss, re.IGNORECASE))

count_vowels('foobar')
count_vowels('gym')

#%%
import re
len(re.findall('python','python is a programming language. python is python.'))

#%%


from rest_framework import generics
from extraUserController.models import User

from .models import Candidate
from .serializers import CandidateModelSerializer

from rest_framework.decorators import api_view
from rest_framework.response import Response

from documentController.models import PDF
from documentController.serializers import PDFSerializer

from extraUserController.models import User
import os
from urllib.parse import unquote
from election_system_316 import settings

from django.http import FileResponse
import base64

# Create your views here.

class CandidateDetailsView(generics.RetrieveAPIView):
    queryset = Candidate.objects.all()
    serializer_class = CandidateModelSerializer
    lookup_field = 'pk'

candidate_details_view = CandidateDetailsView.as_view()

@api_view(["POST","GET"])
def candidate_list_view(request, *args, **kwargs):
    qs = Candidate.objects.all()
    result_data = CandidateModelSerializer(qs, many = True).data

    return Response(data=result_data)

@api_view(["POST","GET"])
def approved_candidate_list_view(request, *args, **kwargs):
    qs = Candidate.objects.all().filter(is_approved = True)
    result_data = CandidateModelSerializer(qs, many = True).data

    return Response(data=result_data)

@api_view(["POST","PUT"])
def create_candidate_view(request, *args, **kwargs):

    user = User.objects.get(studentNumber = request.data["studentid"])
    data = {
        "student_id": user.studentNumber,
        "name":user.name,
        "surname":user.surname,
        "department": user.department,
        "email":user.email,
        "grade": user.grade
        }

    serializer = CandidateModelSerializer(data=data)
    if(serializer.is_valid(raise_exception=True)):
        serializer.save()
        user.hasApplied = True
        user.save()

    candidate = Candidate.objects.get(student_id = user.studentNumber)
    for i in range(1,4):
        file = request.FILES[f"files{i}"]
        if(file):
            document = PDF(file=file, student=candidate)
            document.save()

    return Response(data={
        "status": "added"
    })

@api_view(["POST"])
def candidate_document_view(request, *args, **kwargs):

    studentNumber = request.data["studentid"]
    user = User.objects.get(studentNumber = studentNumber)
    if(user.hasApplied):
        candidate = Candidate.objects.get(student_id = studentNumber)
        qs = PDF.objects.all().filter(student = candidate)
        documents = PDFSerializer(qs,many = True).data
        document_array = []
        path_array = []
        print(settings.MEDIA_ROOT)
        for document in documents:
            file_path = unquote(document['file'])
            path_array.append(file_path)
            file_path = os.path.join(settings.MEDIA_ROOT, file_path[1::])
            with open(file_path, 'rb') as file:
                file_data = file.read()
                base64_data = base64.b64encode(file_data).decode('utf-8')
                document_array.append(base64_data)
        return Response(data={
            "documents": document_array,
            "paths": path_array
        })
    return Response(data={
        "message": f"The user with student id {studentNumber} has not applied"
    })


# -*- coding: utf-8

import re

from docutils import nodes, statemachine
from docutils.parsers import rst

class Event(rst.Directive):
	has_content = True
	required_arguments = 1
	optional_arguments = 0
	final_argument_whitespace = False
	option_spec = {
		'type':    rst.directives.unchanged_required,
		'in':      rst.directives.unchanged_required,
		'subject': rst.directives.unchanged_required,
		'out':     rst.directives.unchanged,
		'since':   rst.directives.unchanged,
		'params':  rst.directives.unchanged
	}

	def _parseInline(self, text):
		string = statemachine.StringList([text])
		para   = nodes.container()

		self.state.nested_parse(string, 0, para)

		return para

	def _buildParamList(self, ul, params):
		for paramline in params.split("\n"):
			match = re.match('^([^ ]+) +\((.*?)\)(?:\s*(.*?))$', paramline)
			item  = nodes.list_item()
			text  = '``%s`` (%s)' % (match.group(1), match.group(2))

			if len(match.groups()) == 3 and len(match.group(3)) > 0:
				text = text + ' (' + match.group(3) + ')'

			children = self._parseInline(text).children

			for child in children:
				if isinstance(child, nodes.paragraph):
					[item.append(t) for t in child.children]
				else:
					item.append(child)

			ul.append(item)

		return ul

	def run(self):
		event   = self.arguments[0]
		anchor  = event.lower().replace('_', '-')
		kind    = self.options.get('type')
		inType  = self.options.get('in')
		outType = self.options.get('out') or 'void'
		subject = self.options.get('subject')
		params  = self.options.get('params') or ''
		since   = self.options.get('since') or ''
		desc    = u'\n'.join(self.content)

		# create section

		# optionally insert zero-width breaks:
		# event.replace('_', u"_\u200B")

		sec = nodes.section()
		sec.append(nodes.title('', event))
		sec['names'].append(anchor)

		self.state.document.note_implicit_target(sec, sec)

		# the signature

		sig = '%s %s(%s)' % (outType, event, inType)

		if kind == 'until':
			sig += ' BREAKS'

		# additional params for this event

		paramlist = None

		if len(params) > 0:
			paramlist = self._buildParamList(nodes.bullet_list(), params)

		# create actual definition list

		dl = nodes.definition_list('',
			nodes.definition_list_item('',
				nodes.term('', '', nodes.strong('', 'Signatur:')),
				nodes.definition('', nodes.literal('', sig))
			),
			nodes.definition_list_item('',
				nodes.term('', '', nodes.strong('', 'Beschreibung:')),
				nodes.definition('', self._parseInline(desc))
			),
			nodes.definition_list_item('',
				nodes.term('', '', nodes.strong('', 'Subject:')),
				nodes.definition('', self._parseInline(subject))
			)
		)

		if paramlist:
			dl.append(nodes.definition_list_item('',
				nodes.term('', '', nodes.strong('', 'Weitere Parameter:')),
				nodes.definition('', paramlist)
			))

		if len(since) > 0:
			since = 'v%s' % since

			dl.append(nodes.definition_list_item('',
				nodes.term('', '', nodes.strong('', u'Hinzugefügt in:')),
				nodes.definition('', self._parseInline(since))
			))

		sec.append(dl)

		return [sec]

def setup(app):
	app.add_directive('slyevent', Event)


import numpy as np
import talib as TA
import pandas as pd
import copy

class QuantCenter():
    def __init__(self, exchange):
        self.init_timestamp = time.time()
        self.exchange = exchange
        self.name = self.exchange.GetName()
        self.currency = self.exchange.GetCurrency()

    def update_account(self):
        self.Balance = None
        self.Amount = None
        self.FrozenBalance = None
        self.FrozenStocks = None

        try:
            self.account = self.exchange.GetAccount()

            self.Balance = self.account['Balance']
            self.Amount = self.account['Stocks']
            self.FrozenBalance = self.account['FrozenBalance']
            self.FrozenStocks = self.account['FrozenStocks']
            return True
        except:
            return False

    def update_ticker(self):

        self.High = None
        self.Low = None
        self.Sell = None
        self.Buy = None
        self.Last = None
        self.Volume = None

        try:
            self.ticker = self.exchange.GetTicker()

            self.High = self.ticker['High']
            self.Low = self.ticker['Low']
            self.Sell = self.ticker['Sell']
            self.Buy = self.ticker['Buy']
            self.Last = self.ticker['Last']
            self.Volume = self.ticker['Volume']
            return True
        except:
            return False

    def update_depth(self):
        self.Asks = None
        self.Bids = None
        self.Asks_Price1 = None
        self.Asks_Amount1 = None
        self.Bids_Price1 = None
        self.Bids_Amount1 = None
        try:
            self.Depth = self.exchange.GetDepth()
            self.Asks = self.Depth['Asks']
            self.Bids = self.Depth['Bids']
            self.Asks_Price1 = self.Asks[0]["Price"]
            self.Asks_Amount1 = self.Asks[0]["Amount"]
            self.Bids_Price1 = self.Bids[0]["Price"]
            self.Bids_Amount1 = self.Bids[0]["Amount"]
            return True
        except:
            return False

    def update_kline(self, period=PERIOD_M5):
        try:
            self.Kline = exchange.GetRecords(period)
            return True
        except:
            return False

    def create_order(self, order_type, price, amount):
        if order_type == 'buy':
            try:
                order_id = self.exchange.Buy(price, amount)
            except:
                return False

        elif order_type == 'sell':
            try:
                order_id = self.exchange.Sell(price, amount)
            except:
                return False

        return order_id

    def fetch_order(self, id):
        ##    Log("Id:", order["Id"], "Price:", order["Price"], "Amount:", order["Amount"], "DealAmount:",
        ##    order["DealAmount"], "Status:", order["Status"], "Type:", order["Type"])
        return self.exchange.GetOrder(id)

    def fetch_uncomplete_orders(self):
        # 获取所有未完成的订单
        return self.exchange.GetOrders()

    def cancel_order(self, order_id):
        ## return True or False
        return self.exchange.CancelOrder(order_id)

    def refresh_data(self, period=PERIOD_M5):

        if not self.update_account():
            return 'false_get_account'

        if not self.update_ticker():
            return 'false_get_ticker'
        if not self.update_depth():
            return 'false_get_depth'
        try:
            self.update_kline(period)
        except:
            return 'false_get_K_line_info'

        return 'refresh_data_finish!'

    def fetch_kline(self, period=PERIOD_M5):
        return self.exchange.GetRecords(period)

    def fetch_ticker(self):
        return self.exchange.GetTicker()

    def fetch_depth(self):
        return self.exchange.GetDepth()

## define Stragety
class Strategy():
    def __init__(self, args):
        self.args = args
        self.quantcenter = args.quantcenter

        self.init_time = time.time()
        self.last_time = time.time()

        self.amount_N = args.amount_N
        self.price_N = args.price_N

        self.min_buy_money = args.min_buy_money
        self.min_sell_money = args.min_sell_money
        self.quantcenter.update_kline(args.kline_period)
        self.kline = pd.DataFrame(self.quantcenter.Kline)
        ##record orders
        self.buy_orders = []
        self.sell_orders = []
        self.trend_orders = []
        ## strategy params
        self.price_threshold = args.price_threshold
        self.position_max_percent = args.position_max_percent
        self.price_percent_period = args.price_percent_period
        self.user_price_period = int(self.price_percent_period / len(self.kline) * 24 * 3600)
        self.price_gap = args.price_gap
        self.max_orders = args.max_orders
        self.order_max_wait_time = args.order_max_wait_time
        ##moving average
        self.price_slip = args.price_slip

    def refresh_data(self, period):

        self.quantcenter.refresh_data(period)
        self.Amount = self.quantcenter.Amount
        self.Balance = self.quantcenter.Balance
        self.Buy_price = self.quantcenter.Buy
        self.Sell_price = self.quantcenter.Sell
        self.potential_buy_amount = round(self.Balance / self.Sell_price, self.amount_N)
        self.potential_sell_amount = round(self.Amount, self.amount_N)

        ##update arr will be used in indicator
        self.kline = pd.DataFrame(self.quantcenter.Kline)
        self.close_Arr = self.kline["Close"].to_numpy()
        self.high_Arr = self.kline["High"].to_numpy()
        self.low_Arr = self.kline["Low"].to_numpy()
        ##update user_define_price_percent
        self.user_dataset = pd.DataFrame(self.quantcenter.fetch_kline(self.user_price_period))
        self.user_Max_price = self.user_dataset.High.max()
        self.user_Min_price = self.user_dataset.Low.min()

    def trade_amount_compute(self, price, trade_side):
        price_percent = (price - self.user_Min_price) / (self.user_Max_price - self.user_Min_price)
        if trade_side == "buy":
            ##高估区间不买入
            if price > self.user_Max_price * self.price_threshold["buy"]:
                return False
                ##percent =1 amount =0  percent = 0 amount =1
            self.min_buy_amount = self.position_max_percent * self.Balance / price * (1.0 - price_percent)
            self.min_buy_amount = max(self.min_buy_amount, 0.0)
            self.min_buy_amount = min(self.min_buy_amount, self.Balance / price)
            self.min_buy_amount = round(self.min_buy_amount, self.amount_N)
            self.min_buy_balance = self.min_buy_amount * price
            if self.min_buy_balance < self.min_buy_money:
                return False
            else:
                return True

        elif trade_side == "sell":
            ##低估不卖出
            if price < self.user_Min_price * self.price_threshold["sell"]:
                return False
                ##percent =1 amount =1  percent = 0 amount =0
            self.min_sell_amount = self.position_max_percent * self.Amount * price_percent
            self.min_sell_amount = max(self.min_sell_amount, 0.0)
            self.min_sell_amount = min(self.min_sell_amount, self.Amount)
            self.min_sell_amount = round(self.min_sell_amount, self.amount_N)
            self.min_sell_balance = self.min_sell_amount * price
            if self.min_sell_balance < self.min_sell_money:
                return False
            else:
                return True

    def double_moving_average(self):
        fast_arr = TA.EMA(self.close_Arr, self.args.short_period)
        slow_arr = TA.EMA(self.close_Arr, self.args.long_period)

        cross_over = fast_arr[-1] > slow_arr[-1] and fast_arr[-2] < slow_arr[-2]
        cross_below = fast_arr[-1] < slow_arr[-1] and fast_arr[-2] > slow_arr[-2]
        RSX = self.rsx()
        if cross_over and RSX[-1] > 50 +self.args.rsx_threshold:
            trade_price = round(self.quantcenter.Bids_Price1 * (1.0 + self.price_slip), self.price_N)
            will_trade = self.trade_amount_compute(trade_price, "buy")
            if will_trade:
                trade_id = self.quantcenter.create_order("buy", trade_price, self.min_buy_amount)
                if trade_id:
                    self.refresh_data(self.args.kline_period)
                    self.trend_orders.append({
                        "side": "buy",
                        "price": trade_price,
                        "amount": self.min_buy_amount,
                        "id": trade_id,
                        "timestamp": Unix()})
        if cross_below and RSX[-1] < 50 - self.args.rsx_threshold :
            trade_price = round(self.quantcenter.Asks_Price1 * (1.0 - self.price_slip), self.price_N)
            will_trade = self.trade_amount_compute(trade_price, "sell")
            if will_trade:
                trade_id = self.quantcenter.create_order("sell", trade_price, self.min_sell_amount)
                if trade_id:
                    self.refresh_data(self.args.kline_period)
                    self.trend_orders.append({
                        "side": "sell",
                        "price": trade_price,
                        "amount": self.min_sell_amount,
                        "id": trade_id,
                        "timestamp": Unix()})
##rsx indicator
    def rsx(self):
        length= int(self.args.rsx_period)  if self.args.rsx_period > 0 else 14
        if self.close_Arr is None:
            return 0
        # variables
        vC, v1C = 0, 0
        v4, v8, v10, v14, v18, v20 = 0, 0, 0, 0, 0, 0
        f0, f8, f10, f18, f20, f28, f30, f38 = 0, 0, 0, 0, 0, 0, 0, 0
        f40, f48, f50, f58, f60, f68, f70, f78 = 0, 0, 0, 0, 0, 0, 0, 0
        f80, f88, f90 = 0, 0, 0

        m = len(self.close_Arr)
        result = [np.nan for _ in range(0, length - 1)] + [0]
        for i in range(length, m):
            if f90 == 0:
                f90 = 1.0
                f0 = 0.0
                if length - 1.0 >= 5:
                    f88 = length - 1.0
                else:
                    f88 = 5.0
                f8 = 100.0 * self.close_Arr[i]
                f18 = 3.0 / (length + 2.0)
                f20 = 1.0 - f18
            else:
                if f88 <= f90:
                    f90 = f88 + 1
                else:
                    f90 = f90 + 1
                f10 = f8
                f8 = 100 * self.close_Arr[i]
                v8 = f8 - f10
                f28 = f20 * f28 + f18 * v8
                f30 = f18 * f28 + f20 * f30
                vC = 1.5 * f28 - 0.5 * f30
                f38 = f20 * f38 + f18 * vC
                f40 = f18 * f38 + f20 * f40
                v10 = 1.5 * f38 - 0.5 * f40
                f48 = f20 * f48 + f18 * v10
                f50 = f18 * f48 + f20 * f50
                v14 = 1.5 * f48 - 0.5 * f50
                f58 = f20 * f58 + f18 * abs(v8)
                f60 = f18 * f58 + f20 * f60
                v18 = 1.5 * f58 - 0.5 * f60
                f68 = f20 * f68 + f18 * v18
                f70 = f18 * f68 + f20 * f70
                v1C = 1.5 * f68 - 0.5 * f70
                f78 = f20 * f78 + f18 * v1C
                f80 = f18 * f78 + f20 * f80
                v20 = 1.5 * f78 - 0.5 * f80

                if f88 >= f90 and f8 != f10:
                    f0 = 1.0
                if f88 == f90 and f0 == 0.0:
                    f90 = 0.0

            if f88 < f90 and v20 > 0.0000000001:
                v4 = (v14 / v20 + 1.0) * 50.0
                if v4 > 100.0:
                    v4 = 100.0
                if v4 < 0.0:
                    v4 = 0.0
            else:
                v4 = 50.0
            result.append(v4)
        return np.array(result)

    def next(self):
        self.double_moving_average()

## main
## define args
class Args():
    amount_N = 4
    price_N = 4
    min_buy_money = 5
    min_sell_money = 5

    kline_period = PERIOD_M5
    position_max_percent = 0.1
    price_threshold = {"buy": 0.999,
                       "sell": 1.001}
    ## true_period (Days)
    price_percent_period = 21
    price_gap = 0.005
    max_orders = 5
    order_max_wait_time = 3600 * 4
    ##Moing average
    short_period = 100
    long_period =169
    price_slip = 2.5e-5
    ##ADX
    ADX_period = 14
    ADX_threshold = 30
    ##RSX
    rsx_period = 14
    rsx_threshold = 15
    quantcenter = QuantCenter(exchange)

def main():
    args = Args()
    strategy = Strategy(args)
    strategy.refresh_data(args.kline_period)
    Log("refresh_data ok")
    while (True):
        Sleep(1000 * 60 * 5)
        # time.sleep(60)
        try:
            ## refresh_data and indicator
            strategy.refresh_data(args.kline_period)
            strategy.next()
        except:
            pass