import numpy as np
import cv2
import shake
import sys
#
#  process image data: find edge, reduce data by mask
#
def imageProc(image, roiVertice, verticeI):

    image = windowFront(image, roiVertice)
    # cv2.imshow('Test', image) # output shown on screen is RGB image, therefore input is BGR
    #
    # use Clahe to raise contrast
    #
    image = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)
    h,l,s = cv2.split(image)
    clahe = cv2.createCLAHE(clipLimit=1.5, tileGridSize=(8,8))
    l     = clahe.apply(l)

    # kernelc = np.ones((11,11), np.uint8)
    # kernelo = np.ones((6,6), np.uint8)
    #s = cv2.morphologyEx(s, cv2.MORPH_CLOSE, kernelc)   # close separate white spots
    #s = cv2.morphologyEx(s, cv2.MORPH_OPEN,  kernelo)   # delete separate white spots

    image = cv2.merge((h,l,s))
    image = cv2.cvtColor(image, cv2.COLOR_HLS2BGR)
    # cv2.imshow('After CLAHE Correction', image)

    if False:    # masking colors

      if True:
        image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
        # catch good white lines under the sun
        lower = np.array([20-4,2,250-4])
        upper = np.array([30+4,6+4,254])
        # lower = np.array([30-1,6-1,253-1])
        # upper = np.array([30+1,6+1,253+1])
        mask  = cv2.inRange(image, lower, upper)
        mask[mask > 0] = 255

        # catch good yellow lines under the sun
        lower    = np.array([23-4,64-4,246-4])
        upper    = np.array([25+4,106+4,253])
        maskTemp = cv2.inRange(image, lower, upper)
        maskTemp[maskTemp > 0] = 255
        mask     = np.add(mask, maskTemp, dtype=np.uint8)

        # catch good white lines under steet light
        lower    = np.array([108-4,21-8,144-4])
        upper    = np.array([113+4,57+4,206+22])
        maskTemp = cv2.inRange(image, lower, upper)
        maskTemp[maskTemp > 0] = 255
        mask     = np.add(mask, maskTemp, dtype=np.uint8)

        # catch dirty yellow lines under steet light
        lower    = np.array([14-4, 121-4, 83-4])
        upper    = np.array([22+4, 185+8, 157+4])
        maskTemp = cv2.inRange(image, lower, upper)
        maskTemp[maskTemp > 0] = 255
        mask     = np.add(mask, maskTemp, dtype=np.uint8)

      # # yellow in tunnel
      # lower    = np.array([20-1,  97-10, 51-2])
      # upper    = np.array([21+4, 100+2,  66+5])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # dirty white in tunnel
      # lower    = np.array([ 16, 133,  71])
      # upper    = np.array([ 19, 175, 130])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # dirty white1 in tunnel
      # lower    = np.array([106,  48,  47])
      # upper    = np.array([109,  60,  59])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dirty dashed white lines
      # lower    = np.array([24-2,   9-0, 200+4])
      # upper    = np.array([60-24, 34+8, 236+32])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dirty1 dashed white lines
      # lower    = np.array([20,  8, 180])
      # upper    = np.array([30, 21, 237])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dashed white lines
      # lower    = np.array([24-5, 27-5,  244-5])
      # upper    = np.array([24+5, 27+5, 244+5])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dashed very white lines
      # lower    = np.array([19-12, 2,   249-9])
      # upper    = np.array([30+15, 8+4, 251+4])
      # maskTemp = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dirty yellow lines under the sun
      # lower = np.array([22-4,  51, 171-6])
      # upper = np.array([25+4, 109, 227])
      # maskTemp  = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch white lines under shadow
      # lower = np.array([107,  48,  69])
      # upper = np.array([112,  61, 118])
      # maskTemp  = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # # catch dirty white lines
      # lower = np.array([ 20,   1, 147])
      # upper = np.array([111,  20, 224])
      # maskTemp  = cv2.inRange(image, lower, upper)
      # maskTemp[maskTemp > 0] = 255
      # mask = np.add(mask, maskTemp, dtype=np.uint8)

      # cv2.imshow('before shake', np.array(mask))

      # shake a few times
      # for i in range(1, 2): mask = shake.mask(mask, 1)
      #mask = maskShake(mask, 3)

  ##    kernel1 = np.ones((11,11), np.uint8)
  ##    kernel2 = np.ones((6,6), np.uint8)
  ##    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE,  kernel1)  # close separate white spots
  ##    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel2)   # delete separate white spots
      # cv2.imshow('After shake', np.array(mask))

      # mask = cv2.GaussianBlur(mask, (3,3), 0)
      # mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel2)  # close white spots
      # mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN,  kernel1)  # delete separate white spots
      # mask = cv2.GaussianBlur(mask, (3,3), 0)
      # image[mask > 0] = [0,0,0]
      #image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
      cv2.imshow('Gray befor Canny', cv2.resize(image,(417,155)))

      if True:
        # get V channel mean of low half of the window
        nLowhalf       = np.uint32(len(image[:,1,1])/2)
        intensityLight = np.mean(image[nLowhalf:,:,2])
        # print('                     intensity: ',intensityLight)

        # set the masked region to black for all channels of image: yellow middle line is marked as black

        if intensityLight < 52:
            # in dark
            image[mask > 0] = [255,255,255]
        else:
            # bright
            image[mask > 0] = [0,0,0]

      image = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
      cv2.imshow('Color befor Canny', cv2.resize(image,(417,155)))
    elif True:
      if True:
        # make S channel of HLS (RGB2HLS for a BGR image)as image for Canny: good for yellow lines under the sun (both RGB2HLS and BGR2HLS work, BGR2HLS is better)
        # make S channel of HSV (RGB2HSV for a BGR image) as image for Canny: good for yellow lines under the sun (both RGB2HLS and BGR2HLS work)
        # image = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

        image = extractColor(image)

        image = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)
        _,l,image1 = cv2.split(image)
        #print ("   hls=", np.min(l),np.max(l), np.min(image1),np.max(image1))

        # use my filter
#        image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
#        _,image,_ = cv2.split(image)

        #
        # make threshold intensity dependent
        #
#        mask = np.zeros_like(l)
#        cv2.fillPoly(mask, verticeI, 255)
#        intensityLight = np.mean(l)
#        #print("                     intensityLight: ", intensityLight)
#        tempVar = np.min([250.0, intensityLight*1.8])
#        thresholdSH = np.uint8(tempVar)
#        thresholdSL = np.uint8(intensityLight*1.1)
#        image[l>thresholdSH] = 255
#        image[l<thresholdSL] = 0
#
#        kernelc = np.ones((4,4), np.uint8)
#        #kernelo = np.ones((4,4), np.uint8)
#        image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelc)  # close/expand separate white spots
        #image = cv2.morphologyEx(image, cv2.MORPH_OPEN,  kernelo) # delete/blacken separate white spots
      else:
        # make GRAY image
        image = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)

      cv2.imshow('my extraction',    cv2.resize(image1,(417,155)))
      # cv2.imshow('Gray befor Canny', cv2.resize(image1,(417,155)))
      #stop()
    else:
# use cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
      laplacian = cv2.Laplacian(image, cv2.CV_64F)
      sobelx    = cv2.Sobel(image, cv2.CV_64F, 1,0, ksize=5)  # x
      sobely    = cv2.Sobel(image, cv2.CV_64F, 0,1, ksize=5)  # y
      sobel     = cv2.Sobel(image, cv2.CV_64F, 1,1, ksize=5)  # y
      cv2.imshow('laplacian', cv2.resize(laplacian,(417,155)))
      cv2.imshow('sobelx',    cv2.resize(sobelx,(417,155)))
      cv2.imshow('sobely',    cv2.resize(sobely,(417,155)))
      cv2.imshow('sobel',     cv2.resize(sobel,(417,155)))
      stop()

    return image   # RGB image

def extractColor(image):

    # image[...,0] = (1-np.sin(0.5*3.14159*image[...,1]/255))*255
    # not get yellow strong sun und shadow, tunnel
    # image[...,1] = np.sin(0.5*3.14159*image[...,1]/255)*255
    # image[...,2] = np.sin(0.5*3.14159*image[...,2]/255)*255
#
    image = np.uint8(image)

    if False:
      s = np.zeros_like(image[...,0], dtype=np.float16)
      l = np.zeros_like(image[...,0], dtype=np.float16)
      numOfRow, numOfCol = s.shape
      for m in range(numOfRow):
          for n in range(numOfCol):
              b,g,r   = image[m,n,:]
              b1      = np.float16(b)/255
              # yellow -> black; white -> dark grey
              # g1      =1- np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      =1- np.cos(0.5*3.14159*np.float16(r)/255)
              # yellow -> black; white -> dark grey
              # g1      = np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      =1- np.cos(0.5*3.14159*np.float16(r)/255)
              # yellow -> dark grey; white -> dark grey
              # g1      = np.sin(0.5*3.14159*np.float16(g)/255)
              # r1      = np.cos(0.5*3.14159*np.float16(r)/255)
              # yellow -> light grey; white -> dark grey
              # g1      = np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      = np.sin(0.5*3.14159*np.float16(r)/255)
              # no good
              # g1      = 1-np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      = np.sin(0.5*3.14159*np.float16(r)/255)
              # yellow -> light grey; white -> dark grey
              # g1      = np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      = 1-np.sin(0.5*3.14159*np.float16(r)/255)
              # yellow -> light grey; white -> dark grey: Canny and Hough work
              # g1      = np.sin(0.5*3.14159*np.float16(g)/255)
              # r1      = 1-np.sin(0.5*3.14159*np.float16(r)/255)
              # yellow -> light grey; white -> dark grey
              # g1      = np.cos(0.5*3.14159*np.float16(g)/255)
              # r1      = np.cos(0.5*3.14159*np.float16(r)/255)
              # looks good bud Canny does not get it
              g1      = np.sin(0.5*3.14159*np.float16(g)/255)
              r1      = np.sin(0.5*3.14159*np.float16(r)/255)

              vmax   = np.float16(np.max([r1,g1,b1]))
              vmin   = np.float16(np.min([r1,g1,b1]))
              li     = np.float16(vmax+vmin)/2
              l[m,n] = li
              dv     = (vmax-vmin)
              li0    = np.abs(2*li-1)
              if (dv == 0) or (li0==1.0):
                  s[m,n] = 0.0
              else:
                s[m,n] = dv/(1.0-li0)

              # vs     = np.float16(vmax+vmin)
              # if li == 0:
                  # s[m,n] = 0.0
              # elif li>0.5:
                  # s[m,n] = dv/(2.0-vs)
              # else:
                  # s[m,n] = dv/vs
              continue
      s = 255*(s-np.min(s))/(np.max(s)-np.min(s))
      l = 255*(l-np.min(l))/(np.max(l)-np.min(l))
      # print ("my hls=", np.min(l),np.max(l), np.min(s),np.max(s))

    return image

# mask image data
#
def windowFront(image, roiVertice):
    # from sendet
    #make mask all zeros with size of image
    # image = np.array(image)
    # print('wdecw: ',image.shape[0],image.shape[1])
    mask = np.zeros((image.shape[0], image.shape[1]), dtype=np.uint8)

    #filling pixels inside the polygons defined by "roiVertice" with the fill color (can be convex or concave)
    #cv2.fillPoly(mask, roiVertice, [255,255,255])
    cv2.fillPoly(mask, roiVertice, 255)

    #returning the image only where mask pixels are nonzero
    # masked = cv2.bitwise_and(image, mask)
    # cv2.imshow('Mask', mask)
    # print('size2: ', mask.shape, image.shape)
    image[mask == 0] = 0
    # zzz = cv2.cvtColor(image, cv2.COLOR_HSV2BGR)
    # cv2.imshow('Image masked', zzz)
    # stop()
    return image

#
# stop by click close window
#
def stop():
    cv2.waitKey(0)
    # input('Any key to stop ... ...')
    cv2.destroyAllWindows()
    sys.exit()

def pause():
    print("Press any key to continue ... ...")
    cv2.waitKey(0)


import numpy as np
from PIL import Image
from wordcloud import WordCloud,ImageColorGenerator

#打开文件，大写转小写
word=open('1.txt','r',encoding='utf-8').read().lower()

