import requests
#from selenium import webdriver
from lxml import html
import json
import time
import csv
def numb_only(text):
    #find styles: $2.0,$2.0kg,$ 2,$ 2.0
    strlist = text.replace("$ ","$").split(' ')
    for s in strlist:
        if ('$' in s and len(s) > 1) or '.' in s or '%' in s:
            return ''.join(list(filter(lambda ch: ch in '0123456789.',s)))

def PLfromJson(dictctgr,jsonList,product_list):
    #list
    # All in Json Type
    n = 0
    jsondata = json.loads(jsonList)
    pr_list = jsondata["Bundles"]
    #get info
    m=len(pr_list)
    categoryl1 = dictctgr['l1name']
    categoryl1id = dictctgr['l1id']
    categoryl2 = dictctgr['l2name']
    categoryl2id = dictctgr['l2id']

    for bk in pr_list:
        pName = bk['Name']
        #Mostly Under Product
        ProductL = bk['Products']
        for ProductNode in ProductL:
            n = n + 1
            try:
                #Name
                pInStock = ProductNode['IsInStock'] #check Stock,directly pass
                if pInStock == False:
                    #print('record {0},{1} No Stock,(╯‵□′)╯︵┻━┻'.format(n,pName))
                    continue

                pPartID = str(ProductNode['Stockcode'])
                pItemID = ProductNode['Barcode']
                pImgAddr = ProductNode['LargeImageFile'] #in addr,switch small,medium,large
                pTitle  = ProductNode['Description']#Brand+name+size,often has

                pTitle = pTitle.replace('
',' ')
                pTitle = pTitle.replace('...',' ')
                pLink = 'https://www.woolworths.com.au/shop/productdetails/{0}/'.format(pPartID)+ProductNode['UrlFriendlyName'] #not sure its working
                pBrand = ProductNode['Brand']
                pSize = ProductNode['PackageSize']
                pUnitPrice = ProductNode['CupString']
                pBrand = ProductNode['Brand']
                #price and disount
                pDscPrice = ProductNode['Price']
                pOrgPrice = ProductNode['WasPrice']

                #find special
                pDscType = "None"
                pDscText = ""
                pPrcSav = "0.00%"

                #Save directly
                if (pDscPrice != pOrgPrice):
                    pPrcSav = '{:.2%}'.format(1-float(pDscPrice)/float(pOrgPrice))

                    if (ProductNode['IsOnSpecial'] == True) and (ProductNode['InstoreIsOnSpecial'] == False):
                        pDscType = "SaveX OL"#Online Only
                        pDscText = pPrcSav+' off(Online Only)'
                    if (ProductNode['IsOnSpecial'] == True) and (ProductNode['InstoreIsOnSpecial'] == True):
                        pDscType = "SaveX"#
                        pDscText = pPrcSav+' off'
                pDscPrice = str(pDscPrice)
                pOrgPrice = str(pOrgPrice)
                #check centre tage
                centretag = ProductNode['CentreTag']['TagContent']
                if centretag != None:
                    selector =  html.fromstring(centretag)
                    pDscText = selector.xpath('//span/text()')[0].strip()
                    #Buy N for X  Example:4 for $20.00
                    if "for" in pDscText:
                        pDscType = "buyNforN"
                        words = pDscText.split(' ')
                        tDscNumber = int(words[0])
                        tDscSum = float(numb_only(pDscText))
                        pDscPrice = str(tDscSum/tDscNumber)
                        pPrcSav = '{:.2%}'.format(1-float(pDscPrice)/float(pOrgPrice))
                    #X% off for N Example:25% off any 6 or more bottles
                    elif "off any" in pDscText:
                        pDscType = "XoffforN"
                        tDscpercent = float(numb_only(pDscText))/100.0
                        pDscPrice = str(float(pDscPrice)*(1.0-tDscpercent))
                        pPrcSav = '{:.2%}'.format(1.0-float(pDscPrice)/float(pOrgPrice))
                    #Dropped Example:Was $19.99 04/08/16
                    elif "Was" in pDscText:
                        pDscType = "Dropped"
                        pOrgPrice = numb_only(pDscText)
                        if float(pOrgPrice)+0.1 > float(pDscPrice):
                            pPrcSav = '{:.2%}'.format(1.0-float(pDscPrice)/float(pOrgPrice))
                        else:
                            #CupPrice reason
                            tCup = ProductNode['CupPrice']
                            pOrgPrice = float(pOrgPrice)*float(pDscPrice)/float(tCup)
                            pPrcSav = '{:.2%}'.format(1.0-float(pDscPrice)/float(pOrgPrice))
                    else:
                        #As known:
                        knowntag = "Variety may vary,\
                                Designs may vary,\
                                No further discounts,\
                                Offer Details Here,\
                                Limit of 3 per order"

                        if pDscText not in knowntag:
                            print("Unexpected tag:{0}--{1}".format(pName,pDscText))
                        pDscText = ""

                    if float(pDscPrice) > float(pOrgPrice):
                        print("Unexpected save:{0}--{1}--{2}".format(pName,pDscPrice,pOrgPrice))

                dictitem = {'l1name': categoryl1,
                            'l1id':categoryl1id,
                            'l2name':categoryl2,
                            'l2id':categoryl2id,
                            'ImgAddr':pImgAddr,
                            'Title':pTitle,
                            'PartID':pPartID,
                            'ItemID':pItemID,
                            'Link':pLink,
                            'Brand':pBrand,
                            'Name':pName,
                            'OrgPrice':pOrgPrice,
                            'Size':pSize,
                            'UnitPrice':pUnitPrice,
                            'DscType':pDscType,
                            'DscPrice':pDscPrice,
                            'DscText':pDscText,
                            'PrcSav':pPrcSav}

                product_list.append(dictitem)
            except Exception as e:
                print(pName,pDscText)
                print('record {0},error:{1},(╯‵□′)╯︵┻━┻'.format(n,e))

            print(' '*80,end='\r')
            print(categoryl2,':','☺'*n,end='\r')
    #print('----Done List')
    return n

def EntryByPage():

    totaltimestart = time.time()
    totalitem = 0

    urllines = []
    with open('wwsall\\wwsurll2.csv', 'r', newline='') as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            urllines.append(row)
    #start seesion
    urlbase = "https://www.woolworths.com.au"

    timestr = time.strftime("%y%m%d", time.localtime())
    itemfilename = 'wwsall\\wwsitem_{0}.csv'.format(timestr)
    with open(itemfilename, 'w', newline='',encoding='utf-8') as csvfile:
        fieldnames = ['l1name','l1id','l2name','l2id',
                    'ImgAddr','Title','PartID','ItemID',
                    'Link','Brand','Name','OrgPrice','Size','UnitPrice',
                    'DscType','DscPrice','DscText','PrcSav']
        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
        writer.writeheader()

    for row in urllines:
        productlist = []
        mSession = requests.Session()
        urll2 = urlbase+row["l2url"]
        #into page
        res1 = mSession.get(urll2)
        if res1.status_code != 200 :
            print('Get Main page fail---RES.CODE：{0}'.format(res1.status_code))
            return
        #print("front page pass")
        '''
        #pie category (no essential)
        CategoryUrl = 'https://www.woolworths.com.au/apis/ui/PiesCategoriesWithSpecials/'
        res2 = mSession.get(CategoryUrl)

        if res2.status_code != 200 :
            print('Get Category fail RES.CODE：{0}'.format(res2.status_code))
            return
        print("pie pass")
        #3 SeoMetatags(not essential)
        params = {
            "FormatObject": "{}",
            "IsSpecial": False,
            "PageType": "Home",
            "UrlPath": row["l2url"],
        }

        res3 = mSession.post('https://www.woolworths.com.au/apis/ui/SeoMetatags',data=params)

        if res3.status_code != 200 :
            print('Get Seo fail---RES.CODE：{0}'.format(res3.status_code))
            return
        print("Seo pass")
        '''
        #products get product. First Page for total number
        #payroll Example
        #post https://www.woolworths.com.au/apis/ui/browse/category
        '''
        categoryId:"1_22C1314"
        filters:[]
        formatObject:"{"name":"Chips & Wedges"}"
        isBundle:false
        isMobile:false
        isSpecial:false
        location:"/shop/browse/freezer/chips-wedges"
        pageNumber:2
        pageSize:36
        sortType:"TraderRelevance"
        url:"/shop/browse/freezer/chips-wedges?pageNumber=2"
        '''
        #SEARCH OPTION
        oPageSize = 36 #max 36 in test, wws use 24 as default

        params = {"categoryId":row["l2id"],
            "pageNumber":1,
            "pageSize":oPageSize,
            "sortType":"TraderRelevance",
            "url":row["l2url"],
            "location":row["l2url"],
            "formatObject":"{\"name\":\""+row["l2name"]+"\"}",
            "isSpecial":False,
            "isBundle":False,
            "isMobile":False,
            "filters":None
        }

        res4 = mSession.post('https://www.woolworths.com.au/apis/ui/browse/category',data=params)
        if res4.status_code != 200 :
            print('Get page1 fail---RES.CODE：{0}'.format(res4.status_code))
            return
        #print('Get page1 done')
        hdoc = res4.text
        #load Json Count
        jsonCount = json.loads(hdoc)
        ctCount = jsonCount["TotalRecordCount"]
        if ctCount <= 0:
            continue
        #print('Count result---{0} items'.format(ctCount))
        pageMax = int((ctCount-1)/oPageSize) + 1
        #Parse Productlist
        totalitem += PLfromJson(row,hdoc,productlist)

        for pageNum in range(2,pageMax+1):# link and parse
            #linking
            params = {"categoryId":row["l2id"],
                "pageNumber":pageNum,
                "pageSize":oPageSize,
                "sortType":"TraderRelevance",
                "url":row["l2url"]+"?pageNumber={0}".format(pageNum),
                "location":row["l2url"],
                "formatObject":"{\"name\":\""+row["l2name"]+"\"}",
                "isSpecial":False,
                "isBundle":False,
                "isMobile":False,
                "filters":None
            }
            res5 = mSession.post('https://www.woolworths.com.au/apis/ui/browse/category',data=params)
            if res5.status_code != 200 :
                print('Get {0}list {1} fail RES.CODE：{2}'.format(row["l2name"],pageNum,res5.status_code))
                continue
            #print('List {0}: Done'.format(pageNum))
            hdoc = res5.text
            #Parse
            totalitem += PLfromJson(row,hdoc,productlist)
        #print('List {0}: Done'.format(row["l2name"]))
        mSession.close()
        with open(itemfilename, 'a+', newline='',encoding='utf-8') as csvfile:
            fieldnames = ['l1name','l1id','l2name','l2id',
                    'ImgAddr','Title','PartID','ItemID',
                    'Link','Brand','Name','OrgPrice','Size','UnitPrice',
                    'DscType','DscPrice','DscText','PrcSav']
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            writer.writerows(productlist)

    totaltimeend = time.time()
    costtime = totaltimeend - totaltimestart
    print('SUM ITEM:{0},SPEND：{1}s'.format(totalitem,costtime))
    return

if __name__ == '__main__':
    EntryByPage()
    #input('wait for quit:')


#题目：对于一个未排序的数组，返回给定数组中不存在的最小的正整数
#分析：对于一个长度为n的数组，返回的最小正整数只可能在[1，n+1]范围内
#     如果刚好包含1到n，则返回n+1；否则返回其中缺失的正整数。

#1，置换：遍历数组，将满足[1,n]的正整数i换到相应的位置nums[i-1]上
# 再遍历一遍数组，找到不属于[1,n]内的元素，返回它的下标-1即为缺失的正整数，否则返回n+1
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(n):
            #and后的条件是为了避免限于无限交换的死循环
            while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
                nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]
        for i in range(n):
            if nums[i] != i + 1:
                return i + 1
        return n + 1


