'''
Title: 2048 Hackathon Project using Reinforcement Learning
Author: Jason Ho, Jeremy Chen, Steven Cheung, Hwai-Liang Tung
Date: January 26th - 27th 2019
'''

# Python library imports
import random
import numpy as np
from collections import defaultdict

class Board:
    '''
    Board is a class method that creates the board that is used for the 2048
    game using numpy arrays to display. In addition, its methods allow for
    full functionality of the game board.

    As its own discrete object, its possible to use it for our reinforcement
    learning object, or as a game by itself that a user can play.
    '''

    def __init__(self, gameOver=False, score=0):
        '''
        Default initialiser which just sets the actual numpy representation
        of the board to be four by four, sets score to be zero and starts the
        game.
        '''
        self.board = np.zeros((4, 4))
        self.gameOver = gameOver
        self.score = score

    def addTile(self):
        '''
        addTile is a method that functions as the randomized part of the 2048
        game that adds a 2 or 4 tile each time that the user moves the board.
        '''
        listOfEmptys = []

        # Double for loop that allows for each element to be checked to see if
        # deemed an empty space, meaning that it has a value of zero.
        for i, x in enumerate(self.board):
            for j, y in enumerate(x):
                if y == 0:
                    listOfEmptys.append((i, j))

        # Finds random place to put the tile by looking at all empty spaces
        element = listOfEmptys[random.randint(0, len(listOfEmptys)-1)]

        # Determines tile value; 90% to be 2, 10% to be 4
        if random.random() < 0.9:
            num = 2
        else:
            num = 4

        # Adds element to the internal board stored in the class variables
        self.board[element[0], element[1]] = num

    def rotateBoardLeft(self):
        '''
        rotateBoardLeft rotates the board ninety degrees to the left in the
        counterclockwise dimension. This method solely exists such that it is
        easier to do computations with the board when combining tiles for score.

        Also, this method makes it easier to permute the board in different
        directions when using the different commands.
        '''
        self.board = np.rot90(self.board)

    def rotateBoardRight(self):
        '''
        rotateBoardRight literally rotates the entire numpy array board to the
        right, or clockwise ninety degrees. Again, this will be used as a
        helper function since it is easier to understand what this is doing
        rather than just having the numpy syntax for rotating the board.
        '''
        self.board = np.rot90(self.board, 3)

    def moveAndUpdateRowLeft(self, j):
        '''
        moveAndUpdateRowLeft is a method that essentially works on one row at
        a time. It takes one row and then moves all of the nonzero digits to the
        left into a new list, l. It then appends zeroes to the end to make up
        for the difference and make sure that the board is still the same square
        that it was beforehand.

        Parameters
        ----------
        j : int
            Represents the row number that the method is called upon in the
            game board array.

        Returns
        ----------
        l : list
            Represents the new row where entire row is moved to the left
        '''
        l = []

        # Iterates through each item in the row and if not zero, appends to l
        for i in range(0, self.board.shape[1]):
            if self.board[j, i] != 0:
                l.append(self.board[j, i])

        # Adds zeroes to the end of l until same size as the original row length
        while len(l) < self.board.shape[1]:
            l.append(0)
        return l

    def moveAndUpdateBoardLeft(self):
        '''
        moveAndUpdateBoardLeft is a method that takes the entire board and then
        moves the board to the left. At the same time, it updates the score of
        the game session when two tiles of the same value hit each other when
        updated and moved to the left.

        In essence this is the master method that is used in order to update
        the board in every single direction.
        '''
        arrayToReturn = []

        # Loop for each row of the board
        for j in range(0, self.board.shape[0]):
            x = self.moveAndUpdateRowLeft(j)

            # Loop to go through each of the elements
            for i in range(0, self.board.shape[1]-1):
                if x[i] == x[i+1] and x[i] != 0:

                    # Fixes score and board when two of a kind touch each other
                    self.board[j, i] = 2 * x[i]
                    self.score += self.board[j, i]
                    self.board[j, i+1] = 0

                # Sets x to be the new board row
                x = self.board[j]

            # Appends the fixed row to the new array
            arrayToReturn.append(self.moveAndUpdateRowLeft(j))

        # Sets board equal to the new fixed board
        self.board = np.array(arrayToReturn)

    def moveAndUpdateBoard(self, move):
        '''
        moveAndUpdateBoard is a method that takes in the move query and then
        translates that into the board. Since everything is handled by helper
        functions defined beforehand, this part of the script is much shorter.

        Parameters
        ----------
        move : str
            Represents the move that is inputted either by the reinforcement
            learning program or the human user
        '''

        # if the user wants to move up
        if move == "Up":
            self.rotateBoardLeft()
            self.moveAndUpdateBoardLeft()
            self.rotateBoardRight()

        # if the user wants to move down
        elif move == "Down":
            self.rotateBoardRight()
            self.moveAndUpdateBoardLeft()
            self.rotateBoardLeft()

        # if the user wants to move left
        elif move == "Left":
            self.moveAndUpdateBoardLeft()

        # if the user wants to move right
        elif move == "Right":
            self.rotateBoardLeft()
            self.rotateBoardLeft()
            self.moveAndUpdateBoardLeft()
            self.rotateBoardRight()
            self.rotateBoardRight()

        # adds tile randomly after move on the board
        self.addTile()

    def availableActions(self):
        '''
        availableActions is a method that finds all of the possible moves that
        the reinforcement learning program or the user can input. Since once
        the board fills up in one direction, it is no longer possible to move
        the board in that direction.

        This method accounts for that and allows for the the correct inputs and
        can provide the correct print statements when a user tries to input
        something that is not allowed.

        Returns
        ---------
        toReturn : list of strings
            Represents the list of moves that are possible and can be used
        '''
        dimension = self.board.shape[0]
        toReturn = []

        # Checks to see if up is a valid move
        for i in range(0, dimension):
            if self.board[0, i] != 0:
                break
        else:
            toReturn.append("Up")

        # Checks to see if down is a valid move
        for i in range(0, dimension):
            if self.board[dimension-1, i] != 0:
                break
        else:
            toReturn.append("Down")

        # Checks to see if Left is a valid move
        for i in range(0, dimension):
            if self.board[i, 0] != 0:
                break
        else:
            toReturn.append("Left")

        # Checks to see if Right is a valid move
        for i in range(0, dimension):
            if self.board[i, dimension] != 0:
                break
        else:
            toReturn.append("Right")
        return toReturn

    def isOver(self):
        '''
        isOver is a method that checks whether or not the end of the game has been
        encountered, meaning that there are no spots that new tiles can be put
        and the board cannot be reduced to make space for new tiles.

        In order words, this means that there are no possible moves available.

        Returns
        -------
        over : boolean
            Represents whether or not a game is over by looking at the board; If
            there are moves that are possible, then the game is not over.
        '''
        aBoolean = False

        for j in range(0, self.board.shape[0]):
            x = self.board[j, :]
            for i in range(0, self.board.shape[1]):
                if x[i] == 0:
                    break
        else:
            aBoolean = True

        over = (self.availableActions() == [] and aBoolean)
        return over


import streamlit as st
import pandas as pd
import plotly.graph_objects as go
from streamlit_plotly_events import plotly_events

from components.utils import compute_mean
from components.icons import st_icons

def st_map(data : pd.DataFrame, list_global_var : list, icons_container, global_means : list):

    st.markdown("##### B. Select a key indicator from the dropdown list and visualise it for all countries using the map:")

    general_list = ['Adolescent fertility rate',
                    'Age at first marriage',
                    'Cause of death, by communicable diseases and maternal, prenatal and nutrition conditions',
                    'Cause of death, by non-communicable diseases',
                    'Contraceptive prevalence',
                    'Educational attainment',
                    'Female share of employment in senior and middle management',
                    'Fertility rate',
                    'Ratio of female to male labor force participation rate',
                    'Wage and salaried workers',
                    'Wanted fertility rate',
                    'Women making their own informed decisions regarding sexual relations, contraceptive use and reproductive health care',
                    'Women who believe a wife is justified refusing sex with her husband if she knows he has sexually transmitted disease'
                    ]
    column_names = list(data.columns)
    initial_variable = st.selectbox('', tuple(general_list))
    new_list = [s for s in column_names if initial_variable in s]
    remove_from_list = initial_variable + ', '

    if(initial_variable == 'Adolescent fertility rate'
       or initial_variable == 'Female share of employment in senior and middle management'
       or initial_variable == 'Fertility rate'
       or initial_variable == 'Ratio of female to male labor force participation rate'
       or initial_variable == 'Wanted fertility rate'
       or initial_variable == 'Women making their own informed decisions regarding sexual relations, contraceptive use and reproductive health care'
       ):
        choosen_variable = new_list[0]
    else:
        st.markdown("")
        st.markdown("Select a sub-category of the gender key chosen: ")
        new_list = list(map(lambda x: x.replace(remove_from_list,''),new_list))
        choosen_variable = st.selectbox('', tuple(new_list))
        choosen_variable = remove_from_list + choosen_variable

    #refresh button
    if st.button("Reset"):
        raise st.experimental_rerun()

    st.markdown(choosen_variable)

    fig = go.Figure(data=go.Choropleth(
        locations=data.index,  # Spatial coordinates
        z=data[choosen_variable].astype(float),  # Data to be color-coded
        locationmode='country names',  # set of locations match entries in `locations`
        colorscale='Viridis',
    ))

    fig.update_layout(margin={"r": 0, "t": 0, "l": 0, "b": 0})

    map_container = st.container()

    with map_container:
        selected_countries = plotly_events(fig, click_event = True, select_event = True)

    list_index = [e['pointIndex'] for e in selected_countries]

    if list_index != []:
        st_icons(compute_mean(data, list_index, list_global_var), icons_container)
    else :
        st_icons(global_means, icons_container)


import os
import shlex
import struct
import platform
import subprocess

hasTermios = False
oldtty = None

try:
    import termios
    import tty
    hasTermios = True
except ImportError:
    hasTermios = False

def hasTermios():
    return hasTermios

def isTerminal(stream):
    return stream.isatty()

def saveTerminalAttrs(stream):
    global oldtty
    if stream.isatty():
        oldtty = termios.tcgetattr(stream)

def getSavedTerminalAttrs():
    return oldtty

def restoreTerminalAttrs(stream):
    global oldtty
    restoreAttrs = getSavedTerminalAttrs()
    if isTerminal(stream) and restoreAttrs:
        termios.tcsetattr(stream, termios.TCSADRAIN, restoreAttrs)

def setTerminalInteractive(stream):
    if stream.isatty():
        tty.setraw(stream.fileno())
        tty.setcbreak(stream.fileno())

# from jtriley/terminalsize.py
def getTerminalSize():
    """ getTerminalSize()
     - get width and height of console
     - works on linux,os x,windows,cygwin(windows)
     originally retrieved from:
     http://stackoverflow.com/questions/566746/how-to-get-console-window-width-in-python
    """
    current_os = platform.system()
    tuple_xy = None
    if current_os == 'Windows':
        tuple_xy = _getTerminalSizeWindows()
        if tuple_xy is None:
            tuple_xy = _getTerminalSizeTPUT()
            # needed for window's python in cygwin's xterm!
    if current_os in ['Linux', 'Darwin'] or current_os.startswith('CYGWIN'):
        tuple_xy = _getTerminalSizeLinux()
    if tuple_xy is None:
        tuple_xy = (80, 25)      # default value
    return tuple_xy