#按空格分词，生成列表
for ch in '\,\.\?\!\(\)\:\'\"\-':
    word=word.replace(ch," ")
words=word.split( )

#词频统计，生成字典
counts={}
for w in words:
    if len(w)==1:
        continue
    else:
        counts[w]=counts.get(w,0)+1

#设置停用词，过滤
sw={"the","that","and","of","to","for","in","does"}
for w in sw:
    del counts[w]

#设置模板和字体
image=np.array(Image.open('1.jpg'))
font="C:\Windows\Fonts\simsun.ttc"

#设置参数
cloud=WordCloud(mask=image,font_path=font,background_color="white",
                max_words=80,min_font_size=10,max_font_size=80)

#按词频绘制
cloud.generate_from_frequencies(counts)

#保存文件
cloud.to_file('yun.jpg')


import cv2 as cv
import datetime
import os
import time

def camera_shoot():
    camera=cv.VideoCapture(0)
    r,frame = camera.read()
    folder='images/'
    if not os.path.exists(folder):
        os.makedirs(folder)
    if r:
        filename = f"Login_on_{datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.jpg"
        path=os.path.join(folder,filename)
        cv.imwrite(path,frame)
        #printf("Image Saved");

        #Video record
        format=cv.VideoWriter_fourcc(*'mp4v')
        out=cv.VideoWriter(f"{folder}Login_on_{filename}.mp4",format,30.0,(640,480))
        start_time=time.time()
        while True:
            r,frame = camera.read()
            out.write(frame)
            remain_time = time.time()-start_time
            if remain_time >= 10:
                out.release()
                break
    camera.release()
    cv.destroyAllWindows()

camera_shoot()


from core.base_extractor import BaseExtractor
from core.core import get_logger
from core.config import DATETIME_FORMATTER
from .models import NftradeData

from typing import Union
import traceback
import json
import datetime
import requests
import peewee

def convert_z_time(str_time: str) -> datetime.datetime:
    NFTRADE_FORMATE_TIME_ORIGIN = "%Y-%m-%dT%H:%M:%S.%fZ"
    return datetime.datetime.strptime(str_time, NFTRADE_FORMATE_TIME_ORIGIN) if str_time else ''

def rename_contract(name: Union[str, None]) -> str:
    trans = {
        "Unknown contract #260084": "MATH x Moonbeam Ecosystem",
        "EXR Racecrafts": "Exiled Racers Racecraft",
        "Unknown contract #513931": "MoonFit Beast and Beauty",
        "EXR Pilot Mint Key": "EXR Mint Pass"
    }
    return trans[name] if name is not None and name in trans.keys() else name

class NftradeDataExtractor(BaseExtractor):

    def fetch(self,
              start_time: datetime.datetime = datetime.datetime.now() - datetime.timedelta(days=1),
              end_time: datetime.datetime = datetime.datetime.now()):
        limit = 50
        link = f"https://api.nftrade.com/api/v1/activities?limit={limit}&skip=%d&chainId=1284"
        header = {
            "Accept": "application/json, text/plain, */*",
            "Referer": "https://nftrade.com/",
            "Host": "api.nftrade.com",
            "Connection": "Close"
        }
        data_fetch = []
        has_next = True
        for offset in range(0, limit * 100 + 1, limit):
            if has_next:
                r = requests.get(link % offset,  headers=header)
                for record in r.json():
                    createdAt = convert_z_time(record.get("createdAt", ''))
                    if createdAt <= end_time and createdAt >= start_time:
                        process_rec = {
                            "idTrade": record.get("id", None),
                            "chainId": record.get("chainId"),
                            "typeRec": record.get("type"),
                            "fromUser": record.get("from"),
                            "toUser": record.get("to"),
                            "createdAt": createdAt.strftime(DATETIME_FORMATTER),
                            "price": float(record.get("price")),
                            "contractAddress": record.get("activityTokens", [{}])[0].get("contractAddress"),
                            "contractName": rename_contract(record.get("activityTokens", [{}])[0].get("contractName")),
                            "tokenId": record.get("activityTokens", [{}])[0].get("tokenID", None),
                            "tokenName": record.get("activityTokens", [{}])[0].get("tokenName", None),
                            "tokenImage": record.get("activityTokens", [{}])[0].get("tokenImage", None),
                            "side": record.get("activityTokens", [{}])[0].get("side")
                        }
                        data_fetch.append(process_rec)
                    else:
                        has_next = False
        return data_fetch

    def extract(self):
        return self.fetch()

    def init_table(self):
        ## Create table if not exists
        try:
            if not NftradeData.table_exists():
                NftradeData.create_table(safe=True)
        except Exception as e:
            get_logger().error(e)
            traceback.print_exc()

    def bulk_upsert(self, records: list[dict]):
        try:
            query = NftradeData.insert_many(records)
            query = query.on_conflict(
                        conflict_target=[NftradeData.idTrade,],
                        update={
                            "chainId":peewee.EXCLUDED.chainId,
                            "typeRec":peewee.EXCLUDED.typeRec,
                            "fromUser":peewee.EXCLUDED.fromUser,
                            "toUser":peewee.EXCLUDED.toUser,
                            "createdAt":peewee.EXCLUDED.createdAt,
                            "price":peewee.EXCLUDED.price,
                            "contractAddress":peewee.EXCLUDED.contractAddress,
                            "contractName":peewee.EXCLUDED.contractName,
                            "tokenId":peewee.EXCLUDED.tokenId,
                            "tokenName":peewee.EXCLUDED.tokenName,
                            "tokenImage":peewee.EXCLUDED.tokenImage,
                            "side":peewee.EXCLUDED.side
                        })
            query.execute()
            get_logger().debug(f"upsert {len(records)} records")
        except Exception as e:
            get_logger().error(e)
            traceback.print_exc()

    def insert(self, record: dict):
        get_logger().debug("insert " + json.dumps(record))
        try:
            NftradeData.create(
                idTrade=record.get("idTrade"),
                chainId=record.get("chainId"),
                typeRec=record.get("typeRec"),
                fromUser=record.get("fromUser"),
                toUser=record.get("toUser"),
                createdAt=record.get("createdAt"),
                price=record.get("price"),
                contractAddress=record.get("contractAddress"),
                contractName=record.get("contractName"),
                tokenId=record.get("tokenId"),
                tokenName=record.get("tokenName"),
                tokenImage=record.get("tokenImage"),
                side=record.get("side"),
            )
        except Exception as e:
            get_logger().error(e)
            traceback.print_exc()

    def update(self, record: dict):
        get_logger().debug("update " + json.dumps(record))
        comming_id = record.get("idTrade")
        try:
            update_query = NftradeData\
                .update(record)\
                .where(NftradeData.idTrade == comming_id)
            update_query.execute()
        except Exception as e:
            get_logger().error(e)
            traceback.print_exc()

    def exist(self, record: dict):
        record_exists = False
        comming_id = record.get("idTrade")
        if comming_id:
            record_exists = NftradeData\
                .select("idTrade")\
                .where(NftradeData.idTrade == comming_id)\
                .exists()
        else:
            raise ValueError("idTrade is empty!!")
        return record_exists


#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author: Stanley Wang

import pexpect
actions = [
    ('', '# ', 'starting'),
    ('power on', 'Changing power on succeeded', ''),
    ('discoverable on', 'Changing discoverable on succeeded', ''),
    ('connect B8:09:8A:F3:ED:FC', 'Connection succeedful', 'connecting keyboard'),
    ('connect E8:80:2E:E6:D6:0E', 'Connection succeedful', 'connecting touchpad'),
    ('connect 2C:41:A1:47:69:F5', 'Connection succeedful', 'connecting speaker'),
    ('exit', '', ''),
]

cmd = 'bluetoothctl'
print(f'Running cmd:{cmd}')
ctl = pexpect.spawn(cmd)
for action, expect, memo in actions:
    try:
        print(memo if memo else action)
        if action: ctl.sendline(action)
        if expect: idx = ctl.expect(expect, timeout=5)
    except pexpect.EOF:
        print("EOF")
    except pexpect.TIMEOUT:
        print("TIMEOUT")
ctl.close()


# built-in
import json
from collections import OrderedDict
from hashlib import sha256
from pathlib import Path
from typing import Optional

# external
from dephell_pythons import Pythons
from dephell_specifier import RangeSpecifier

# app
from ..models import RootDependency
from .pipfile import PIPFileConverter

# https://stackoverflow.com/a/23820416
# https://github.com/pypa/pipfile/blob/master/examples/Pipfile.lock
# https://github.com/pypa/pipfile/blob/master/pipfile/api.py

class PIPFileLockConverter(PIPFileConverter):
    lock = True

    def can_parse(self, path: Path, content: Optional[str] = None) -> bool:
        if isinstance(path, str):
            path = Path(path)
        if content:
            return ('pipfile-spec' in content and 'sha256' in content)
        else:
            return (path.name == 'Pipfile.lock')

    def loads(self, content) -> RootDependency:
        doc = json.loads(content, object_pairs_hook=OrderedDict)
        deps = []
        root = RootDependency(raw_name=self._get_name(content=content))

        python = doc.get('requires', {}).get('python_version', '')
        if python not in {'', '*'}:
            root.python = RangeSpecifier('==' + python)

        for section, is_dev in [('default', False), ('develop', True)]:
            for name, content in doc.get(section, {}).items():
                subdeps = self._make_deps(root, name, content)
                for dep in subdeps:
                    dep.envs = {'dev'} if is_dev else {'main'}
                deps.extend(subdeps)
        root.attach_dependencies(deps)
        return root

    def dumps(self, reqs, project: RootDependency, content=None) -> str:
        packages = {True: OrderedDict(), False: OrderedDict()}
        for req in reqs:
            packages[req.is_dev][req.name] = dict(self._format_req(req=req))

        python = Pythons(abstract=True).get_by_spec(project.python)
        data = OrderedDict([
            ('_meta', OrderedDict([
                ('sources', [OrderedDict([
                    ('url', 'https://pypi.python.org/simple'),
                    ('verify_ssl', True),
                    ('name', 'pypi'),
                ])]),
                ('requires', {'python_version': str(python.version)}),
            ])),
            ('default', packages[False]),
            ('develop', packages[True]),
        ])
        data['_meta']['hash'] = {'sha256': self._get_hash(data)}
        data['_meta']['pipfile-spec'] = 6
        return json.dumps(data, indent=4, separators=(',', ': '))

    @staticmethod
    def _get_hash(data: dict) -> str:
        content = json.dumps(data, sort_keys=True, separators=(',', ':'))
        return sha256(content.encode('utf8')).hexdigest()

    def _format_req(self, req):
        result = dict()
        for name, value in req:
            if name == 'rev':
                name = 'ref'
            if name in self.fields:
                result[name] = value
        return result


import matplotlib.pyplot as plt

expenses = ['Food','Rent','Books','Sports','Other']
values = [500,450,200,300,550]

plt.pie(values, labels = expenses,autopct = '% 0.2f%%',explode = [0.05,0.05,0.05,0.05,0.05])
#To make pie chart as Doughnut chart add below pie chart
plt.pie([1,1], labels = None,radius = 0.5,colors = ['white','white'],explode = [-0.005,-0.005])
plt.title('Overview of expenses',fontsize = 20,color = 'Red')

plt.show()


import numpy as np
import matplotlib.pyplot as plt
import os

#################
# This file explores the 1D Frantz-Nodvik Equations for a two
# level system given a flat top pulse.
# This shows how the pulse responds after a gain medium.
# Also assuming a constant population inversion through out the entire medium.
#################

def calculate_photon_density(n0, sigma, delta0, eta, tau, c, x, t):
    # Parameters: sigma - absorption cross section
    #             delta0 - const inversion
    #             eta - total number of photons/unit area
    #             tau - pulse width
    #             c - speed of light in vacuum

    # Variables: x - spatial
    #            t - time

    n = n0/(1-(1-np.exp(-sigma*delta0*x))*np.exp(-2*sigma*eta*(t-x/c)/tau))

    return n