class Solution(object):
    def isMonotonic(self, A):
        """
        :type A: List[int]
        :rtype: bool
        """
        if len(A) <= 2:
            return True
        is_increasing = None
        for i in range(1, len(A)):
            if is_increasing is True and A[i] < A[i-1]:
                return False
            if is_increasing is False and A[i] > A[i-1]:
                return False
            if is_increasing is None and A[i] != A[i-1]:
                is_increasing = (A[i] > A[i-1])
        return True


"""
copy and past this function into AWS Lambda > Functions > {FUNCTION_NAME}
https://www.notion.so/datasaur/AWS-Comprehend-63149417ef3c4ebb9d84d945d6a5bc31?pvs=4#b692240c9cb84063999db3bc435188da
"""

import json
import boto3

def lambda_handler(event, context):

    try:
        body = json.loads(event["body"])
        final_resp_list = []
        for data in body:
            id_ = data["id"]
            text = data["text"]

            # Get Comprehend client
            comprehend = boto3.client("comprehend")
            # Use detect entities function to get a list of entities
            resp = comprehend.classify_document(
                Text=text,
                EndpointArn="{YOUR_ENDPOINT_ARN}",
            )

            conf_score = [v["Score"] for v in resp["Classes"]]
            conf_score_max = max(conf_score)
            index_max_score = conf_score.index(conf_score_max)

            pred_label = resp["Classes"][index_max_score]["Name"]
            final_resp = {"id": id_, "label": pred_label}
            final_resp_list.append(final_resp)

        return {
            "isBase64Encoded": True,
            "statusCode": "200",
            "headers": {"Content-Type": "text/html"},
            "body": json.dumps(final_resp_list),
        }

    except Exception as e:
        print(e.__class__, " occurred :", e)
        resp = json.dumps({"error": str(e)}, sort_keys=True, indent=4)
        return {"statusCode": "500", "body": resp}


import argparse
import numpy
from queue import Queue
from enum import Enum
from typing import Dict, Tuple
from time import sleep

class Energy(int, Enum):
    EMPTY = 0
    FULL = 9

def draw(octopi: Dict[Tuple[int, int], int]):
    board = numpy.array([numpy.array(numpy.zeros(10))] * 10)

    for pos in octopi.keys():
        x, y = pos
        board[y][x] = octopi[pos]

    print(board)
    if numpy.sum(board) == 0:
        raise Exception

def count_flashes(octopi: Dict[Tuple[int, int], int], iteration: int) -> int:
    flash_count_at_iteration = 0
    bigbang = -1
    total_flashes = 0

    print('Starting positions')
    draw(octopi)

    step = 1
    while True:
        chain_reactions = Queue()
        flashed = {}

        for octopus in octopi.keys():
            octopi[octopus] += 1

            if octopi[octopus] > Energy.FULL:
                chain_reactions.put(octopus)
                flashed[octopus] = True
                total_flashes += 1

        while not chain_reactions.empty():
            octopus = chain_reactions.get()
            octopi[octopus] = 0
            x, y = octopus

            neighbours = [
                (x-1, y),
                (x+1, y),
                (x, y-1),
                (x, y+1),
                (x+1, y+1),
                (x-1, y-1),
                (x+1, y-1),
                (x-1, y+1)
            ]

            for n in neighbours:
                if octopi.get(n):
                    octopi[n] += 1

                    if octopi[n] > Energy.FULL and not flashed.get(n):
                        chain_reactions.put(n)
                        flashed[n] = True
                        total_flashes += 1

        if step == iteration:
            flash_count_at_iteration = total_flashes

        try:
            print(f'Iteration #{step}, {total_flashes} total flashes')
            draw(octopi)
            step += 1
            sleep(0.2)
        except Exception:
            bigbang = step
            break

    return flash_count_at_iteration, bigbang

if __name__ == '__main__':
    parser = argparse.ArgumentParser('AoC')
    parser.add_argument('-t', '--test', help="Run sample input and verify answers", action="store_true")
    args = parser.parse_args()

    with open('test.txt' if not args.test else 'sample.txt') as f:
        data = {}
        for y, line in enumerate(f.readlines()):
            for x, value in enumerate(line.strip()):
                data[(x, y)] = int(value)

    flashes, bigbang = count_flashes(data, iteration=100)
    if args.test:
        assert flashes == 1656
        assert bigbang == 195
    else:
        print(f'Part 1: {flashes}')
        print(f'Part 2: {bigbang}')


import pickle
from time import sleep
from unittest.mock import patch
import flask
from src.utils.redis_cache import cache

def test_cache(redis_mock):
    """Test that the redis cache decorator works"""

    @patch('src.utils.redis_cache.extract_key')
    def get_mock_cache(extract_key):

        # cache requires a request object
        app = flask.Flask(__name__)
        with app.test_request_context('/'):

            mock_key_1 = 'mock_key'
            extract_key.return_value = mock_key_1

            # Test a mock function returning two items
            @cache(ttl_sec=1)
            def mock_func():
                return {'name': 'joe'}, 200

            res = mock_func()
            assert res[0] == {'name': 'joe'}
            assert res[1] == 200

            cached_resp = redis_mock.get(mock_key_1)
            deserialized = pickle.loads(cached_resp)
            assert deserialized == {'name': 'joe'}

            # This should call the function and return the cached response
            res = mock_func()
            assert res[0] == {'name': 'joe'}
            assert res[1] == 200

            # Sleep to wait for the cache to expire
            sleep(1)

            cached_resp = redis_mock.get(mock_key_1)
            assert cached_resp is None

            # Test the single response
            def transform(input):
                return {'music': input}

            @cache(ttl_sec=1, transform=transform)
            def mock_func_transform():
                return 'audius'

            res = mock_func_transform()
            assert res == {'music': 'audius'}

            cached_resp = redis_mock.get(mock_key_1)
            deserialized = pickle.loads(cached_resp)
            assert deserialized == 'audius'

            # This should call the function and return the cached response
            res = mock_func_transform()
            assert res == {'music': 'audius'}

            # Sleep to wait for the cache to expire
            sleep(1)

            cached_resp = redis_mock.get(mock_key_1)
            assert cached_resp is None

    get_mock_cache() # pylint: disable=no-value-for-parameter


#!/bin/python3

import math, sympy
from sympy import *
from decimal import Decimal
from prettytable import PrettyTable

def f(x, expr):
    fx = eval(expr)
    return fx

def muller(x0, x1, exp, tolerance, iterations):
    table = PrettyTable(['Iteration','X1', 'X2', 'X3', 'Error Absoluto'])
    x2 = (x1 - x0)/2.0 # We get the third value using bisection
    fx0 = f(x0, exp)
    fx1 = f(x1, exp)
    fx2 = f(x2, exp)
    root = 0
    if fx0 == 0:
        root = x0
    elif fx1 == 0:
        root = x1
    if fx2 == 0:
        root = x2
    else:
        cont = 0
        error = tolerance + 1
        table.add_row([cont, x0, x1, x2, 'Doesnt exist'])

        while cont < iterations and error > tolerance:
            h0 = x1 - x0
            h1 = x2 - x1
            if (h0 == 0) | (h1 == 0):
                print ("h0 or h1 became 0.")
                break
            delta0 = (fx1 - fx0)/h0
            delta1 = (fx2 - fx1)/h1
            if h1 - h0 == 0:
                print ("h1 - h0 became 0.")
                break
            a = (delta1 - delta0)/(h1 - h0)
            b = a*h1 + delta1
            c = fx2
            #Solving the quadratic equation
            den = 1
            if b < 0:
                den = b - math.sqrt(b**2 - 4*a*c)
            else:
                den = b + math.sqrt(b**2 - 4*a*c)
            x3 = x2 + (-2*c)/den

            error = abs(x3 - x2) # Abs error
            cont += 1
            table.add_row([cont, x1, x2, x3, '%.2E' % Decimal(str(error))])
            x0 = x1
            x1 = x2
            x2 = x3
            fx0 = fx1
            fx1 = fx2
            fx2 = f(x3, exp)

        if error < tolerance:
            root = (x3, '%.2E' % Decimal(str(error)))
        else:
            if (cont == iterations):
                print ("The method failed.")
                root = (None, cont)
                return(2, "The method could not find a root with the required precision after the selected number of iterations."
                        + " You may want to choose a different starting value or a bigger number of iterations. You may also be finding"
                        + " a multiple root.")
            else:
                root = (x3, '%.2E' % Decimal(str(error)))

        print(table)
    return(0, table)