def _getTerminalSizeWindows():
    try:
        from ctypes import windll, create_string_buffer
        # stdin handle is -10
        # stdout handle is -11
        # stderr handle is -12
        h = windll.kernel32.GetStdHandle(-12)
        csbi = create_string_buffer(22)
        res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
        if res:
            (bufx, bufy, curx, cury, wattr,
             left, top, right, bottom,
             maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
            sizex = right - left + 1
            sizey = bottom - top + 1
            return sizex, sizey
    except:
        pass

def _getTerminalSizeTPUT():
    # get terminal width
    # src: http://stackoverflow.com/questions/263890/how-do-i-find-the-width-height-of-a-terminal-window
    try:
        cols = int(subprocess.check_call(shlex.split('tput cols')))
        rows = int(subprocess.check_call(shlex.split('tput lines')))
        return (cols, rows)
    except:
        pass

def _getTerminalSizeLinux():
    def ioctl_GWINSZ(fd):
        try:
            import fcntl
            import termios
            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
            return cr
        except:
            pass
    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
    if not cr:
        try:
            fd = os.open(os.ctermid(), os.O_RDONLY)
            cr = ioctl_GWINSZ(fd)
            os.close(fd)
        except:
            pass
    if not cr:
        try:
            cr = (os.environ['LINES'], os.environ['COLUMNS'])
        except:
            return None
    return int(cr[1]), int(cr[0])

def decodeTerminalBytes(bytes):
    return bytes.decode(errors='ignore')

if __name__ == "__main__":
    sizex, sizey = getTerminalSize()
    print('width =', sizex, 'height =', sizey)


import turtle
#printing a star
turtle.begin_fill()
turtle.pencolor("blue")
turtle.fillcolor("orange")
for i in range(5):
    turtle.forward(140)
    turtle.left(144)
turtle.end_fill()
turtle.done()


'''
    func:爬取知乎每日最热话题
    date:2018/11/15
    author:monty
'''
from bs4 import BeautifulSoup as bs
import requests
import lxml
from pyquery import PyQuery as pq

def getPage(url):
    headers={
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    }

    response=requests.get(url,headers=headers)
    return response.text

def pageparse(html):
    soup=bs(html,'lxml')
    result=soup.select('.explore-feed')
    rs=[]
    for i in result:
        r={}
        r['title']=i.find('h2').text.strip()
        r['click']=i.select('.zm-item-vote')[0].text.strip()
        r['author']=i.select('.author-link-line')[0].text.strip()
        r['authorurl']="https://www.zhihu.com"+i.select('span a')[0].attrs['href']
        doc=pq(i.select('.content')[0].text)
        doc.remove('a')
        r['content']=doc.text().strip()
        rs.append(r)
    return rs
def save(items,filename):
    file=open(filename,'a',encoding='utf-8')
    for item in items:
        file.write(item['title']+"\n作者："+item['author']+"\t"*2+"作者联系方式:"+item['authorurl']+"\t"*2+"点赞数："+item['click']+"\n"+item['content'])
        file.write("\n"+"="*120+"\n\n\n")
    file.close()
if __name__=="__main__":
    url='https://www.zhihu.com/explore'
    html=getPage(url)
    rs=pageparse(html)
    save(rs,'zhihu.txt')


"""
Given an array of meeting time intervals consisting of start and end times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of conference rooms required.

Example 1:

Input: [[0, 30],[5, 10],[15, 20]]
Output: 2
Example 2:

Input: [[7,10],[2,4]]
Output: 1
"""

class Solution:
    ## 时间复杂度高
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: int
        """
        if len(intervals) <= 1:
            return len(intervals)

        max_count = 0
        intervals.sort(key = lambda x:x.start)
        for start in (interval.start for interval in intervals):
            count = 0
            for interval in intervals:
                if start < interval.start:
                    break
                if start >= interval.end:
                    continue

                if start >= interval.start and start < interval.end:
                    count += 1
            if count > max_count:
                max_count = count
        return max_count

class Solution:
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: int
        """
        starts,ends = [],[]
        for interval in intervals:
            starts.append(interval.start)
            ends.append(interval.end)

        starts.sort()
        ends.sort()

        room,end = 0,0
        for start in starts:
            if start < ends[end]: room += 1
            else: end += 1
        return room

# 扫描线算法
class Solution:
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: int
        """
        starts,ends = [],[]
        for interval in intervals:
            starts.append(interval.start)
            ends.append(interval.end)

        starts.sort()
        ends.sort()

        room,end = 0,0
        for start in starts:
            if start < ends[end]: room += 1
            else: end += 1
        return room

class Solution:
    def minMeetingRooms(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: int
        """
        points = []
        for interval in intervals:
            points.append((interval.start,1))
            points.append((interval.end,-1))

        points.sort()
        count,room = 0,0
        for _,delta in points:
            count += delta
            room = max(room,count)

        return room


import os
from PIL import Image, ImageOps

img_create = Image.new('L',(7000,6720))
pixels = img_create.load()

mnistF = open('digit_raw.bin','rb')
mnistD = mnistF.read()
mnistS = int.from_bytes(b'\xFF','big')

trackIndex = 0

def crapsingle(a,b) :
	x = a*28
	y = b*28
	global trackIndex

	while x < (a+1)*28 :
		while y < (b+1)*28:
			pixel_bin = mnistD[trackIndex:trackIndex+1]
			pixel = int.from_bytes(pixel_bin,'big')
			#print('index : ' + str(x) + ' : ' + str(y) + ' : ' + str(z) + ' : ' + str(pixel))
			trackIndex = trackIndex + 1
			pixels[x,y] = pixel
			y = y+1
		y = b*28
		x = x+1
	#print('fuck you : ' + str(a) + " : " + str(b))

def megacrap() :
	m = 0
	n = 0
	while m < 250 :
		while n < 240 :
			crapsingle(m,n)
			n = n + 1
		n = 0
		m = m + 1

megacrap()
img_create = ImageOps.mirror(img_create)
img_create = img_create.rotate(90)
img_create.save('test.bmp')


from typing import List

# Definition for a binary tree node.
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def buildTree(self, preorder: List[int], inorder: List[int]) -> TreeNode:
        # 예외 처리: 빈 순회 리스트
        if len(preorder)==0:
            return None

        root = TreeNode(preorder[0])
        root_idx = inorder.index(root.val)
        left_len = root_idx

        left = self.buildTree(preorder[1:1+left_len], inorder[:left_len])
        right = self.buildTree(preorder[1+left_len:], inorder[left_len+1:])

        root.left, root.right = left, right
        return root


class Recommendationr:
    def __init__(self,redditUsers):

        self.redditUsers = redditUsers
        self.dataset = self.formatDataset()

    def formatDataset(self):
        tmpDataset = {}

        for user in self.redditUsers.users:
            tmpDataset[user] = self.redditUsers.users[user].dataset

        return tmpDataset

    def pearsonSimilarity(self,dataset,person1,person2):
        import Pearson.Pearson as Pearson
        pearson = Pearson.Pearson()

       # print "scipy- "
       # print pearson.calculateSimSciPy(dataset,person1,person2)
       # print "oreilly -"
       # print pearson.calculateSim(dataset,person1,person2)
        return pearson.calculateSim(dataset,person1,person2)

    # Gets recommendations for a person by using a weighted average
    # of every other user's rankings
    def getRecommendations(self,person,similarity=pearsonSimilarity):

      prefs = self.dataset
      totals={}
      simSums={}
      for other in prefs:
        # don't compare me to myself
        if other==person: continue
        sim=similarity(self,prefs,person,other)

        # ignore scores of zero or lower
        if sim<=0: continue
        for item in prefs[other]:

          # only score movies I haven't seen yet
          if item not in prefs[person] or prefs[person][item]==0:
            # Similarity * Score
            totals.setdefault(item,0)
            totals[item]+=prefs[other][item]*sim  #multiplica o que o outro acha pela similiaridade que tem com ele
            # Sum of similarities
            simSums.setdefault(item,0)
            simSums[item]+=sim

      # Create the normalized list
      rankings=[(total/simSums[item],item) for item,total in totals.items()]

      # Return the sorted list
      rankings.sort()
      rankings.reverse()
      return rankings

def main():
    return

if __name__ == '__main__':
    main()


import subprocess as sp
from multiprocessing import Process
from os.path import exists
from datetime import datetime
from flask import flash

def tv_record(name, url):

    loc = '/Novus_recording_system/clips/'

    def ffmpeg(name, url, loc):

        process = sp.Popen(['ffmpeg',
                            '-re',
                            '-nostats',
                            '-loglevel', '0',
                            '-progress', 'timestamps/' + name + '.ts',
                            '-i', url,
                            '-stimeout', '10000',
                            '-c:a', 'libvo_aacenc',
                            '-b:a', '64000',
                            '-ac', '1',
                            '-ar', '16000',
                            '-af', 'aresample=async=1',
                            '-c:v', 'libx264',
                            '-preset', 'ultrafast',
                            '-b:v', '768K',
                             '-vf', 'scale=320:240',
                            '-f', 'segment',
                            '-segment_time', '120',
                            '-segment_atclocktime', '1',
                            '-strftime', '1',
                            '-reset_timestamps', '1',
                            loc + name + '.%Y-%m-%d_%H-%M-%S.mp4'])

        with open('pids/' + name + '.pid', 'w') as f:
            f.write(str(process.pid))

        print(str(datetime.now().strftime('%d-%m-%Y__%H:%M:%S ')) + 'started recording', name, 'on process id:', str(process.pid))
        return process.pid

    p = Process(target=ffmpeg, args=(name, url, loc))

    if exists(loc):
        p.start()

    else:
        print(str(datetime.now().strftime('%d-%m-%Y__%H:%M:%S ')) + loc, 'is not mounted')
        flash(loc + ' is not mounted')


import numpy as np
import scipy.constants as spc
from matplotlib import pyplot as plt
from netCDF4 import date2num
import spiceypy as spice
import cartopy.crs as ccrs

from .. import ocean
from .. import atmosphere
from .. import spacecraft as sc
from .. import dielectric

def plot_raw_inputs():
    o = ocean.ocean(mode='flat')

    lat = np.arange(90, -90, -1)
    lon = np.arange(-180, 180, 1)
    llat, llon = np.meshgrid(lat, lon, indexing='ij')
    current_time = date2num(o.time, o.time_reference)
    sst = o.sst_interp((llat, llon)) - spc.zero_Celsius
    sss = o.sss_interp((llat, llon))
    land = o.landmask_interp((llat, llon))
    uwind = o.uwind_interp((current_time, llat, llon))
    vwind = o.vwind_interp((current_time, llat, llon))
    prwtr = o.prwtr_interp((current_time, llat, llon))
    TEC = o.TEC_interp((llat, llon))
    del o
    plt.figure()
    plt.title('Sea Surface Temperature')
    plt.imshow(sst, cmap='jet')
    plt.colorbar(orientation='horizontal')
    plt.clim(vmin=0, vmax=30)

    plt.figure()
    plt.title('Sea Surface Salinity')
    plt.imshow(sss, cmap='jet')
    plt.colorbar(orientation='horizontal')
    plt.clim(vmin=30, vmax=38)

    plt.figure()
    plt.title('Land mask')
    plt.imshow(land, cmap='jet')

    plt.figure()
    plt.title('Zonal Wind')
    plt.imshow(uwind, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Meridional Wind')
    plt.imshow(vwind, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Precipitable Water')
    plt.imshow(prwtr, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.figure()
    plt.title('Total Electron Content')
    plt.imshow(TEC, cmap='jet')
    plt.colorbar(orientation='horizontal')

    plt.show()
    plt.close('all')

def plot_TB_map():
    mesh_spacing = 1
    lat_flat = np.linspace(89.5, -89.5, int(180 / mesh_spacing))
    lon_flat = np.linspace(-179.5, 179.5, int(360 / mesh_spacing))
    lon, lat = np.meshgrid(lon_flat, lat_flat)
    o = ocean.ocean(mode='flat')
    omap = o.get_ocean_TB(np.array([1e3]), theta=40)
    omap_v = omap[0][0] * (1 - o.landmask_interp((lat, lon)))
    omap_h = omap[1][0] * (1 - o.landmask_interp((lat, lon)))
    omap_v[omap_v < 50] = np.nan
    omap_h[omap_h < 50] = np.nan
    fig, ax = plt.subplots()
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.gridlines(color='k', draw_labels=True)
    extent = (-179.5, 179.5, -89.5, 89.5)
    mode = np.median(omap_v[omap_v > 20])
    offset = 10
    plot = ax.imshow(omap_v, origin='upper', extent=extent, transform=ccrs.PlateCarree(), cmap='turbo', vmin=mode - offset, vmax=mode + offset)
    fig.colorbar(plot, shrink=1, pad=0.1, label='Brightness Temperature (K)', orientation='horizontal')
    plt.savefig('Vpol_TB.png', dpi=300, transparent=True)

    fig2, ax2 = plt.subplots()
    ax2 = plt.axes(projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.gridlines(color='k', draw_labels=True)
    extent = (-179.5, 179.5, -89.5, 89.5)
    mode = np.median(omap_h[omap_h > 20])
    offset = 10
    plot = ax2.imshow(omap_h, origin='upper', extent=extent, transform=ccrs.PlateCarree(), cmap='turbo', vmin=mode - offset, vmax=mode + offset)
    fig2.colorbar(plot, shrink=1, pad=0.1, label='Brightness Temperature (K)', orientation='horizontal')
    plt.savefig('Hpol_TB.png', dpi=300, transparent=True)

def plot_dielectric():
    frequency = np.logspace(3, 6, 1000)
    salinity = np.linspace(30, 40, 10)
    temperature = 293 * np.ones(len(salinity))
    eps = dielectric.h2o_liquid_saline_KleinSwift(frequency[:, np.newaxis], temperature[np.newaxis, :], salinity[np.newaxis, :])
    plt.figure()
    plt.loglog(frequency, np.real(eps))
    plt.figure()
    plt.loglog(frequency, -np.imag(eps))

def plot_spectrum():

    o = ocean.ocean(mode='flat')
    frequency = np.linspace(0.5e3, 100e3, 1000)
    TBV, TBH = o.get_ocean_TB(frequency=frequency, sst=300, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=40)

    plt.figure()
    plt.title(r'Ocean Emission Spectrum')
    plt.semilogx(frequency / 1e3, TBH, label=r'T$_B^H$')
    plt.semilogx(frequency / 1e3, TBV, label=r'T$_B^V$')
    plt.xlabel('Frequency (GHz)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(1.1, 201, r'T: 300K, S: 35 psu, $\theta$: 40$^\circ$')
    plt.legend()
    plt.savefig('freq_spectrum.png', format='png', dpi=300, transparent=True)

    angle = np.linspace(0, 80, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=angle)

    plt.figure()
    plt.title(r'Ocean Emission with Angle')
    plt.plot(angle, TBH, label=r'T$_B^H$')
    plt.plot(angle, TBV, label=r'T$_B^V$')
    plt.xlabel('Angle (Degrees)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(11, 240, r'T: 300K, S: 35 psu, F: 1 GHz')
    plt.legend()
    plt.savefig('angle_spectrum.png', format='png', dpi=300, transparent=True)

    wind = np.linspace(0, 20, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=wind, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Wind speed')
    plt.plot(wind, TBH, label=r'T$_B^H$')
    plt.plot(wind, TBV, label=r'T$_B^V$')
    plt.xlabel('Wind speed (m/s)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(2.5, 90.4, r'T: 300K, S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('wind_spectrum.png', format='png', dpi=300, transparent=True)

    gal = np.linspace(0, 20, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=35, uwind=0, vwind=0, gal_max=gal, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Wind speed')
    plt.plot(gal, TBH, label=r'T$_B^H$')
    plt.plot(gal, TBV, label=r'T$_B^V$')
    plt.xlabel('Galactic Brightness Temperature (K)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(2.5, 104, r'T: 300K, S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('gal_spectrum.png', format='png', dpi=300, transparent=True)

    sst = np.linspace(273, 323, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=sst, sss=35, uwind=0, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Temperature')
    plt.plot(sst, TBH, label=r'T$_B^H$')
    plt.plot(sst, TBV, label=r'T$_B^V$')
    plt.xlabel('Sea Surface Temperature (K)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(290, 96, r'S: 35 psu, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('sst_spectrum.png', format='png', dpi=300, transparent=True)

    sss = np.linspace(30, 40, 100)
    TBV, TBH = o.get_quick_ocean_TB(frequency=1e3, sst=300, sss=sss, uwind=0, vwind=0, gal_max=0, lat=0, angle=20)

    plt.figure()
    plt.title(r'Ocean Emission with Salinity')
    plt.plot(sss, TBH, label=r'T$_B^H$')
    plt.plot(sss, TBV, label=r'T$_B^V$')
    plt.xlabel('Sea Surface Salinity (psu)')
    plt.ylabel('Brightness Temperature (K)')
    plt.grid(b=True)
    plt.text(32, 95, r'T: 300K, F: 1 GHz, $\theta$: 20$^\circ$')
    plt.legend()
    plt.savefig('sss_spectrum.png', format='png', dpi=300, transparent=True)

def plot_weighting_function():
    res = 0.2
    ghz = np.array([23.8, 31.4, 50.3, 52.8, 53.596, 54.40, 54.94, 55.50, 57.29, 57.61, 89])
    atm = atmosphere.atmosphere()
    angle = np.radians(40)
    t = np.array([300.])
    p = np.array([1e5])
    prwtr = np.array([0])
    lwtr = np.array([0])
    T, P, dens, wv, lw = atm.isa_profiles(t, p, prwtr, lwtr, res=res)
    tau, tbar = atm.mrtm(ghz, P[::-1], T[::-1], wv[::-1], lw[::-1])
    transup = np.exp(-1 * np.cumsum(tau / np.cos(angle), axis=0))
    wup = -np.gradient(transup, axis=0)
    z = np.arange(0, 100 - res, res)[::-1]
    cmap = plt.cm.viridis(np.linspace(0, 1, len(ghz)))
    for i in range(len(ghz)):
        plt.plot(wup[:, i], z, color=cmap[i], label='%.2f GHz' % ghz[i])
    plt.legend()
    plt.xlabel('Weighting Function')
    plt.ylabel('Altitude')
    plt.xlim(0, np.max(wup) + 0.2 * np.max(wup))
    plt.ylim(0, 110)
    plt.legend()
    plt.tight_layout()
    plt.savefig('weight.png', dpi=300, transparent=True)

def plot_spacecraft_tracks():
    s = sc.spacecraft()
    epochs = np.arange(0, 5 * 24 * 60 * 60, 2)
    s.write_tle_kernels(inclination=np.radians(98.12), height=680e3, look_angle=40, start_epoch=epochs[0], end_epoch=epochs[-1] + 1)
    pos, times = spice.spkpos('-999', epochs, 'ITRF93', 'NONE', '399')
    ll_arr = np.array([spice.reclat(x) for x in pos])
    # spoint = np.array([spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'LT+S', '-999', 'SPACECRAFT', point[x])[0] for x in range(0, len(epochs))])
    splist = []
    for x in range(0, len(epochs)):
        try:
            spoint = spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'NONE', '-999', 'RADIOMETER', np.array([1, 0, 0]))
        except spice.stypes.NotFoundError:
            spoint = [np.array([1, 0, 0]), 0]
        splist.append(spoint[0])
        pos, light = spice.spkpos('-999', epochs[x], 'ITRF93', 'LT+S', '399')
        pp = spice.reclat(pos)
        # print('SPK Lat: %f' % np.degrees(pp[2]))
        # print('SPK Lon: %f' % np.degrees(pp[1]))
        # print(spoint[0])
        # pp = spice.reclat(spoint[0])
        # print('CK Lat: %f' % np.degrees(pp[2]))
        # print('CK Lon: %f' % np.degrees(pp[1]))
    ll_parr = np.array([spice.reclat(x) for x in splist])
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.plot(np.degrees(ll_arr[:, 1]), np.degrees(ll_arr[:, 2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='blue')
    ax.plot(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='red')
    ax.set_extent([-180, 180, -90, 90])

    # Revists
    # import cartopy.crs as ccrs
    # from skimage import filters
    # lonbins = np.arange(-180, 180 + 3, 3)
    # latbins = np.arange(-90, -30 + 1, 1)
    # lats = np.degrees(ll_parr[:, 2])
    # lons = np.degrees(ll_parr[:, 1])
    # res, lonb, latb = np.histogram2d(lons, lats, bins=[lonbins, latbins], density=False)
    # gi = filters.gaussian(res.T, sigma=2)
    # ax = plt.subplot(1, 1, 1, projection=ccrs.SouthPolarStereo())
    # plt.pcolormesh(lonb, latb, gi / np.max(gi.flatten()), transform=ccrs.PlateCarree())
    # plt.colorbar()
    # ax.coastlines()
    # ax.gridlines(color='k', linestyle=':')
    # ax.set_extent([-180, 180, -90, -60], crs=ccrs.PlateCarree())

    return ll_parr

def visual_reference(epoch):
    s = sc.spacecraft()
    height = 700e3
    s.write_tle_kernels(inclination=np.radians(80), height=height)

    fig = plt.figure(figsize=(10, 20))
    ax = fig.add_subplot(211, projection='3d')

    # Plot Earth
    u = np.linspace(0, 2 * np.pi, 500)
    v = np.linspace(0, np.pi, 500)
    rad = s.earth_mean_radius / 1e3
    x = rad * np.outer(np.cos(u), np.sin(v))
    y = rad * np.outer(np.sin(u), np.sin(v))
    z = rad * np.outer(np.ones(np.size(u)), np.cos(v))
    ax.plot_wireframe(x, y, z, color='black', alpha=0.4)
    pos, times = spice.spkpos('-999', epoch, 'ITRF93', 'NONE', '399')
    pos_norm = pos * (rad / np.linalg.norm(pos))
    ax.scatter(pos[0], pos[1], pos[2], color='blue')
    ax.quiver(0, 0, 0, pos_norm[0], pos_norm[1], pos_norm[2], arrow_length_ratio=0.1, color='blue')

    pos2, times = spice.spkpos('399', epoch, 'SPACECRAFT', 'NONE', '-999')
    mat = spice.pxform('SPACECRAFT', 'ITRF93', epoch)
    pos2 = mat @ pos2
    pos2_norm = pos2 * ((height / 1e3) / np.linalg.norm(pos))
    ax.quiver(pos[0], pos[1], pos[2], pos2_norm[0], pos2_norm[1], pos2_norm[2], color='red')

    try:
        spoint = spice.sincpt('ELLIPSOID', 'EARTH', epoch, 'ITRF93', 'NONE', '-999', 'SPACECRAFT', np.array([1, 0, 0]))[0]
        ax.scatter(spoint[0], spoint[1], spoint[2], color='green')
        ll_arr2 = spice.reclat(spoint)
        print("Lon/Lat SPOINT: %f, %f" % (np.degrees(ll_arr2[1]), np.degrees(ll_arr2[2])))

    except:
        ll_arr2 = np.array([1, 0, 0])

    ll_arr = spice.reclat(pos)
    ax2 = fig.add_subplot(212, projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.plot(np.degrees(ll_arr[1]), np.degrees(ll_arr[2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='blue')
    ax2.plot(np.degrees(ll_arr2[1]), np.degrees(ll_arr2[2]), transform=ccrs.PlateCarree(), linestyle='none', marker='.', color='green')
    ax2.set_extent([-180, 180, -90, 90])
    print("Lon/Lat SUB: %f, %f" % (np.degrees(ll_arr[1]), np.degrees(ll_arr[2])))

def plot_spacecraft_temps():
    o = ocean.ocean()
    s = sc.spacecraft()
    s.write_tle_kernels(inclination=np.radians(80), height=700e3, angle=40)
    epochs = np.arange(0, 1 * 60 * 60, 1)  # np.arange(0, 1 * 24 * 60 * 60, 1 * 60)
    splist = []
    for x in range(0, len(epochs)):
        try:
            spoint = spice.sincpt('ELLIPSOID', 'EARTH', epochs[x], 'ITRF93', 'NONE', '-999', 'RADIOMETER', np.array([1, 0, 0]))
        except spice.stypes.NotFoundError:
            spoint = [np.array([1, 0, 0]), 0]
        splist.append(spoint[0])
        pos, light = spice.spkpos('-999', epochs[x], 'ITRF93', 'LT+S', '399')
        pp = spice.reclat(pos)
        print('SPK Lat: %f' % np.degrees(pp[2]))
        print('SPK Lon: %f' % np.degrees(pp[1]))
        print(spoint[0])
        pp = spice.reclat(spoint[0])
        print('CK Lat: %f' % np.degrees(pp[2]))
        print('CK Lon: %f' % np.degrees(pp[1]))
    ll_parr = np.array([spice.reclat(x) for x in splist])
    llat, llon = np.meshgrid(np.degrees(ll_parr[:, 2]), np.degrees(ll_parr[:, 1]))
    TBV, TBH, U, V = o.get_ocean_TB(1e3, llat, llon, theta=40)  # Placeholder for true angle calc

    plt.figure(1)
    ax = plt.axes(projection=ccrs.PlateCarree())
    ax.coastlines()
    ax.scatter(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), c=np.diag(TBV[0, :, :]), cmap='viridis', transform=ccrs.PlateCarree(), s=1)
    # ax.colorbar()

    ax.set_extent([-180, 180, -90, 90])
    plt.savefig('TBV2.pdf', format='pdf', dpi=300)

    plt.figure(2)
    ax2 = plt.axes(projection=ccrs.PlateCarree())
    ax2.coastlines()
    ax2.scatter(np.degrees(ll_parr[:, 1]), np.degrees(ll_parr[:, 2]), c=np.diag(TBH[0, :, :]), cmap='viridis', transform=ccrs.PlateCarree(), s=1)
    # ax.colorbar()

    ax2.set_extent([-180, 180, -90, 90])
    plt.savefig('TBH2.pdf', format='pdf', dpi=300)


from typing import List, Set, Tuple

from aoc.utils import get_input

AllergenEntry = Tuple[Set[str], Set[str]]
AllergenMap = List[AllergenEntry]

def parse_food(food: str) -> AllergenEntry:
    ingredients_raw, _, allergens_raw = food.partition(' (contains ')
    ingredients = set(ingredients_raw.split())
    allergens = set(allergens_raw[:-1].split(', '))
    return allergens, ingredients

def find_unsafe_ingredients(allergen_map: AllergenMap) -> Set[str]:
    by_allergen = {}
    for allergens, ingredients in allergen_map:
        for allergen in allergens:
            if allergen not in by_allergen:
                by_allergen[allergen] = set(ingredients)
            else:
                by_allergen[allergen].intersection_update(ingredients)
    return set([ingredient
                for ingredients in by_allergen.values()
                for ingredient in ingredients])

def solve_part_one(ingredients_raw: str) -> int:
    allergen_map = [parse_food(food) for food in ingredients_raw.splitlines()]
    unsafe = find_unsafe_ingredients(allergen_map)
    all_ingredients = [ingredient
                       for _, ingredients in allergen_map
                       for ingredient in ingredients]
    safe = set(all_ingredients).symmetric_difference(unsafe)
    return sum([all_ingredients.count(ingredient) for ingredient in safe])

if __name__ == "__main__":
    ingredients_raw = get_input(2020, 21)
    result = solve_part_one(ingredients_raw)
    print(result)


import re
import collections

from enum import Enum

from ydk._core._dm_meta_info import _MetaInfoClassMember, _MetaInfoClass, _MetaInfoEnum
from ydk.types import Empty, YList, YLeafList, DELETE, Decimal64, FixedBitsDict
from ydk._core._dm_meta_info import ATTRIBUTE, REFERENCE_CLASS, REFERENCE_LIST, REFERENCE_LEAFLIST,     REFERENCE_IDENTITY_CLASS, REFERENCE_ENUM_CLASS, REFERENCE_BITS, REFERENCE_UNION, ANYXML_CLASS

from ydk.errors import YPYError, YPYModelError
from ydk.providers._importer import _yang_ns
_meta_table = {
    'VlanModeTypeEnum' : _MetaInfoEnum('VlanModeTypeEnum', 'ydk.models.openconfig.openconfig_vlan',
        {
            'ACCESS':'ACCESS',
            'TRUNK':'TRUNK',
        }, 'openconfig-vlan', _yang_ns._namespaces['openconfig-vlan']),
    'Vlans.Vlan.Config.StatusEnum' : _MetaInfoEnum('StatusEnum', 'ydk.models.openconfig.openconfig_vlan',
        {
            'ACTIVE':'ACTIVE',
            'SUSPENDED':'SUSPENDED',
        }, 'openconfig-vlan', _yang_ns._namespaces['openconfig-vlan']),
    'Vlans.Vlan.Config' : {
        'meta_info' : _MetaInfoClass('Vlans.Vlan.Config',
            False,
            [
            _MetaInfoClassMember('name', ATTRIBUTE, 'str' , None, None,
                [], [],
                '''                Interface VLAN name.
                ''',
                'name',
                'openconfig-vlan', False),
            _MetaInfoClassMember('status', REFERENCE_ENUM_CLASS, 'StatusEnum' , 'ydk.models.openconfig.openconfig_vlan', 'Vlans.Vlan.Config.StatusEnum',
                [], [],
                '''                Admin state of the VLAN
                ''',
                'status',
                'openconfig-vlan', False),
            _MetaInfoClassMember('vlan-id', ATTRIBUTE, 'int' , None, None,
                [('1', '4094')], [],
                '''                Interface VLAN id.
                ''',
                'vlan_id',
                'openconfig-vlan', False),
            ],
            'openconfig-vlan',
            'config',
            _yang_ns._namespaces['openconfig-vlan'],
        'ydk.models.openconfig.openconfig_vlan'
        ),
    },
    'Vlans.Vlan.State.StatusEnum' : _MetaInfoEnum('StatusEnum', 'ydk.models.openconfig.openconfig_vlan',
        {
            'ACTIVE':'ACTIVE',
            'SUSPENDED':'SUSPENDED',
        }, 'openconfig-vlan', _yang_ns._namespaces['openconfig-vlan']),
    'Vlans.Vlan.State' : {
        'meta_info' : _MetaInfoClass('Vlans.Vlan.State',
            False,
            [
            _MetaInfoClassMember('member-ports', REFERENCE_LEAFLIST, 'str' , None, None,
                [], [],
                '''                List of current member ports including access ports
                and trunk ports that support this vlan
                ''',
                'member_ports',
                'openconfig-vlan', False),
            _MetaInfoClassMember('name', ATTRIBUTE, 'str' , None, None,
                [], [],
                '''                Interface VLAN name.
                ''',
                'name',
                'openconfig-vlan', False),
            _MetaInfoClassMember('status', REFERENCE_ENUM_CLASS, 'StatusEnum' , 'ydk.models.openconfig.openconfig_vlan', 'Vlans.Vlan.State.StatusEnum',
                [], [],
                '''                Admin state of the VLAN
                ''',
                'status',
                'openconfig-vlan', False),
            _MetaInfoClassMember('vlan-id', ATTRIBUTE, 'int' , None, None,
                [('1', '4094')], [],
                '''                Interface VLAN id.
                ''',
                'vlan_id',
                'openconfig-vlan', False),
            ],
            'openconfig-vlan',
            'state',
            _yang_ns._namespaces['openconfig-vlan'],
        'ydk.models.openconfig.openconfig_vlan'
        ),
    },
    'Vlans.Vlan' : {
        'meta_info' : _MetaInfoClass('Vlans.Vlan',
            False,
            [
            _MetaInfoClassMember('vlan-id', ATTRIBUTE, 'int' , None, None,
                [('1', '4094')], [],
                '''                references the configured vlan-id
                ''',
                'vlan_id',
                'openconfig-vlan', True),
            _MetaInfoClassMember('config', REFERENCE_CLASS, 'Config' , 'ydk.models.openconfig.openconfig_vlan', 'Vlans.Vlan.Config',
                [], [],
                '''                Configuration parameters for VLANs
                ''',
                'config',
                'openconfig-vlan', False),
            _MetaInfoClassMember('state', REFERENCE_CLASS, 'State' , 'ydk.models.openconfig.openconfig_vlan', 'Vlans.Vlan.State',
                [], [],
                '''                State variables for VLANs
                ''',
                'state',
                'openconfig-vlan', False),
            ],
            'openconfig-vlan',
            'vlan',
            _yang_ns._namespaces['openconfig-vlan'],
        'ydk.models.openconfig.openconfig_vlan'
        ),
    },
    'Vlans' : {
        'meta_info' : _MetaInfoClass('Vlans',
            False,
            [
            _MetaInfoClassMember('vlan', REFERENCE_LIST, 'Vlan' , 'ydk.models.openconfig.openconfig_vlan', 'Vlans.Vlan',
                [], [],
                '''                Configured VLANs keyed by id
                ''',
                'vlan',
                'openconfig-vlan', False),
            ],
            'openconfig-vlan',
            'vlans',
            _yang_ns._namespaces['openconfig-vlan'],
        'ydk.models.openconfig.openconfig_vlan'
        ),
    },
}
_meta_table['Vlans.Vlan.Config']['meta_info'].parent =_meta_table['Vlans.Vlan']['meta_info']
_meta_table['Vlans.Vlan.State']['meta_info'].parent =_meta_table['Vlans.Vlan']['meta_info']
_meta_table['Vlans.Vlan']['meta_info'].parent =_meta_table['Vlans']['meta_info']


#!/usr/bin/env python3
# rsyslog produces raw stats in a log file in either @CEE or plain JSON.
# E.g.
# `Mon Jul  1 15:31:19 2019: { "name": "imudp(*:10514)", "origin": "imudp", "submitted": 100000 }`
# `Mon Jul  1 15:31:19 2019: { "name": "resource-usage", "origin": "impstats", "utime": 607857, "stime": 630538, "maxrss": 4504, "minflt": 532, "majflt": 0, "inblock": 0, "oublock": 50768, "nvcsw": 139802, "nivcsw": 16, "openfiles": 14 }``

import argparse
import re
import io
import sys
import warnings
import datetime
import json
import collections
import statistics

def datetimes_to_iso(o):
  """
  convert datetime.datetime instances into string representations
  handle some types of collections by recursively walking keys and/or values in a dict or list
  helps avoid json.dumps() 'TypeError: keys must be str, int, float, bool or None, not datetime.datetime'
  """
  if isinstance(o, datetime.datetime):
    return o.isoformat()
  if isinstance(o, list):
    return [datetimes_to_iso(i) for i in o]
  if isinstance(o, dict):
    return {datetimes_to_iso(k): datetimes_to_iso(v) for (k, v) in o.items()}
  if isinstance(o, tuple):
    return tuple(datetimes_to_iso(i) for i in o)
  return o

def prune_none_and_empty(d):
  """
  Remove keys that have either null values, empty strings or empty arrays
  See: https://stackoverflow.com/a/27974027/5472
  """
  if isinstance(d, list):
    return [v for v in (prune_none_and_empty(v) for v in d) if v]
  if isinstance(d, dict):
    return {k: v for k, v in ((k, prune_none_and_empty(v)) for k, v in d.items()) if v}
  return d

parser = argparse.ArgumentParser(description='Process results from rsyslog impstats in JSON format.')
parser.add_argument('-i', '--input-rsyslog-pstats-file', default='-', help='defaults to \'-\' which is <stdout>')
parser.add_argument('-o', '--output-summary-json-file', default='-', help='defaults to \'-\' which is <stdout>')
parser.add_argument('-a', '--aggregate-stats', action='store_true',  help='show overall statistics grouped per metric in the \'agg_stats\' key')
parser.add_argument('-v', '--show-values', action='store_true',  help='list the metric values within the \'agg_stats\' key')
parser.add_argument('-0', '--show-zero-values', action='store_true', help='Show zero or null values within the \'agg_stats\' key')
parser.add_argument('-s', '--original-stats', action='store_true', help='Output a \'original_stats\' key that includes the original stats. Always shows zero values.')
parser.add_argument('-n', '--no-flatten', action='store_true', help='Group stats per timestamp and don\'t flatten output')
parser.epilog='Summarised output is added at the end. The default is to print a timestamp for every stat (flattend) format.'
args = parser.parse_args()

# input
if args.input_rsyslog_pstats_file == '-':
  input_stream = sys.stdin
else:
  input_stream = open(args.input_rsyslog_pstats_file, 'r')

# output
if args.output_summary_json_file == '-':
  output_stream = sys.stdout
else:
  output_stream = open(args.output_summary_json_file, 'w')

METRICS_WHERE_SUM_HAS_MEANING = {
  # queue
  'msgs.received',
  'called.recvmsg',
  'discarded.nf',
  'discarded.full',
  'full',
  # inputs
  # imptcp & imudp
  'submitted',
  # imptcp
  'sessions.opened',
  'sessions.closed',
  'sessions.openfailed',
  'bytes.received',
  'bytes.decompressed',
  # imdup worker thread
  'called.recvmmsg',
  'called.recvmsg',
  'msgs.received',
  # rsyslog action metrics
  'processed',
  'failed',
  'suspended',
  'resumed',
  # rsyslog resource usage related to http://man7.org/linux/man-pages/man2/getrusage.2.html
  'utime',
  'stime',
  'minflt',
  'majflt',
  'inblock',
  'oublock',
  'nvcsw',
  'nivcsw'
}
# some metric names are generated dynamically and can only determined later
dynamic_metrics_where_sum_has_meaning = set()
JSON_ARRAY_OBJECT_START = '{['
JSON_ARRAY_OBJECT_END = ']}'
# Note:
# - The date header of the messages, e.g. `Mon Jul  1 15:31:19 2019:` is a fixed length of 24 char before `:`.
# - @cee format can optionally be in use
PATTERN = '^(?P<str_timestamp>.{24}): (?:@cee: )?(?P<json_stat>\{.*\})$'
re_extract = re.compile(PATTERN)

# Collections to process, aggregate and report results
stats_ordered = collections.OrderedDict()
results = {}

# Note, used regex in case other content is in the file, e.g. shared syslog file.
line_count = 0
for line in input_stream:
  line_count += 1
  matched = re_extract.match(line)
  # skip if match failed
  if not (matched and 'str_timestamp' in matched.groupdict() and 'json_stat' in matched.groupdict()):
    warnings.warn('Skipped line {} of {} because timestamp and/or JSON pattern did not match.'.format(line_count, input_stream.name))
    continue
  # parse
  stat_timestamp = datetime.datetime.strptime(matched['str_timestamp'], '%a %b %d %H:%M:%S %Y')
  json_stat = json.loads(matched['json_stat'])
  if stat_timestamp not in stats_ordered:
    stats_ordered[stat_timestamp] = []
    stats_ordered[stat_timestamp].append(json_stat)
  else:
    stats_ordered[stat_timestamp].append(json_stat)

if not stats_ordered:
  raise ValueError('Unable to match any rsyslog pstats in JSON or CEE format from {}'.format(input_stream.name))

# Process timestamps for each stat
if args.original_stats:
  if args.no_flatten:
    original_stats = stats_ordered
  else:
    original_stats = []
    for k_timestamp, v_stats in stats_ordered.items():
      #for stat in v_stats:
      #  stat['timestamp'] = k_timestamp
      #  stats.append(stat)
      # Create new dict in order cooerse timestamp as the first key
      for stat in v_stats:
        current_stat = {'timestamp': k_timestamp}
        current_stat.update(stat)
        original_stats.append(current_stat)
  results['original_stats'] = original_stats

# Re-organise and group values per stat name, origin and set of metrics in preperation for overall stats calculations later
grouped_stats = {}
for (k_timestamp, v_stats) in stats_ordered.items():
  for stat in v_stats:
    if stat['name'] not in grouped_stats:
      grouped_stats[stat['name']] = {'origin': stat['origin'], 'metrics': {}}
    for k, v in stat.items():
      # only sum when values are numerics
      if isinstance(v, (int, float)):
        if k not in grouped_stats[stat['name']]['metrics']:
          grouped_stats[stat['name']]['metrics'][k] = {'values': {k_timestamp: v}}
        else:
          grouped_stats[stat['name']]['metrics'][k]['values'].update({k_timestamp: v})
      # process dynstats related items which groups items into values and flatten it into the way other stats are structured
      elif (stat['origin'] == 'dynstats.bucket' or stat['origin'] == 'dynstats.bucket') and k == 'values':
        assert isinstance(v, dict), 'dynstats.bucket object imported from JSON has unexpected structure'
        for dk, dv in v.items():
          if dk not in grouped_stats[stat['name']]['metrics']:
            dynamic_metrics_where_sum_has_meaning.add(dk)
            grouped_stats[stat['name']]['metrics'][dk] = {'values': {k_timestamp: dv}}
          else:
            grouped_stats[stat['name']]['metrics'][dk]['values'].update({k_timestamp: dv})

# Calculate stats from grouped metric values
agg_stats = grouped_stats
for (k_gstat, v_gstat) in grouped_stats.items():
  for (k_metric, v_metric) in v_gstat['metrics'].items():
    values_non_zero = prune_none_and_empty(v_metric['values'])
    agg_stats[k_gstat]['metrics'][k_metric].update({'count': len(v_metric['values'])})
    agg_stats[k_gstat]['metrics'][k_metric].update({'count_non_zero': len(values_non_zero)})
    agg_stats[k_gstat]['metrics'][k_metric].update({'min': min(v_metric['values'].values())})
    agg_stats[k_gstat]['metrics'][k_metric].update({'max': max(v_metric['values'].values())})
    agg_stats[k_gstat]['metrics'][k_metric].update({'mean': statistics.mean(v_metric['values'].values())})
    if args.show_zero_values:
      mean_non_zero, t_min, t_max, t_delta_s = None, None, None, None
    if values_non_zero:
      mean_non_zero = statistics.mean(values_non_zero.values())
      # min / max timestamp values assume values dict is still ordered by time
      t_min = list(values_non_zero.keys())[0]
      t_max = list(values_non_zero.keys())[-1]
      t_delta_s = (t_max - t_min).seconds
      agg_stats[k_gstat]['metrics'][k_metric].update({'mean_non_zero': mean_non_zero})
      agg_stats[k_gstat]['metrics'][k_metric].update({'timestamp_non_zero_min': t_min})
      agg_stats[k_gstat]['metrics'][k_metric].update({'timestamp_non_zero_max': t_max})
      agg_stats[k_gstat]['metrics'][k_metric].update({'time_delta_seconds_non_zero': t_delta_s})
    # summations for stats where summation makes sense
    if k_metric in METRICS_WHERE_SUM_HAS_MEANING or k_metric in dynamic_metrics_where_sum_has_meaning:
      agg_stats[k_gstat]['metrics'][k_metric].update({'sum': sum(v_metric['values'].values())})
    if args.show_values:
      if not args.show_zero_values:
        agg_stats[k_gstat]['metrics'][k_metric].update({'values': values_non_zero})
    else:
      del(agg_stats[k_gstat]['metrics'][k_metric]['values'])

if args.aggregate_stats:
  results['agg_stats'] = agg_stats
  t_start = list(stats_ordered.keys())[0]
  t_end = list(stats_ordered.keys())[-1]
  t_runtime_s = (t_end - t_start).seconds
  results['timestamp_start'] = t_start
  results['timestamp_end'] = t_end
  results['runtime_seconds'] = t_runtime_s

# wrap results in a container so it can be combined with outher json sources
results_with_prefix = {'rsyslog_pstats': results}

if output_stream.name == '<stdout>':
  output_stream.write(json.dumps(datetimes_to_iso(results_with_prefix), indent=2))
  output_stream.write('\n')
else:
  output_stream.write(json.dumps(datetimes_to_iso(results_with_prefix), separators=(',', ':')))

# Cleanup
if input_stream.name != '<stdin>':
  input_stream.close()
if output_stream.name != '<stdout>':
  output_stream.close()


#!/usr/bin/env python
#coding:utf-8
#time: 2016/3/16 16:13
__author__ = 'songhailong'
import time
def time_today():
    print(time.time())
    print(time.ctime())
    print(time.strftime("%Y%m%d%H%M%S",time.localtime()))
    print(time.strftime("%Y-%m-%d",time.localtime()))

def timestamp_datetime(value):
    format = '%Y-%m-%d %H:%M:%S'
    # value为传入的值为时间戳(整形)，如：1332888820
    value = time.localtime(value)
    ## 经过localtime转换后变成
    ## time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=0)
    # 最后再经过strftime函数转换为正常日期格式。
    dt = time.strftime(format, value)
    return dt

def datetime_timestamp(dt):
     #dt为字符串
     #中间过程，一般都需要将字符串转化为时间数组
     time.strptime(dt, '%Y-%m-%d %H:%M:%S')
     ## time.struct_time(tm_year=2012, tm_mon=3, tm_mday=28, tm_hour=6, tm_min=53, tm_sec=40, tm_wday=2, tm_yday=88, tm_isdst=-1)
     #将"2012-03-28 06:53:40"转化为时间戳
     s = time.mktime(time.strptime(dt, '%Y-%m-%d %H:%M:%S'))
     return int(s)

if __name__ == '__main__':
    start=time.clock()
    d1 = datetime_timestamp('2016-06-10 22:30:00')
    d = datetime_timestamp('2016-06-10 23:00:00')
    print(d1,d)
    s = timestamp_datetime(1466331485)
    print(s)
    end=time.clock()


from datetime import datetime
import time
import sys
counter_compare = 0
counter_replace = 0

server_file = sys.argv[1]

handle = open(server_file, "r")
Heap_array = handle.read()
handle.close()
print(Heap_array)
Heap_array = Heap_array.split()
print(Heap_array)
for i in range(0, len(Heap_array)):
    Heap_array[i] = int(Heap_array[i])
print(type(Heap_array))
print(Heap_array)
print("Array before shell", Heap_array )

start_time = datetime.now()
s = ''' '''
def heapify(arr, n, i):
    # Find largest among root and children
    largest = i
    l = 2 * i + 1
    r = 2 * i + 2

    if l < n and arr[i] < arr[l]:
        largest = l

    if r < n and arr[largest] < arr[r]:
        largest = r

    # If root is not largest, swap with largest and continue heapifying
    if largest != i:
        arr[i],arr[largest] = arr[largest],arr[i]
        heapify(arr, n, largest)

def heapSort(arr):
    n = len(arr)

    # Build max heap
    for i in range(n, 0, -1):
        heapify(arr, n, i)

    for i in range(n-1, 0, -1):
        # swap
        arr[i], arr[0] = arr[0], arr[i]

        #heapify root element
        heapify(arr, i, 0)

arr = Heap_array
heapSort(arr)
print('Array after shaker', Heap_array )
print(" Lenght:", len(Heap_array))
print("Time:")
print(datetime.now() - start_time)
for i in range(0, len(Heap_array)):
    shell_array[i] = str(Heap_array[i])
result =''.join(Heap_array)
handle = open("server_outcoming.txt", "w")
handle.write(result)
handle.close()


import numpy as np
import pytest

from neurobiases import TriangularModel, utils
from neurobiases.em_utils import marginal_log_likelihood_linear_tm_wrapper
from numpy.testing import assert_allclose, assert_raises

def test_random_state():
    """Tests that the random seeds correctly set the coupling and tuning
    parameters."""
    tm1 = TriangularModel(coupling_rng=1234, tuning_rng=4321)
    tm2 = TriangularModel(coupling_rng=1234, tuning_rng=9876)
    tm3 = TriangularModel(coupling_rng=9876, tuning_rng=4321)
    tm4 = TriangularModel(coupling_rng=9876, tuning_rng=9876)

    # Random seed for parameters
    assert_allclose(tm1.a.ravel(), tm2.a.ravel())
    assert_raises(AssertionError, assert_allclose, tm1.b.ravel(), tm2.b.ravel())
    assert_allclose(tm3.a.ravel(), tm4.a.ravel())
    assert_raises(AssertionError, assert_allclose, tm3.b.ravel(), tm4.b.ravel())
    assert_allclose(tm1.b.ravel(), tm3.b.ravel())
    assert_allclose(tm1.B.ravel(), tm3.B.ravel())
    assert_raises(AssertionError, assert_allclose, tm1.a.ravel(), tm3.a.ravel())
    assert_allclose(tm2.b.ravel(), tm4.b.ravel())
    assert_allclose(tm2.B.ravel(), tm4.B.ravel())
    assert_raises(AssertionError, assert_allclose, tm2.a.ravel(), tm4.a.ravel())

    # Random seed for data
    X1, Y1, y1 = tm1.generate_samples(n_samples=50, rng=2332)
    X2, Y2, y2 = tm1.generate_samples(n_samples=50, rng=2332)
    assert_allclose(X1, X2)
    assert_allclose(Y1, Y2)
    assert_allclose(y1, y2)

def test_sparsity():
    """Test that the sparsity inputs correctly set the number of non-zero
    parameters."""
    N = 20
    coupling_sparsity = 0.25
    M = 40
    tuning_sparsity = 0.1
    tm = TriangularModel(N=N, coupling_sparsity=coupling_sparsity,
                         M=M, tuning_sparsity=tuning_sparsity,
                         coupling_rng=1234,
                         tuning_rng=4321)
    assert np.count_nonzero(tm.a.ravel() == 0) == int(N * coupling_sparsity)
    assert np.count_nonzero(tm.b.ravel() == 0) == int(M * tuning_sparsity)

def test_neural_variance():
    """Tests that the analytic expressions for the variance of the neural
    activity are correctly calculated."""
    tm1 = TriangularModel(parameter_design='direct_response', N=10, M=20, K=2)
    tm2 = TriangularModel(parameter_design='basis_functions', N=10, M=20, K=2)

    for tm in [tm1, tm2]:
        # Generate samples
        X, Y, y = tm.generate_samples(n_samples=100000, return_noise=False)

        # Non-target signal variance
        non_target_signal = np.dot(X, tm.B)
        empirical_variance = np.var(non_target_signal, axis=0)
        true_variance = tm.non_target_signal_variance(limits=(0, 1))
        assert_allclose(true_variance, empirical_variance, rtol=0.1)

        # Non-target variance
        empirical_variance = np.var(Y, axis=0)
        true_variance = tm.non_target_variance(limits=(0, 1))
        assert_allclose(true_variance, empirical_variance, rtol=0.1)

        # Target signal variance
        target_signal = np.dot(X, tm.b) + np.dot(Y, tm.a)
        empirical_variance = np.var(target_signal)
        true_variance = tm.target_signal_variance(limits=(0, 1))
        assert_allclose(true_variance, empirical_variance, rtol=0.1)

        # Target neuron variance
        empirical_variance = np.var(y)
        true_variance = tm.target_variance(limits=(0, 1))
        assert_allclose(true_variance, empirical_variance, rtol=0.1)

def test_snr():
    """Tests that the total variance of the neural activity reflects the
    signal-to-noise ratio."""
    tm1 = TriangularModel(parameter_design='direct_response', N=10, M=20, K=2)
    tm2 = TriangularModel(parameter_design='basis_functions', N=10, M=20, K=2)

    for tm in [tm1, tm2]:
        snr = tm.noise_kwargs['snr']
        # Generate samples
        X, Y, y = tm.generate_samples(n_samples=100000, return_noise=False)

        # Non-target neural activity
        true_signal_variance = tm.non_target_signal_variance(limits=(0, 1))
        true_total_variance = (1 + 1. / snr) * true_signal_variance
        empirical_variance = np.var(Y, axis=0)
        assert_allclose(true_total_variance, empirical_variance, rtol=0.1)

        # Target neural activity
        true_signal_variance = tm.target_signal_variance(limits=(0, 1))
        true_noise_variance = true_signal_variance / snr
        noise = y - np.dot(X, tm.b) - np.dot(Y, tm.a)
        empirical_noise_variance = np.var(noise)
        assert_allclose(true_noise_variance, empirical_noise_variance, rtol=0.1)

def test_noise_clusters():
    """Test that clustered noise correlations are generated correctly."""
    corr_cluster = 0.3
    # One latent factor
    tm = TriangularModel(parameter_design='direct_response',
                         K=1,
                         corr_cluster=corr_cluster)
    # Compare true and generated correlation matrices
    corr = utils.cov2corr(tm.get_noise_cov())
    true_corr = corr_cluster * np.ones((tm.N + 1, tm.N + 1))
    np.fill_diagonal(true_corr, np.ones(tm.N + 1))
    assert_allclose(corr, true_corr)

    # Three latent factors
    tm = TriangularModel(parameter_design='direct_response',
                         N=6,
                         K=3,
                         corr_cluster=corr_cluster)

    # compare true and generated correlation matrices
    corr = utils.cov2corr(tm.get_noise_cov())
    true_corr = np.array([
        [1, 0, 0, corr_cluster, corr_cluster, 0, 0],
        [0, 1, corr_cluster, 0, 0, 0, 0],
        [0, corr_cluster, 1, 0, 0, 0, 0],
        [corr_cluster, 0, 0, 1, corr_cluster, 0, 0],
        [corr_cluster, 0, 0, corr_cluster, 1, 0, 0],
        [0, 0, 0, 0, 0, 1, corr_cluster],
        [0, 0, 0, 0, 0, corr_cluster, 1]
    ])
    assert_allclose(corr, true_corr, atol=1e-6)

def test_identifiability():
    """Tests that the identifiability transform leaves the likelihood
    unchanged."""
    tm1 = TriangularModel(parameter_design='direct_response', N=10, M=20, K=2)
    tm2 = TriangularModel(parameter_design='basis_functions', N=10, M=20, K=2)

    for tm in [tm1, tm2]:
        # Generate samples
        X, Y, y = tm.generate_samples(n_samples=10000, return_noise=False)
        # Likelihood with original parameters
        pre_ll = marginal_log_likelihood_linear_tm_wrapper(
            X=X, Y=Y, y=y, tm=tm
        )
        # Identifiability transform
        delta = np.random.normal(loc=0, scale=5.0, size=tm.K)
        tm.identifiability_transform(delta)
        # Likelihood with transfored parameters
        post_ll = marginal_log_likelihood_linear_tm_wrapper(
            X=X, Y=Y, y=y, tm=tm
        )
        assert_allclose(pre_ll, post_ll)

def test_identifiability_warning():
    """Tests that a warning is received if the model is not identifiable."""
    # Check that identifiability warning is raised
    with pytest.warns(RuntimeWarning) as record:
        TriangularModel(coupling_sparsity=0., tuning_sparsity=0., K=3)
    assert len(record) == 1
    # Check that identifiability warning is not raised
    with pytest.warns(None) as record:
        TriangularModel(coupling_sparsity=0.5, tuning_sparsity=0.5, K=3)
    assert len(record) == 0


SC_NAMES = ["SB6_P0", "SB6_P1", "SB6_P2", "SB6_P3", "SB6_P4", "SB6_P5"]
DATA_FLD = "static/data"
RUNTIME_FLD = "static/runtime"
MUSIC_ROOT = "mp3s/music"
SC_CONFS = f"{DATA_FLD}/cards-config.json"
MAX_PIDS = 32768

PRC_NAME_SB6_SERVER = "sb6server"
PRC_NAME_SB6_MONITOR = "sb6monitor"


import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

import main

PATH = "/home/www/uploads"

def on_created(event):
    main.main(f"{PATH}/config.cfg")

if __name__ == "__main__":
    event_handler = FileSystemEventHandler()

    event_handler.on_created = on_created

    observer = Observer()
    observer.schedule(event_handler, PATH, recursive=True)
    observer.start()

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


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

from header import *
import optparse
import sys
import os
import random

def run():

	parser = optparse.OptionParser('main.py')

	# Target option
	parser.add_option("-d", dest="path", metavar="target dir path", help="target's Directory path")
	parser.add_option("-f", dest="file", metavar="target json file name", help="target Json file name")

	# dummy option
	parser.add_option("-t", dest="thread", metavar="thread num", type='int', help="Threads num")

	# pulse time option
	parser.add_option("-s", dest="steady", metavar="sec", type='float', help="input : float - steady pulse time (sec)")
	parser.add_option("-r", dest="random", metavar="from to", type='int', nargs=2, help="input : int ,int - random pulse time range from (int) to (int)")
	parser.add_option("-g", dest="gauss", metavar="avg sd", type='int', nargs = 2, help="input : int, int - Average, Standard Deviation / According to gaussian distributions")

	# loop option
	parser.add_option("-l", dest="loop", metavar="loop num", type='int', help="input : -1(infinite loop), n(Packet Scenario repeat")

	(options, args) = parser.parse_args()
	# Need Modi
	# 입력인자가 없다면 종료
	if len(sys.argv)-1 == 0:
		printe(parser.usage)
		exit(1)

	# Make Class Packet and Store Information
	# 파일을 읽어서 패킷 리스트로 읽음
	PKT_List = ReadJsonFile(options)

	# Find Total Packet Number in Packet List
	total_pkt_num = 0
	for pkt in PKT_List:
		total_pkt_num += pkt.Data_part.pps

	# Find Loop Count (need exception)
	loopCount = options.loop

	'''
	# check loop num
	if options.loop == None :
		printe("insert loop option")
		exit(1)
	'''

	######### Insert Loop Here #########

	# Identify Dummy mode or Pulse time mode in this Scenario
	ThOrTime = identifyMode(options, total_pkt_num)

	# Verification and Convertion
	for p in PKT_List :
		veri_type_checker(p.Data_part.DataField)
		RandToValue(p.Data_part.DataField)
		Converter(p.Data_part.DataField)
		veri_range_checker(p.Data_part.DataField)

	# Transmission  Here

	#for pkt in PKT_List :
	#	pkt.print_packet_info()

	# Print Result
	print(" * Total Packet Number : " + str(total_pkt_num))
	if type(ThOrTime) == int :
		print(" *     Tread Number    : " + str(ThOrTime))
	elif type(ThOrTime) == list :
		print(" *     Time Table      : " + str(ThOrTime))
	print(" *     Loop   Count    : " + str(loopCount))

if __name__ == "__main__":
	run()


from PIL import Image
import pytesseract
# image = Image.open('./破解验证码/2.jpg')
image = Image.open('./破解验证码/asd.gif')
image = image.convert('L')

def binarizing(img, threshold):
    # threshold表示阀值
    pixdata = img.load()
    w, h = img.size
    for y in range(h):
        for x in range(w):
            if pixdata[x, y] < threshold:
                pixdata[x, y] = 0
            else:
                pixdata[x, y] = 255
    return img

def depoint(img):
    # input: gray image
    pixdata = img.load()
    w, h = img.size
    for y in range(1, h - 1):
        for x in range(1, w - 1):
            count = 0
            if pixdata[x, y - 1] > 245:
                count = count + 1
            if pixdata[x, y + 1] > 245:
                count = count + 1
            if pixdata[x - 1, y] > 245:
                count = count + 1
            if pixdata[x + 1, y] > 245:
                count = count + 1
            if count > 2:
                pixdata[x, y] = 255
    return img

image = binarizing(image, 140)
image = depoint(image)
print(image.getbbox())
print(pytesseract.image_to_string(image))
print('chen')
image.show()


# 텐서보드를 사용해서 Projector를 구현할 때 오류가 있음
# 이 오류를 해결하기 위해서 작성해야 할 것
from torch.utils.tensorboard import SummaryWriter
import matplotlib.pyplot as plt
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
import src.utils.interface_file_io as file_io
import numpy as np
import os
import json

# import tensorflow as tf
import librosa
import tensorboard as tb
# tf.io.gfile = tb.compat.tensorflow_stub.io.gfile
# console: tensorboard --logdir=runs --bind_all
# # nohup tensorboard --logdir=runs --bind_all > /dev/null 2>&1
# nohup tensorboard --logdir=runs --host 0.0.0.0 > /dev/null 2>&1 &

def set_tensorboard_writer(name):
    writer = SummaryWriter(name) # 'runs/fashion_mnist_experiment_1'
    return writer

def inspect_model(writer, model, data):
    writer.add_graph(model, data)

def close_tensorboard_writer(writer):
    writer.close()

def add_dataset_figure(writer, dataloader, desc="Train", epoch=0):
    dataiter = iter(dataloader)
    waveform01, waveform02, _, _ = dataiter.next()
    fig = plt.figure()
    plt.plot(waveform01[0].t().numpy(), alpha=0.5)
    plt.plot(waveform02[0].t().numpy(), alpha=0.5)
    plt.title("sample waveform visualization")
    writer.add_figure('Visualize{}'.format(desc), fig, epoch)
    plt.close()

def visualization_dataset_by_byol(writer, dataloader, desc="Train", epoch=0):
    dataiter = iter(dataloader)
    waveform01, waveform02 = dataiter.next()
    fig = plt.figure()
    plt.plot(waveform01[0].t().numpy(), alpha=0.5)
    plt.plot(waveform02[0].t().numpy(), alpha=0.5)
    plt.title("sample waveform visualization")
    writer.add_figure('Visualize{}'.format(desc), fig, epoch)
    plt.close()
    # writer.add_audio('Visualize{}'.format(desc), waveform01[0], epoch, sample_rate=16000)

def add_dataset_figure_by_byol(writer, dataloader, desc="Train", epoch=0):
    dataiter = iter(dataloader)
    waveform01, waveform02 = dataiter.next()
    fig = plt.figure()
    plt.plot(waveform01[0].t().numpy(), alpha=0.5)
    plt.plot(waveform02[0].t().numpy(), alpha=0.5)
    plt.title("sample waveform visualization")
    writer.add_figure('Visualize{}'.format(desc), fig, epoch)
    plt.close()

def add_latent_heatmap(writer, data, title, desc, epoch):
    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    ax1.matshow(data)
    writer.add_figure('{}/{}'.format(title, desc), fig, epoch)
    plt.close()

def add_latents_heatmap(writer, output, title, desc, step):
    fig, axes = plt.subplots(1, 4)
    for i in range(4):
        axes[i].matshow(output[i], aspect='equal')  # , aspect='auto')
    writer.add_figure('{}/{}'.format(title, desc), fig, step)
    plt.close()

def add_confusion_matrix(writer, title, desc, step, label_num, targets, predicts):
    labels = np.arange(label_num)
    output = confusion_matrix(targets, predicts, labels=labels)
    norm_output = output / output.astype(np.float).sum(axis=1)

    fig = plt.figure()
    ax1 = fig.add_subplot(1, 1, 1)
    ax1.matshow(norm_output)
    xaxis = np.arange(len(labels))
    ax1.set_xticks(xaxis)
    ax1.set_yticks(xaxis)
    ax1.set_xticklabels(labels)
    ax1.set_yticklabels(labels)

    writer.add_figure('{}/{}'.format(title, desc), fig, step)
    plt.close()

def add_classification_matrix(config, epoch, writer, title, desc,step, label_num, targets, predicts):
    labels = list(map(str, list(np.arange(label_num))))
    out = classification_report(targets, predicts, target_names=labels, output_dict=True)
    base_directory = os.path.join(config['checkpoint_save_directory_path'], config['checkpoint_file_name'])
    file_path = os.path.join(base_directory,
                             config['checkpoint_file_name'] + "-model-best-epoch-{}-clf.json".format(epoch))
    if not os.path.exists(os.path.join(config['checkpoint_save_directory_path'], config['checkpoint_file_name'])):
        file_io.make_directory(os.path.join(config['checkpoint_save_directory_path'], config['checkpoint_file_name']))
    with open(file_path, 'w') as f:
        json.dump(out, f)

    x1 = np.arange(1, label_num * 2, 2)
    x2 = x1 + 0.5
    x3 = x1 + 1

    precision_value = []
    recall_value = []
    f1_value = []

    for data in labels:
        precision_value.append(out[data]['precision'])
        recall_value.append(out[data]['recall'])
        f1_value.append(out[data]['f1-score'])

    fig = plt.figure()
    plt.bar(x1, precision_value, color='r', width=0.5, label='precision')
    plt.bar(x2, recall_value, color='g', width=0.5, label='recall')
    plt.bar(x3, f1_value, color='b', width=0.5, label='fl-score')
    plt.xticks(x2, labels)
    plt.legend()

    writer.add_figure('{}/{}'.format(title, desc), fig, step)
    plt.close()

def add_classification_avg_matrix(writer, title, desc, step, label_num, targets, predicts):
    labels = np.arange(label_num)
    term_labels = ['macro avg', 'weighted avg']
    out = classification_report(targets, predicts, target_names=labels, output_dict=True)

    x1 = [1, 3]
    x2 = [1.5, 3.5]
    x3 = [2, 4]

    precision_value = []
    recall_value = []
    f1_value = []
    for data in term_labels:
        precision_value.append(out[data]['precision'])
        recall_value.append(out[data]['recall'])
        f1_value.append(out[data]['f1-score'])

    fig = plt.figure()
    plt.bar(x1, precision_value, color='r', width=0.5, label='precision')
    plt.bar(x2, recall_value, color='g', width=0.5, label='recall')
    plt.bar(x3, f1_value, color='b', width=0.5, label='fl-score')
    plt.xticks(x2, term_labels)
    plt.legend()

    writer.add_figure('{}/{}'.format(title, desc), fig, step)
    plt.close()


# Pokemon
import pandas as pd

# 创建一个字典
raw_data = {'name': ['Bulbasaru', 'Charmander', 'Squirtle', 'Caterpie'],
            'evolution': ['Ivysaru', 'Charmenleon', 'Wartotrtle', 'Metapod'],
            'type': ['grass', 'fire', 'water', 'bug'],
            'pokedex': ['yes', 'no', 'yes', 'no'],
            'hp': [45, 39, 44, 45]
            }

# 命名数据框
pokemon = pd.DataFrame(raw_data)

# 调整数据框列名的顺序为name, type, hp, evolution, pokedex
pokemon = pokemon[['name', 'type', 'hp', 'evolution', 'pokedex']]

# 插入地区属性
pokemon['place'] = ['park', 'street', 'lake', 'forest']

# 输出各列的数据类型
pokemon.dtypes


#!/usr/bin/env python3

outputDirectory='../2-tables.out'
import os,shutil
for directory in ('meta','content'):
	outputSubDirectory=os.path.join(outputDirectory,directory)
	if not os.path.exists(outputSubDirectory):
		os.makedirs(outputSubDirectory)
	for filename in os.listdir(directory):
		shutil.copy(
			os.path.join(directory,filename),
			outputSubDirectory
		)

import makeTablesFromCsv
import makeTablesFromOdf
import makeTablesFromXlsx

# currently broken and not used:
# import makeInvestmentTablesFromXlsx


# ---API list---
# top_n
# search
# recommend_item_cf
# recommend_user_cf

import flask
from flask import render_template, jsonify, request, make_response
from flask_cors import CORS
import pandas as pd
import numpy as np
import re
import jieba as jb
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.neighbors import NearestNeighbors
from scipy.sparse import csr_matrix
import json
import time

app = flask.Flask(__name__)
app.config["DEBUG"] = True
CORS(app, supports_credentials=True)

def readCSV():
    products = pd.read_csv('./products_join_categories.csv')
    products = products.loc[:, ~products.columns.str.contains('^Unnamed')]
    products.set_index( ['productId'] , inplace=True, drop=True )
    products = products.rename({'name': 'product_name'}, axis='columns')
    categories = pd.read_csv( './categories.csv')
    rating = pd.read_csv('./ratings_drop.csv' , usecols=[ 'userId' , 'productId' , 'rating'])
    rating.dropna(subset=["userId"], inplace = True)
    rating.dropna(subset=["rating"], inplace = True)
    products.dropna(subset=["product_name"], inplace = True)
    return products, categories , rating

def readCSVWord():
    product_lists = pd.read_csv( './product_lists_with_cut.csv').fillna('')
    top_20_words1 = pd.read_csv( './top_20_word1.csv', names = ['cut_name' , 'count'])
    top_20_words2 = pd.read_csv( './top_20_word2.csv', names = ['cut_name' , 'count'])
    top_20_words3 = pd.read_csv( './top_20_word3.csv', names = ['cut_name' , 'count'])
    product_lists.dropna(subset=["name"], inplace = True)
    return product_lists, top_20_words1, top_20_words2, top_20_words3

def processText(text, join_str = " ", array = False):
    text = str(text)
    if text.strip()=='':
        return ''
    r = '[’!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~]+'
    text = re.sub(r, '', text)
    # cut word, GitBub: https://github.com/fxsjy/jieba
    text = join_str.join([w for w in list(jb.cut(text)) if w !=' '])
    return text

def recommendations(text,num = 20):
    res = []
    ss = [processText(text, ",")]
    ss_vec = tfidf.transform(ss)
    cos_sim = cosine_similarity(ss_vec, tfidf_vec)
    arr =cos_sim[0]
    idxs=list(np.argsort(-arr)[:num])
    for idx in idxs:
        row = product_lists[product_lists.index==idx]
        productId = row.productId.values[0]
        name = row.cut_name.values[0]

        res.append({
            'productId' : str(productId),
            'product_name' : name.replace(" ", ""),
            'cat1' : str(products.loc[idx].cat1),
            'cat2' : str(products.loc[idx].cat2),
            'cat3' : str(products.loc[idx].cat3),
            'cat1_name' : products.loc[idx].cat1_name,
            'cat2_name' : products.loc[idx].cat2_name,
            'cat3_name' : products.loc[idx].cat2_name,
            'cos' : str(arr[idx])
        })
    return res

def filterRatingArray():
    global rating
    useRatingCount = rating['userId'].value_counts()
    ratingFiltered = rating[rating['userId'].isin(useRatingCount[useRatingCount >= 50 ].index)]
    productRatingCount = rating['productId'].value_counts()
    ratingFiltered = ratingFiltered[ratingFiltered['userId'].isin(productRatingCount[productRatingCount >= 100 ].index)]
    del useRatingCount
    del productRatingCount
    return ratingFiltered , rating

def findByKItemByTopKUsers(ratingFilteredPivotByUser,userId,distances,indices,k):
    global products
    prediction=0
    similarities = 1-distances.flatten()
    sum_wt = np.sum(similarities)
    wtd_sum = 0

    # all - user rated!
    notRatedItems = np.setdiff1d(ratingFilteredPivotByUser.columns.to_numpy() , ratingFilteredPivotByUser[ (ratingFilteredPivotByUser.index == userId) ].iloc[0].nonzero()[0] )
    simArray = np.array([similarities]).T * ratingFilteredPivotByUser.ix[indices.flatten()].filter(notRatedItems.tolist()).to_numpy()
    sortedIndex = (simArray.sum(axis=0)/sum_wt).argsort()[::-1][:10]
    result = []
    for index , productId in enumerate(sortedIndex.tolist()):
        result.append({
            'productId' : str(notRatedItems[productId]),
            'product_name' : products.loc[notRatedItems[productId]].product_name,
            'cat1' : str(products.loc[notRatedItems[productId]].cat1),
            'cat2' : str(products.loc[notRatedItems[productId]].cat2),
            'cat3' : str(products.loc[notRatedItems[productId]].cat3),
            'cat1_name' : products.loc[notRatedItems[productId]].cat1_name,
            'cat2_name' : products.loc[notRatedItems[productId]].cat2_name,
            'cat3_name' : products.loc[notRatedItems[productId]].cat2_name,
        })
    return result

def findTopKByItemCf(ratingFilteredPivot,itemId, k):
    #user based:
    ratingFilteredMatrix = csr_matrix(ratingFilteredPivot.values)
    model_knn = NearestNeighbors(metric = 'cosine', algorithm = 'brute')
    model_knn.fit(ratingFilteredMatrix)
    NearestNeighbors(algorithm='brute', leaf_size=30, metric='cosine', metric_params=None, n_jobs=1, n_neighbors=k, p=2, radius=1.0)

    #489000->productId
    queryIndex = ratingFilteredPivot.index.get_loc(itemId)
    # queryIndex = np.random.choice(ratingFilteredPivot.shape[0])
    distances, indices = model_knn.kneighbors(ratingFilteredPivot.iloc[queryIndex, :].values.reshape(1, -1), n_neighbors=k+1)
    return distances, indices

def findTopKByUserCf(ratingFilteredPivotByUser,userId):
    raitingFilteredMatrix = csr_matrix(ratingFilteredPivotByUser.values)
    model_knn = NearestNeighbors(metric = 'cosine', algorithm = 'brute')
    model_knn.fit(raitingFilteredMatrix)
    NearestNeighbors(algorithm='brute', leaf_size=30, metric='cosine', metric_params=None, n_jobs=1, n_neighbors=5, p=2, radius=1.0)
    #119->userId
    #114416 , 3400 , 17750 ,83601 => 0.7
    # 127020.0 => 0.3
    # 127579.0 => 0.3
    queryIndex = ratingFilteredPivotByUser.index.get_loc(userId)
    distances, indices = model_knn.kneighbors(ratingFilteredPivotByUser.iloc[queryIndex, :].values.reshape(1, -1), n_neighbors=6)
    return distances, indices

start_time = time.time()
print("Starting....")
products, categories, rating = readCSV()
product_lists, top_20_words1, top_20_words2, top_20_words3 = readCSVWord()

tfidf  = TfidfVectorizer(analyzer='word', ngram_range=(1, 1), min_df=0).fit(product_lists['cut_name'])
tfidf_vec = tfidf.transform(product_lists['cut_name'])

rating , ratingOrigin = filterRatingArray()
rating.drop_duplicates(subset=['userId', 'productId'], keep='first' , inplace =True )
ratingFilteredPivot = rating.pivot( index='productId' , columns='userId' , values="rating" ).fillna(0)
ratingFilteredPivotByUser = rating.pivot( index='userId' , columns='productId' , values="rating" ).fillna(0)
print("--- %s seconds ---" % (time.time() - start_time))

def makeResponse(result_text):
    response = make_response(jsonify(data=result_text))
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'OPTIONS,HEAD,GET,POST'
    response.headers['Access-Control-Allow-Headers'] = 'x-requested-with'
    return response

# tf-idf
@app.route('/top_n', methods=['GET'])
def top_n_word():
    n = request.args.get('n') or "1"
    if int(n) > 3:
        n = "1"
    str_n = "top_20_words" + n
    exec("global %s" % str_n)
    words = globals()[str_n].to_dict('index')
    res = [(v) for k, v in words.items()]
    return(makeResponse(res))
    #return render_template("aaa.html")

@app.route('/search', methods=['GET'])
def search():
    query_str = request.args.get('query_str')
    res = recommendations(query_str)
    return(makeResponse(res))

# knn
@app.route('/recommend_item_cf', methods=['GET'])
def recommendByItemCf():
    global ratingFilteredPivot
    global ratingOrigin
    global products
    itemId = int(request.args.get('itemid'))
    k = int(request.args.get('k') or '10')
    #489000

    topK = []
    if itemId in ratingFilteredPivot.index:
        distances, indices = findTopKByItemCf(ratingFilteredPivot,itemId,k)
        for i in range(0, len(distances.flatten())):
            topK.append({
                'product_name' : products.loc[ratingFilteredPivot.index[indices.flatten()[i]]].product_name,
                'cat1_name' : products.loc[ratingFilteredPivot.index[indices.flatten()[i]]].cat1_name
            })
    else:
        if products.loc[itemId].cat3 is None:
            tempDataSet = (products.cat2 == products.loc[itemId].cat2)
        else:
            tempDataSet = (products.cat3 == products.loc[itemId].cat3)
        temp = ratingOrigin[ratingOrigin.productId.isin(products.loc[tempDataSet].index) ].sort_values(by='rating', ascending=False)[:10].productId.tolist()
        for i in temp:
          topK.append({
              'product_name' : products.loc[i].product_name,
              'cat1_name' : products.loc[i].cat1_name
          })
    return makeResponse(topK)

@app.route('/recommend_user_cf', methods=['GET'])
def recommendByUserCf():
    global ratingFilteredPivotByUser
    global products
    userId = int(request.args.get('userid'))
    k = int(request.args.get('k') or '10')
    #7488
    distances, indices = findTopKByUserCf(ratingFilteredPivotByUser,userId)
    topK = findByKItemByTopKUsers(ratingFilteredPivotByUser,userId,distances,indices,k)
    return makeResponse(topK)

@app.route('/find_product', methods=['GET'])
def findProductById():
    global products
    global ratingOrigin
    productId = int(request.args.get('productId'))
    product = products.loc[productId]
    avgRating = ratingOrigin.loc

    return makeResponse(
    {
        'productId' : str(productId),
        'product_name' : products.loc[productId].product_name,
        'cat1' : str(products.loc[productId].cat1),
        'cat2' : str(products.loc[productId].cat2),
        'cat3' : str(products.loc[productId].cat3),
        'cat2_name' : products.loc[productId].cat2_name,
        'cat3_name' : products.loc[productId].cat2_name,
        'cat1_name' : products.loc[productId].cat1_name,
        'rating' : ratingOrigin[ratingOrigin.productId == productId].mean().rating
    })

app.run(host='0.0.0.0', port=5000)


# Importing OpenCV library

import cv2 as cv
#Reading images

# img1 = cv.imread('pics/cat1.jpeg')
# img2 = cv.imread('pics/dog2.jpeg')

# cv.imshow('dog', img2)

#Reading videos

capture_vid = cv.VideoCapture('videos/Cute Cat - 3092.mp4')

while True:
    isTrue, frame = capture_vid.read()
    cv.imshow('video', frame)

    if cv.waitKey(20) & 0xFF==ord('d'):
        break

capture.release()
cv.destroyAllWindows()


from django.urls import path
from django.urls.resolvers import URLPattern
from . import views

app_name = "tasks"

urlpatterns = [
    path("taskssearch/", views.TaskFilterView.as_view(), name="task_search"),
    path("projects/", views.ProjectList.as_view(), name="list_projects"),
    path("projects/create", views.ProjectCreateView.as_view(), name="create_project"),
    path("projects/<str:pk>", views.TaskListView.as_view(), name="list_task"),
    path(
        "projects/<str:pk>/update",
        views.ProjectUpdateView.as_view(),
        name="update_project",
    ),
    path(
        "projects/<str:pk>/delete",
        views.ProjectDeleteView.as_view(),
        name="delete_project",
    ),
    path(
        "projects/<str:pk>/tasks/create",
        views.TaskCreateView.as_view(),
        name="create_task",
    ),
    path(
        "projects/<str:pk>/tasks/<str:task_pk>/update",
        views.TaskUpdateView.as_view(),
        name="update_task",
    ),
    path(
        "projects/<str:pk>/tasks/<str:task_pk>/markascomplete",
        views.task_completed_view,
        name="mark_as_complete",
    ),
    path(
        "projects/<str:pk>/tasks/<str:task_pk>/delete",
        views.TaskDeleteView.as_view(),
        name="delete_task",
    ),
    path(
        "overduetasks/",
        views.TaskOverdueListView.as_view(),
        name="list_all_overdue_tasks",
    ),
    path(
        "overduetasks/<str:pk>",
        views.TaskOverdueListView.as_view(),
        name="list_overdue_tasks",
    ),
]


# coding=utf-8

from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import math
from unittest import TestCase
from util import misc
from util.geometry import Polygon, Rectangle

class TestMisc(TestCase):

    def test_load_text_file(self):
        filename = "./resources/lineReco1.txt"
        res = ["29,80;1321,88", "9,215;506,215;684,199;1139,206",
               "32,329;537,340;621,320;1322,331", "1399,99;2342,98;2611,125",
               "1402,215;2259,206;2599,224", "1395,339;2228,321;2661,342"]

        self.assertEqual(res, misc.load_text_file(filename))

    def test_parse_string(self):
        polygon = misc.parse_string("1,2;2,3;4,5")
        self.assertEqual(polygon.n_points, 3)
        self.assertEqual(polygon.x_points, [1, 2, 4])
        self.assertEqual(polygon.y_points, [2, 3, 5])

    def test_poly_to_string(self):
        polygon = Polygon([1, 2, 4], [2, 3, 5], 3)
        res = "1,2;2,3;4,5"
        self.assertEqual(res, misc.poly_to_string(polygon))

    def test_get_polys_from_file_txt(self):
        poly_file_name = "./resources/lineReco7.txt"
        # poly_file_name = "./resources/lineReco10_withError.txt"
        # poly_file_name = "./resources/lineEmpty.txt"
        polygon1 = Polygon([29, 1321], [80, 88], 2)
        polygon2 = Polygon([9, 506, 684, 1139], [215, 215, 199, 206], 3)
        polygon3 = Polygon([32, 537, 621, 1322], [329, 340, 320, 331], 4)

        p_list, error = misc.get_polys_from_file(poly_file_name)
        if p_list is None and len(misc.load_text_file(poly_file_name)) > 0:
            print("Skip page..")
            self.assertEqual(error, True)
            self.assertEqual(p_list, None)
            return
        elif p_list is None and len(misc.load_text_file(poly_file_name)) == 0:
            print("Empty text file..")
            self.assertEqual(error, False)
            self.assertEqual(p_list, None)
            return

        [p1, p2, p3] = p_list

        self.assertEqual(polygon1.x_points, p1.x_points)
        self.assertEqual(polygon2.x_points, p2.x_points)
        self.assertEqual(polygon3.x_points, p3.x_points)

        self.assertEqual(polygon1.y_points, p1.y_points)
        self.assertEqual(polygon2.y_points, p2.y_points)
        self.assertEqual(polygon3.y_points, p3.y_points)

        self.assertEqual(error, False)

    # TODO: add a toy example for loading a PAGEXML file
    def test_polys_from_file_xml(self):
        poly_file_name = "./resources/page_test.xml"
        p_list, error = misc.get_polys_from_file(poly_file_name)
        print(len(p_list))

    def test_blow_up(self):
        poly_in = Polygon([0, 3, 4, 5, 7, 5], [1, 3, 5, 3, 1, 0], 6)
        poly_out = misc.blow_up(poly_in)
        res = Polygon([0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 6, 5], [1, 2, 2, 3, 4, 5, 4, 3, 2, 1, 1, 0], 12)

        self.assertEqual(res.x_points, poly_out.x_points)
        self.assertEqual(res.y_points, poly_out.y_points)
        self.assertEqual(res.n_points, 12)

    def test_thin_out(self):
        poly_in1 = Polygon([0, 1, 2, 3, 4, 4, 5, 5, 6, 7, 6, 5], [1, 2, 2, 3, 4, 5, 4, 3, 2, 1, 1, 0], 12)
        des_dist_1 = 1  # no changes
        des_dist_2 = 2  # distance of 2
        des_dist_100 = 100  # just consider min points (=20)

        poly1_1 = misc.thin_out(poly_in1, des_dist_1)
        poly1_2 = misc.thin_out(poly_in1, des_dist_2)
        poly1_100 = misc.thin_out(poly_in1, des_dist_100)

        for poly in [poly1_1, poly1_2, poly1_100]:
            self.assertEqual(poly_in1.x_points, poly.x_points)
            self.assertEqual(poly_in1.y_points, poly.y_points)
            self.assertEqual(poly_in1.n_points, poly.n_points)

        poly_in2 = Polygon()
        for (x, y) in zip(range(60), range(60)):
            poly_in2.add_point(x, y)

        poly2_1 = misc.thin_out(poly_in2, des_dist_1)
        poly2_2 = misc.thin_out(poly_in2, des_dist_2)
        poly2_100 = misc.thin_out(poly_in2, des_dist_100)

        self.assertEqual(poly_in2.x_points, poly2_1.x_points)
        self.assertEqual(poly_in2.y_points, poly2_1.y_points)
        self.assertEqual(poly_in2.n_points, poly2_1.n_points)

        self.assertEqual(range(0, 58, 2) + [59], poly2_2.x_points)
        self.assertEqual(range(0, 58, 2) + [59], poly2_2.y_points)
        self.assertEqual(30, poly2_2.n_points)

        self.assertEqual(range(0, 30, 3) + range(31, 57, 3) + [59], poly2_100.x_points)
        self.assertEqual(range(0, 30, 3) + range(31, 57, 3) + [59], poly2_100.y_points)
        self.assertEqual(20, poly2_100.n_points)

    def test_norm_poly_dists(self):
        des_dist = 2
        # Should not be changed (n_points <= 20 after blow_up)
        polygon1 = Polygon(range(20), range(20), 20)
        res1 = polygon1
        # Should be changed, s.t. the normed polygon has 20 (nearly equidistant) pixels
        polygon2 = Polygon(range(30), range(30), 30)
        res2 = Polygon([0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 29],
                       [0, 1, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 27, 29], 20)
        # Should not be changed, since des_dist = 2
        polygon3 = Polygon(range(0, 40, 2), range(0, 40, 2), 20)
        res3 = polygon3
        # Should be changed, s.t. every two pixels have a distance of des_dist = 2 (except for the last two pixels)
        polygon4 = Polygon(range(0, 90, 3), range(0, 90, 3), 30)
        res4 = Polygon(range(0, 86, 2) + [87], range(0, 86, 2) + [87], 44)

        poly_list = [polygon1, polygon2, polygon3, polygon4]

        normed_poly_list = misc.norm_poly_dists(poly_list, des_dist)
        res_list = [res1, res2, res3, res4]

        for normed_poly, res in zip(normed_poly_list, res_list):
            self.assertEqual(res.x_points, normed_poly.x_points)
            self.assertEqual(res.y_points, normed_poly.y_points)
            self.assertEqual(res.n_points, normed_poly.n_points)

    def test_calc_reg_line_stats(self):
        # We consider the negative y-values (since we handle computer vision problems..)
        # angle = 0°, n = 0.0
        polygon1 = Polygon(range(5), [0] * 5, 5)
        angle1, n1 = misc.calc_reg_line_stats(polygon1)

        # angle = 315°, n = 0.0
        polygon2 = Polygon(range(5), range(5), 5)
        angle2, n2 = misc.calc_reg_line_stats(polygon2)

        # angle = 306°, n = -11/13
        polygon3 = Polygon([0, 1, 2, 2, 3], [1, 2, 3, 4, 5], 5)
        angle3, n3 = misc.calc_reg_line_stats(polygon3)

        # angle ~ 354°, n = -2,3
        polygon4 = Polygon([0, 1, 2, 2, 3, 4], [1, 2, 3, 4, 5, 0], 6)
        angle4, n4 = misc.calc_reg_line_stats(polygon4)

        # Example where -math.pi / 2 < angle <= -math.pi / 4 and poly.y_points[0] > poly.y_points[-1]
        polygon5 = Polygon(range(100), range(0, 198, 2) + [-1], 100)
        angle5, n5 = misc.calc_reg_line_stats(polygon5)

        # Line y = 0 -> n = 0.0 and angle = 0.0
        self.assertEqual(0.0, angle1)
        self.assertEqual(0.0, n1)
        # Line y = -x -> n = 0.0 and angle = -pi/4 + 7*pi/4
        self.assertEqual(7 * math.pi / 4, angle2)
        self.assertEqual(0.0, n2)
        # Line y = -35/26*x - 11/13 -> n = -11/13 and angle = -0.931882342 + 2*pi
        self.assertAlmostEqual(-0.931882342 + 2 * math.pi, angle3, places=8)
        self.assertAlmostEqual(-11 / 13, n3, places=8)
        # Line y = -0.1*x - 2.3 -> n = -2.3 and angle = -0.0996686525 + 2*pi
        self.assertAlmostEqual(-0.0996686525 + 2 * math.pi, angle4, places=8)
        self.assertEqual(-2.3, n4)
        # Line y = -1.8817821782*x - 3.86178217822 -> n = -3.86178217822 and angle = -1.08233671731 + pi
        self.assertAlmostEqual(-1.08233671731 + math.pi, angle5, places=8)
        self.assertAlmostEqual(-3.86178217822, n5, places=8)

    def test_get_dist_fast(self):
        bb = Rectangle(0, 0, 10, 10)
        p_list = [[x, y] for x in [-1, 5, 11] for y in [-1, 5, 11]]
        dist_list = []
        for p in p_list:
            dist_list += [misc.get_dist_fast(p, bb)]
        self.assertEqual(2, dist_list[0])
        self.assertEqual(1, dist_list[1])
        self.assertEqual(2, dist_list[2])
        self.assertEqual(1, dist_list[3])
        self.assertEqual(0, dist_list[4])
        self.assertEqual(1, dist_list[5])
        self.assertEqual(2, dist_list[6])
        self.assertEqual(1, dist_list[7])
        self.assertEqual(2, dist_list[8])

    def test_get_in_dist(self):
        points1 = [[1, 1], [0, 0]]
        points2 = [[2, 0], [0, 0]]
        or_vec1 = [1, 0]
        or_vec2 = [1 / math.sqrt(2), 1 / math.sqrt(2)]
        in_dist1 = misc.get_in_dist(points1[0], points1[1], or_vec1[0], or_vec1[1])
        in_dist2 = misc.get_in_dist(points2[0], points2[1], or_vec2[0], or_vec2[1])
        in_dist3 = misc.get_in_dist(points1[1], points1[0], or_vec1[0], or_vec1[1])
        in_dist4 = misc.get_in_dist(points2[1], points2[0], or_vec2[0], or_vec2[1])

        self.assertEqual(1, in_dist1)
        self.assertAlmostEqual(math.sqrt(2), in_dist2, places=8)
        self.assertEqual(-1, in_dist3)
        self.assertAlmostEqual(-math.sqrt(2), in_dist4, places=8)

    def test_get_off_dist(self):
        points1 = [[1, 1], [0, 0]]
        points2 = [[2, 0], [0, 0]]
        or_vec1 = [1, 0]
        or_vec2 = [1 / math.sqrt(2), 1 / math.sqrt(2)]
        in_dist1 = misc.get_off_dist(points1[0], points1[1], or_vec1[0], or_vec1[1])
        in_dist2 = misc.get_off_dist(points2[0], points2[1], or_vec2[0], or_vec2[1])
        in_dist3 = misc.get_off_dist(points1[1], points1[0], or_vec1[0], or_vec1[1])
        in_dist4 = misc.get_off_dist(points2[1], points2[0], or_vec2[0], or_vec2[1])

        self.assertEqual(1, in_dist1)
        self.assertAlmostEqual(math.sqrt(2), in_dist2, places=8)
        self.assertEqual(-1, in_dist3)
        self.assertAlmostEqual(-math.sqrt(2), in_dist4, places=8)

    def test_calc_tols(self):
        pass

    def test_f_measure(self):
        pass