def main(save_path):
    # define standard parameters (from paper)
    eta = 4*10**18 #photons/cm^2
    L = 10 # 10 cm long medium
    tau = 6*10**(-9) #6ns long pulse...pretty big but going with paper
    delta0 = 8*10**8 #c 1/cm^3 ompletey excited initial population density
    sigma = 2.5*10**(-20) # cm^2 cross section for ruby at room temp
    c = 30 #cm/ns
    n0 = 1 #normalize

    #Calculate time profile of pulse at x = 0 (beginning of medium)
    x = 0
    times_x0 = np.arange(0+x/c, tau+x/c, tau/100)
    n_x0 = np.zeros(len(times_x0))
    for i in range(len(n_x0)):
        t = times_x0[i]
        n_x0[i] = calculate_photon_density(n0, sigma, delta0, eta, tau, c, x, t)
    plt.plot(times_x0, n_x0,'-o')
    plt.show()

    #Calculate time profile of pulse at x = 10 cm (beginning of medium)
    x = L
    times_x10 = np.arange(0+x/c, tau+x/c, tau/100)
    n_x10 = np.zeros(len(times_x10))
    for i in range(len(n_x10)):
        t = times_x10[i]
        n_x10[i] = calculate_photon_density(n0, sigma, delta0, eta, tau, c, x, t)
    plt.plot(times_x10, n_x10, '-o')
    plt.show()

    #Calculate time profile of pulse at x = 10 cm (beginning of medium)
    x = L/2
    times_x5 = np.arange(0+x/c, tau+x/c, tau/100)
    n_x5 = np.zeros(len(times_x5))
    for i in range(len(n_x10)):
        t = times_x5[i]
        n_x5[i] = calculate_photon_density(n0, sigma, delta0, eta, tau, c, x, t)
    plt.plot(times_x5, n_x5, '-o')
    plt.show()

    #end_time = tau+L/c
    #times_x5 = np.arange(0, end_time, tau/100)
    #n_x5 = np.zeros(len(times_x5))
    #for i in range(len(n_x10)):
     #   t = times_x5[i]
    #    n_x5[i] = calculate_photon_density(n0, sigma, delta0, eta, tau, c, x, t)
    #plt.plot(times_x5, n_x5, '-o')
    #plt.show()

if __name__ == '__main__':
    path = os.getcwd()
    main(save_path='path')


import copy
import itertools
import logging
import logging.config
import weakref

from ..base import Unspecified, attrs_of
from ..core import simple_types, private
from ..interface import Plugin, Executable, call_plugins
from ..descriptors import Link, Delegate, Or, Choice, OfType, List, Dict

_loglevels = ['CRITICAL', 'FATAL', 'ERROR', 'WARNING', 'WARN',
              'INFO', 'DEBUG', 'NOTSET']

def _loglevel(default=Unspecified, *alternatives):
    levels = _loglevels + list(map(str.lower, _loglevels))
    ts = (Choice(*levels, nodefault=True), OfType(int)) + alternatives
    return Or(*ts, default=default)

def _level_as_int(lvl):
    if isinstance(lvl, int):
        return lvl
    return getattr(logging, lvl.upper())

class Logger(Plugin):

    r"""
    Interface to pre-configured `logging.Logger`.

    It does the following automatically:

    - make a logger with an appropriate dotted name
    - set up handler

    .. Some infernal hack to make the doctest consistent:
       >>> Logger._idgen = itertools.count()

    >>> from compapp import Computer
    >>> class MyAppForLoggerDemo(Computer):
    ...     def run(self):
    ...         self.log.error('error message')
    ...         self.log.info('info message')
    >>> app = MyAppForLoggerDemo()
    >>> app.log.formatters['default']['format'] = \
    ...     '%(levelname)s %(name)s | %(message)s'
    >>> app.log.handlers['console']['stream'] = 'ext://sys.stdout'
    >>> app.execute()
    ERROR compapp.plugins.misc.MyAppForLoggerDemo.0 | error message

    .. attribute:: log

       An instance of `logging.Logger`.
       This is accessible in and after `.Executable.run` or
       `.Executable.load` hooks.

       .. todo:: Make it accessible all the time.

    .. attribute:: critical
                   error
                   warn
                   info
                   debug

       Shortcut for `.log`\ `.debug <logging.Logger.debug>` etc.

    """

    configurator = Or(OfType(logging.config.BaseConfigurator),
                      Link('...log.configurator'),
                      isparam=False)

    handlers = Or(List(str),
                  Dict(str, Dict(str, simple_types)),
                  Link('...log.handlers'),
                  # Next Dict trait is same as the one above; it's
                  # just for holding the default value.  Dict is used
                  # instead of passing `default=` to Or to make a new
                  # instance for each instance of Logger.
                  Dict(str, Dict(str, simple_types), default=dict(
                      console={
                          'class': 'logging.StreamHandler',
                          'formatter': 'default',
                          'stream': 'ext://sys.stderr',
                      },
                      file={
                          'class': 'logging.FileHandler',
                          'formatter': 'verbose',
                          'datastore': True,
                          'filename': 'run.log',
                      })))
    """
    The dictionary *handlers* of the `logging configuration
    dictionary`_.  Each handler may contain a special configuration
    ``'datastore': True`` indicating that this handler is configured
    only if datastore is accessible.  For nested classes, this
    attribute is ignored if `.ownconfig` is not `True` (default is
    ``'auto'``).

    .. _`logging configuration dictionary`: https://docs.python.org/library/logging.config.html#dictionary-schema-details
    """

    formatters = Dict(str, Dict(str, str), default=dict(
        basic=dict(format=logging.BASIC_FORMAT),
        default=dict(
            format='%(levelname)s %(asctime)s %(name)s | %(message)s',
            datefmt="%Y-%m-%d %H:%M:%S",
        ),
        verbose=dict(
            format='%(asctime)s:' + logging.BASIC_FORMAT,
        ),
    ))
    """
    The dictionary *formatters* of the `logging configuration
    dictionary`_.  See also `.handlers`.
    """

    ownconfig = Choice('auto', True, False)
    """
    If ``'auto'`` (default), configure handlers if the owner is the
    root app and reuse the handlers of owner's logger otherwise.  The
    value `True` forces this logger plugin to make own handlers.  The
    value `False` forces the reuse (which is an error if the owner is
    the root app).
    """

    level = Or(_loglevel(), Link('...log.level'), default='ERROR')
    """
    Logger level.  Default is ``'ERROR'``.
    """

    critical = Link('.logger.critical')
    error = Link('.logger.error')
    warn = Link('.logger.warn')
    info = Link('.logger.info')
    debug = Link('.logger.debug')

    datastore = Delegate()

    nametemplate = '{self.__class__.__module__}.{self.__class__.__name__}.{id}'
    _idgen = itertools.count()

    def prepare(self):
        self.logger = logging.getLogger(self.nametemplate.format(
            self=private(self).owner, id=next(self._idgen)))
        self.logger.setLevel(_level_as_int(self.level))

        if self.should_configure():
            assert isinstance(self.handlers, dict)
            self.configure()
        handlers = list(self.configurator.config['handlers'])
        self.configurator.add_handlers(self.logger, handlers)

    def configure(self):
        handlers = copy.deepcopy(self.handlers)
        is_writable = (hasattr(self, 'datastore') and
                       self.datastore.is_writable())
        for key, hndlr in list(handlers.items()):
            if hndlr.pop('datastore', False):
                if is_writable:
                    hndlr['filename'] = self.datastore.path(hndlr['filename'])
                else:
                    del handlers[key]

        self.configurator = logging.config.DictConfigurator(dict(
            version=1,
            formatters=self.formatters,
            handlers=handlers,
            disable_existing_loggers=False,
        ))
        self.configurator.configure()

    def should_configure(self):
        if self.ownconfig == 'auto':
            return not hasattr(self, 'configurator')
        return self.ownconfig

class DebugNS(object):

    def __init__(self, debug):
        self.__debug = weakref.proxy(debug)

    def __setattr__(self, name, value):
        if name.startswith('_'):
            super(DebugNS, self).__setattr__(name, value)
        if self.__debug.is_enabled():
            if self.__debug.is_logging_debug():
                self.__debug.log.debug('{0} = {1!r}'.format(name, value))
            super(DebugNS, self).__setattr__(name, value)

class Debug(Plugin):

    r"""
    Debug helper plugin.

    Since `.Computer` does not allow random attributes to be set,
    it's hard to debug or interactively investigate simulation and
    analysis by storing temporary variable to the `.Computer`
    instance.  `Debug` provides the place for that.

    - If `store` flag is *not* set, it does not store anything;
      assignment would be just no-op.  This is useful for debugging
      memory-consuming object.
    - If `logger` is defined, and its level is DEBUG, assignment
      to `Debug` object writes out debug message.

    Example
    -------

    >>> from compapp import Computer
    >>> class MySimulator(Computer):
    ...
    ...     def run(self):
    ...         tmp = list(range(3))
    ...         self.dbg.tmp = tmp
    ...         self.results.div = [x / len(tmp) for x in tmp]
    ...
    >>> app = MySimulator()
    >>> app.log.level = 'DEBUG'

    Before ``app.execute()``, let's tweak logger output so
    that output is concise:

    >>> app.log.formatters['default']['format'] = \
    ...     '%(levelname)s %(name)s | %(message)s'
    >>> app.log.handlers['console']['stream'] = 'ext://sys.stdout'

    .. Some infernal hack to make the doctest consistent:
       >>> app.log._idgen = itertools.count()

    Finally...:

    >>> app.execute()                                  # doctest: +ELLIPSIS
    DEBUG compapp.plugins.misc.MySimulator.0 | ...
    DEBUG compapp.plugins.misc.MySimulator.0 | tmp = [0, 1, 2]
    DEBUG compapp.plugins.misc.MySimulator.0 | ...

    >>> app.dbg.tmp
    [0, 1, 2]

    Note that executing the same app without ``.log.level = 'DEBUG'``
    suppress the logging and storing the temporary variable.  The
    Debug plugin also can be disabled independent of the log level by
    setting its `.enable` to `False`.

    >>> app = MySimulator()
    >>> app.execute()
    >>> app.dbg.tmp
    Traceback (most recent call last):
      ...
    AttributeError: 'DebugNS' object has no attribute 'tmp'

    """

    log = Link('..log')
    enable = Choice('auto', True, False)
    """
    If ``'auto'`` (default), enable this plugin if the log level of
    `Logger` plugin is ``'DEBUG'`` or lower.  `True` (`False`) enables
    (disables) this plugin independent of the log level.
    """

    def __init__(self, *args, **kwds):
        super(Debug, self).__init__(*args, **kwds)
        self.ns = DebugNS(self)

    def is_logging_debug(self):
        return hasattr(self, 'log') and \
            self.log.logger.getEffectiveLevel() <= logging.DEBUG

    def is_enabled(self):
        if self.enable == 'auto':
            return self.is_logging_debug()
        return self.enable