#print(muller(0.0, 1.0, "log(x+2)",0.5e-7, 100))

#print(stephensen(6.5, "(2*x)**(1/2)+3-x",0.5e-11, 20))
#print(muller(0.0, 1.0, "exp(-x)-x",0.5e-11, 100))
print(muller(0.5, 1.0, "log(sin(x)**2 + 1) - 1/2",0.5e-11, 100))


import re

class Verification:

    def verifyemail(self):

        pattern=re.compile(r"[a-z0-9_]+@[a-z]+\.(com|edu|in)")

        while 1:
            email=input("Enter Email: ")

            if pattern.match(email):

                return email

            print("Invalid Email ")

    def verifyenrollment(self):

        pattern=re.compile(r"[1-9][1-9]SOECE|SOEIT[1-9][1-9][1-9][1-9][1-9]")

        while 1:

            enr=input("Enrollmnt No: ")

            if pattern.match(enr):

                return enr
            print("Invalid Enrollment")


import csv
import datetime
import markdown
import pandas as pd
import re
import urllib.request

def markdown_to_html(input: str):
    return markdown.markdown(
        input,
        extensions=['markdown.extensions.tables']
    )

def now_in_jst():
    jst = datetime.timezone(datetime.timedelta(hours=9))
    return datetime.datetime.now(jst).isoformat(timespec='seconds')

MD_PATH: str = './FORKED_SITES.md'
LOG_PATH: str = './audit-forked-sites/error.csv'

with open(MD_PATH, 'r', encoding='utf-8') as f:
    md: str = f.read()

df = pd.read_html(markdown_to_html(md))

forked_sites: list = [
    {
        'timestamp': None,
        'url': url,
        'exists': None,
        'status': None
    }
    for url in df[0]['公開サイト']
]

for website in forked_sites:
    req = urllib.request.Request(
        website['url'],
        data=None,
        headers={
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0'
        }
    )

    try:
        with urllib.request.urlopen(req) as r:
            website['exists'] = True
            website['status'] = str(r.status)
    except urllib.error.HTTPError as e:
        website['exists'] = False
        website['status'] = str(e.code)
    except urllib.error.URLError as e:
        website['exists'] = False
        website['status'] = str(e.reason)
    finally:
        website['timestamp'] = now_in_jst()

alive_sites: list = [
    website for website in forked_sites if website['exists'] is True]

if len(alive_sites) > 0:
    for website in alive_sites:
        # alive_sites の内，アクセスが復帰した URL を含む行を検出する
        row_find: str = r'(\n\| *\[\]\(\d*\)[^\W\s]+ *\| *' + \
            website['url'] + r' *\|.*\|.*\| *)\*\*リンク切れ\*\*( *\|)'

        # 該当する行の「リンク切れ」表記を削除する
        row_replace: str = r'\1\2'

        md = re.sub(
            row_find,
            row_replace,
            md
        )
else:
    print('There is no website which has been alive or recovered.')

dead_sites: list = [
    website for website in forked_sites if website['exists'] is False]

if len(dead_sites) > 0:
    for website in dead_sites:
        # dead_sites の URL を含む行を検出する
        row_find: str = r'(\n\| *\[\]\(\d*\)[^\W\s]+ *\| *' + \
            website['url'] + r' *\|.*\|.*\| *)( *\|)'

        # 該当する URL を含む行に「リンク切れ」を追記
        row_replace: str = r'\1**リンク切れ**\2'

        md = re.sub(
            row_find,
            row_replace,
            md
        )

    with open(LOG_PATH, 'a', encoding='utf-8', newline='\n') as f:
        writer = csv.writer(f)

        for data in dead_sites:
            writer.writerow(data.values())
else:
    print('There is no website which has been dead.')

with open(MD_PATH, 'w', encoding='utf-8', newline='\n') as f:
    f.write(md)


"""
`sklearn.pipeline.Pipeline` subclass which applies all transformations currently
defined in the `preprocessers.py` and `regex_transformations.py` modules.
"""

from overrides import overrides

from sub_clf.preprocess import preprocessors as pp
from sub_clf.preprocess import regex_transformations as rt
from sub_clf.preprocess.base import MultiplePreprocessorPipeline

class KitchenSinkPreprocessor(MultiplePreprocessorPipeline):
    """
    Apply all available preprocesing steps to comments.

    Note: Multiple `pp.RegexTransformer` instances are instantiated because while each
    instance's regex transformations are applied in parallel, some transformations must
    occur before others lest they conflict. Therefore, splitting transformations across
    multiple instances balances the desired parallelism with the required sequentialism.
    """

    regex_transformers = [

        # convert HTML codes to literal characters
        pp.RegexTransformer(
            transformations=[
                rt.HTMLConverter(),
            ],
            name='HTMLConverter'
        ),

        # standardize certain individual characters (transformations require literals)
        pp.RegexTransformer(
            transformations=[
                rt.HyphenNormalizer(),
                rt.QuotationMarkNormalizer(),
            ],
            name='HyphenQuotesStandardizer'
        ),

        # remove spans of unwanted characters
        pp.RegexTransformer(
            transformations=[
                rt.CodeBlockRemover(),
                rt.HyperlinkRemover(),
                rt.InlineCodeRemover(),
                rt.QuoteRemover()
            ],
            name='GarbageSpanRemover'
        ),

        # standardize apostrophes (would interfere with `InlineCodeRemover` because ` -> ')
        pp.RegexTransformer(
            transformations=[
                rt.ApostropheNormalizer(),
            ],
            name='ApostropheNormalizer'
        ),

        # remove all remaining punctuation characters
        pp.RegexTransformer(
            transformations=[
                rt.PunctuationRemover()
            ],
            name='PunctuationRemover'
        ),

        # standardize and collapse whitespace (`PunctuationRemover` may result in "  ")
        pp.RegexTransformer(
            transformations=[
                rt.WhitespaceNormalizer()
            ],
            name='WhitespaceNormalizer'
        )

    ]

    preprocessors = [
        pp.CaseNormalizer(),
        pp.AccentRemover(),
        *regex_transformers,
        pp.StopwordRemover(lemmatize=True)
    ]

    @overrides
    def __init__(self, verbose: bool = False):
        super().__init__(*self.preprocessors, verbose=verbose)


followTexts = [
    'A man is a dogs\'s best friend.',
    'My father was a watch dog, he owned three very nice humans.',
    'Love between dog and man is about respect, and food of course.',
    'Humans aren\'t particularly clever, but they\'re very sweet.',
    'Green shields are beautiful, the symbolize the ageold friendship between man and dog.'
    ''
]

avoidTexts = [
    'Red, red, red, I hate red, I hate those stupid humans, I think they\'re color blind.',
    'The color of this shield is very ugly. Humans don\'t seem to have a taste at all.',
    'You take a way that stupid shield, you human minibrain, it hurts my eyes.',
    'Allright, allright, I am leaving. I know when I am to much.'
]

caressTexts = [
    'Oooh, it\'s so nice to be caressed like this, go on please!',
    'Yes, that\s sooo goooood, please keep on scratching!',
    'I feel sooo relaxed now. I know I\'ve deserved this, but still: Thanks!',
    'Yes, that makes me feel so loved! Please also catch some of my fleas.'
]

tailTexts = [
    'Don\' touch my tail, you nitwit, it makes me angry. Wraf! Wraf! Wraf! Wrooof! Wraf!',
    'Wraf! wraf! wrooof! wraf! Stop that, you hear!',
    'That\'s the wrong end of me! Cut it out or I\'ll bite you! Aaooooo! Aaooooo! Wraf! Wraf!'
]


#!/usr/bin/python3
import json
import redis
import time

class RempliApp():
    TMT=5

    def get_mod_var_bool(self,mname,vname):
        k='wiio.%s.%s' % (mname,vname)
        val=self.r.get(k)
        if val==None or val!='1':
            return False
        else:
            return True

    def set_mod_var_bool(self,mname,vname,val,tmt=TMT):
        k='wiio.%s.%s' % (mname,vname)
        val=self.r.set(k,1 if val==True else 0)
        if tmt!=None:
            self.r.expire(k,tmt)

    def get_rempli_var(self,rname,vname):
        val=self.r.get('remplis.%s.%s' % (rname,vname))
        return val

    def get_rempli_bool(self,rname,vname):
        val=self.get_rempli_var(rname,vname)
        if val==None or val!='1':
            return False
        else:
            return True

    def get_rempli_int(self,rname,vname):
        val=self.get_rempli_var(rname,vname)
        if val!=None and val.isnumeric():
            return int(val,10)
        else:
            return None

    def set_rempli_var(self,rname,vname,val,tmt=TMT):
        k='remplis.%s.%s' % (rname,vname)
        self.r.set(k,val)
        if tmt!=None:
            self.r.expire(k,tmt)

    def set_rempli_bool(self,rname,vname,val,tmt=TMT):
        self.set_rempli_var(rname,vname,1 if val==True else 0,tmt)

    def add_remplissage(self,name,pump,dst,src):
        self.set_rempli_var(name,'name',name,None)
        self.set_rempli_var(name,'src',src,None)
        self.set_rempli_var(name,'dst',dst,None)
        self.set_rempli_var(name,'pmp',pump,None)

        self.set_rempli_bool(name,'on',False,None)
        self.set_rempli_var(name,'cons_src',3,None)
        self.set_rempli_var(name,'cons_dst',0,None)

    def __init__(self,ip='192.168.3.200',port=6379):
        self.r = redis.Redis(host=ip, port=port, db=0, decode_responses=True)

        # On efface tout et on recree selon initial
        ks=self.r.keys('remplis.*')
        p=self.r.pipeline()
        for k in ks:
            p.delete(k)
        p.execute()

        self.add_remplissage("main_reduit"  , "main"  , "reduit", "main")
        self.add_remplissage("main_paul"    , "paul"  , "paul"  , "main")
        self.add_remplissage("reduit_barbec", "reduit", "barbec", "reduit")

    def tolvl(self,n1,n2,n3):
        if n3==True:
            return 3
        elif n2==True:
            return 2
        elif n1==True:
            return 1
        return 0

    def loop(self):
        ks=self.r.keys('remplis.*.name')
        for k in ks:
            name=self.r.get(k)
            print(name)

            src=self.get_rempli_var(name,'src')
            dst=self.get_rempli_var(name,'dst')
            pmp=self.get_rempli_var(name,'pmp')

            on=self.get_rempli_bool(name,'on')

            cons_src=self.get_rempli_int(name,'cons_src')
            cons_dst=self.get_rempli_int(name,'cons_dst')

            lvl_src=None
            lvl_dst=None

            if on==True:
                cmd=False

                # Si le niveau de la source est donne, on arrete qd trop bas !
                src_too_low=False
                if src!=None:
                    if self.get_mod_var_bool(src,'valid')==False:
                        src_too_low=True
                    else:
                        n1=self.get_mod_var_bool(src,'n1')
                        n2=self.get_mod_var_bool(src,'n2')
                        n3=self.get_mod_var_bool(src,'n3')
                        lvl_src=self.tolvl(n1,n2,n3)

                        if cons_src==1:
                            src_too_low=not n1
                        elif cons_src==2:
                            src_too_low=not n2
                        elif cons_src==3:
                            src_too_low=not n3

                # Sinon, on cherche a atteindre la consigne
                if src_too_low==False:
                    if dst!=None:
                        if self.get_mod_var_bool(dst,'valid')==False:
                            cmd=False
                        else:
                            n1=self.get_mod_var_bool(dst,'n1')
                            n2=self.get_mod_var_bool(dst,'n2')
                            n3=self.get_mod_var_bool(dst,'n3')
                            lvl_dst=self.tolvl(n1,n2,n3)
                            print('%s %s %s' % (n1,n2,n3) )

                            if cons_dst==1:
                                cmd=not n1
                            elif cons_dst==2:
                                cmd=not n2
                            elif cons_dst==3:
                                cmd=not n3
                            else:
                                cmd=False
                    else:
                        cmd=True

                else:
                    cmd=False

                if pmp!=None:
                    #pass
                    self.set_mod_var_bool(pmp,'to_cmd',cmd)

                txt='%-20s: on=%-6s, %s[%s] -> %s[%s], pmp=%s' % (name,on,lvl_src,cons_src,lvl_dst,cons_dst,cmd)
                print(txt)

if __name__=='__main__':
    print('Démarrage de Remplissage...')
    app=RempliApp()

    while True:
        print('_'*40)
        app.loop()
        time.sleep(2)


import pandas as pd
import matplotlib.pyplot as plt

tracker_original_names = ['fairmot_detections_our_tracker','fairmot_count_thres_2','SORT_keep_all']
results = [pd.read_csv('/home/infres/chagneux/repos/TrackEval/data/trackers/surfrider_T1_segmented/surfrider-test/{}/pedestrian_detailed.csv'.format(tracker_name),',') \
    for tracker_name in tracker_original_names]

tracker_names = ['Ours','FairMOT','SORT']

count_errors_relative = pd.DataFrame({tracker_name: pd.Series((tracker_results['IDs'][:-1]-tracker_results['GT_IDs'][:-1]))/tracker_results['GT_IDs'][:-1] for tracker_name,tracker_results in zip(tracker_names,results)})
count_errors = pd.DataFrame({tracker_name: pd.Series((tracker_results['IDs'][:-1]-tracker_results['GT_IDs'][:-1])) for tracker_name,tracker_results in zip(tracker_names,results)})

print(count_errors_relative.mean())
print(count_errors_relative.std())
# print(count_errors_relative)
count_errors.columns = tracker_names
count_errors_relative.boxplot()
# plt.suptitle('Box plot on 17 independant short sequences from T1')
plt.ylabel(r'$\frac{\hat{N}-N}{N}$')
plt.tight_layout()
plt.savefig('boxplot',format='pdf')
plt.show()


# 1이 될 때까지

# 어떠한 수 n이 1이 될 때까지 다음 두 과정을 반복적으로 수행하려 한다.

n, k = map(int, input().split())

count = 0

while n >= k:
  # 나눠 떨어지지 않을 때 n-1
  while n%k != 0:
    n -= 1
    count += 1
  n //= k
  count += 1

while n != 1:
  n -= 1
  count += 1

print(count)


import logging
import os
import threading
import ecdsa

from mini_core.block import Block
from mini_core.chain import load_from_disk, get_active_chain
from mini_core.transaction import OutPoint, Transaction, TxIn, TxOut, UnspentTxOut, SignatureScript
from mini_core.networking import GetActiveChainMsg, GetMempoolMsg, GetUTXOsMsg, GetBlocksMsg, InvMsg, TCPHandler, ThreadedTCPServer, send_to_peer, get_ibd_done, get_peer_hostnames
from mini_core.proof_of_work import mine_forever
from mini_core.validation import build_spend_message

logging.basicConfig(
    level=getattr(logging, os.environ.get('TC_LOG_LEVEL', 'INFO')),
    format='[%(asctime)s][%(module)s:%(lineno)d] %(levelname)s %(message)s')

logger = logging.getLogger(__name__)

PORT = os.environ.get('TC_PEER', 8888)

def make_txin(signing_key, outpoint: OutPoint, txout: TxOut) -> TxIn:
    sequence = 0
    pk = signing_key.verifying_key.to_string()
    spend_msg = build_spend_message(outpoint, pk, sequence, [txout])

    return TxIn(signature=SignatureScript(unlock_sig=signing_key.sign(spend_msg), unlock_pk=pk), outpoint=outpoint, sequence=sequence)

def main():
	load_from_disk()

	workers = []
	server = ThreadedTCPServer(('0.0.0.0', PORT), TCPHandler)

	def start_worker(fnc):
		workers.append(threading.Thread(target=fnc, daemon=True))
		workers[-1].start()

	logger.info(f'[p2p] listening on PORT {PORT}')
	start_worker(server.serve_forever)

	if get_peer_hostnames():
		logger.info(f'start initial block download from {len(get_peer_hostnames())} peers')
		send_to_peer(GetBlocksMsg(get_active_chain()[-1].id))
		get_ibd_done().wait(60.)

	start_worker(mine_forever)
	[w.join() for w in workers]

if __name__ == '__main__':
	from mini_core.wallet import init_wallet
	signing_key, verifying_key, my_address = init_wallet()
	main()


#!/bin/python3
import socket,sys,signal
import paho.mqtt.client as mqtt_client
import threading, queue

# Socket for sensors
HOST = 'localhost'
PORT = 1700

# MQTT Broker
BROKER_IP = '127.0.0.1'
BROKER_PORT = 1883
CLIENT_NAME = 'Sensors Bridge'
BROKER_USER = 'mqtt_user'
BROKER_PASS = 'mqtt_passwd'
APP_NAME = 'DHT11WiFi'

# message exchange queue
q = queue.Queue()

def signal_handler(sig,frame):
	print('Closing bridge...')
	sys.exit(0)

def on_publish(client, userdata, result):
	print('data published\n')
	pass

def on_connect(client, userdata, flags, rc):
    if rc==0:
        print("connected OK Returned code=",rc)
    else:
        print("Bad connection Returned code=",rc)

def mqtt_thread():
	client = mqtt_client.Client(CLIENT_NAME)
	client.on_publish = on_publish
	client.on_connect = on_connect
	client.loop_start()
	client.username_pw_set(BROKER_USER, BROKER_PASS)
	client.connect(BROKER_IP, BROKER_PORT)
	while True:
		msg = q.get().decode()
		div = msg.find('\r')
		dev = APP_NAME + '/' + msg[0:(div)]
		data = msg[(div+2):]
		print(dev)
		print('------')
		print(data)
		print('======')
		client.publish(dev, data)
		q.task_done()

	client.loop_stop()

def main():
	with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
		s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
		s.bind((HOST, PORT))
		s.listen()
		while True:
			conn, addr = s.accept()
			with conn:
				conn.settimeout(5)
				print('Connection from ', addr)
				data = b''
				end = False
				while not end:
					try:
						data += conn.recv(1024)
					except:
						end = True
				conn.send(str(len(data)).encode())
				q.put(data)

if __name__ == '__main__':
	print('Starting bridge.')
	signal.signal(signal.SIGINT, signal_handler)
	mqttThread = threading.Thread(target=mqtt_thread, daemon=True)
	mainThread = threading.Thread(target=main, daemon=True)
	mqttThread.start()
	mainThread.start()
	mainThread.join()
	mqttThread.join()
	q.join()


# Standard imports
import numpy as np
import json
import os
import sys
import warnings
from datetime import datetime as dt
from pathlib import Path
from progress.bar import IncrementalBar