class Figure(Plugin):

    r"""
    A wrapper around `matplotlib.pyplot.figure`.

    Automatically save and (optionally) show the figure at the end of
    execution.

    Examples
    --------

    Normally, `Figure` is prepared by an `.Executable` subclass such
    as `.Computer`.  To manually play with `Figure`, it is equivalent
    to do:

    >>> figure = Figure()
    >>> figure.prepare()

    `Calling <__call__>` a `Figure` instance gives you a matplotlib
    figure.

    >>> figure()                                       # doctest: +ELLIPSIS
    <matplotlib.figure.Figure object at ...>

    It also has `.subplots` which is just a thin wrapper around
    `matplotlib.pyplot.subplots`:

    >>> fig, (ax1, ax2) = figure.subplots(2)

    .. Manually close:
       >>> figure.defer.call()

    Suppose you have a nested `.Computer`\ s:

    >>> from compapp.apps import Computer
    >>> class MyApp(Computer):
    ...     class sub(Computer):
    ...         class sub(Computer):
    ...             pass

    .. glossary::

       Global `.Figure` plugin configuration

         The attribute `.autoclose` is `.Link`\ ed to the plugin of
         the owner `Computer`.  It makes possible to configure
         `Figure` plugins "globally":

    >>> app = MyApp()
    >>> app.sub.figure.autoclose  # default value
    True
    >>> app.figure.autoclose = False
    >>> app.sub.figure.autoclose
    False
    >>> app.sub.sub.figure.autoclose
    False

    A "sub-tree" of the `.Computer`\ s can be configured separately:

    >>> app.sub.figure.autoclose = True
    >>> app.sub.sub.figure.autoclose
    True
    >>> app.figure.autoclose
    False

    Similar global/sub-tree configuration mechanism works for the
    `.show` attribute:

    >>> app.figure.show  # default value
    False
    >>> app.figure.show = True
    >>> app.sub.figure.show
    True
    >>> app.sub.sub.figure.show
    True

    .. Run the code below in a clean temporary directory:
       >>> getfixture('cleancwd')

    >>> import os
    >>> from compapp import Computer
    >>> class MyApp(Computer):
    ...     def run(self):
    ...         self.figure()
    ...         self.figure(name='alpha')
    ...         self.figure(name='beta')
    ...
    >>> app = MyApp()
    >>> app.datastore.dir = 'out'
    >>> app.execute()
    >>> sorted(f for f in os.listdir('out') if f.startswith('figure-'))
    ['figure-0.png', 'figure-alpha.png', 'figure-beta.png']

    See also
    --------
    :ref:`ex-simple_plots`
    :ref:`ex-named_figure`

    """

    ext = 'png'

    datastore = Delegate()
    r"""
    `.Delegate`\ ed attribute accessing to a `.BaseDataStore`.
    """

    show = Or(OfType(bool), Link('...figure.show'), default=False)
    """
    Automatically call `matplotlib.pyplot.show` if `True`.  The
    default is `False`, if not specified by the :term:`owner class`.
    See: :term:`Global Figure plugin configuration`.
    """

    autoclose = Or(OfType(bool), Link('...figure.autoclose'), default=True)
    """
    Automatically close matplotlib figures if `True` which is the
    default, if not specified by the :term:`owner class`.
    See: :term:`Global Figure plugin configuration`.
    """

    def prepare(self):
        self._figures = {}
        self._num = 0

    def register(self, fig, name=None):
        """
        Register `fig` so that it is automatically saved, showed and closed.
        """
        self._set_fig(name, fig)

    def _set_fig(self, name, fig):
        from matplotlib import pyplot

        if name is None:
            while str(self._num) in self._figures:
                self._num += 1
            name = str(self._num)
            self._num += 1
        assert isinstance(name, str)

        self._figures[name] = fig

        @self.defer.keyed('save')
        def _():
            if not (hasattr(self, 'datastore') and
                    self.datastore.is_writable()):
                return
            path = self.datastore.path(name + '.' + self.ext)
            fig.savefig(path)

        if self.autoclose:
            self.defer(fig)(pyplot.close)

        return fig

    def __call__(self, *args, **kwds):
        """
        Make a new matplotlib figure.

        All the positional and keyword arguments are passed to
        `matplotlib.pyplot.figure` except one keyword argument *name*.

        Parameters
        ----------
        name : str, int, or None
            Unique name of the figure.  It is an error to call this
            method with the same *name* twice.

        Returns
        -------
        fig : matplotlib.figure.Figure

        """
        from matplotlib import pyplot
        name = kwds.pop('name', None)
        assert name not in self._figures
        return self._set_fig(name, pyplot.figure(*args, **kwds))

    def __getitem__(self, name):
        """
        Make a new matplotlib figure or get the new one.

        Examples
        --------
        The usual preparation (see: `Figure`):

        >>> figure = Figure()
        >>> figure.prepare()

        If figure is created with a name, it can be accessed by the
        dict-like interface:

        >>> fig_a = figure(name='a')
        >>> assert fig_a is figure['a']  # access an existing figure
        >>> fig_b = figure['b']  # create a new figure
        >>> assert fig_b is figure['b']

        Note that a new figure is created always when *name* is
        `None`:

        >>> assert figure[None] is not figure[None]

        .. Manually close:
           >>> figure.defer.call()

        Parameters
        ----------
        name : str, int, or None
            Unique name of the figure.

        Returns
        -------
        fig : matplotlib.figure.Figure

        """
        from matplotlib import pyplot

        try:
            return self._figures[name]
        except KeyError:
            pass

        return self._set_fig(name, pyplot.figure())

    def save(self):
        self.defer.call('save')

    def finish(self):
        if self.show:
            from matplotlib import pyplot
            pyplot.show()

    def subplots(self, *args, **kwds):
        """
        Wrapper around `matplotlib.pyplot.subplot`.

        All the positional and keyword arguments are passed to
        `matplotlib.pyplot.subplot` except one keyword argument
        *name*.

        Parameters
        ----------
        name : str, int, or None
            Unique name of the figure.  It is an error to call this
            method with the same *name* twice.

        Returns
        -------
        fig : `matplotlib.figure.Figure`
        ax : `matplotlib.axes.Axes` or `tuple`

        """
        from matplotlib import pyplot
        name = kwds.pop('name', None)
        assert name not in self._figures
        ret = fig, _ = pyplot.subplots(*args, **kwds)
        self._set_fig(name, fig)
        return ret

def is_runnable(excbl):
    if getattr(excbl, 'argrange', (None, None))[0] != 0:
        return False
    for name in excbl.paramnames(type=Link):
        if not hasattr(excbl, name):
            return False
    # All the links are accessible, meaning that all
    # "implicit upstreams" are already run.
    return True

class AutoUpstreams(Plugin):

    """
    Automatically execute upstreams.
    """

    @staticmethod
    def is_runnable(excbl):
        return getattr(excbl, 'is_runnable', lambda: is_runnable(excbl))()

    def prepare(self):
        owner = private(self).owner
        executables = list(attrs_of(owner, Executable))
        while executables:
            for i, excbl in enumerate(executables):
                if self.is_runnable(excbl):
                    break
            else:
                return
            del executables[i]
            excbl.execute()

class PluginWrapper(Plugin):

    """
    Combine multiple plugins into one plugin.

    Some plugin such as `AutoDump` has no "interface" and just works
    behind-the-scene.  In this case, having ``MyApp.autodump =
    AutoDump`` is just wasting user's name-space.  This class avoid
    this by moving all those behind-the-scene plugins into one name.
    See `.Computer.plugin` for its use-case.

    """

    def __getattr__(self, name):
        return getattr(private(self).owner, name)

def makemethod(method):
    def func(self):
        call_plugins(self, method)
    return func

for method in set(dir(Plugin)) - set(dir(Plugin.mro()[1])):
    if method.startswith('_'):
        continue
    setattr(PluginWrapper, method, makemethod(method))
del method

def real_owner(self):
    owner = private(self).owner
    if isinstance(owner, PluginWrapper):  # FIXME: ugly special case
        owner = private(owner).owner
    return owner


from urllib import parse
from django import template

register = template.Library()

def video_embed(context, url):
    url_data = urlparse.urlparse(url)
    query = urlparse.parse_qs(url_data.query)
    try:
        video_id = query["v"][0]
        context['embed_url'] = ('http://youtube.com/embed/%s' % video_id)
    except KeyError:
        context['video_url'] = url
    return context('trail_detail.html', {'youtube_video': youtube_video})


import logging
import argparse
from time import sleep

from telegram_notifier import telegram_notify
from settings import token

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

if __name__ == '__main__':

    parser = argparse.ArgumentParser()
    parser.add_argument('--username', dest='uname')
    parser.add_argument('--message', dest='msg')
    args = parser.parse_args()

    @telegram_notify(token, args.uname, args.msg)
    def fn():
        sleep(10)

    fn()


import json
from pathlib import Path

def flesh_and_blood_summary(path: Path):
    with path.open(newline='') as jsonfile:
        year_json = json.load(jsonfile)

        # Calculate self / anonymous ids
        self_id = year_json['userInfo']['meRefId']
        anonymous_id = None
        for player in year_json['players']:
            if player['isAnonymous']:
                anonymous_id = player['id']

        # Setup stat variables
        game_formats = {}
        # blitz = {
        #     'heroes': {},
        #     'plays': 0,
        #     'times_went_first': 0,
        #     'wins': 0,
        #     'losses': 0,
        #     'ties': 0,
        #     'wins_when_first': 0,
        # }

        # Parse data from plays
        for play in year_json['plays']:
            if play['ignored']:
                continue

            # Get game format object to use
            game_format = play.get('board')

            if game_format is None:
                print("Missing format for game " + play['uuid'])
                continue

            game_format_stats = game_formats.get(game_format)

            if game_format_stats is None:
                game_format_stats = {
                    'heroes': {},
                    'plays': 0,
                    'times_went_first': 0,
                    'wins': 0,
                    'losses': 0,
                    'ties': 0,
                    'wins_when_first': 0,
                }
                game_formats[game_format] = game_format_stats

            # Calculate stats
            game_format_stats['plays'] += 1

            winner_exists = False
            self_role = None
            self_start_player = False
            self_won = False
            heroes_played_against = set()

            for player in play['playerScores']:
                role = player.get('role')
                hero = game_format_stats['heroes'].get(role)

                if hero is None:
                    hero = {
                        'played_as': 0,
                        'times_went_first_as': 0,
                        'wins_as': 0,
                        'losses_as': 0,
                        'ties_as': 0,
                        'wins_when_first_as': 0,
                        'played_against': 0,
                        'times_went_first_against': 0,
                        'wins_against': 0,
                        'losses_against': 0,
                        'ties_against': 0,
                        'wins_when_first_against': 0,
                    }

                    game_format_stats['heroes'][role] = hero

                if player['winner']:
                    winner_exists = True

                # Player is me
                if player['playerRefId'] == self_id:
                    self_role = role
                    hero['played_as'] += 1

                    if player['startPlayer']:
                        self_start_player = True
                        game_format_stats['times_went_first'] += 1
                        hero['times_went_first_as'] += 1
                    if player['winner']:
                        self_won = True
                        game_format_stats['wins'] += 1
                        hero['wins_as'] += 1
                    if player['startPlayer'] and player['winner']:
                        game_format_stats['wins_when_first'] += 1
                        hero['wins_when_first_as'] += 1
                # Player is not me
                else:
                    heroes_played_against.add(role)

                    if player['winner']:
                        game_format_stats['losses'] += 1
                        hero['losses_against'] += 1

            for hero_against in heroes_played_against:
                hero_object = game_format_stats['heroes'].get(hero_against)
                hero_object['played_against'] += 1

                if self_start_player:
                    hero_object['times_went_first_against'] += 1
                if self_won:
                    hero_object['wins_against'] += 1
                if self_start_player and self_won:
                    hero_object['wins_when_first_against'] += 1

            if not winner_exists:
                game_format_stats['ties'] += 1

                game_format_stats['heroes'].get(self_role)['ties_as'] += 1
                for hero in heroes_played_against:
                    game_format_stats['heroes'].get(hero)['ties_against'] += 1
            elif not self_won:
                game_format_stats['heroes'].get(self_role)['losses_as'] += 1

    # Print results
    output_text = ""

    for game_format_name in sorted(game_formats):
        output_text += create_format_results_table(game_format_name, game_formats[game_format_name])
        output_text += "\n"

    print(output_text)