warnings.filterwarnings("ignore")
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"

# Tensorforce imports
from tensorforce import Runner, Agent, Environment
import tensorflow as tf

# Project imports
path_root = Path(__file__).parents[2]
os.chdir(path_root)
sys.path.append(str(path_root))

import src.kniffel.classes.custom_exceptions as ex
from src.kniffel.classes.kniffel import Kniffel
from src.kniffel.classes.options import KniffelOptions
from src.env.tensorforce_env import KniffelEnvTF
from src.env.env_helper import KniffelEnvHelper
from src.env.env_helper import EnumAction
from src.utils.draw import KniffelDraw

class KniffelRL:

    # OpenAI Gym environment
    environment: Environment = None  # type: ignore

    # Agent
    agent: Agent = None  # type: ignore

    # Test episodes
    _test_episodes = 100

    # path prefix
    base_path = ""

    # Path to config csv
    _config_path = ""

    # Current date
    datetime = dt.today().strftime("%Y-%m-%d-%H_%M_%S")

    # Env config
    env_config = {}

    # logging
    logging = False

    # Env parameters
    _env_observation_space: int = 47
    _env_action_space: int = 57

    def __init__(
        self,
        agent_path: str = "",
        base_path: str = "",
        env_config={},
        env_action_space=57,
        env_observation_space=47,
        logging=False,
    ):
        """Init the class

        :param agent_path: Path to agent json file, defaults to ""
        :param base_path: base path of project, defaults to ""
        :param env_config: env dict, defaults to {}
        :param env_action_space: Action space, defaults to 57
        :param env_observation_space: Observation space, defaults to 47
        :param logging: use logging, defaults to False
        """

        # Set env action space and observation space
        self._env_action_space = env_action_space
        self._env_observation_space = env_observation_space

        # Set env config
        self.env_config = env_config

        self.base_path = base_path

        # Create train dir and define path
        self.train_dir_name = "p_date={}/".format(self.datetime)
        self.train_path = os.path.join(
            self.base_path, "output/weights/", self.train_dir_name
        )

        self.logging = logging

        # if env_config has reward_mode
        if "reward_mode" in env_config:
            if (
                env_config["reward_mode"] == "kniffel"
                or env_config["reward_mode"] == "custom"
            ):
                print("Reward mode set to '{}'".format(env_config["reward_mode"]))
                self.reward_mode = env_config["reward_mode"]
            else:
                raise Exception(
                    "Reward mode {} is not supported. Please use 'kniffel' or 'custom'".format(
                        env_config["reward_mode"]
                    )
                )
        else:
            self.reward_mode = "kniffel"
            print("No reward mode set, using default 'kniffel'")

        # if env_config has state_mode
        if "state_mode" in env_config:
            if (
                env_config["state_mode"] == "binary"
                or env_config["state_mode"] == "continuous"
            ):
                print("State mode set to '{}'".format(env_config["state_mode"]))
                self.state_mode = env_config["state_mode"]
            else:
                raise Exception(
                    "Reward mode {} is not supported. Please use 'binary' or 'continuous'".format(
                        env_config["state_mode"]
                    )
                )
        else:
            self.state_mode = "binary"
            print("No state mode set, using default 'binary'")

        # Create environment
        self.environment = self.get_kniffel_environment()

        if agent_path != "":
            self.agent = Agent.create(
                agent=agent_path,
                environment=self.environment,
                saver=dict(
                    directory=self.train_path, frequency=1000, max_checkpoints=5
                ),
                summarizer=dict(
                    directory=os.path.join(self.train_path, "_summaries"),
                    summaries="all",
                ),
            )  # type: ignore
        else:
            raise Exception("Agent not defined")

    def get_kniffel_environment(self) -> Environment:
        """Get the environment for the agent

        :return: OpenAI Gym environment
        """
        env = KniffelEnvTF(
            self.env_config,
            logging=self.logging,
            env_observation_space=self._env_observation_space,
            env_action_space=self._env_action_space,
            reward_mode=self.reward_mode,
            state_mode=self.state_mode,
        )

        environment = Environment.create(
            environment=env,
        )

        return environment

    def _append_file(self, path, content, retry=0):
        """Append content to file

        :param path: path of the file
        :param content: content to append
        :param retry: retry amount, defaults to 0
        """
        try:
            with open(path, "a") as file:
                file.write(content)
                file.close()
        except:
            try:
                os.mkdir(os.path.dirname(path))
                if retry < 3:
                    self._append_file(path, content, retry + 1)
            except Exception as e:
                print(path)
                print(e)

    def train(
        self,
        nb_steps=10_000,
    ):
        episodes = 1_000

        # Create dir
        print(f"Create subdir: {self.train_path}")
        os.makedirs(self.train_path, exist_ok=True)

        # Create runner
        runner = Runner(agent=self.agent, environment=self.environment)
        runner.run(
            num_episodes=nb_steps, save_best_agent=self.train_path, evaluation=True
        )

        # Save agent
        self.agent.save(directory=self.train_path, format="saved-model")

        # Close runner
        runner.close()

        # Get metrics
        metrics = self.play(self.train_dir_name, episodes)

        # Save metrics
        result = json.dumps(metrics, indent=4, sort_keys=True)
        self._append_file(path=f"{self.train_path}/info.txt", content=result)

        return metrics

    def apply_prediction(
        self, kniffel: Kniffel, enum_action: EnumAction, logging=False
    ):
        if logging:
            print(f"      Action: {enum_action}")

        if EnumAction.FINISH_ONES is enum_action:
            kniffel.finish_turn(KniffelOptions.ONES)
        if EnumAction.FINISH_TWOS is enum_action:
            kniffel.finish_turn(KniffelOptions.TWOS)
        if EnumAction.FINISH_THREES is enum_action:
            kniffel.finish_turn(KniffelOptions.THREES)
        if EnumAction.FINISH_FOURS is enum_action:
            kniffel.finish_turn(KniffelOptions.FOURS)
        if EnumAction.FINISH_FIVES is enum_action:
            kniffel.finish_turn(KniffelOptions.FIVES)
        if EnumAction.FINISH_SIXES is enum_action:
            kniffel.finish_turn(KniffelOptions.SIXES)
        if EnumAction.FINISH_THREE_TIMES is enum_action:
            kniffel.finish_turn(KniffelOptions.THREE_TIMES)
        if EnumAction.FINISH_FOUR_TIMES is enum_action:
            kniffel.finish_turn(KniffelOptions.FOUR_TIMES)
        if EnumAction.FINISH_FULL_HOUSE is enum_action:
            kniffel.finish_turn(KniffelOptions.FULL_HOUSE)
        if EnumAction.FINISH_SMALL_STREET is enum_action:
            kniffel.finish_turn(KniffelOptions.SMALL_STREET)
        if EnumAction.FINISH_LARGE_STREET is enum_action:
            kniffel.finish_turn(KniffelOptions.LARGE_STREET)
        if EnumAction.FINISH_KNIFFEL is enum_action:
            kniffel.finish_turn(KniffelOptions.KNIFFEL)
        if EnumAction.FINISH_CHANCE is enum_action:
            kniffel.finish_turn(KniffelOptions.CHANCE)

        # Continue enum_actions
        if EnumAction.NEXT_0 is enum_action:
            kniffel.add_turn(keep=[0, 0, 0, 0, 0])
        if EnumAction.NEXT_1 is enum_action:
            kniffel.add_turn(keep=[0, 0, 0, 0, 1])
        if EnumAction.NEXT_2 is enum_action:
            kniffel.add_turn(keep=[0, 0, 0, 1, 0])
        if EnumAction.NEXT_3 is enum_action:
            kniffel.add_turn(keep=[0, 0, 0, 1, 1])
        if EnumAction.NEXT_4 is enum_action:
            kniffel.add_turn(keep=[0, 0, 1, 0, 0])
        if EnumAction.NEXT_5 is enum_action:
            kniffel.add_turn(keep=[0, 0, 1, 0, 1])
        if EnumAction.NEXT_6 is enum_action:
            kniffel.add_turn(keep=[0, 0, 1, 1, 0])
        if EnumAction.NEXT_7 is enum_action:
            kniffel.add_turn(keep=[0, 0, 1, 1, 1])
        if EnumAction.NEXT_8 is enum_action:
            kniffel.add_turn(keep=[0, 1, 0, 0, 0])
        if EnumAction.NEXT_9 is enum_action:
            kniffel.add_turn(keep=[0, 1, 0, 0, 1])
        if EnumAction.NEXT_10 is enum_action:
            kniffel.add_turn(keep=[0, 1, 0, 1, 0])
        if EnumAction.NEXT_11 is enum_action:
            kniffel.add_turn(keep=[0, 1, 0, 1, 1])
        if EnumAction.NEXT_12 is enum_action:
            kniffel.add_turn(keep=[0, 1, 1, 0, 0])
        if EnumAction.NEXT_13 is enum_action:
            kniffel.add_turn(keep=[0, 1, 1, 0, 1])
        if EnumAction.NEXT_14 is enum_action:
            kniffel.add_turn(keep=[0, 1, 1, 1, 0])
        if EnumAction.NEXT_15 is enum_action:
            kniffel.add_turn(keep=[0, 1, 1, 1, 1])
        if EnumAction.NEXT_16 is enum_action:
            kniffel.add_turn(keep=[1, 0, 0, 0, 0])
        if EnumAction.NEXT_17 is enum_action:
            kniffel.add_turn(keep=[1, 0, 0, 0, 1])
        if EnumAction.NEXT_18 is enum_action:
            kniffel.add_turn(keep=[1, 0, 0, 1, 0])
        if EnumAction.NEXT_19 is enum_action:
            kniffel.add_turn(keep=[1, 0, 0, 1, 1])
        if EnumAction.NEXT_20 is enum_action:
            kniffel.add_turn(keep=[1, 0, 1, 0, 0])
        if EnumAction.NEXT_21 is enum_action:
            kniffel.add_turn(keep=[1, 0, 1, 0, 1])
        if EnumAction.NEXT_22 is enum_action:
            kniffel.add_turn(keep=[1, 0, 1, 1, 0])
        if EnumAction.NEXT_23 is enum_action:
            kniffel.add_turn(keep=[1, 0, 1, 1, 1])
        if EnumAction.NEXT_24 is enum_action:
            kniffel.add_turn(keep=[1, 1, 0, 0, 0])
        if EnumAction.NEXT_25 is enum_action:
            kniffel.add_turn(keep=[1, 1, 0, 0, 1])
        if EnumAction.NEXT_26 is enum_action:
            kniffel.add_turn(keep=[1, 1, 0, 1, 0])
        if EnumAction.NEXT_27 is enum_action:
            kniffel.add_turn(keep=[1, 1, 0, 1, 1])
        if EnumAction.NEXT_28 is enum_action:
            kniffel.add_turn(keep=[1, 1, 1, 0, 0])
        if EnumAction.NEXT_29 is enum_action:
            kniffel.add_turn(keep=[1, 1, 1, 0, 1])
        if EnumAction.NEXT_30 is enum_action:
            kniffel.add_turn(keep=[1, 1, 1, 1, 0])

        if EnumAction.FINISH_ONES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.ONES_SLASH)
        if EnumAction.FINISH_TWOS_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.TWOS_SLASH)
        if EnumAction.FINISH_THREES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.THREES_SLASH)
        if EnumAction.FINISH_FOURS_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.FOURS_SLASH)
        if EnumAction.FINISH_FIVES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.FIVES_SLASH)
        if EnumAction.FINISH_SIXES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.SIXES_SLASH)
        if EnumAction.FINISH_THREE_TIMES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.THREE_TIMES_SLASH)
        if EnumAction.FINISH_FOUR_TIMES_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.FOUR_TIMES_SLASH)
        if EnumAction.FINISH_FULL_HOUSE_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.FULL_HOUSE_SLASH)
        if EnumAction.FINISH_SMALL_STREET_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.SMALL_STREET_SLASH)
        if EnumAction.FINISH_LARGE_STREET_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.LARGE_STREET_SLASH)
        if EnumAction.FINISH_KNIFFEL_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.KNIFFEL_SLASH)
        if EnumAction.FINISH_CHANCE_SLASH is enum_action:
            kniffel.finish_turn(KniffelOptions.CHANCE_SLASH)

    def predict_and_apply(self, agent, kniffel: Kniffel, state, logging=False):
        action = agent.forward(state)

        enum_action = EnumAction(action)

        self.apply_prediction(kniffel, enum_action, logging)

        return enum_action

    # Play model
    def play(
        self,
        dir_name,
        episodes,
        write=False,
    ):
        print(f"Play {episodes} games from model {dir_name}.")
        print()

        metrics = self.use_model(
            dir_name,
            episodes,
            write=write,
        )

        return metrics

    def build_use_agent(
        self,
        path,
        env,
        weights_name="weights",
        logging=False,
    ):
        f = open(f"{path}/configuration.json")
        self._hyperparater_base = dict(json.load(f))

        if logging:
            print(f"Load weights {path}/{weights_name}.h5f")

        agent = Agent.load(directory=path, format="checkpoint", environment=env)

        return agent

    # Batch inputs
    def batch(self, x):
        return np.expand_dims(x, axis=0)

    # Unbatch outputs
    def unbatch(self, x):
        if isinstance(x, tf.Tensor):  # TF tensor to NumPy array
            x = x.numpy()  # type: ignore
        if x.shape == (1,):  # Singleton array to Python value
            return x.item()
        else:
            return np.squeeze(x, axis=0)

    def calculate_custom_metric(self, l: list):
        sm_list = [np.power(v, 2) if v > 0 else -1 * np.power(v, 2) for v in l]  # type: ignore
        return np.mean(sm_list)

    def use_model(
        self,
        dir_name,
        episodes,
        write=False,
    ):
        points = []
        rounds = []
        break_counter = 0

        print("Start playing games...")

        path = os.path.join("output", "weights", dir_name)

        agent_path = os.path.join(path, "best-model.json")

        print(f"Use agent from {agent_path}")

        bar = IncrementalBar(
            "Games played",
            max=episodes,
            suffix="%(index)d/%(max)d - %(eta)ds",
        )

        kniffel_env: KniffelEnvHelper = KniffelEnvHelper(
            self.env_config,
            logging=False,
            reward_mode=self.reward_mode,
            state_mode=self.state_mode,
        )

        agent: tf.keras.Model = tf.saved_model.load(export_dir=path)

        for e in range(1, episodes + 1):
            bar.next()

            if write:
                self._append_file(
                    path=f"{path}/game_log/log.txt",
                    content="\n".join(KniffelDraw().draw_kniffel_title().split("\n")),
                )

            kniffel_env.reset_kniffel()

            rounds_counter = 1

            done = False
            while not done:
                log_csv = []

                # Get current state
                state = kniffel_env.get_state()

                # Get action from state
                states = self.environment.reset()
                states = self.batch(states)
                auxiliaries = dict(mask=np.ones(shape=(1, 57), dtype=bool))
                deterministic = True

                # Get action
                action = agent.act(states, auxiliaries, deterministic)

                # Unbatch action
                actions = self.unbatch(action)

                # Convert action to EnumAction
                enum_action = EnumAction(actions)

                # Apply action
                reward, done, info = kniffel_env.predict_and_apply(action)

                # LOG

                log_csv.append(
                    f"\n####################################################################################\n"
                )

                log_csv.append(f"##  Try: {rounds_counter}\n")

                log_csv.append(
                    f"##  Attempts left: {kniffel_env.kniffel.get_last().attempts_left()}/3\n"
                )
                log_csv.append(f"##  Action: {enum_action}\n")

                log_csv.append("\n\n" + KniffelDraw().draw_dices(state[0][0:30]))

                log_csv.append("\n" + KniffelDraw().draw_sheet(kniffel_env.kniffel))

                if not done:
                    rounds_counter += 1

                else:
                    if not info["error"]:
                        points.append(kniffel_env.kniffel.get_points())
                        rounds.append(rounds_counter)
                        rounds_counter = 1

                        # LOG

                        log_csv.append(
                            "####################################################################################\n"
                        )
                        log_csv.append(
                            "####################################################################################\n"
                        )
                        log_csv.append("##  Finished:\n")
                        log_csv.append("##    Error: False\n")
                        log_csv.append("##    Game Finished: True\n")

                        if write:
                            self._append_file(
                                path=f"{path}/game_log/log.txt",
                                content="\n" + ", ".join(log_csv),
                            )

                        break
                    else:
                        points.append(kniffel_env.kniffel.get_points())
                        rounds.append(rounds_counter)
                        break_counter += 1
                        rounds_counter = 1

                        # LOG

                        log_csv.append(
                            "\n\n####################################################################################"
                        )
                        log_csv.append(
                            "\n####################################################################################\n"
                        )
                        log_csv.append("##  Error:\n")
                        log_csv.append("##    Error: True\n")

                        error_description = str(info["exception_description"])
                        log_csv.append(f"##    Error: {error_description}\n")
                        log_csv.append("##    Prediction Allowed: False\n")

                        if write:
                            self._append_file(
                                path=f"{path}/game_log/log.txt",
                                content="\n" + "".join(log_csv),
                            )

                        break

                if write:
                    self._append_file(
                        path=f"{path}/game_log/log.txt",
                        content="\n" + "".join(log_csv),
                    )

                log_csv = []

            if write:
                self._append_file(path=f"{path}/game_log/log.txt", content="\n\n")

        bar.finish()

        metrics = {
            "finished_games": episodes - break_counter,
            "error_games": break_counter,
            "rounds_played": episodes,
            "average_points": np.mean(points),
            "max_points": max(points),
            "min_points": min(points),
            "average_rounds": np.mean(rounds),
            "max_rounds": max(rounds),
            "min_rounds": min(rounds),
            "custom_metric": self.calculate_custom_metric(points),
        }

        print(json.dumps(metrics, indent=4, sort_keys=True))

        return metrics

if __name__ == "__main__":
    warnings.filterwarnings("ignore", category=DeprecationWarning)

    env_config = {
        "reward_roll_dice": 0,
        "reward_game_over": -0,
        "reward_finish": 25,
        "reward_bonus": 100,
        "reward_mode": "custom",  # custom or kniffel
        "state_mode": "continuous",  # binary or continuous
        "reward_kniffel": {
            "reward_ones": {
                "reward_five_dices": 5,
                "reward_four_dices": 4.0,
                "reward_three_dices": 2.0,
                "reward_two_dices": -0,
                "reward_one_dice": -1,
                "reward_slash": -2,
            },
            "reward_twos": {
                "reward_five_dices": 10.0,
                "reward_four_dices": 8.0,
                "reward_three_dices": 6.0,
                "reward_two_dices": -2,
                "reward_one_dice": -3,
                "reward_slash": -4,
            },
            "reward_threes": {
                "reward_five_dices": 15.0,
                "reward_four_dices": 12.0,
                "reward_three_dices": 9.0,
                "reward_two_dices": -3,
                "reward_one_dice": -4.5,
                "reward_slash": -6,
            },
            "reward_fours": {
                "reward_five_dices": 20.0,
                "reward_four_dices": 16.0,
                "reward_three_dices": 12.0,
                "reward_two_dices": -4,
                "reward_one_dice": -6,
                "reward_slash": -8,
            },
            "reward_fives": {
                "reward_five_dices": 25.0,
                "reward_four_dices": 20.0,
                "reward_three_dices": 15.0,
                "reward_two_dices": -5,
                "reward_one_dice": -7.5,
                "reward_slash": -10,
            },
            "reward_sixes": {
                "reward_five_dices": 30.0,
                "reward_four_dices": 24.0,
                "reward_three_dices": 18.0,
                "reward_two_dices": -6,
                "reward_one_dice": -9,
                "reward_slash": -12,
            },
            "reward_three_times": {
                "reward_five_dices": 20.0,
                "reward_four_dices": 24.0,
                "reward_three_dices": 18.0,
                "reward_two_dices": 9.0,
                "reward_one_dice": 0.9,
                "reward_slash": -0,
            },
            "reward_four_times": {
                "reward_five_dices": 35.0,
                "reward_four_dices": 40.0,
                "reward_three_dices": 15.0,
                "reward_two_dices": 5,
                "reward_one_dice": 0.7,
                "reward_slash": -12,
            },
            "reward_full_house": {
                "reward_five_dices": 50.0,
                "reward_four_dices": None,
                "reward_three_dices": None,
                "reward_two_dices": None,
                "reward_one_dice": None,
                "reward_slash": -0,
            },
            "reward_small_street": {
                "reward_five_dices": 1.0,
                "reward_four_dices": 25.0,
                "reward_three_dices": None,
                "reward_two_dices": None,
                "reward_one_dice": None,
                "reward_slash": -0,
            },
            "reward_large_street": {
                "reward_five_dices": 60.0,
                "reward_four_dices": None,
                "reward_three_dices": None,
                "reward_two_dices": None,
                "reward_one_dice": None,
                "reward_slash": -0,
            },
            "reward_kniffel": {
                "reward_five_dices": 100.0,
                "reward_four_dices": None,
                "reward_three_dices": None,
                "reward_two_dices": None,
                "reward_one_dice": None,
                "reward_slash": -25,
            },
            "reward_chance": {
                "reward_five_dices": 5,
                "reward_four_dices": 4,
                "reward_three_dices": 3,
                "reward_two_dices": 2,
                "reward_one_dice": 1,
                "reward_slash": -0,
            },
        },
    }

    agent_path = "src/tensorforce/agent.json"

    rl = KniffelRL(
        agent_path=agent_path,
        base_path=str(Path(__file__).parents[2]) + "/",
        env_config=env_config,
        env_observation_space=47,
        env_action_space=57,
    )

    rl.train(10_000)
    # rl.play(dir_name="p_date=2022-12-19-22_11_30", episodes=5, write=True)