def create_format_results_table(format_name, format_object):
    output_text = ""

    win_percent = round(format_object['wins'] / format_object['plays'] * 100, 2) if format_object['plays'] > 0 else 0.0
    win_percent_when_first = round(format_object['wins_when_first'] / format_object['times_went_first'] * 100, 2) if format_object['times_went_first'] > 0 else 0.0

    output_text += f"### {format_name}\n"

    output_text += f"#### Overall\n"
    output_text += "| Plays | Wins | Losses | Ties | Win Percentage | Times Went First | Wins When First Player | Win % When First Player |\n"
    output_text += "| --- | --- | --- | --- | --- | --- | --- | --- |\n"
    output_text += f"| {format_object['plays']} | {format_object['wins']} | {format_object['losses']} | {format_object['ties']} | {win_percent}% | {format_object['times_went_first']} | {format_object['wins_when_first']} | {win_percent_when_first}% |\n"
    output_text += "\n"

    output_text += f"#### Hero Stats As\n"
    output_text += "| Hero | Plays | Wins | Losses | Ties | Win Percentage | Times Went First | Wins When First Player | Win % When First Player |\n"
    output_text += "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n"

    for hero in sorted(format_object['heroes']):
        hero_object = format_object['heroes'][hero]

        plays = hero_object['played_as']

        if plays == 0:
            continue

        times_went_first = hero_object['times_went_first_as']
        wins = hero_object['wins_as']
        losses = hero_object['losses_as']
        ties = hero_object['ties_as']
        win_percent = round(wins / plays * 100, 2) if plays > 0 else 0.0
        wins_when_first = hero_object['wins_when_first_as']
        win_percent_when_first = round(wins_when_first / times_went_first * 100, 2) if times_went_first > 0 else 0.0

        output_text += f"| {hero} | {plays} | {wins} | {losses} | {ties} | {win_percent}% | {times_went_first} | {wins_when_first} | {win_percent_when_first}% |\n"

    output_text += "\n"

    output_text += f"#### Hero Stats Against\n"
    output_text += "| Hero | Plays | Wins | Losses | Ties | Win Percentage | Times Went First | Wins When First Player | Win % When First Player |\n"
    output_text += "| --- | --- | --- | --- | --- | --- | --- | --- | --- |\n"

    for hero in sorted(format_object['heroes']):
        hero_object = format_object['heroes'][hero]

        plays = hero_object['played_against']

        if plays == 0:
                continue

        times_went_first = hero_object['times_went_first_against']
        wins = hero_object['wins_against']
        losses = hero_object['losses_against']
        ties = hero_object['ties_against']
        win_percent = round(wins / plays * 100, 2) if plays > 0 else 0.0
        wins_when_first = hero_object['wins_when_first_against']
        win_percent_when_first = round(wins_when_first / times_went_first * 100, 2) if times_went_first > 0 else 0.0

        output_text += f"| {hero} | {plays} | {wins} | {losses} | {ties} | {win_percent}% | {times_went_first} | {wins_when_first} | {win_percent_when_first}% |\n"

    output_text += "\n"

    return output_text


from flask import render_template,redirect,session,request, flash
from flask_app import app
from flask_app.models.user import User
from flask_app.models.band import Band

@app.route('/new/band')
def new_band():
    if 'user_id' not in session:
        return redirect('/logout')
    data = {
        "id":session['user_id']
    }
    return render_template('new_band.html',user=User.get_by_id(data))

@app.route('/create/band',methods=['POST'])
def create_band():
    if 'user_id' not in session:
        return redirect('/logout')
    if not Band.validate_band(request.form):
        return redirect('/new/band')
    data = {
        "name": request.form["name"],
        "genre": request.form["genre"],
        "home_city": request.form["home_city"],
        "founders_id": session["user_id"]
    }
    Band.save(data)
    return redirect('/home')

@app.route('/edit/band/<int:id>')
def edit_band(id):
    if 'user_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    user_data = {
        "id":session['user_id']
    }
    return render_template("edit_band.html",edit=Band.get_one(data),user=User.get_by_id(user_data))

@app.route('/update/band',methods=['POST'])
def update_band():
    if 'user_id' not in session:
        return redirect('/logout')
    if not Band.validate_band(request.form):
        return redirect('/new/band')
    data = {
        "name": request.form["name"],
        "genre": request.form["genre"],
        "home_city": request.form["home_city"],
        "id": request.form['id']
    }
    Band.update(data)
    return redirect('/home')

@app.route('/show/band/<int:id>')
def show_band(id):
    if 'user_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    user_data = {
        "id":session['user_id']
    }
    return render_template("show_band.html",band=Band.get_one(data),user=User.get_by_id(user_data))

@app.route('/destroy/band/<int:id>')
def destroy_band(id):
    if 'user_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    Band.destroy(data)
    return redirect('/home')


#!/usr/bin/python3
# -*- coding: utf-8 -*-

import main_fee_dialog
from PyQt5.QtWidgets import QDialog, QComboBox, QLineEdit,QDateTimeEdit,QDateEdit
from PyQt5.QtCore import pyqtSignal, QDateTime

class FeeDialog(QDialog, main_fee_dialog.Ui_Dialog):
    _dataSignal = pyqtSignal(type({}))

    def __init__(self, parentNew=None):
        self.parentWindow = parentNew
        QDialog.__init__(self, parentNew)
        self.setupUi(self)
        self.dateTimeEdit_fdate.setDisplayFormat("yyyy-MM-dd HH:mm:ss")

        self.pushButton_submit.clicked.connect(self.data_slot)
        self.pushButton_exit.clicked.connect(self.close_slot)

    def fill_data(self, record):
        """
        父窗口传入子窗口数据
        :param record: tuple
        :return: None
        """
        self.lineEdit_fno.setText(record[0])
        self.lineEdit_fnumber.setText(record[1])
        Vtime = QDateTime.fromString(record[6], "yyyy-MM-dd HH:mm:ss")
        self.dateTimeEdit_fdate.setDateTime(Vtime)
        self.lineEdit_rno.setText(record[3])
        self.lineEdit_cno.setText(record[4])
        self.lineEdit_pno.setText(record[5])
        self.lineEdit_frecipefee.setText(record[6])
        self.lineEdit_fdiscount.setText(record[7])
        self.lineEdit_fsum.setText(record[8])

    def data_slot(self):
        data = {'fno': "{}".format(self.lineEdit_fno.text()),
                'fnumber': "{}".format(self.lineEdit_fnumber.text()),
                'fdate': "'{}'".format(self.dateTimeEdit_fdate.text()),
                'rno': "{}".format(self.lineEdit_rno.text()),
                'cno': "{}".format(self.lineEdit_cno.text()),
                'pno': "'{}'".format(self.lineEdit_pno.text()),
                'frecipefee': "{}".format(self.lineEdit_frecipefee.text()),
                'fdiscount': "{}".format(self.lineEdit_fdiscount.text()),
                'fsum': "{}".format(self.lineEdit_fsum.text()),
                }
        self._dataSignal.emit(data)
        self.close()

    def close_slot(self):
        self.close()


import torch
import torch.nn as nn
import torchvision
import torch.nn.functional as F

resnet = torchvision.models.resnet.resnet50(pretrained=True)
from .transformer import ViT
import cv2
import numpy as np

class ConvBlock(nn.Module):
    """
    Helper module that consists of a Conv -> BN -> ReLU
    """

    def __init__(self, in_channels, out_channels, padding=1, kernel_size=3, stride=1, with_nonlinearity=True):
        super().__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, padding=padding, kernel_size=kernel_size, stride=stride)
        self.bn = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU()
        self.with_nonlinearity = with_nonlinearity

    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        if self.with_nonlinearity:
            x = self.relu(x)
        return x

class Bridge(nn.Module):
    """
    This is the middle layer of the UNet which just consists of some
    """

    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.bridge = nn.Sequential(
            ConvBlock(in_channels, out_channels),
            ConvBlock(out_channels, out_channels)
        )

    def forward(self, x):
        return self.bridge(x)

class UpBlockForUNetWithResNet50(nn.Module):
    """
    Up block that encapsulates one up-sampling step which consists of Upsample -> ConvBlock -> ConvBlock
    """

    def __init__(self, in_channels, out_channels, up_conv_in_channels=None, up_conv_out_channels=None,
                 upsampling_method="conv_transpose"):
        super().__init__()

        if up_conv_in_channels == None:
            up_conv_in_channels = in_channels
        if up_conv_out_channels == None:
            up_conv_out_channels = out_channels

        if upsampling_method == "conv_transpose":
            self.upsample = nn.ConvTranspose2d(up_conv_in_channels, up_conv_out_channels, kernel_size=2, stride=2)
        elif upsampling_method == "bilinear":
            self.upsample = nn.Sequential(
                nn.Upsample(mode='bilinear', scale_factor=2),
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1)
            )
        self.conv_block_1 = ConvBlock(in_channels, out_channels)
        self.conv_block_2 = ConvBlock(out_channels, out_channels)

    def forward(self, up_x, down_x):
        """

        :param up_x: this is the output from the previous up block
        :param down_x: this is the output from the down block
        :return: upsampled feature map
        """
        x = self.upsample(up_x)
        x = torch.cat([x, down_x], 1)
        x = self.conv_block_1(x)
        x = self.conv_block_2(x)
        return x