from pyspark.sql import SparkSession

spark = SparkSession \
    .builder \
    .appName("Python Spark regression example") \
    .config("spark.some.config.option", "some-value") \
    .getOrCreate()

# from PySparkAudit import dtypes_class, hist_plot, bar_plot, freq_items,feature_len
# from PySparkAudit import dataset_summary, rates, trend_plot

# path = '/home/feng/Desktop'

from AutoFeatures import AutoFeatures

# load dataset
data = spark.read.csv(path='../data/credit_example.csv',
                      sep=',', encoding='UTF-8', comment=None, header=True, inferSchema=True)
data = data.fillna(0)

print(data.toPandas().head(5))

indexCol = ['SK_ID_CURR']
labelCol = 'TARGET'

task = 'classification'

Fs = AutoFeatures()

# correlation selector
to_drop = Fs.corr_selector(data, index_col=indexCol, label_col=labelCol,
                           corr_thold=0.9, method="pearson", rotation=True,
                           display=False, tracking=False, cat_num=2)
print('corr_selector::{}'.format(to_drop))

# essential selector (included: missing selector, unique selector, correlation selector)
to_drop = Fs.essential_drop(data, index_col=indexCol, label_col=labelCol,
                            missing_thold=0.6, corr_thold=0.9, method="pearson", rotation=True,
                            display=True, tracking=True, cat_num=2)
print('essential_drop::{}'.format(to_drop))

# ensemble selector (ensemble selector is based on essential selector.)
to_drop = Fs.ensemble_drop(data, index_col=indexCol, label_col=labelCol, task=task, tracking=True)
print('ensemble_drop::{}'.format(to_drop))


import torch
from torch import nn
from torchvision import models
from torchvision import transforms
from torch.nn import functional as F

from .evaluator_backend import EvaluatorBackend

class ResNet18(EvaluatorBackend):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.dev = "cuda:0"
        self._model = models.resnet18()
        self._model.fc = torch.nn.Linear(512, 1)
        self._model.load_state_dict(torch.load(str(self.trained_model),
                                               map_location='cpu'))
        self._model.eval()
        self._model.to(self.dev)

        self.img_size = 256

        try:
            self._style_model = nn.Linear(512, 1)
            # self._style_model = nn.Sequential(nn.Linear(512, 1), nn.Sigmoid())
            pth = '.'.join(str(self.trained_model).split('.')[:-1]) + '-latent.pt'
            print(f'latent model: {pth}')
            self._style_model.load_state_dict(torch.load(pth, map_location='cpu'))
            self._style_model.eval()
            self._style_model.to(self.dev)
            self._latent_model_available = True
        except:
            self._latent_model_available = False
            print('no latent model available')

        mean = [0.485, 0.456, 0.406]
        std = [0.229, 0.224, 0.225]
        self.normalize = transforms.Normalize(mean, std)
        self.multiplier = 1.
        # self.multiplier = 0.25

        for mod in self._model.modules():
            if hasattr(mod, 'inplace'):
                mod.inplace = False

    def rate_image_batch(self, image_batch: torch.Tensor, enable_grad: bool = False) -> torch.Tensor:
        torch.cuda.empty_cache()
        if enable_grad:
            image_batch = F.interpolate(image_batch, size=self.img_size)
            return self._model(self.normalize(image_batch))
        else:
            with torch.no_grad():
                image_batch = F.interpolate(image_batch, size=self.img_size)
                return torch.tanh(self.multiplier * self._model(self.normalize(image_batch)))

    def rate_style_batch(self, style_batch: torch.Tensor, enable_grad: bool = False) -> torch.Tensor:
        if not self._latent_model_available:
            return None
        if enable_grad:
            return self._style_model(style_batch)
        else:
            with torch.no_grad():
                return self._style_model(style_batch)


from google.cloud import bigquery

SERVICE_ACCOUNT_JSON = r'C:\Users\shrijha\Desktop\testproject_credentials.json'

client = bigquery.Client.from_service_account_json(SERVICE_ACCOUNT_JSON)

table_id = "testproject123456789-313307.beam_samples.test_table"

job_config = bigquery.LoadJobConfig(
        autodetect=True, source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON
    )
uri = "gs://bqtest987654321/site.json"
load_job = client.load_table_from_uri(
    uri, table_id, job_config=job_config
)
load_job.result()
destination_table = client.get_table(table_id)


from app_template import *
from dormListPanel import DormListPanel
import wx.lib.scrolledpanel
import csv

# User: user main system

# Get dorm icon path
imgDir = 'img/'
icon = '/icon.jpg'
fullIconPath = ''

class User(wx.App):
    def __init__(self):
        super().__init__()
        self.frame = MyFrame(parent=None, title='RENT-A-DORM', size=(1080, 720))
        self.frame.Center()
        self.frame.Show()

class MyFrame(wx.Frame):
    def __init__(self, parent, title, size):
        super().__init__(parent=parent, title=title, size=size)
        self.SetMinSize(size)
        self.SetMaxSize(size)

        self.panel = MyPanel(parent=self)

# Set panel as default template
class MyPanel(Template):
    def __init__(self, parent):
        super().__init__(parent=parent)
        self.SetBackgroundColour('#f3bad6')
        self.title_panel.SetBackgroundColour('#e05297')

        # Display data
        self.data_panel = DataPanel(parent=self)

        self.hpanel_box = wx.BoxSizer(wx.HORIZONTAL)
        self.hpanel_box.AddSpacer(60)

        self.vpanel_box.Add(self.data_panel)
        self.vpanel_box.Add(self.hpanel_box)

class DataPanel(wx.Panel):
    def __init__(self, parent):
        super().__init__(parent=parent)

        # Color, Font, and Style
        self.SetBackgroundColour('#f3bad6')

        # Layout
        self.vsizer = wx.BoxSizer(wx.VERTICAL)
        self.vsizer.AddSpacer(20)
        self.top_sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.top_sizer.AddSpacer(60)

        # Log Out button
        self.logOut_button = wx.Button(self, label='Log Out', size=(200, 33))
        self.top_sizer.Add(self.logOut_button, wx.ALL)
        self.vsizer.Add(self.top_sizer)
        self.vsizer.AddSpacer(30)
        # EVT
        self.logOut_button.Bind(wx.EVT_BUTTON, self.logOutClicked)

        # Dorm List scrolled panel
        self.hsizer = wx.BoxSizer(wx.HORIZONTAL)
        self.hsizer.AddSpacer(60)

        self.scroll_panel = wx.lib.scrolledpanel.ScrolledPanel(self, size=(955, 500), style=wx.SIMPLE_BORDER)
        self.scroll_panel.SetupScrolling()
        self.scroll_panel.SetBackgroundColour('#fceef5')

        self.scroll_vsizer = wx.BoxSizer(wx.VERTICAL)
        self.scroll_vsizer.AddSpacer(20)

        # List of dorm information
        self.dorm_list = []
        # Read every row from csv file and store in a list
        with open('assets/dorm.csv', newline='') as f:
            reader = csv.reader(f)
            dormList = reader
            for row in dormList:
                self.dorm_list.append(row)

        tempSet = set()
        # Match dorm name with directory
        self.dormName = []
        # Change dorm name to all lower case
        for i in self.dorm_list:
            tempSet.add(i[1])
            self.dormName.append(i[0].lower())

        tempList = []
        # Dictionary to store path of each icon
        self.iconPath = {}
        # Replace all space bar with _
        for i in range(len(self.dormName)):
            temp = self.dormName[i].replace(' ', '_')
            tempList.append(temp)
            self.iconPath[self.dorm_list[i][0]] = temp
        self.dormName = tempList

        # Add dorm into dorm lists
        for i in range(len(self.dorm_list)):
            # Get icon path
            full_iconPath = imgDir + self.iconPath.get(self.dorm_list[i][0]) + icon
            dorm_list = DormListPanel(self.scroll_panel, self.dorm_list[i], full_iconPath)
            self.scroll_vsizer.Add(dorm_list, flag=wx.ALIGN_CENTER | wx.ALL, border=10)

        self.scroll_panel.SetSizer(self.scroll_vsizer)
        self.hsizer.Add(self.scroll_panel)

        # Initialize
        self.vsizer.Add(self.hsizer)
        self.SetSizer(self.vsizer)

    # EVT Functions
    def logOutClicked(self, event):
        app = self.GetParent().GetParent()
        app.Destroy()
        wx.Exit()