class SE_Block(nn.Module):
    def __init__(self, c, r=16):
        super().__init__()
        self.squeeze = nn.AdaptiveAvgPool2d(1)
        self.excitation = nn.Sequential(
            nn.Linear(c, c // r, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(c // r, c, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        bs, c, _, _ = x.shape
        y = self.squeeze(x).view(bs, c)
        y = self.excitation(y).view(bs, c, 1, 1)
        x = x * y.expand_as(x)
        return y
from torch.nn import init

def weights_init_normal(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_xavier(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.xavier_normal_(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.xavier_normal_(m.weight.data, gain=1)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_kaiming(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
    elif classname.find('Linear') != -1:
        init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_orthogonal(m):
    classname = m.__class__.__name__
    # print(classname)
    if classname.find('Conv') != -1:
        init.orthogonal_(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.orthogonal_(m.weight.data, gain=1)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def init_weights(net, init_type='normal'):
    # print('initialization method [%s]' % init_type)
    if init_type == 'normal':
        net.apply(weights_init_normal)
    elif init_type == 'xavier':
        net.apply(weights_init_xavier)
    elif init_type == 'kaiming':
        net.apply(weights_init_kaiming)
    elif init_type == 'orthogonal':
        net.apply(weights_init_orthogonal)
    else:
        raise NotImplementedError('initialization method [%s] is not implemented' % init_type)

# 获得两个卷积后的结果
class unetConv2(nn.Module):
    def __init__(self, in_size, out_size, is_batchnorm, n=2, ks=3, stride=1, padding=1):  # is_batchnorm卷积后是否做归一化处理
        super(unetConv2, self).__init__()
        self.n = n
        self.ks = ks
        self.stride = stride
        self.padding = padding
        s = stride
        p = padding
        if is_batchnorm:  # 卷积后，做数据归一化处理
            for i in range(1, n + 1):  # range(start, stop, step)计数迭代的过程中不包括stop
                conv = nn.Sequential(nn.Conv2d(in_size, out_size, ks, s, p),
                                     nn.BatchNorm2d(out_size),
                                     nn.ReLU(inplace=True), )
                setattr(self, 'conv%d' % i, conv)
                in_size = out_size

        else:  # 卷积后不做数据归一化处理，可能会出现卷积得到的数据过大，导致ReLU的网络性能不稳定
            for i in range(1, n + 1):
                conv = nn.Sequential(nn.Conv2d(in_size, out_size, ks, s, p),
                                     nn.ReLU(inplace=True), )
                setattr(self, 'conv%d' % i, conv)
                in_size = out_size

        # initialise the blocks  #自定义参数初始化方法
        for m in self.children():  # children包括net的方法
            init_weights(m, init_type='kaiming')  # 意思是给网络的每一层赋予权重

    def forward(self, inputs):  # 返回每一个编码模块的结果
        x = inputs
        for i in range(1, self.n + 1):  # n表示卷积层的个数，为2
            conv = getattr(self, 'conv%d' % i)
            x = conv(x)

        return x

class unetUp(nn.Module):
    def __init__(self, in_size, out_size, is_deconv, n_concat=2):
        super(unetUp, self).__init__()
        # self.conv = unetConv2(in_size + (n_concat - 2) * out_size, out_size, False)
        self.conv = unetConv2(out_size * 2, out_size, False)
        if is_deconv:
            self.up = nn.ConvTranspose2d(in_size, out_size, kernel_size=4, stride=2, padding=1)
        else:
            self.up = nn.UpsamplingBilinear2d(scale_factor=2)

        # initialise the blocks
        for m in self.children():
            if m.__class__.__name__.find('unetConv2') != -1: continue
            init_weights(m, init_type='kaiming')

    def forward(self, inputs0, *input):
        # print(self.n_concat)
        # print(input)
        outputs0 = self.up(inputs0)
        for i in range(len(input)):
            outputs0 = torch.cat([outputs0, input[i]], 1)
        return self.conv(outputs0)

class unetUp_origin(nn.Module):
    def __init__(self, in_size, out_size, is_deconv, n_concat=2):
        super(unetUp_origin, self).__init__()
        # self.conv = unetConv2(out_size*2, out_size, False)
        if is_deconv:
            self.conv = unetConv2(in_size + (n_concat - 2) * out_size, out_size, False)
            self.up = nn.ConvTranspose2d(in_size, out_size, kernel_size=4, stride=2, padding=1)
        else:
            self.conv = unetConv2(in_size + (n_concat - 2) * out_size, out_size, False)
            self.up = nn.UpsamplingBilinear2d(scale_factor=2)

        # initialise the blocks
        for m in self.children():
            if m.__class__.__name__.find('unetConv2') != -1: continue
            init_weights(m, init_type='kaiming')

    def forward(self, inputs0, *input):
        # print(self.n_concat)
        # print(input)
        outputs0 = self.up(inputs0)
        for i in range(len(input)):
            outputs0 = torch.cat([outputs0, input[i]], 1)
        return self.conv(outputs0)

class TransMUNet(nn.Module):
    DEPTH = 6

    def __init__(self, n_classes=2,
                 patch_size: int = 16,
                 emb_size: int = 512,
                 img_size: int = 256,
                 n_channels=3,
                 feature_scale=4,
                 is_deconv=True,
                 is_batchnorm=True,
                 depth: int = 4,
                 n_regions: int = (256 // 16) ** 2,
                 output_ch: int = 1,
                 bilinear=True):
        super().__init__()
        self.n_classes = n_classes
        self.transformer = ViT(in_channels=n_channels,
                               patch_size=patch_size,
                               emb_size=emb_size,
                               img_size=img_size,
                               depth=depth,
                               n_regions=n_regions)
        resnet = torchvision.models.resnet.resnet50(pretrained=True)
        down_blocks = []
        up_blocks = []
        self.input_block = nn.Sequential(*list(resnet.children()))[:3]
        self.input_pool = list(resnet.children())[3]
        for bottleneck in list(resnet.children()):
            if isinstance(bottleneck, nn.Sequential):
                down_blocks.append(bottleneck)
        self.down_blocks = nn.ModuleList(down_blocks)
        self.bridge = Bridge(2048, 2048)
        up_blocks.append(UpBlockForUNetWithResNet50(2048, 1024))
        up_blocks.append(UpBlockForUNetWithResNet50(1024, 512))
        up_blocks.append(UpBlockForUNetWithResNet50(512, 256))
        up_blocks.append(UpBlockForUNetWithResNet50(in_channels=128 + 64, out_channels=128,
                                                    up_conv_in_channels=256, up_conv_out_channels=128))
        up_blocks.append(UpBlockForUNetWithResNet50(in_channels=64 + 3, out_channels=64,
                                                    up_conv_in_channels=128, up_conv_out_channels=64))

        self.up_blocks = nn.ModuleList(up_blocks)

        self.out = nn.Conv2d(128, n_classes, kernel_size=1, stride=1)

        self.boundary = nn.Sequential(nn.Conv2d(64, 32, kernel_size=1, stride=1),
                                      nn.BatchNorm2d(32), nn.ReLU(inplace=True),
                                      nn.Conv2d(32, 1, kernel_size=1, stride=1, bias=False),
                                      nn.Sigmoid())

        self.se = SE_Block(c=64)
        self.is_deconv = is_deconv  # 作用？？
        self.in_channels = 3
        self.is_batchnorm = is_batchnorm  # 一个卷积层后是否进行归一化处理，以防止ReLU处理时，由于数据过大，导致网络性能不稳定。
        self.feature_scale = feature_scale

        filters = [32,64, 128, 256, 512]  # feature channels

        ## -------------Encoder--------------
        # 这是一个编码层
        self.conv1 = unetConv2(self.in_channels, filters[0], self.is_batchnorm)
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)

        self.conv2 = unetConv2(filters[0], filters[1], self.is_batchnorm)
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)

        self.conv3 = unetConv2(filters[1], filters[2], self.is_batchnorm)
        self.maxpool3 = nn.MaxPool2d(kernel_size=2)

        self.conv4 = unetConv2(filters[2], filters[3], self.is_batchnorm)
        self.maxpool4 = nn.MaxPool2d(kernel_size=2)

        self.conv5 = unetConv2(filters[3], filters[4], self.is_batchnorm)

        ## -------------Decoder--------------
        self.CatChannels = filters[0]  # 每个decoder用5个尺度的特征图进行拼接，每个尺度的特征图的特征通道都为64，即filter[0]
        self.CatBlocks = 5  # 每个decoder有来自五个尺度的特征图进行拼接
        self.UpChannels = self.CatChannels * self.CatBlocks  # 每个decoder拼接后的特征通道数量 320

        '''stage 4d'''
        # Deccoder4中，获取较小四层的详细信息的拼接操作
        # 对En1的操作 maxpooling(8), 64, 3*3
        # h1->320*320, hd4->40*40, Pooling 8 times
        self.h1_PT_hd4 = nn.MaxPool2d(8, 8,
                                      ceil_mode=True)  # MaxPool2d(kernel_size, stride, ceil_mode) kernel_size指最大池的窗口大小，stride是一次移动的步长，ceil_mode是向上取整。
        self.h1_PT_hd4_conv = nn.Conv2d(filters[0], self.CatChannels, 3, padding=1)  # padding对卷积后的特征图进行了边缘像素的修补。
        self.h1_PT_hd4_bn = nn.BatchNorm2d(self.CatChannels)  # 参数为特征通道的数量
        self.h1_PT_hd4_relu = nn.ReLU(inplace=True)  # inplace=True 函数会把输出直接覆盖到输入中。

        # 对En2的操作，maxpooling(4), 64, 3*3
        # h2->160*160, hd4->40*40, Pooling 4 times
        self.h2_PT_hd4 = nn.MaxPool2d(4, 4, ceil_mode=True)
        self.h2_PT_hd4_conv = nn.Conv2d(filters[1], self.CatChannels, 3, padding=1)
        self.h2_PT_hd4_bn = nn.BatchNorm2d(self.CatChannels)
        self.h2_PT_hd4_relu = nn.ReLU(inplace=True)

        # 对En3的操作，maxpooling(2), 64, 3*3
        # h3->80*80, hd4->40*40, Pooling 2 times
        self.h3_PT_hd4 = nn.MaxPool2d(2, 2, ceil_mode=True)
        self.h3_PT_hd4_conv = nn.Conv2d(filters[2], self.CatChannels, 3, padding=1)
        self.h3_PT_hd4_bn = nn.BatchNorm2d(self.CatChannels)
        self.h3_PT_hd4_relu = nn.ReLU(inplace=True)

        # 对同层En4的操作，64， 3*3。 同层没有最大池的操作。
        # h4->40*40, hd4->40*40, Concatenation
        self.h4_Cat_hd4_conv = nn.Conv2d(filters[3], self.CatChannels, 3, padding=1)
        self.h4_Cat_hd4_bn = nn.BatchNorm2d(self.CatChannels)
        self.h4_Cat_hd4_relu = nn.ReLU(inplace=True)

        # Decoder4中，获取较大层的粗粒度信息的拼接操作
        # bilinear upsample(2)
        # hd5->20*20, hd4->40*40, Upsample 2 times
        self.hd5_UT_hd4 = nn.Upsample(scale_factor=2, mode='bilinear')  # 14*14  #scale_factor指定输出为输入的多少倍
        self.hd5_UT_hd4_conv = nn.Conv2d(filters[4], self.CatChannels, 3, padding=1)
        self.hd5_UT_hd4_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd5_UT_hd4_relu = nn.ReLU(inplace=True)

        # fusion(h1_PT_hd4, h2_PT_hd4, h3_PT_hd4, h4_Cat_hd4, hd5_UT_hd4)
        # #特征聚合机制
        self.conv4d_1 = nn.Conv2d(self.UpChannels, self.UpChannels, 3, padding=1)  # 16
        self.bn4d_1 = nn.BatchNorm2d(self.UpChannels)
        self.relu4d_1 = nn.ReLU(inplace=True)

        '''stage 3d'''
        # h1->320*320, hd3->80*80, Pooling 4 times
        self.h1_PT_hd3 = nn.MaxPool2d(4, 4, ceil_mode=True)
        self.h1_PT_hd3_conv = nn.Conv2d(filters[0], self.CatChannels, 3, padding=1)
        self.h1_PT_hd3_bn = nn.BatchNorm2d(self.CatChannels)
        self.h1_PT_hd3_relu = nn.ReLU(inplace=True)

        # h2->160*160, hd3->80*80, Pooling 2 times
        self.h2_PT_hd3 = nn.MaxPool2d(2, 2, ceil_mode=True)
        self.h2_PT_hd3_conv = nn.Conv2d(filters[1], self.CatChannels, 3, padding=1)
        self.h2_PT_hd3_bn = nn.BatchNorm2d(self.CatChannels)
        self.h2_PT_hd3_relu = nn.ReLU(inplace=True)

        # h3->80*80, hd3->80*80, Concatenation
        self.h3_Cat_hd3_conv = nn.Conv2d(filters[2], self.CatChannels, 3, padding=1)
        self.h3_Cat_hd3_bn = nn.BatchNorm2d(self.CatChannels)
        self.h3_Cat_hd3_relu = nn.ReLU(inplace=True)

        # hd4->40*40, hd4->80*80, Upsample 2 times
        self.hd4_UT_hd3 = nn.Upsample(scale_factor=2, mode='bilinear')  # 14*14
        self.hd4_UT_hd3_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3,
                                         padding=1)  # 注意此处卷积的输入channels为UpChannels,即Decoder4聚合后的特征通道数量。
        self.hd4_UT_hd3_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd4_UT_hd3_relu = nn.ReLU(inplace=True)

        # hd5->20*20, hd4->80*80, Upsample 4 times
        self.hd5_UT_hd3 = nn.Upsample(scale_factor=4, mode='bilinear')  # 14*14
        self.hd5_UT_hd3_conv = nn.Conv2d(filters[4], self.CatChannels, 3, padding=1)
        self.hd5_UT_hd3_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd5_UT_hd3_relu = nn.ReLU(inplace=True)

        # fusion(h1_PT_hd3, h2_PT_hd3, h3_Cat_hd3, hd4_UT_hd3, hd5_UT_hd3)
        self.conv3d_1 = nn.Conv2d(self.UpChannels, self.UpChannels, 3, padding=1)  # 16
        self.bn3d_1 = nn.BatchNorm2d(self.UpChannels)
        self.relu3d_1 = nn.ReLU(inplace=True)

        '''stage 2d '''
        # h1->320*320, hd2->160*160, Pooling 2 times
        self.h1_PT_hd2 = nn.MaxPool2d(2, 2, ceil_mode=True)
        self.h1_PT_hd2_conv = nn.Conv2d(filters[0], self.CatChannels, 3, padding=1)
        self.h1_PT_hd2_bn = nn.BatchNorm2d(self.CatChannels)
        self.h1_PT_hd2_relu = nn.ReLU(inplace=True)

        # h2->160*160, hd2->160*160, Concatenation
        self.h2_Cat_hd2_conv = nn.Conv2d(filters[1], self.CatChannels, 3, padding=1)
        self.h2_Cat_hd2_bn = nn.BatchNorm2d(self.CatChannels)
        self.h2_Cat_hd2_relu = nn.ReLU(inplace=True)

        # hd3->80*80, hd2->160*160, Upsample 2 times
        self.hd3_UT_hd2 = nn.Upsample(scale_factor=2, mode='bilinear')  # 14*14
        self.hd3_UT_hd2_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3, padding=1)
        self.hd3_UT_hd2_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd3_UT_hd2_relu = nn.ReLU(inplace=True)

        # hd4->40*40, hd2->160*160, Upsample 4 times
        self.hd4_UT_hd2 = nn.Upsample(scale_factor=4, mode='bilinear')  # 14*14
        self.hd4_UT_hd2_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3, padding=1)
        self.hd4_UT_hd2_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd4_UT_hd2_relu = nn.ReLU(inplace=True)

        # hd5->20*20, hd2->160*160, Upsample 8 times
        self.hd5_UT_hd2 = nn.Upsample(scale_factor=8, mode='bilinear')  # 14*14
        self.hd5_UT_hd2_conv = nn.Conv2d(filters[4], self.CatChannels, 3, padding=1)
        self.hd5_UT_hd2_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd5_UT_hd2_relu = nn.ReLU(inplace=True)

        # fusion(h1_PT_hd2, h2_Cat_hd2, hd3_UT_hd2, hd4_UT_hd2, hd5_UT_hd2)
        self.conv2d_1 = nn.Conv2d(self.UpChannels, self.UpChannels, 3, padding=1)  # 16
        self.bn2d_1 = nn.BatchNorm2d(self.UpChannels)
        self.relu2d_1 = nn.ReLU(inplace=True)

        '''stage 1d'''
        # h1->320*320, hd1->320*320, Concatenation
        self.h1_Cat_hd1_conv = nn.Conv2d(filters[0], self.CatChannels, 3, padding=1)
        self.h1_Cat_hd1_bn = nn.BatchNorm2d(self.CatChannels)
        self.h1_Cat_hd1_relu = nn.ReLU(inplace=True)

        # hd2->160*160, hd1->320*320, Upsample 2 times
        self.hd2_UT_hd1 = nn.Upsample(scale_factor=2, mode='bilinear')  # 14*14
        self.hd2_UT_hd1_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3, padding=1)
        self.hd2_UT_hd1_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd2_UT_hd1_relu = nn.ReLU(inplace=True)

        # hd3->80*80, hd1->320*320, Upsample 4 times
        self.hd3_UT_hd1 = nn.Upsample(scale_factor=4, mode='bilinear')  # 14*14
        self.hd3_UT_hd1_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3, padding=1)
        self.hd3_UT_hd1_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd3_UT_hd1_relu = nn.ReLU(inplace=True)

        # hd4->40*40, hd1->320*320, Upsample 8 times
        self.hd4_UT_hd1 = nn.Upsample(scale_factor=8, mode='bilinear')  # 14*14
        self.hd4_UT_hd1_conv = nn.Conv2d(self.UpChannels, self.CatChannels, 3, padding=1)
        self.hd4_UT_hd1_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd4_UT_hd1_relu = nn.ReLU(inplace=True)

        # hd5->20*20, hd1->320*320, Upsample 16 times
        self.hd5_UT_hd1 = nn.Upsample(scale_factor=16, mode='bilinear')  # 14*14
        self.hd5_UT_hd1_conv = nn.Conv2d(filters[4], self.CatChannels, 3, padding=1)
        self.hd5_UT_hd1_bn = nn.BatchNorm2d(self.CatChannels)
        self.hd5_UT_hd1_relu = nn.ReLU(inplace=True)

        # fusion(h1_Cat_hd1, hd2_UT_hd1, hd3_UT_hd1, hd4_UT_hd1, hd5_UT_hd1)
        self.conv1d_1 = nn.Conv2d(self.UpChannels, self.UpChannels, 3, padding=1)  # 16
        self.bn1d_1 = nn.BatchNorm2d(self.UpChannels)
        self.relu1d_1 = nn.ReLU(inplace=True)

        # output
        self.outconv1 = nn.Conv2d(self.UpChannels, n_classes, 3, padding=1)  # 最后通过3*3卷积，将320通道转为n_classes通道。
        self.aaaa = nn.Conv2d(1, 64, kernel_size=1, stride=1)

        # initialise weights
        for m in self.modules():
            if isinstance(m, nn.Conv2d):  # isinstance(object, classes)判断实例object是否为classes类型，是则返回true
                init_weights(m, init_type='kaiming')  # 【理解权重函数？？】
            elif isinstance(m, nn.BatchNorm2d):
                init_weights(m, init_type='kaiming')

    def forward(self, x, with_additional=False):
        [global_contexual, regional_distribution, region_coeff] = self.transformer(x)
        pre_pools = dict()
        # pre_pools[f"layer_0"] = x
        # x = self.input_block(x)
        # pre_pools[f"layer_1"] = x
        # x = self.input_pool(x)
        #
        # for i, block in enumerate(self.down_blocks, 2):
        #     x = block(x)
        #     if i == (TransMUNet.DEPTH - 1):
        #         continue
        #     pre_pools[f"layer_{i}"] = x
        #
        # x = self.bridge(x)
        #
        # for i, block in enumerate(self.up_blocks, 1):
        #     key = f"layer_{TransMUNet.DEPTH - 1 - i}"
        #     x = block(x, pre_pools[key])
        ## -------------Encoder-------------
        h1 = self.conv1(x)  # h1->320*320*64

        h2 = self.maxpool1(h1)
        h2 = self.conv2(h2)  # h2->160*160*128

        h3 = self.maxpool2(h2)
        h3 = self.conv3(h3)  # h3->80*80*256

        h4 = self.maxpool3(h3)
        h4 = self.conv4(h4)  # h4->40*40*512

        h5 = self.maxpool4(h4)
        hd5 = self.conv5(h5)  # h5->20*20*1024

        ## -------------Decoder-------------
        # decoder4
        h1_PT_hd4 = self.h1_PT_hd4_relu(self.h1_PT_hd4_bn(self.h1_PT_hd4_conv(self.h1_PT_hd4(h1))))
        h2_PT_hd4 = self.h2_PT_hd4_relu(self.h2_PT_hd4_bn(self.h2_PT_hd4_conv(self.h2_PT_hd4(h2))))
        h3_PT_hd4 = self.h3_PT_hd4_relu(self.h3_PT_hd4_bn(self.h3_PT_hd4_conv(self.h3_PT_hd4(h3))))
        h4_Cat_hd4 = self.h4_Cat_hd4_relu(self.h4_Cat_hd4_bn(self.h4_Cat_hd4_conv(h4)))
        hd5_UT_hd4 = self.hd5_UT_hd4_relu(self.hd5_UT_hd4_bn(self.hd5_UT_hd4_conv(self.hd5_UT_hd4(hd5))))
        hd4 = self.relu4d_1(self.bn4d_1(self.conv4d_1(
            torch.cat((h1_PT_hd4, h2_PT_hd4, h3_PT_hd4, h4_Cat_hd4, hd5_UT_hd4), 1))))  # hd4->40*40*UpChannels

        # decoder3
        h1_PT_hd3 = self.h1_PT_hd3_relu(self.h1_PT_hd3_bn(self.h1_PT_hd3_conv(self.h1_PT_hd3(h1))))
        h2_PT_hd3 = self.h2_PT_hd3_relu(self.h2_PT_hd3_bn(self.h2_PT_hd3_conv(self.h2_PT_hd3(h2))))
        h3_Cat_hd3 = self.h3_Cat_hd3_relu(self.h3_Cat_hd3_bn(self.h3_Cat_hd3_conv(h3)))
        hd4_UT_hd3 = self.hd4_UT_hd3_relu(self.hd4_UT_hd3_bn(self.hd4_UT_hd3_conv(self.hd4_UT_hd3(hd4))))
        hd5_UT_hd3 = self.hd5_UT_hd3_relu(self.hd5_UT_hd3_bn(self.hd5_UT_hd3_conv(self.hd5_UT_hd3(hd5))))
        hd3 = self.relu3d_1(self.bn3d_1(self.conv3d_1(
            torch.cat((h1_PT_hd3, h2_PT_hd3, h3_Cat_hd3, hd4_UT_hd3, hd5_UT_hd3), 1))))  # hd3->80*80*UpChannels

        # decoder2
        h1_PT_hd2 = self.h1_PT_hd2_relu(self.h1_PT_hd2_bn(self.h1_PT_hd2_conv(self.h1_PT_hd2(h1))))
        h2_Cat_hd2 = self.h2_Cat_hd2_relu(self.h2_Cat_hd2_bn(self.h2_Cat_hd2_conv(h2)))
        hd3_UT_hd2 = self.hd3_UT_hd2_relu(self.hd3_UT_hd2_bn(self.hd3_UT_hd2_conv(self.hd3_UT_hd2(hd3))))
        hd4_UT_hd2 = self.hd4_UT_hd2_relu(self.hd4_UT_hd2_bn(self.hd4_UT_hd2_conv(self.hd4_UT_hd2(hd4))))
        hd5_UT_hd2 = self.hd5_UT_hd2_relu(self.hd5_UT_hd2_bn(self.hd5_UT_hd2_conv(self.hd5_UT_hd2(hd5))))
        hd2 = self.relu2d_1(self.bn2d_1(self.conv2d_1(
            torch.cat((h1_PT_hd2, h2_Cat_hd2, hd3_UT_hd2, hd4_UT_hd2, hd5_UT_hd2), 1))))  # hd2->160*160*UpChannels

        # decoder1
        h1_Cat_hd1 = self.h1_Cat_hd1_relu(self.h1_Cat_hd1_bn(self.h1_Cat_hd1_conv(h1)))
        hd2_UT_hd1 = self.hd2_UT_hd1_relu(self.hd2_UT_hd1_bn(self.hd2_UT_hd1_conv(self.hd2_UT_hd1(hd2))))
        hd3_UT_hd1 = self.hd3_UT_hd1_relu(self.hd3_UT_hd1_bn(self.hd3_UT_hd1_conv(self.hd3_UT_hd1(hd3))))
        hd4_UT_hd1 = self.hd4_UT_hd1_relu(self.hd4_UT_hd1_bn(self.hd4_UT_hd1_conv(self.hd4_UT_hd1(hd4))))
        hd5_UT_hd1 = self.hd5_UT_hd1_relu(self.hd5_UT_hd1_bn(self.hd5_UT_hd1_conv(self.hd5_UT_hd1(hd5))))
        hd1 = self.relu1d_1(self.bn1d_1(self.conv1d_1(
            torch.cat((h1_Cat_hd1, hd2_UT_hd1, hd3_UT_hd1, hd4_UT_hd1, hd5_UT_hd1), 1))))  # hd1->320*320*UpChannels

        # 输出
        d1 = self.outconv1(hd1)  # d1->320*320*n_classes
        x = F.sigmoid(d1)
        x = self.aaaa(x)
        #print("xxx", np.shape(x))

        B_out = self.boundary(x)
        B = B_out.repeat_interleave(int(x.shape[1]), dim=1)
        x = self.se(x)

        x = x + B
        att = regional_distribution.repeat_interleave(int(x.shape[1]), dim=1)
        x = x * att
        x = torch.cat((x, global_contexual), dim=1)
        x = self.out(x)
        del pre_pools
        x = torch.sigmoid(x)
        if with_additional:
            return x, B_out, region_coeff
        else:
            return x
# F1 score (F-measure) or DSC: 0.8790826235509107
# Accuracy: 0.9548275375366211
# Specificity: 0.9688620258305293
# Sensitivity: 0.8908453429595539
# val_mode

#UNet3+


"""
Module that holds functions supporting various model methods. Not designed to be user-facing
"""

import numpy as np
import numba as nb

@nb.njit(cache=True, nogil=True)
def sgd(
    data,
    seed,
    global_bias,
    data_range,
    tol,
    user_bias,
    user_vecs,
    user_bias_reg,
    user_fact_reg,
    item_bias,
    item_vecs,
    item_bias_reg,
    item_fact_reg,
    n_iterations,
    row_indices,
    col_indices,
    learning_rate,
    verbose,
):
    """SGD Update. This implementation is nearly identitical the the SVD implementation used by Simon Funk in the Netflix challenge and implemented in Surprise with a few small differences. We currently only support a single learning rate for all parameters (Surprise supports independent learning rates, but doesn't use them by default), we don't train in batched epochs but rather over *all* training data in each iteration, and we force user and item factor values to be >=0 after each pass over the training data."""

    error_history = np.zeros((n_iterations))
    converged = False
    last_e = 0
    norm_rmse = np.inf
    delta = np.inf
    np.random.seed(seed)
    for this_iter in range(n_iterations):

        # Generate shuffled order to loop over training data
        # Recall that row_indices and col_indices need to be looped over simultaneously to properly index each training value at [row, col]
        training_indices = np.arange(len(row_indices))
        np.random.shuffle(training_indices)

        if verbose and this_iter > 0 and this_iter % 10 == 0:
            disp_norm_error = np.round(100 * norm_rmse, 2)
            # Numba doesn't like f-strings
            print(
                "Iter:",
                this_iter,
                " Norm RMSE:",
                disp_norm_error,
                "%  Delta Convg:",
                delta,
                "||",
                tol,
            )

        # Loop over every data point in the training set, make a prediction, calculate error, and update biases and vectors
        # Very similar to Surprise's SVD implementation: https://github.com/NicolasHug/Surprise/blob/master/surprise/prediction_algorithms/matrix_factorization.pyx#L159
        # Because we're iterating an user-item combo at a time, track total error
        total_error = 0
        for idx in training_indices:
            u = row_indices[idx]
            i = col_indices[idx]

            prediction = global_bias + user_bias[u] + item_bias[i]
            prediction += user_vecs[u, :] @ item_vecs[:, i]

            # Use changes in e to determine tolerance
            e = data[u, i] - prediction  # error

            # Update biases
            user_bias[u] += learning_rate * (e - user_bias_reg * user_bias[u])
            item_bias[i] += learning_rate * (e - item_bias_reg * item_bias[i])

            # Update latent factors
            user_vecs[u, :] += learning_rate * (
                e * item_vecs[:, i] - user_fact_reg * user_vecs[u, :]
            )
            item_vecs[:, i] += learning_rate * (
                e * user_vecs[u, :] - item_fact_reg * item_vecs[:, i]
            )

            # Keep track of total squared error
            total_error += np.power(e, 2)

        # Force non-negativity. Surprise does this per-epoch via re-initialization. We do this per sweep over all training data, e.g. see: https://github.com/NicolasHug/Surprise/blob/master/surprise/prediction_algorithms/matrix_factorization.pyx#L671
        user_vecs = np.maximum(user_vecs, 0)
        item_vecs = np.maximum(item_vecs, 0)

        # Normalize the current error with respect to the range of the dataset
        rmse = np.sqrt(total_error / len(training_indices))
        norm_rmse = rmse / data_range
        error_history[this_iter] = norm_rmse

        # Compute the delta to see if we should stop iterating
        delta = np.abs(np.abs(norm_rmse) - np.abs(last_e))
        # If we've converged break out of iteration
        if delta < tol:
            converged = True
            error_history = error_history[: this_iter + 1]
            break
        # Otherwise update the error
        last_e = norm_rmse

    return (
        error_history,
        converged,
        this_iter,
        delta,
        norm_rmse,
        user_bias,
        user_vecs,
        item_bias,
        item_vecs,
    )

@nb.njit(cache=True, nogil=True)
def mult(X, W, H, data_range, eps, tol, n_iterations, verbose):
    """Lee & Seung (2001) multiplicative update rule"""

    last_e = 0
    error_history = np.zeros((n_iterations))
    converged = False
    norm_rmse = np.inf
    delta = np.inf

    for this_iter in range(n_iterations):

        if verbose and this_iter > 0 and this_iter % 10 == 0:
            disp_norm_error = np.round(100 * norm_rmse, 2)
            # Numba doesn't like f-strings
            print(
                "Iter:",
                this_iter,
                " Norm RMSE:",
                disp_norm_error,
                "%  Delta Convg:",
                delta,
                "||",
                tol,
            )

        # Update H
        numer = W.T @ X
        denom = W.T @ W @ H + eps
        H *= numer
        H /= denom

        # Update W
        numer = X @ H.T
        denom = W @ H @ H.T + eps
        W *= numer
        W /= denom

        # Make prediction and get error
        errors = X - W @ H
        rmse = np.sqrt(np.mean(np.power(errors, 2)))

        # Normalize current error with respect to max of dataset
        norm_rmse = rmse / data_range
        error_history[this_iter] = norm_rmse

        # Compute delta to see if we should stop iterating
        delta = np.abs(np.abs(norm_rmse) - np.abs(last_e))
        if delta < tol:
            converged = True
            error_history = error_history[: this_iter + 1]
            break
        # Otherwise update the error
        last_e = norm_rmse

    return error_history, converged, this_iter, delta, norm_rmse, W, H


import paho.mqtt.client as mqtt
import json
import datetime

from pyparsing import one_of

client = mqtt.Client("room-controller")

# sensing topics
# 326project/smartbuilding/hvac/<floorno>/<roomno>/temperature
tempSensorTopic = "326project/smartbuilding/hvac/0/0/temperature"
tempSensorTopic2 = "326project/smartbuilding/hvac/0/1/temperature"
# 326project/smartbuilding/hvac/<floorno>/<roomno>/pressure
presSensorTopic = "326project/smartbuilding/hvac/0/0/pressure"
presSensorTopic2 = "326project/smartbuilding/hvac/0/1/pressure"

# control topics
# 326project/smartbuilding/hvac/<floorno>/<roomno>/control/ahu
ahuControlTopic = "326project/smartbuilding/hvac/0/0/control/ahu"
ahuControlTopic2 = "326project/smartbuilding/hvac/0/1/control/ahu"

# change threasholds
# 326project/smartbuilding/hvac/<floorno>/<roomno>/control/temp-thresh
tempThreasholdChangeTopic = "326project/smartbuilding/hvac/0/0/control/temp-thresh"
tempThreasholdChangeTopic2 = "326project/smartbuilding/hvac/0/1/control/temp-thresh"
# 326project/smartbuilding/hvac/<floorno>/<roomno>/control/pressure-thresh
pressureThreasholdChangeTopic = "326project/smartbuilding/hvac/0/0/control/pressure-thresh"
pressureThreasholdChangeTopic2 = "326project/smartbuilding/hvac/0/1/control/pressure-thresh"

tempThreashold = 30 # default
tempThreashold2 = 30 # default

pressureThreashold = 1 # default
pressureThreashold2 = 1 # default

# allowed ranges
tempCanChange = 1
tempCanChange2 = 1

pressureCanChange = 0.1
pressureCanChange2 = 0.1

# previous values
previousBlowerSpeed = 40 # default
previousBlowerSpeed2 = 40 # default

previousRatio = 0.3 # default
previousRatio2 = 0.3 # default

def on_message_for_temp(client, userdata, message):
    data = json.loads(message.payload)
    values = list(data.values())
    temperature = values[1]

    global previousBlowerSpeed
    global previousRatio

    if (temperature < (tempThreashold - tempCanChange)):  # increase the ratio by 0.1
        previousRatio += 0.1
        if previousRatio > 1:
            previousRatio = 1
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed,
            "ratio": round(previousRatio, 2)
        }
        client.publish(ahuControlTopic, json.dumps(x))
        print("published to topic " + ahuControlTopic + " new ratio - " + str(previousRatio))

    elif (temperature > tempThreashold + tempCanChange):
        previousRatio -= 0.1
        if previousRatio < 0:
            previousRatio = 0

        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed,
            "ratio": round(previousRatio, 2)
        }
        client.publish(ahuControlTopic, json.dumps(x))
        print("published to topic " + ahuControlTopic + " new ratio - " + str(previousRatio))

def on_message_for_pressure(client, userdata, message):
    data = json.loads(message.payload)
    values = list(data.values())
    pressure = values[1]

    global previousBlowerSpeed
    global previousRatio

    if (pressure < (pressureThreashold - pressureCanChange)):  # increase the blower speed by 1
        previousBlowerSpeed = min(previousBlowerSpeed+1, 100)
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed,
            "ratio": round(previousRatio, 2)
        }
        client.publish(ahuControlTopic, json.dumps(x))
        print("published to topic " + ahuControlTopic + " new blower speed - " + str(previousBlowerSpeed))

    elif (pressure > pressureThreashold + pressureCanChange):
        previousBlowerSpeed = max(previousBlowerSpeed-1, 0)
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed,
            "ratio": round(previousRatio, 2)
        }
        client.publish(ahuControlTopic, json.dumps(x))
        print("published to topic " + ahuControlTopic + " new blower speed - " + str(previousBlowerSpeed))

##### Change threasholds

# changing temp threashold
def on_message_for_temp_threshold(client, userdata, message):
    data = json.loads(message.payload)

    global tempThreashold
    values = list(data.values())
    tempThreashold = values[1]
    print()
    print("**********************************")
    print("new threashold temperature is " + str(tempThreashold))
    print("**********************************")
    print()