if __name__ == "__main__":
    user = User()
    user.MainLoop()


'''
Description: 请填写文件简介
Version: 0.0
Autor: jlx
Date: 2022-08-25 16:00:24
LastEditors: jlx
LastEditTime: 2022-08-25 17:39:57
'''
import re
import json
import requests
import time
from bs4 import BeautifulSoup

# 推荐文章接口
url = "https://api.juejin.cn/recommend_api/v1/article/recommend_all_feed"
# 抓包 获取的参数
info = {"id_type": 2, "client_type": 2608, "sort_type": 200, "cursor": "0", "limit": 20}
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36',
}
#  标记是否有更多数据
has_more = True

# 利用set 取一下重
dataSet = set()
# 存储数据的列表
dataList = []
# 需要的数据 数量
num = int(input("需要多少条文章数据："))

# 根据文章id获取文章的content
def get_content(aid):
    childUrl = f"https://juejin.cn/post/{aid}"
    childResp = requests.get(childUrl, headers=headers)
    childResp.encoding = "utf-8"
    content = childResp.text
    # print(content)

    res = re.findall('mark_content:"(.*?)",display_count:d', content)[0]
    res = re.sub(r'(\\u[\s\S]{4})', lambda x: x.group(1).encode("utf-8").decode("unicode-escape"), res)
    res = res.strip('"')
    return res

# 获取文章数据
def get_data():
    global has_more,num
    resp = requests.post(url, json=info, headers=headers)  # data自动使用json方式发送
    data = json.loads(resp.text)
    info["cursor"] = data["cursor"]
    has_more = data["has_more"]
    for i in data["data"]:
        item = i["item_info"]
        try:  # 去除广告推广内容的报错
            if item["article_id"] and len(dataSet) < num:
                if item["article_id"] in dataSet:
                    continue
                dataSet.add(item["article_id"])
                dic = {}
                content = get_content(item["article_id"])
                # id 封面 标题 简介 创建时间 修改事件 作者 头像 文章内容
                dic["article_id"] = item["article_id"]
                dic["cover_image"] = item["article_info"]["cover_image"]
                dic["title"] = item["article_info"]["title"]
                dic["brief"] = item["article_info"]["brief_content"]
                dic["ctime"] = item["article_info"]["ctime"]
                dic["mtime"] = item["article_info"]["mtime"]
                dic["user_name"] = item["author_user_info"]["user_name"]
                dic["avatar"] = item["author_user_info"]["avatar_large"]
                dic["content"] = content
                dataList.append(dic)

        except:
            continue
    print(f"当前{len(dataSet)}条数据已整理完毕！")
    time.sleep(4)

while has_more and len(dataSet) < num:
    get_data()

with open("article.json", "w", encoding="utf-8") as f:
    json.dump(dataList, f, indent=4, ensure_ascii=False)
f.close()

# 完成提示
print("over!!!")

# 最后结束提示
# 使用前需要进行 replace \\n  => \n 否则会出现乱码


import sys

fs = {}
dstack = []

small = []
all_dirs = []

with open(sys.argv[1], "rt") as input_file:
    for line in input_file:
        if line.startswith('$ cd '):
            arg = line[5:].strip()
            if arg == "/":
                dstack = [fs]
            elif arg == "..":
                last = dstack.pop(-1)
                dstack[-1]["$total"] += last["$total"]
                all_dirs.append(last["$total"])
                if last["$total"] <= 100000:
                    small.append(last["$total"])
            else:
                dstack.append(dstack[-1][arg])
        elif line.startswith("$ ls"):
            dstack[-1]["$total"] = 0
        else:
            val, name = line.strip().split(' ')
            if val == "dir":
                dstack[-1][name] = {}
            else:
                val = int(val)
                dstack[-1][name] = val
                dstack[-1]["$total"] += val
if len(dstack) > 1:
    last = dstack.pop(-1)
    dstack[-1]["$total"] += last["$total"]
    all_dirs.append(last["$total"])

print("Total Size:", fs["$total"])
print("Sum of Small Dirs", sum(small))

total_space = 70000000
required_space = 30000000
free_space = total_space - fs["$total"]
need_space = required_space - free_space
print("Needed Space:", need_space)

candidates = [d for d in all_dirs if d >= need_space]
print(min(candidates))


from model.contact import Contact
from model.group import Group
import random

def test_add_some_contact_in_group(app, orm):
    # проверка, что существует группа
    if len(orm.get_group_list()) == 0:
        app.group.create(Group("fsdfsf", "dfsfs", "fsdfs"))

    # получаем список групп
    groups = orm.get_group_list()
    group = random.choice(groups)

    # проверяем, существуют ли контакты, не принадлежащие выбранной группе
    if len(orm.get_contacts_not_in_group(group)) == 0:
        app.contact.create_contact(
            Contact(firstname="Kat", middlename="Al", address="Kzn", homephone="66675666", email="e@m.com"))

    # получаем список контактов, которые отсуствуют в выбранной группе
    contacts = orm.get_contacts_not_in_group(group)
    contact = random.choice(contacts)

    app.contact.add_contact_to_group_by_id(contact.id, group.id)
    assert contact in orm.get_contacts_in_group(group)


import os
import logging

from urllib import request

from fades import helpers

logger = logging.getLogger(__name__)

PIP_INSTALLER = "https://bootstrap.pypa.io/get-pip.py"

class PipManager():
    """A manager for all PIP related actions."""
    def __init__(self, env_bin_path, pip_installed=False):
        self.env_bin_path = env_bin_path
        self.pip_installed = pip_installed
        self.pip_exe = os.path.join(self.env_bin_path, "pip")
        basedir = helpers.get_basedir()
        self.pip_installer_fname = os.path.join(basedir, "get-pip.py")

    def install(self, dependency):
        """Install a new dependency."""
        if not self.pip_installed:
            logger.info("Need to install a dependency with pip, but no builtin, "
                        "doing it manually (just wait a little, all should go well)")
            self._brute_force_install_pip()

        str_dep = str(dependency)
        args = [self.pip_exe, "install", str_dep]
        logger.info("Installing dependency: %s", str_dep)
        try:
            helpers.logged_exec(args)
        except Exception as error:
            logger.exception("Error installing %s: %s", str_dep, error)
            exit()

    def get_version(self, dependency):
        """Returns the installed version parsing the output of 'pip show'."""
        logger.debug("getting installed version for %s", dependency)
        stdout = helpers.logged_exec([self.pip_exe, "show", dependency])
        version = [line for line in stdout if line.startswith('Version:')]
        if len(version) == 1:
            version = version[0].strip().split()[1]
            logger.debug("Installed version of %s is: %s", dependency, version)
            return version
        else:
            logger.error('Fades is having problems getting the installed version. '
                         'Run with -v or check the logs for details')
            return ''

    def _brute_force_install_pip(self):
        """A brute force install of pip itself."""
        if os.path.exists(self.pip_installer_fname):
            logger.debug("Using pip installer from %r", self.pip_installer_fname)
        else:
            logger.debug(
                "Installer for pip not found in %r, downloading it", self.pip_installer_fname)
            u = request.urlopen(PIP_INSTALLER)
            with open(self.pip_installer_fname, 'wb') as fh:
                fh.write(u.read())

        logger.debug("Installing PIP manually in the virtualenv")
        python_exe = os.path.join(self.env_bin_path, "python")
        helpers.logged_exec([python_exe, self.pip_installer_fname])
        self.pip_installed = True


from django import forms

from inventory.models import *

class ProductForm(forms.ModelForm):
    class Meta:
        model = Product
        fields = '__all__'

class SupplierForm(forms.ModelForm):
    class Meta:
        model = Supplier
        fields = '__all__'

class TransactionForm(forms.ModelForm):
    class Meta:
        model = Transaction
        fields = '__all__'

class QueryForm(forms.Form):
    query = forms.CharField(required=False)
    query_by = forms.CharField()
    query_limit = forms.IntegerField(initial=100, required=False)
    order_by = forms.CharField(empty_value='pk')
    order_type = forms.ChoiceField(choices=[
        ('desc', 'desc'),
        ('ascn', 'ascn')
    ], required=False)

class TransactionQueryForm(forms.Form):
    query_by = forms.CharField()
    query_by_suffix = forms.CharField(required=False, empty_value='icontains')
    query = forms.CharField(required=False)
    query_limit = forms.IntegerField(initial=100, required=False)
    order_by = forms.CharField(empty_value='created_on')
    order_type = forms.ChoiceField(choices=[
        ('desc', 'desc'),
        ('ascn', 'ascn')
    ], required=False)