# changing pressure threashold
def on_message_for_pressure_threshold(client, userdata, message):
    data = json.loads(message.payload)
    global pressureThreashold
    values = list(data.values())
    pressureThreashold = values[1]
    print()
    print("**********************************")
    print("new threashold pressure is " + str(pressureThreashold))
    print("**********************************")
    print()

# ---------------------------------------------------------------------------------------------------------------------
def on_message_for_temp2(client, userdata, message):
    data = json.loads(message.payload)
    values = list(data.values())
    temperature = values[1]

    global previousBlowerSpeed2
    global previousRatio2

    if (temperature < (tempThreashold2 - tempCanChange2)):  # increase the ratio by 0.1
        previousRatio2 += 0.1
        if previousRatio2 > 1:
            previousRatio2 = 1
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed2,
            "ratio": round(previousRatio2, 2)
        }
        client.publish(ahuControlTopic2, json.dumps(x))
        print("published to topic " + ahuControlTopic2 + " new ratio - " + str(previousRatio2))

    elif (temperature > tempThreashold2 + tempCanChange2):
        previousRatio2 -= 0.1
        if previousRatio2 < 0:
            previousRatio2 = 0

        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed2,
            "ratio": round(previousRatio2, 2)
        }
        client.publish(ahuControlTopic2, json.dumps(x))
        print("published to topic " + ahuControlTopic2 + " new ratio - " + str(previousRatio2))

def on_message_for_pressure2(client, userdata, message):
    data = json.loads(message.payload)
    values = list(data.values())
    pressure = values[1]

    global previousBlowerSpeed2
    global previousRatio2

    if (pressure < (pressureThreashold2 - pressureCanChange2)):  # increase the blower speed by 1
        previousBlowerSpeed2 = min(previousBlowerSpeed2+1, 100)
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed2,
            "ratio": round(previousRatio2, 2)
        }
        client.publish(ahuControlTopic2, json.dumps(x))
        print("published to topic " + ahuControlTopic2 + " new blower speed - " + str(previousBlowerSpeed2))

    elif (pressure > pressureThreashold2 + pressureCanChange2):
        previousBlowerSpeed2 = max(previousBlowerSpeed2-1, 0)
        x = {
            "time": datetime.datetime.utcnow().strftime('%Y%m%d%H%M%S'),
            "speed": previousBlowerSpeed2,
            "ratio": round(previousRatio2, 2)
        }
        client.publish(ahuControlTopic2, json.dumps(x))
        print("published to topic " + ahuControlTopic2 + " new blower speed - " + str(previousBlowerSpeed2))

##### Change threasholds

# changing temp threashold2
def on_message_for_temp_threshold2(client, userdata, message):
    data = json.loads(message.payload)

    global tempThreashold2
    values = list(data.values())
    tempThreashold2 = values[1]
    print()
    print("**********************************")
    print("new threashold temperature is " + str(tempThreashold2))
    print("**********************************")
    print()

# changing pressure threashold
def on_message_for_pressure_threshold2(client, userdata, message):
    data = json.loads(message.payload)

    global pressureThreashold2
    values = list(data.values())
    pressureThreashold2 = values[1]
    print()
    print("**********************************")
    print("new threashold pressure is " + str(pressureThreashold2))
    print("**********************************")
    print()

client.message_callback_add(tempSensorTopic, on_message_for_temp)
client.message_callback_add(presSensorTopic, on_message_for_pressure)
client.message_callback_add(tempThreasholdChangeTopic, on_message_for_temp_threshold)
client.message_callback_add(pressureThreasholdChangeTopic, on_message_for_pressure_threshold)

client.message_callback_add(tempSensorTopic2, on_message_for_temp2)
client.message_callback_add(presSensorTopic2, on_message_for_pressure2)
client.message_callback_add(tempThreasholdChangeTopic2, on_message_for_temp_threshold2)
client.message_callback_add(pressureThreasholdChangeTopic2, on_message_for_pressure_threshold2)

client.connect("10.40.18.10", port=1883)

client.subscribe([(tempSensorTopic, 0), (presSensorTopic, 0),
                  (tempThreasholdChangeTopic, 0), (pressureThreasholdChangeTopic, 0),
                  (tempSensorTopic2, 0), (presSensorTopic2, 0),
                  (tempThreasholdChangeTopic2, 0), (pressureThreasholdChangeTopic2, 0)
                  ])
client.loop_forever()