import sys
import argparse
import math

def calculate_nominal_interest(interest):
    nominal_interest = interest / (12 * 100)
    return nominal_interest

def calculate_months(principal, monthly_payment, interest):
    nominal_interest = calculate_nominal_interest(interest)
    num_months = math.ceil(math.log(monthly_payment / (monthly_payment - nominal_interest * principal), 1 + nominal_interest))
    return num_months

def calculate_annuity_payment(principal, interest, num_months):
    nominal_interest = calculate_nominal_interest(interest)
    payment = math.ceil(principal * (nominal_interest * (1 + nominal_interest) ** num_months) / ((1 + nominal_interest) ** num_months - 1))
    return payment

def calculate_differentiated_payment(principal, interest, num_months, current_period):
    nominal_interest = calculate_nominal_interest(interest)
    payment = math.ceil((principal/num_months) + nominal_interest * (principal - ((principal * (current_period - 1))/ num_months)))
    return payment

def calculate_principal(interest, num_months, monthly_payment):
    nominal_interest = calculate_nominal_interest(interest)
    principal = math.floor(monthly_payment / ((nominal_interest * (1 + nominal_interest) ** num_months) / ((1 + nominal_interest) ** num_months - 1)))
    return principal

def calculate_total_payment(payment_type, principal, interest, periods):
    if payment_type == 'diff':
        total_payment = differentiated_payment(principal, interest, periods, verbose=False)
    elif payment_type == 'annuity':
        total_payment = payment * periods
    return total_payment

def print_months(num_months):
    years = math.floor(num_months / 12)
    months = num_months % (years * 12)
    if years == 1:
        yrs = 'year'
    else:
        yrs = 'years'
    if months == 1:
        mon = 'month'
    else:
        mon = 'months'
    if years >= 1 and months == 0:
        print(f'You need {years} {yrs} to repay this credit!')
    elif years == 0 and months >= 1:
        print(f'You need {months} {mon} to repay this credit!')
    else:
        print(f'You need {years} {yrs} and {months} {mon} to repay this credit!')

def differentiated_payment(principal, interest, periods, verbose=True):
    current_period = 0
    total_payment = 0
    while current_period < periods:
        current_period += 1
        payment = calculate_differentiated_payment(principal, interest, periods, current_period)
        total_payment += payment
        if verbose:
            print(f'Month {current_period}: payment is {payment}')
    return total_payment

def error(value_1, value_2, value_3, value_4, value_5):
    if value_1 or value_2 or value_3 or value_4 or value_5:
        print('Incorrect parameters')
        sys.exit()

# returns True to trigger error if --interest is None
def check_interest(interest):
    if interest == None:
        return True

# returns True to trigger error if --type is not 'annuity' or 'diff'
def check_type(payment_type):
    if payment_type == 'annuity' or payment_type == 'diff':
        return False
    else:
        return True

# returns True to trigger error if # parameters with a value is == 4
def check_parameters(params):
    counter = 0
    for param in params:
        if param is None:
            pass
        else:
            counter += 1
    if counter == 4:
        return False
    else:
        return True

# returns True if param is less than 0
def check_for_neg(param):
    if param is None:
        return False
    elif int(param) < 0:
        return True
    else:
        return False

# returns True to trigger error if param in params list returns a result in check_for_neg
def check_negs(params):
    for param in params[1:]:
        result = check_for_neg(param)
        if result:
            return True
    return False

# returns True to trigger error if payment_type is 'diff' and payment is not None
def check_diff_payment(payment_type, payment):
    if payment_type == 'diff' and payment != None:
        return True
    else:
        return False

parser = argparse.ArgumentParser()

# required argument
parser.add_argument('--type', type=str, required=True)

#optional arguments
parser.add_argument('--principal', type=float, default=None, help='the value of the credit principal')
parser.add_argument('--payment', type=float, default=None, help='the value of the monthly payment')
parser.add_argument('--periods', type=float, default=None, help='the number of periods to repay the credit')
parser.add_argument('--interest', type=float, default=None, help='the percentage interest on the credit')

args = parser.parse_args()

payment_type = args.type
principal = args.principal
payment = args.payment
periods = args.periods
interest = args.interest

params = [payment_type, principal, payment, periods, interest]

# check for errors
error(check_interest(interest),
      check_type(payment_type),
      check_parameters(params),
      check_negs(params),
      check_diff_payment(payment_type, payment))

# do the math
if payment_type == 'annuity':
    if principal is None:
        principal = calculate_principal(interest, periods, payment)
        print(f'Your credit principal = {principal}!')
    elif periods is None:
        periods = calculate_months(principal, payment, interest)
        print_months(periods)
    else:
        payment = calculate_annuity_payment(principal, interest, periods)
        print(f'Your annuity payment = {payment}!')
elif payment_type == 'diff':
    if principal is None:
        principal = calculate_principal(interest, periods, payment)
        print(f'Your credit principal = {principal}!')
    elif periods is None:
        periods = calculate_months(principal, payment, interest)
        print_months(periods)
    else:
        differentiated_payment(principal, interest, periods)
total = calculate_total_payment(payment_type, principal, interest, periods)
print(f'Overpayment = {int(total - principal)}')


#!/usr/bin/env python
# -*- coding: UTF-8 -*-
# coding=utf-8

"""
@author: Li Tian
@contact: 694317828@qq.com
@software: pycharm
@file: sample_data_deal.py
@time: 2019/2/8 20:30
@desc: 输入数据处理框架
"""

from figuredata_deal.figure_deal_test2 import preprocess_for_train
import tensorflow as tf

# 创建文件列表，并通过文件列表创建输入文件队列。在调用输入数据处理流程前，需要统一所有原始数据的格式
# 并将它们存储到TFRecord文件中。下面给出的文件列表应该包含所有提供训练数据的TFRecord文件。
files = tf.train.match_filenames_once('file_pattern-*')
filename_queue = tf.train.string_input_producer(files, shuffle=False)

# 使用类似前面介绍的方法解析TFRecord文件里的数据。这里假设image中存储的是图像的原始数据，label为该
# 样例所对应的标签。height、width和channels给出了图片的维度。
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
    serialized_example,
    features={
        'image': tf.FixedLenFeature([], tf.string),
        'label': tf.FixedLenFeature([], tf.int64),
        'height': tf.FixedLenFeature([], tf.int64),
        'width': tf.FixedLenFeature([], tf.int64),
        'channels': tf.FixedLenFeature([], tf.int64),
    }
)
image, label = features['image'], features['label']
height, width = features['height'], features['width']
channels = features['channels']

# 从原始图像数据解析出像素矩阵，并根据图像尺寸还原图像。
decoded_image = tf.decode_raw(image, tf.uint8)
decoded_image.set_shape([height, width, channels])
# 定义神经网络输入层图片的大小
image_size = 299
# preprocess_for_train为前面提到的图像预处理程序
distorted_image = preprocess_for_train(decoded_image, image_size, image_size, None)

# 将处理后的图像和标签数据通过tf.train.shuffle_batch整理成神经网络训练时需要的batch。
min_after_dequeue = 10000
batch_size = 100
capacity = min_after_dequeue + 3 * batch_size
image_batch, label_batch = tf.train.shuffle_batch([distorted_image, label], batch_size=batch_size, capacity=capacity, min_after_dequeue=min_after_dequeue)

# 定义神经网络的结构以及优化过程， image_batch可以作为输入提供给神经网络的输入层。
# label_batch则提供了输入batch中样例的正确答案。
# 学习率
learning_rate = 0.01
# inference是神经网络的结构
logit = inference(image_batch)
# loss是计算神经网络的损失函数
loss = cal_loss(logit, label_batch)
# 训练过程
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss)

# 声明会话并运行神经网络的优化过程
with tf.Session() as sess:
    # 神经网络训练准备工作。这些工作包括变量初始化、线程启动。

    sess.run((tf.global_variables_initializer(), tf.local_variables_initializer()))
    coord = tf.train.Coordinator()
    threads = tf.train.start_queue_runners(sess=sess, coord=coord)

    # 神经网络训练过程。
    TRAINING_ROUNDS = 5000
    for i in range(TRAINING_ROUNDS):
        sess.run(train_step)

    # 停止所有线程
    coord.request_stop()
    coord.join(threads)


# Assuming Python 3
import csv
from io import StringIO
import re
from munkres import Munkres

class QualtricsKBFCSVImporter(object):

    def __init__(self, filename=None, csv_content_string=None, legacy_format=False):
        # Initial inputs
        self.filename = filename
        self.csv_content_string = csv_content_string
        self.legacy_format = legacy_format
        #
        self.raw_data = list()
        self.raw_fieldnames = list()
        self.data = dict()
        self.organization_rankings = list()
        self.respondents = list()
        self.organizations = list()
        # Variables used in the initial processing of the CSV data, not meant to be used after
        self.__header_row_index = None
        self.__data_start_row_index = None
        self.__organization_name_pattern = None
        self.__organizations_by_column_index = dict()
        # This is the alternate value provided in case there is no response in the file, e.g. ''. This will be
        # parsed into an integer. This should represent a value larger than any of the actual values in the data.
        self.__NONRESPONSE_VALUE_TEXT = '99'
        self.__first_name_column_index = None
        self.__last_name_column_index = None

        if self.legacy_format:
            self.__header_row_index = 1
            self.__data_start_row_index = 2
            # Created regex using https://pythex.org/
            self.__organization_name_pattern = re.compile(r'-(?P<organization>.*)(?=-Rank)')
        else:
            self.__header_row_index = 1
            self.__data_start_row_index = 3
            # Created regex using https://pythex.org/
            self.__organization_name_pattern = re.compile(r'(?<=- Ranks - Preference - )(?P<organization>.*)(?= - Rank)')

        if self.filename:
            with open(self.filename, 'r') as f:
                self.raw_data = list(csv.reader(f))
        elif self.csv_content_string:
            self.raw_data = list(csv.reader(StringIO(self.csv_content_string)))

        # Extract column indices for the fields we care about, and extract organization names from the column headings they're embedded in
        self.raw_fieldnames = self.raw_data[self.__header_row_index]
        for column_index, field in enumerate(self.raw_fieldnames):
            if re.search(self.__organization_name_pattern, field):
                organization_name = re.search(self.__organization_name_pattern, field).groupdict()['organization']
                self.__organizations_by_column_index[organization_name] = column_index
                self.organizations.append(organization_name)
            elif 'First Name' in field:
                self.__first_name_column_index = column_index
            elif 'Last Name' in field:
                self.__last_name_column_index = column_index
        # Extract the data we care about, keyed by the full name of the respondent and then by the organization name
        respondent_name_from_row = lambda row: row[self.__last_name_column_index] + ', ' + row[self.__first_name_column_index]
        for row in self.raw_data[self.__data_start_row_index:]:
            respondent_name = respondent_name_from_row(row)
            self.respondents.append(respondent_name)
            self.data[respondent_name] = dict()
            for organization_name, column_index in self.__organizations_by_column_index.items():
                            value = row[column_index] or self.__NONRESPONSE_VALUE_TEXT
                            if value == '0':
                                value = self.__NONRESPONSE_VALUE_TEXT
                            self.data[respondent_name][organization_name] = int(value)
        self.respondents = sorted(self.respondents)
        self.organizations = sorted(self.organizations)
        # Build the numeric 2-d array, with the rows corresponding to the respondents and the columns
        # corresponding to the organizations, with each numeric value representing the priority that
        # respondent gave to that organization (max value if the respondent did not specifically
        # rank it).
        for respondent in self.respondents:
            organization_rankings_row = list()
            for organization in self.organizations:
                organization_rankings_row.append(self.data[respondent][organization])
            self.organization_rankings.append(organization_rankings_row)

    def BestOrganizationFit(self):
        m = Munkres()
        indexes = m.compute(self.organization_rankings)
        bestfit_array = list()
        for row, column in indexes:
            respondent = self.respondents[row]
            organization = self.organizations[column]
            ranking = self.organization_rankings[row][column]
            bestfit_array.append({'respondent': respondent, 'organization': organization, 'ranking': ranking})
        return bestfit_array


import os
import Tkinter as tk
import tkFileDialog
import tkMessageBox
import shelve
import multiprocessing

from .. setup_functions	import open_user_prefs,set_default_prefs

from tools_TkTooltip	import ToolTip
from tools_general		import tryProgramCall

class ConfigWindow(tk.LabelFrame):
	def __init__(self, master, mainWindow):
		self.master = master
		self.mainWindow = mainWindow
		self.master.title('Configuration Panel')

		self.master.resizable(width=False, height=False)
		self.master.protocol('WM_DELETE_WINDOW', self.close)

		tk.LabelFrame.__init__(self,master,width=420,height=190,borderwidth=0)
		self.pack(expand=True,fill='both',padx=4,pady=4)
		self.pack_propagate(True)

		self.loadPrefs()
		self.createWidgets()
		self.setVars()

	def loadPrefs(self):
		try:
			self.prefs = open_user_prefs( mode='c' )
		except Exception as e:
			tkMessageBox.showerror("Error",'Cannot read or create MESMER preferences file: %s' % (e),parent=self)
			self.master.destroy()

	def savePrefs(self):
		self.prefs['mesmer_base_dir']	= self.mesmerPath.get()
		self.prefs['mesmer_scratch']	= self.scratchPath.get()
		self.prefs['cpu_count']			= self.numCores.get()

		# append mesmer run arguments
		tmp = self.prefs['run_arguments']

		if(self.prefs['mesmer_scratch'] != ''):
			tmp['scratch'] = self.prefs['mesmer_scratch']
		tmp['threads'] = self.prefs['cpu_count']
		self.prefs['run_arguments'] = tmp

		self.prefs.close()
		self.loadPrefs() #reload, due to to broken db implementation in some OSes

	def resetPrefs(self):
		self.prefs = open_user_prefs( mode='c' )
		set_default_prefs( self.prefs )
		self.savePrefs()
		self.setVars()

	def setVars(self):
		if(self.prefs.has_key('mesmer_base_dir')):
			self.mesmerPath.set( self.prefs['mesmer_base_dir'] )
		else:
			self.mesmerPath.set( os.getcwd() )

		if(self.prefs.has_key('mesmer_scratch')):
			self.scratchPath.set( self.prefs['mesmer_scratch'] )
		else:
			self.scratchPath.set( '' )

		if(self.prefs.has_key('cpu_count') ):
			self.numCores.set( self.prefs['cpu_count'] )
		else:
			self.numCores.set( multiprocessing.cpu_count() )

	def setMESMERPath(self):
		tmp = tkFileDialog.askdirectory(title='Select directory containing MESMER executables, or cancel to leave as default:',mustexist=True,parent=self)
		self.mesmerPath.set(tmp)

	def setScratchPath(self):
		tmp = tkFileDialog.askdirectory(title='Select directory to use as scratch space, or cancel to use default.',mustexist=True,parent=self)
		self.scratchPath.set(tmp)

	def checkPaths(self):
		ok = True
		if(self.mesmerPath.get() == ''):
			if(not tryProgramCall('mesmer')):
				tkMessageBox.showwarning("Warning","The MESMER executables are not available on the system path.\nTry resetting the MESMER preferences, or setting the MESMER installation path manually.",parent=self)
				ok = False
		elif(not os.access(os.path.join(self.mesmerPath.get(),'mesmer.py'), os.R_OK)):
			tkMessageBox.showwarning("Warning","MESMER executables are not installed in this directory.",parent=self)
			ok = False

		if(self.scratchPath.get() != '' and not os.access(self.scratchPath.get(), os.W_OK)):
			tkMessageBox.showwarning("Warning","The MESMER scratch path is not writable.",parent=self)
			ok = False

		if(ok):
			self.savePrefs()
			self.mainWindow.Ready = True
			self.mainWindow.updateWidgets()
			self.master.destroy()

	def close(self):
		self.prefs.close()
		self.master.destroy()

	def createWidgets(self):
		self.container = tk.Frame(self,borderwidth=0)
		self.container.pack()

		self.mesmerPath = tk.StringVar()
		self.mesmerPathLabel = tk.Label(self.container, text='Explicit path to MESMER installation:')
		self.mesmerPathLabel.grid(column=0,row=0,columnspan=3,sticky=tk.W)
		self.mesmerPathEntry = tk.Entry(self.container,width=40,textvariable=self.mesmerPath)
		self.mesmerPathEntry.grid(column=0,columnspan=2,row=1,sticky=tk.E)
		self.mesmerPathButton = tk.Button(self.container, text='Set...',command=self.setMESMERPath)
		self.mesmerPathButton.grid(column=2,columnspan=2,row=1,sticky=tk.W)

		self.scratchPath = tk.StringVar()
		self.mesmerScratchLabel = tk.Label(self.container, text='Directory to use as scratch space:')
		self.mesmerScratchLabel.grid(column=0,row=2,columnspan=3,sticky=tk.W)
		self.mesmerScratchEntry = tk.Entry(self.container,width=40,textvariable=self.scratchPath)
		self.mesmerScratchEntry.grid(column=0,columnspan=2,row=3,sticky=tk.E)
		self.mesmerScratchButton = tk.Button(self.container, text='Set...',command=self.setScratchPath)
		self.mesmerScratchButton.grid(column=2,row=3,sticky=tk.W)

		self.numCores = tk.IntVar()
		self.numCoresLabel = tk.Label(self.container, text='Number of cores to use for multithreading:')
		self.numCoresLabel.grid(column=0,row=4,sticky=tk.W,pady=10)
		self.numCoresEntry = tk.Spinbox(self.container,width=10,textvariable=self.numCores,from_=1,to=24)
		self.numCoresEntry.grid(column=1,columnspan=2,row=4,sticky=tk.E,pady=10)

		self.resetPrefsButton = tk.Button(self.container, text='Reset Preferences',command=self.resetPrefs)
		self.resetPrefsButton.grid(column=0,row=5,sticky=tk.W,pady=6)
		self.mesmerCheckButton = tk.Button(self.container, text='Close',command=self.close)
		self.mesmerCheckButton.grid(column=1,row=5,sticky=tk.E,pady=6)
		self.mesmerDoneButton = tk.Button(self.container, text='Save',default=tk.ACTIVE,command=self.checkPaths)
		self.mesmerDoneButton.grid(column=2,row=5,sticky=tk.W,pady=6)


from __future__ import annotations

from pathlib import Path
import typing as t

import yaml

from dcdb.types import *

if t.TYPE_CHECKING:
    from .types import Card, Character
    from .engine import Engine, PathLike

class YMLua(t.NamedTuple):

    front_matter: t.Dict[str, t.Any]
    script: str

    @classmethod
    def parse(cls, path: PathLike) -> YMLua:
        with open(path) as f:
            docs = f.read().split('---\n')
        front_matter = docs[1]
        # Add blank lines so script errors report the correct line number
        front_matter_length = len(front_matter.split('\n')) + 1
        script = '\n' * front_matter_length + docs[2]
        front_matter = yaml.safe_load(front_matter)
        return cls(front_matter, script)

class EntityLoader:

    extension: str = '.ymlua'

    engine: Engine
    script_dir: Path

    def __init__(self, engine: Engine, script_dir: PathLike) -> None:
        self.engine = engine
        self.script_dir = Path(script_dir)

    def script_path(self, id: str) -> PathLike:
        return self.script_dir.joinpath(*id.split('.')).with_suffix(self.extension)

    def build_card(self, id: str) -> Card:
        self.engine.logger.debug('Building card %s', id)
        path = self.script_path(id)
        front_matter, script = YMLua.parse(path)
        name = front_matter['name']
        type_name = front_matter['type'].upper()
        try:
            type = CardType[type_name]
        except KeyError as e:
            raise ValueError(f'Invalid card type: {type_name}') from e
        color_name = front_matter['color'].upper()
        try:
            color = Color[color_name]
        except KeyError as e:
            raise ValueError(f'Invalid color: {color_name}') from e
        cost = int(front_matter['cost'])
        vp = int(front_matter['vp'])
        card = Card(self.engine, id, name, type, color, cost, vp)
        initialize = self.engine.interpreter.initializer(script, str(path))
        initialize(card)
        self.engine.logger.debug('Finished building card %s', id)
        return card

    def build_character(self, id: str) -> Character:
        self.engine.logger.debug('Building character %s', id)
        path = self.script_path(id)
        front_matter, script = YMLua.parse(path)
        name = front_matter['name']
        type_name = front_matter['type'].upper()
        try:
            type = CharacterType[type_name]
        except KeyError as e:
            raise ValueError(f'Invalid character type: {type_name}') from e
        character = Character(self.engine, id, name, type)
        initialize = self.engine.interpreter.initializer(script, str(path))
        initialize(character)
        self.engine.logger.debug('Finished building character %s', id)
        return character

class SetLoader:

    set: t.Mapping
    engine: Engine
    entity_loader: EntityLoader

    def __init__(self, engine: Engine, set_path: PathLike, script_dir: PathLike) -> None:
        with open(set_path) as f:
            self.set = yaml.safe_load(f)
        self.engine = engine
        self.entity_loader = EntityLoader(self.engine, script_dir)

    def build(self, key: str) -> t.List[Card]:
        cards = []
        for card_id, count in self.set[key].items():
            for _ in range(count):
                cards.append(self.entity_loader.build_card(card_id))
        return cards

    def build_starters(self) -> t.Iterable[Card]:
        return self.build('starters')

    def build_main_deck(self) -> t.Iterable[Card]:
        return self.build('main_deck')

    def build_kicks(self) -> t.Iterable[Card]:
        return self.build('kicks')

    def build_weaknesses(self) -> t.Iterable[Card]:
        return self.build('weaknesses')

    def build_sv_top(self) -> t.Iterable[Card]:
        cards = []
        try:
            for card_id, count in self.set['super_villains']['top'].items():
                for _ in range(count):
                    cards.append(self.entity_loader.build_card(card_id))
        except KeyError:
            pass
        return cards

    def build_sv_middle(self) -> t.Iterable[Card]:
        cards = []
        try:
            for card_id, count in self.set['super_villains']['middle'].items():
                for _ in range(count):
                    cards.append(self.entity_loader.build_card(card_id))
        except KeyError:
            pass
        return cards

    def build_character(self, id: str) -> Character:
        return self.entity_loader.build_character(id)


"""Index analyzer plugin for Hashlookup."""

import logging

from flask import current_app
import requests

from timesketch.lib.analyzers import interface
from timesketch.lib.analyzers import manager
from timesketch.lib import emojis

logger = logging.getLogger("timesketch.analyzers.hashlookup")

class HashlookupAnalyzer(interface.BaseAnalyzer):
    """Analyzer for Hashlookup."""

    NAME = "hashlookup_analyzer"
    DISPLAY_NAME = "Hashlookup"
    DESCRIPTION = "Mark events using Hashlookup"

    def __init__(self, index_name, sketch_id, timeline_id=None, **kwargs):
        """Initialize the Analyzer.

        Args:
            index_name: OpenSearch index name
            sketch_id: The ID of the sketch.
            timeline_id: The ID of the timeline.
        """
        super().__init__(index_name, sketch_id, timeline_id=timeline_id)
        self.hashlookup_url = kwargs.get("hashlookup_url")
        self.total_event_counter = 0
        self.request_set = set()
        self.result_dict = dict()

    @staticmethod
    def get_kwargs():
        """Get kwargs for the analyzer.

        Returns:
            Info to connect to Hashlookup.
        """

        hashlookup_url = current_app.config.get("HASHLOOKUP_URL")

        if not hashlookup_url:
            logger.error("Hashlookup conf not found")
            return []

        matcher_kwargs = [{"hashlookup_url": hashlookup_url}]
        return matcher_kwargs

    def get_hash_info(self, hash_value):
        """Search event on Hashlookup.

        Args:
            hash_value:  hash value that will be check
                         if it's a known one on hashlookup.

        Returns:
            JSON of Hashlookup's results.
        """
        results = requests.get(f"{self.hashlookup_url}sha256/{hash_value}")

        result_loc = results.json()
        if not "message" in result_loc and results.status_code != 200:
            logger.error("Error with Hashlookup url")
            return []
        # If message in result_loc then the hash is not find in Hashlookup
        if "message" in result_loc:
            return []

        return result_loc

    def mark_event(self, event, hash_value):
        """Annotate an event with data from Hashlookup.

        Tags with validate emoji, adds a comment to the event.

        Args:
            event:  The OpenSearch event object that contains this hash and needs
                    to be tagged or to add an attribute.
            hash_value:  A string of a sha256 hash value.
        """

        event.add_comment(f"{self.hashlookup_url}sha256/{hash_value}")

        event.add_tags(["Hashlookup"])
        event.add_emojis([emojis.get_emoji("VALIDATE")])
        event.commit()

    def query_hashlookup(self, query, return_fields):
        """Get event from timesketch, request Hashlookup and mark event.

        Args:
            query:  Search for all events that contains sha256 value.
            return_fields:  Fields return with a matching event.
        """

        events = self.event_stream(query_string=query, return_fields=return_fields)
        create_a_view = False
        for event in events:
            hash_value = None
            for key in return_fields:
                if key in event.source.keys():
                    hash_value = event.source.get(key)
                    break

            if len(hash_value) != 64:
                logger.warning(
                    "The extracted hash does not match the required "
                    "length (64) of a SHA256 hash. Skipping this "
                    "event! Hash: %s - Length: %d",
                    hash_value,
                    len(hash_value),
                )
                error_hash_counter += 1
                continue

            if not hash_value in self.request_set:
                result = self.get_hash_info(hash_value)
                if result:
                    self.total_event_counter += 1
                    create_a_view = True
                    self.mark_event(event, hash_value)
                    self.result_dict[hash_value] = True
                else:
                    self.result_dict[hash_value] = False
                self.request_set.add(hash_value)
            elif self.result_dict[hash_value]:
                self.total_event_counter += 1
                self.mark_event(event, hash_value)

        if create_a_view:
            self.sketch.add_view(
                view_name="Hashlookup",
                analyzer_name=self.NAME,
                query_string=('tag:"Hashlookup"'),
            )

    def run(self):
        """Entry point for the analyzer.

        Returns:
            String with summary of the analyzer result
        """
        if not self.hashlookup_url:
            return "No Hashlookup configuration settings found, aborting."

        # Note: Add fieldnames that contain sha256 values in your events.
        query = (
            "_exists_:hash_sha256 OR _exists_:sha256 OR _exists_:hash OR "
            "_exists_:sha256_hash"
        )

        # Note: Add fieldnames that contain sha256 values in your events.
        return_fields = ["hash_sha256", "hash", "sha256", "sha256_hash"]
        self.query_hashlookup(query, return_fields)

        return f"Hashlookup Matches: {self.total_event_counter}"

manager.AnalysisManager.register_analyzer(HashlookupAnalyzer)


import json
import logging
import unittest

from mock import Mock, patch

from jarr.bootstrap import conf
from jarr.controllers import ArticleController, FeedController
from jarr.crawler.crawlers.classic import ClassicCrawler
from jarr.crawler.main import clusterizer, process_feed
from jarr.crawler.requests_utils import (response_calculated_etag_match,
                                         response_etag_match)
from jarr.lib.enums import FeedType
from jarr.lib.const import UNIX_START
from jarr.lib.utils import digest
from jarr.models.feed import Feed
from tests.base import JarrFlaskCommon

logger = logging.getLogger('jarr')
BASE_COUNT = 36

def crawler():
    user_ids = set()
    for feed in FeedController().list_fetchable(limit=1):
        process_feed.apply(args=[feed.id])
        user_ids.add(feed.user_id)
    for user_id in user_ids:
        clusterizer.apply(args=[user_id])

class CrawlerTest(JarrFlaskCommon):
    feed_path = 'tests/fixtures/example.feed.atom'

    def setUp(self):
        super().setUp()
        with open(self.feed_path) as fd:
            self._content = fd.read()
        self._is_secure_served \
            = patch('jarr.lib.url_cleaners.is_secure_served')
        self._p_req = patch('jarr.crawler.crawlers.abstract.jarr_get')
        self._p_con = patch('jarr.crawler.crawlers.classic.FeedBuilderControl'
                            'ler.construct_from_xml_feed_content')
        self.is_secure_served = self._is_secure_served.start()
        self.jarr_req = self._p_req.start()
        self.jarr_con = self._p_con.start()

        self.is_secure_served.return_value = True
        self.resp_status_code = 200
        self.resp_headers = {}
        self.resp_raise = None

        def _api_req(url, **kwargs):
            if url.startswith('feed') and len(url) == 6:
                resp = Mock(status_code=self.resp_status_code,
                            headers=self.resp_headers, history=[],
                            content=self._content, text=self._content)
                resp.raise_for_status.return_value = self.resp_raise
                resp.json = lambda: json.loads(self._content)
                return resp

            url = url.split(conf.api_root)[1].strip('/')
            kwargs.pop('allow_redirects', None)
            kwargs.pop('params', None)
            kwargs.pop('json', None)
            if 'auth' in kwargs:
                kwargs['user'] = kwargs['auth'][0]
                del kwargs['auth']
            response = self._api('get', url, **kwargs)
            response.raise_for_status = Mock()
            return response

        self.jarr_con.return_value = {}
        self.jarr_req.side_effect = _api_req

    def tearDown(self):
        self._is_secure_served.stop()
        self._p_req.stop()
        self._p_con.stop()
        super().tearDown()

    @staticmethod
    def _reset_feeds_freshness(**kwargs):
        if 'expires' not in kwargs:
            kwargs['expires'] = UNIX_START
        if 'last_retrieved' not in kwargs:
            kwargs['last_retrieved'] = UNIX_START
        if 'etag' not in kwargs:
            kwargs['etag'] = ''
        if 'last_modified' not in kwargs:
            kwargs['last_modified'] = ''
        FeedController().update({}, kwargs)

    def test_http_crawler_add_articles(self):
        self.assertEqual(BASE_COUNT, ArticleController().read().count())

        crawler()
        articles = list(ArticleController().read())
        new_count = len(articles)
        self.assertNotEqual(BASE_COUNT, new_count)
        self.assertTrue(BASE_COUNT < new_count)

        for art in articles:
            self.assertFalse('srcset=' in art.content)
            self.assertFalse('src="/' in art.content)

        self.resp_status_code = 304
        crawler()
        self.assertEqual(new_count, ArticleController().read().count())

    def test_no_add_on_304(self):
        self.resp_status_code = 304
        self.assertEqual(BASE_COUNT, ArticleController().read().count())
        crawler()
        self.assertEqual(BASE_COUNT, ArticleController().read().count())

    def test_no_add_feed_skip(self):
        self.resp_status_code = 304
        self.assertEqual(BASE_COUNT, ArticleController().read().count())
        crawler()
        FeedController().update({}, {'filters': [{"type": "tag contains",
                                                  "action on": "match",
                                                  "pattern": "pattern5",
                                                  "action": "skipped"},
                                                 {"type": "simple match",
                                                  "action on": "match",
                                                  "pattern": "pattern5",
                                                  "action": "mark as read"},
                                                 {"type": "regex",
                                                  "action on": "match",
                                                  "pattern": "pattern5",
                                                  "action": "skipped"}]})

        crawler()
        self.assertEqual(BASE_COUNT, ArticleController().read().count())

    def test_matching_etag(self):
        self._reset_feeds_freshness(etag='fake etag')
        self.resp_headers = {'etag': 'fake etag'}
        self.assertEqual(BASE_COUNT, ArticleController().read().count())

        crawler()

        self.assertEqual(BASE_COUNT, ArticleController().read().count())
        self._reset_feeds_freshness(etag='jarr/"%s"' % digest(self._content))
        self.resp_headers = {'etag': 'jarr/"%s"' % digest(self._content)}

        crawler()
        self.assertEqual(BASE_COUNT, ArticleController().read().count())

        self._reset_feeds_freshness(etag='jarr/fake etag')
        self.resp_headers = {'etag': '########################'}

        crawler()
        self.assertNotEqual(BASE_COUNT, ArticleController().read().count())

class JsonCrawlerTest(CrawlerTest):
    feed_path = 'tests/fixtures/feed.json'

    def setUp(self):
        super().setUp()
        self.resp_headers = {'content-type': 'application/json'}
        FeedController().update({}, {'feed_type': 'json'})

class CrawlerMethodsTest(unittest.TestCase):

    def setUp(self):
        super().setUp()
        self.feed = Feed(user_id=1, id=1, title='title',
                         description='description', etag='', error_count=5,
                         feed_type=FeedType.classic, link='link')
        self.resp = Mock(text='text', headers={}, status_code=304, history=[])

    def test_etag_matching_w_constructed_etag(self):
        self.feed.etag = 'jarr/"%s"' % digest('text')
        self.assertFalse(response_etag_match(self.feed, self.resp))
        self.assertTrue(response_calculated_etag_match(self.feed, self.resp))

    def test_etag_no_matching_wo_etag(self):
        self.feed.etag = ''
        self.assertFalse(response_etag_match(self.feed, self.resp))
        self.assertFalse(response_calculated_etag_match(self.feed, self.resp))

    def test_etag_matching(self):
        self.resp.headers['etag'] = self.feed.etag = 'etag'
        self.assertTrue(response_etag_match(self.feed, self.resp))
        self.assertFalse(response_calculated_etag_match(self.feed, self.resp))

    @patch('jarr.crawler.main.FeedController.update')
    def test_set_feed_error_w_error(self, fctrl_update):
        original_error_count = self.feed.error_count
        ClassicCrawler(self.feed).set_feed_error(Exception('an error'))

        fctrl_update.assert_called_once()
        filters, data = fctrl_update.mock_calls[0][1]
        self.assertEqual(filters['id'], self.feed.id)
        self.assertEqual(original_error_count + 1, data['error_count'])
        self.assertEqual('an error', data['last_error'])

    @patch('jarr.crawler.main.FeedController.update')
    def test_set_feed_error_w_parsed(self, fctrl_update):
        original_error_count = self.feed.error_count
        ClassicCrawler(self.feed).set_feed_error(
                parsed_feed={'bozo_exception': 'an error'})

        fctrl_update.assert_called_once()
        filters, data = fctrl_update.mock_calls[0][1]
        self.assertEqual(filters['id'], self.feed.id)
        self.assertEqual(original_error_count + 1, data['error_count'])
        self.assertEqual('an error', data['last_error'])

    @patch('jarr.crawler.main.FeedController.update')
    def test_clean_feed(self, fctrl_update):
        ClassicCrawler(self.feed).clean_feed(self.resp)
        fctrl_update.assert_called_once()
        filters, data = fctrl_update.mock_calls[0][1]

        self.assertEqual(filters['id'], self.feed.id)
        self.assertTrue('link' not in data)
        self.assertTrue('title' not in data)
        self.assertTrue('description' not in data)
        self.assertTrue('site_link' not in data)
        self.assertTrue('icon_url' not in data)

    @patch('jarr.crawler.main.FeedController.update')
    def test_clean_feed_update_link(self, fctrl_update):
        self.resp.history.append(Mock(status_code=301))
        self.resp.url = 'new_link'
        ClassicCrawler(self.feed).clean_feed(self.resp)

        fctrl_update.assert_called_once()
        filters, data = fctrl_update.mock_calls[0][1]
        self.assertEqual(filters['id'], self.feed.id)
        self.assertEqual('new_link', data['link'])
        self.assertTrue('title' not in data)
        self.assertTrue('description' not in data)
        self.assertTrue('site_link' not in data)
        self.assertTrue('icon_url' not in data)


from setuptools import setup, find_packages

with open("requirements.txt") as f:
	install_requires = f.read().strip().split("\n")

# get version from __version__ variable in crm/__init__.py
from crm import __version__ as version

setup(
	name="crm",
	version=version,
	description="ParaLogic CRM",
	author="ParaLogic",
	author_email="info@paralogic.io",
	packages=find_packages(),
	zip_safe=False,
	include_package_data=True,
	install_requires=install_requires
)


class Solution:
    def findComplement(self, num: int) -> int:
        bin_rep = bin(num)
        complement = []

        for bit in bin_rep[2:]:
            if bit == '0':
                complement.append('1')
                continue

            complement.append('0')

        return int(''.join(complement), 2)


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
:mod:`accelerometer`
==================

Updated by lkasso <hello@mbientlab.com>
Created by hbldh <henrik.blidh@nedomkull.com>
Created on 2016-04-10

"""

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

import time

from pymetawear.discover import select_device
from pymetawear.client import MetaWearClient

address = select_device()
c = MetaWearClient(str(address), debug=True)
print("New client created: {0}".format(c))

print("Get possible accelerometer settings...")
settings = c.accelerometer.get_possible_settings()
print(settings)

time.sleep(1.0)

print("Write accelerometer settings...")
c.accelerometer.set_settings(data_rate=3.125, data_range=4.0)

time.sleep(1.0)

print("Check accelerometer settings...")
settings = c.accelerometer.get_current_settings()
print(settings)

print("Subscribing to accelerometer signal notifications...")
c.accelerometer.high_frequency_stream = False
c.accelerometer.notifications(lambda data: print(data))

time.sleep(10.0)

print("Unsubscribe to notification...")
c.accelerometer.notifications(None)

time.sleep(5.0)

c.disconnect()


# TASK:
#
# Please read: https://en.wikipedia.org/wiki/Tower_of_Hanoi

# disks stacked on one rod in order of decreasing size, the smallest at the top
Towers = [[5, 4, 3, 2, 1],
    [],
    []
]

Bashni = [
    [],
    [],
    [5, 4, 3, 2, 1]
]

def reshit():
    print("Welcome to Hanoi Towers", Bashni)
    hod_otkuda = int(input("Hoditj otkuda? ==>:"))
    hod_chto = int(input("Hoditj chem? ==>:"))
    hod_kuda = int(input("Hoditj kuda? ==>:"))

    # Если размер одной из башень(0[],1[],2[]) равен нулю(0), то нечем ходить
    if len(Bashni[hod_otkuda])==0:
        print("Nechem hoditj")
        return False
    # После первого хода выбора массива, мы выбираем елемент массива,
    # И этот выбор НЕ евляется минимальным индексом этого массива, то нельзя им ходить
    if hod_chto !=min(Bashni[hod_otkuda]):
        print("Ty ne mozhesh hoditj etim kruglishkom")
        return False
    # Если размер масива равен 0, то можно поместить первый элемент hod_otkuda[hod_chto] => hod_kuda[hod_chto]
    elif len(Bashni[hod_kuda])==0:
        Bashni[hod_kuda].append(hod_chto)
        Bashni[hod_otkuda].remove(hod_chto)
    elif hod_chto < min(Bashni[hod_kuda]):
        Bashni[hod_kuda].append(hod_chto)
        Bashni[hod_otkuda].remove(hod_chto)
    else:
        print("You cannot move there")
        return False
    if (Bashni[2] == [5,4,3,2,1]) or (Bashni[1] == [5,4,3,2,1]):
        print("You have won!")
        return True

while True:
    reshit()

# The objective of the puzzle is to move the entire stack to the last rod, obeying the following rules:
#
# 1. Only one disk may be moved at a time.
# 2. Each move consists of taking the upper disk from one of the stacks and placing it on top of another stack or on an empty rod.
# 3. No disk may be placed on top of a disk that is smaller than it.

# please implement function to solve to puzzle


"""
OpenQuake configuration file
"""

from __future__ import absolute_import, division, print_function, unicode_literals

import os
import pprint
import copy
import numpy as np
import json
from configobj import Section, ConfigObj
from validate import Validator

__all__ = ['OQ_Params']

class ConfigError(Exception):
	pass

class OQ_Params(ConfigObj):
	"""
	Class representing OQ configuration parameters

	:param ini_filespec:
		str, full path to .INI file
		(default: None)
	:param calculation_mode:
		str, calculation mode, e.g. "classical", "event_based"
		(default: "classical")
	:param description:
		str, description of model run
		(default: "")
	:param site_type:
		str, type of site specification, e.g. "grid", "sites"
		(default: "grid")
	"""
	def __init__(self, ini_filespec=None, calculation_mode="classical",
				description="", site_type="grid"):
		configspec = os.path.join(os.path.dirname(os.path.realpath( __file__ )),
								"configspec.gem")
		super(OQ_Params, self).__init__(ini_filespec, configspec=configspec,
									write_empty_values=True, list_values=False)
		if not ini_filespec:
			## Construct dictionary with sensible default values
			General_params = Section(self, 1, self, name="general")
			General_params["description"] = description
			General_params["calculation_mode"] = calculation_mode
			General_params.comments["calculation_mode"] = ["classical, "
															"event_based, ..."]
			General_params["random_seed"] = 42

			Geometry_params = Section(self, 1, self, name="geometry")
			if site_type == "grid":
				Geometry_params["region"] = []
				# TODO: check order: lon, lat or lat, lon?
				Geometry_params.comments["region"] = ["lon, lat of polygon "
							"vertices (in clock or counter-clock wise order)"]
				Geometry_params["region_grid_spacing"] = 10
				Geometry_params.comments["region_grid_spacing"] = ["km"]
			elif site_type in ("site", "sites"):
				# TODO: check if this still exists
				Geometry_params["sites"] = []

			LogicTree_params = Section(self, 1, self, name="logic_tree")
			LogicTree_params["number_of_logic_tree_samples"] = 1
			LogicTree_params.comments["number_of_logic_tree_samples"] = [
										"Monte Carlo sampling of logic tree"]

			Erf_params = Section(self, 1, self, name="erf")
			Erf_params["rupture_mesh_spacing"] = 5
			Erf_params.comments["rupture_mesh_spacing"] = ["km"]
			Erf_params["area_source_discretization"] = 5
			Erf_params.comments["area_source_discretization"] = ["km"]
			Erf_params["width_of_mfd_bin"] = 0.2
			Erf_params.comments["width_of_mfd_bin"] = ["bin width of the "
										"magnitude frequency distribution"]

			Site_params = Section(self, 1, self, name="site_params")
			Site_params["reference_vs30_type"] = "inferred"
			Site_params.comments["reference_vs30_type"] = ["measured or inferred"]
			# TODO: what other options are there?
			Site_params["reference_vs30_value"] = 760.
			Site_params.comments["reference_vs30_value"] = ["(m/s)"]
			Site_params["reference_depth_to_2pt5km_per_sec"] = 2
			Site_params.comments["reference_depth_to_2pt5km_per_sec"] = [
						"The depth to where shear-wave velocity = 2.5 km/sec.",
						"Cambpell basin depth. Measure is (km)"]
			Site_params["reference_depth_to_1pt0km_per_sec"] = 100.
			# TODO: in m?
			## Note: don't set reference_kappa by default, as it is not standard
			#Site_params["reference_kappa"] = 0.01
			#Site_params.comments["reference_kappa"] = ["kappa value, in seconds"]

			Calculation_params = Section(self, 1, self, name="calculation")
			Calculation_params["source_model_logic_tree_file"] = \
												"source_model_logic_tree.xml"
			Calculation_params.comments["source_model_logic_tree_file"] = [
								"file containing erf logic tree structure"]
			Calculation_params["gsim_logic_tree_file"] = "gmpe_logic_tree.xml"
			Calculation_params.comments["gsim_logic_tree_file"] = [
								"file containing gmpe logic tree structure"]
			Calculation_params["investigation_time"] = 50
			Calculation_params.comments["investigation_time"] = ["years"]
			Calculation_params["intensity_measure_types_and_levels"] = '{"PGA": []}'
			# TODO: in event-based example, it's only intensity_measure_types!
			Calculation_params["truncation_level"] = 3
			Calculation_params.comments["truncation_level"] = ["(1,2,3,...)"]
			Calculation_params["maximum_distance"] = 200
			Calculation_params.comments["maximum_distance"] = [
										"maximum integration distance (km)"]

			Output_params = Section(self, 1, self, name="output")
			# TODO: is export_dir the same as output_dir in previous versions of OQ?
			Output_params["export_dir"] = "computed_output/%s" % calculation_mode
			Output_params.comments["export_dir"] = ["output directory - "
													"relative to this file"]

			ClassicalOutput_params = ConfigObj()
			ClassicalOutput_params["mean_hazard_curves"] = True
			ClassicalOutput_params.comments["mean_hazard_curves"] = [
												"Compute mean hazard curve"]
			#ClassicalOutput_params["quantile_hazard_curves"] = [0.05, 0.16, 0.50, 0.84, 0.95]
			ClassicalOutput_params["quantile_hazard_curves"] = \
												"0.05, 0.16, 0.50, 0.84, 0.95"
			ClassicalOutput_params.comments["quantile_hazard_curves"] = [
											"List of quantiles to compute"]
			ClassicalOutput_params["hazard_maps"] = True
			ClassicalOutput_params["uniform_hazard_spectra"] = True
			ClassicalOutput_params["poes"] = "0.1"
			# TODO: 0.1 = 10 percent?
			ClassicalOutput_params.comments["poes"] = ["List of POEs to use "
												"for computing hazard maps"]

			Disagg_params = Section(self, 1, self, name="disaggregation")
			Disagg_params["poes_disagg"] = "0.1"
			Disagg_params["mag_bin_width"] = 0.5
			Disagg_params["distance_bin_width"] = 7.5
			Disagg_params["coordinate_bin_width"] = 0.2
			Disagg_params["num_epsilon_bins"] = 6

			# TODO: the following output params are probably for event-based only
			EventBasedOutput_params = ConfigObj()
			EventBasedOutput_params["complete_logic_tree_ses"] = True
			EventBasedOutput_params["complete_logic_tree_gmf"] = True
			EventBasedOutput_params["ground_motion_fields"] = True

			EventBased_params = Section(self, 1, self, name="event_based_params")
			EventBased_params["ses_per_logic_tree_path"] = 5
			EventBased_params["ground_motion_correlation_model"] = "JB2009"
			EventBased_params["ground_motion_correlation_params"] = \
												'{"vs30_clustering": True}'

			self["general"] = General_params
			self["geometry"] = Geometry_params
			self.comments["geometry"] = [""]
			self["logic_tree"] = LogicTree_params
			self.comments["logic_tree"] = [""]
			self["erf"] = Erf_params
			self.comments["erf"] = [""]
			self["site_params"] = Site_params
			self.comments["site_params"] = [""]
			self["calculation"] = Calculation_params
			self.comments["calculation"] = [""]
			if self.calculation_mode == "classical":
				Output_params.merge(ClassicalOutput_params)
				for key in ClassicalOutput_params.keys():
					Output_params.comments[key] = ClassicalOutput_params.comments[key]
			if self.calculation_mode == "disaggregation":
				self["disaggregation"] = Disagg_params
				self.comments["disaggregation"] = [""]
			if calculation_mode == "event_based":
				self["event_based_params"] = EventBased_params
				self.comments["event_based_params"] = [""]
				Output_params.merge(EventBasedOutput_params)
				for key in EventBasedOutput_params.keys():
					Output_params.comments[key] = EventBasedOutput_params.comments[key]
			self["output"] = Output_params
			self.comments["output"] = [""]

		self.validator = Validator()
		self.__initialized = True

	def __getattr__(self, name):
		key = name.lower()
		for section_name in self.sections:
			if key in self[section_name].keys():
				return self[section_name][key]
		raise AttributeError(name)

	def __setattr__(self, name, value):
		if not '_OQ_Params__initialized' in self.__dict__:
			## This test allows attributes to be set in the __init__ method
			return super(OQ_Params, self).__setattr__(name, value)
		elif name in self.__dict__:
			## Any normal attributes are handled normally
			super(OQ_Params, self).__setattr__(name, value)
		else:
			## Allow dictionary elements to be set as if they were attributes
			key = name.lower()
			if key == "calculation_mode":
				raise ConfigError("Calculation mode cannot be changed "
								"after initialization")
			## POES and QUANTILE_LEVELS don't follow the rules...
			elif key == "poes":
				self["output"]["poes"] = " ".join(map(str, value))
			elif key == "poes_disagg":
				self["disaggregation"]["poes_disagg"] = " ".join(map(str, value))
			elif (key == "quantile_hazard_curves"
				and self["general"]["calculation_mode"] == "classical"):
				self["output"]["quantile_hazard_curves"] = ", ".join(map(str, value))
			elif (key == "percentiles"
				and self["general"]["calculation_mode"] == "classical"):
				self["output"]["quantile_hazard_curves"] = ", ".join(map(str,
													[val/100. for val in value]))
			elif key == "intensity_measure_types_and_levels":
				self.set_imts(value)
			# TODO: we will need to do something similar for ground_motion_correlation_params
			else:
				for section_name in self.sections:
					if key in self[section_name].keys():
						self[section_name][key] = self.validator.check(
									self.configspec[section_name][key], value)
						break
				else:
					raise AttributeError(name)

	def validate(self):
		"""
		Validate parameters according to configspec
		"""
		for section_name in self.sections:
			for key, value in self[section_name].items():
				## Workaround to prevent validation failure when there is only 1 site
				if section_name == "geometry" and key == "sites":
					if not isinstance(value, list):
						value = [value]
				self.validator.check(self.configspec[section_name][key], value)
		## The following doesn't work:
		#return super(OQ_Params, self).validate(self.validator, preserve_errors=True)

	def compare(self, other_params):
		"""
		Compare with another OQ_Params object

		:param other_params:
			instance of :class:`OQ_Params`
		"""
		for section_name in self.sections:
			for key in self[section_name]:
				if key in other_params[section_name]:
					value1 = self[section_name][key]
					value2 = other_params[section_name][key]
					if (self.validator.check(self.configspec[section_name][key], value1)
						!= other_params.validator.check(self.configspec[section_name][key], value2)):
						print("%s: values differ" % key)
						print("  this: %s" % value1)
						print("  other: %s" % value2)
				else:
					print("%s: missing in other" % key)
			for key in other_params[section_name]:
				if not key in self[section_name]:
					print("%s: defined in other" % key)

#	def set_imts(self, imts):
#		"""
#		Set intensity measure types and levels

#		:param imts:
#			Dictionary mapping intensity measure type objects (see
#			:mod:`oqhazlib.imt`) to lists of intensity measure levels.
#		"""
#		if isinstance(imts, dict):
#			#self["calculation"]["intensity_measure_types_and_levels"] = repr(imts)
#			## Copy to a new dictionary with seriazable keys
#			imts2 = {}
#			for key in imts.keys():
#				imts2[repr(key)] = imts[key]
#			self["calculation"]["intensity_measure_types_and_levels"] = json.dumps(imts2, default=list)
#		elif isinstance(imts, str):
#			self["calculation"]["intensity_measure_types_and_levels"] = imts
#		else:
#			raise TypeError("IMTS must be dict or string")

	def set_imts(self, imts):
		"""
		Set intensity measure types and levels

		:param imts:
			Dictionary mapping string for intensity measure type
			to lists of intensity measure levels.
		"""
		if isinstance(imts, dict):
			self["calculation"]["intensity_measure_types_and_levels"] = \
				json.dumps(imts, default=list)
		else:
			raise TypeError("IMTS must be dict or string")

	def set_grid_or_sites(self, sites=[], grid_outline=[], grid_spacing=10.):
		"""
		Set locations (grid or sites) where to compute hazard

		:param sites:
			list of (lon, lat) tuples or oqhazlib Site objects
			(default: [])
		:param grid_outline:
			list of points ((lon, lat) tuples) defining the outline of a
			regular grid. If grid_outline contains only 2 points, these
			are considered as the lower left and upper right corners.
			Alternatively, may also be [lonmin, lonmax, latmin, latmax]
			(default: [])
		:param grid_spacing:
			Float, grid spacing in km
			(default: 10)
		"""
		if sites and len(sites) > 0:
			self["geometry"]["sites"] = []
			for point in sites:
				if hasattr(point, "location"):
					lon, lat = point.location.longitude, point.location.latitude
				else:
					lon, lat = point[:2]
				self["geometry"]["sites"].append(" ".join(map(str, (lon, lat))))
			## Workaround to prevent trailing comma if there is only 1 site
			if len(self["geometry"]["sites"]) == 1:
				self["geometry"]["sites"] = self["geometry"]["sites"][0]
			## Remove grid parameters if necessary
			if "region" in self["geometry"]:
				del self["geometry"]["region"]
				del self["geometry"]["region_grid_spacing"]

		elif grid_outline and len(grid_outline) > 0:
			self["geometry"]["region"] = []
			if len(grid_outline) == 1:
				raise ConfigError("grid_outline must contain 2 points at least")
			elif len(grid_outline) == 2:
				ll, ur = grid_outline
				lr = (ur[0], ll[1])
				ul = (ll[0], ur[1])
				grid_outline = [ll, lr, ur, ul]
			elif len(grid_outline) == 4 and np.isscalar(grid_outline[0]):
				lonmin, lonmax, latmin, latmax = grid_outline
				ll = (lonmin, latmin)
				ul = (lonmin, latmax)
				ur = (lonmax, latmax)
				lr = (lonmax, latmin)
				grid_outline = [ll, lr, ur, ul]
			for lon, lat in grid_outline:
				self["geometry"]["region"].append(" ".join(map(str, (lon, lat))))
			self["geometry"]["region_grid_spacing"] = grid_spacing
			## Remove sites key if present
			if "sites" in self["geometry"]:
				del self["geometry"]["sites"]

	def set_soil_site_model_or_reference_params(self, soil_site_model_file=None,
					reference_vs30_value=760.0, reference_vs30_type="inferred",
					reference_depth_to_1pt0km_per_sec=100.,
					reference_depth_to_2pt5km_per_sec=2., reference_kappa=None):
		"""
		Set site parameters, either as site model or as reference parameters

		:param soil_site_model_file:
			String, full path specification of file containing site model.
			If specified, soil_site_model_file takes precedence over
			other parameters
			(default: None)
		:param reference_vs30_value:
			Float, reference vs30 value in m/s
			(default: 760.)
		:param reference_vs30_type:
			String, reference vs30 type ("measured" or "inferred")
			(default: "inferred")
		:param reference_depth_to_1pt0km_per_sec:
			Float, reference depth to vs=1.0 km/s, specified in m
			(default: 100.)
		:param reference_depth_to_2pt5km_per_sec:
			Float, reference depth to vs=2.5 km/s, specified in km
			(default: 2.)
		:param reference_kappa:
			Float, reference kappa value, specified in s
			(default: None)
		"""
		if soil_site_model_file:
			self["site_params"]["site_model_file"] = soil_site_model_file
			## Remove reference_params keys if present
			if "reference_vs30_value" in self["site_params"]:
				del self["site_params"]["reference_vs30_value"]
				del self["site_params"]["reference_vs30_type"]
				del self["site_params"]["reference_depth_to_1pt0km_per_sec"]
				del self["site_params"]["reference_depth_to_2pt5km_per_sec"]
			if "reference_kappa" in self["site_params"]:
				del self["site_params"]["reference_kappa"]
		else:
			self["site_params"]["reference_vs30_value"] = reference_vs30_value
			self["site_params"]["reference_vs30_type"] = reference_vs30_type
			self["site_params"]["reference_depth_to_1pt0km_per_sec"] = reference_depth_to_1pt0km_per_sec
			self["site_params"]["reference_depth_to_2pt5km_per_sec"] = reference_depth_to_2pt5km_per_sec
			if reference_kappa:
				self["site_params"]["reference_kappa"] = reference_kappa
			## Remove soil_site_model_file key if present
			if "site_model_file" in self["site_params"]:
				del self["site_params"]["site_model_file"]

	# TODO: the following methods will need to be checked when we know how deaggregation parameters are specified in job.ini

	def set_epsilon_bin_limits(self, bin_width=0.5):
		"""
		Set epsilon bin limits from bin width:

		:param bin_width:
			float, bin width for epsilon values
			(default: 0.5)
		"""
		if self.calculation_mode == "Disaggregation":
			num_bins, remainder = divmod(self.truncation_level, bin_width)
			self.epsilon_bin_limits = np.linspace(0, self.truncation_level + remainder,
												num_bins+1)

	def set_distance_bin_limits(self, bin_width=15):
		"""
		Set distance bin limits from bin width:

		:param bin_width:
			float, bin width for distance values (in km)
			(default: 15)
		"""
		if self.calculation_mode == "Disaggregation":
			num_bins, remainder = divmod(self.maximum_distance, bin_width)
			self.distance_bin_limits = np.linspace(0, self.maximum_distance + remainder,
													num_bins+1)

	def set_magnitude_bin_limits(self, Mmax, bin_width=None):
		"""
		Set magnitude bin limits from Mmax and bin width

		:param Mmax:
			float, maximum magnitude
		:param bin_width:
			float, bin width for magnitude values
			(default: None, will use :prop:`width_of_mfd_bin`
		"""
		if self.calculation_mode == "Disaggregation":
			if not bin_width:
				bin_width = self.width_of_mfd_bin
			Mrange = Mmax - self.minimum_magnitude
			num_bins, remainder = divmod(Mrange, bin_width)
			self.magnitude_bin_limits = np.linspace(self.minimum_magnitude,
													Mmax + remainder, num_bins+1)

	def set_latitude_bin_limits(self, lat_min, lat_max, bin_width=0.1):
		"""
		Set latitude bin limits from latitude bounds and bin_width

		:param lat_min:
			float, minimum latitude (in degrees)
		:param lat_max:
			float, maximum latitude (in degrees)
		:param bin_width:
			float, bin width from latitude values (in degrees)
			(default: 0.1)
		"""
		if self.calculation_mode == "Disaggregation":
			lat_range = lat_max - lat_min
			num_bins, remainder = divmod(lat_range, bin_width)
			self.latitude_bin_limits = np.linspace(lat_min, lat_max + remainder,
													num_bins+1)

	def set_longitude_bin_limits(self, lon_min, lon_max, bin_width=0.1):
		"""
		Set longitude bin limits from longitude bounds and bin_width

		:param lon_min:
			float, minimum longitude (in degrees)
		:param lon_max:
			float, maximum longitude (in degrees)
		:param bin_width:
			float, bin width from longitude values (in degrees)
			(default: 0.1)
		"""
		if self.calculation_mode == "Disaggregation":
			lon_range = lon_max - lon_min
			num_bins, remainder = divmod(lon_range, bin_width)
			self.longitude_bin_limits = np.linspace(lon_min, lon_max + remainder,
													num_bins+1)

	def clear(self):
		"""
		Clear all configuration parameters
		"""
		configspec = self.configspec
		filename = self.filename
		super(OQ_Params, self).clear()
		self.filename = filename
		self.configspec = configspec

	def pretty_print(self):
		"""
		Print configuration parameters as a dictionary
		"""
		pp = pprint.PrettyPrinter()
		for section_name in self.sections:
			section = self[section_name]
			print("[%s]" % section.name)
			pp.pprint(section.dict())

	def print_screen(self):
		"""
		Print contents of INI file to screen
		"""
		filename = self.filename
		self.filename = None
		for line in self.write():
			print(line)
		self.filename = filename

	def write_config(self, ini_filespec):
		"""
		Write INI file

		:param ini_filespec:
			full path specification to output INI file
		"""
		of = open(ini_filespec, "w")
		self.write(of)
		of.close()

if __name__ == "__main__":
	import openquake.hazardlib as oqhazlib
	ini_filespec = r"C:\Temp\job.ini"
	calculation_mode = "classical"
	site_type = "sites"
	params = OQ_Params(calculation_mode=calculation_mode, site_type=site_type)

	## Get and set some parameters
	params.random_seed = 30
	print(params.random_seed)
	params.percentiles = [16, 50, 84]
	params.intensity_measure_types_and_levels = {"PGA": np.arange(0.1, 1.1, 0.1)}
	params.set_grid_or_sites(grid_outline=[(4.0, 50.0), [5.0, 51.0]], grid_spacing=10.)
#	params.validate()

	print(params.intensity_measure_types_and_levels)

	## Print or write to file
	params.print_screen()
	#params.write_config(ini_filespec)

	#params2 = OQ_Params(ini_filespec)
	#params.compare(params2)


def get_django_application():
    if "django_application" not in globals():
        #django 处理wsgi的函数
        import django
        if django.get_version().startswith('1.3'):
            import django.core.handlers.wsgi
            django_application = django.core.handlers.wsgi.WSGIHandler()
        else:
            # 在模块级别保存wsgi application
            from django.core.wsgi import get_wsgi_application
            django_application = get_wsgi_application()
        globals()['django_application'] = django_application
    else:
        django_application = globals()['django_application']
    return django_application

class PatchDjango(object):
    def __init__(self, server, engine):
        self._server = server
        self._engine = engine
        self._init = False

    def __monkey_patch_django(self):
        from django.core import urlresolvers
        from .server import appengine_scheduler
        import functools

        def get_engine_callback(callback):
            #resolve会递归查找，没必要返回多次。
            if '__is_engine_callback' in callback.__dict__:
                return callback

            @functools.wraps(callback)
            def __engine_callback(*args, **kwargs):
                return appengine_scheduler(self._engine, callback, args, kwargs)

            setattr(__engine_callback, '__is_engine_callback', True)
            return __engine_callback

        # 覆盖RegexURLResolver，使得执行handler的时候使用engine的调度器
        class PatchRegexURLResolver(urlresolvers.RegexURLResolver):
            def resolve(self, path):
                resolver_match = super(PatchRegexURLResolver, self).resolve(path)
                callback = resolver_match.func

                # 重新设置callback函数
                resolver_match.func = get_engine_callback(callback)
                return resolver_match

        urlresolvers.RegexURLResolver = PatchRegexURLResolver

        # patch staitc file handler
        from django.contrib.staticfiles import views
        serve = views.serve

        views.serve = get_engine_callback(serve)

    def patch_django_Server(self):
        from .config import settings
        from .. import helper
        from .util import str_startswith_str_list

        def match_failure(environ, start_response):
            PATH_INFO = environ.get("PATH_INFO")
            if settings.DJANGO_URLS and not str_startswith_str_list(PATH_INFO, settings.DJANGO_URLS):
                return helper.not_found(start_response)
            else:
                try:
                    if not self._init:
                        # 动态载入django设置
                        # 使django的callback 和 static file handler支持appengine调度器
                        self.__monkey_patch_django()
                        self._init = True
                    django_application = get_django_application()

                    ret = django_application(environ=environ, start_response=start_response)
                except ImportError:
                    # 载入django 框架出错
                    ret = None
                # 处理结果
                if ret is None:
                    return helper.server_error(start_response)
                return ret

        self._server.match_failure = match_failure

def patch_django(server, engine):
    # 当访问到django的时候才载入django引擎，节省资源
    PatchDjango(server, engine).patch_django_Server()

#=======================================================================================================================


# coding=utf-8
import os
from collections import OrderedDict
from qgis.PyQt.QtCore import QSettings
from qgis.PyQt.QtSql import QSqlQuery
from qgis.core import QgsMessageLog, Qgis

from veriso.base.utils.utils import tr, dynamic_import
from veriso.base.utils.exceptions import VerisoError
from veriso.base.utils.utils import (get_modules_dir, yaml_load_file,
                                     get_subdirs, get_default_db)

def get_layers_from_topic(topic, module_name):
    """Converts the layer information into a dictionary from
    a topic list.

    Adds the geometry column name if there are more than
    one geometry column in a layer.

    Returns: Dictionary with all the necessary data.
    """
    dd = {}
    for table in topic["tables"]:
        dd[table] = dd.get(table, 0) + 1

    i = 0
    layers = []
    for table in topic["tables"]:
        my_layer = {
            "type": "postgres", "featuretype": table,
            "key": topic["primary_keys"][i],
            "geom": topic["geometry_columns"][i],
            "group": tr(topic["topic"], context=module_name),
            "title": tr(topic["class_names"][i], context=module_name)}
        i += 1
        # If there is more than one geometry column in the table
        # the name of the geometry columns is written in brackets
        # following the name of the table.
        if dd[table] > 1:
            my_layer["title"] = my_layer["title"] + " (" + tr(
                my_layer["geom"], context=module_name) + ")"

        layers.append(my_layer)

    return layers

def get_topics_tables(module_name):
    """Requests the topics and tables from the topic_tables database table.
    This table was created in the postprocessing step.

    Returns:
      False: If something went wrong when trying to get the list from the
      database. Otherwise a python dictionary.
    """
    try:
        db = get_default_db()

        # I think libpg cannot deal with arrays from postgresql. So we
        # return a comma sperated string.
        # Everything is ordered alphanumerical. Not sure if we would know
        #  enough to sort by interlis model ordering?!
        db_schema = QSettings("CatAIS", "VeriSO").value("project/dbschema")

        sql = ("SELECT topic,"
               "array_to_string(array_agg(sql_name ORDER BY sql_name),',') "
               "as tables, "
               "array_to_string(array_agg(coalesce(f_geometry_column,'') "
               "ORDER BY sql_name),',') as geometry_columns, "
               "array_to_string(array_agg(class_name ORDER BY sql_name), "
               "',') as class_names, "
               "array_to_string(array_agg(primary_key ORDER BY sql_name),"
               "',') as primary_keys "
               "FROM " + db_schema + ".t_topics_tables GROUP BY topic "
                                     "ORDER BY topic;")

        query = db.exec_(sql)

        if not query.isActive():
            message = "Error while reading from database."
            QgsMessageLog.logMessage(tr(message), module_name,
                                     Qgis.Critical)
            QgsMessageLog.logMessage(
                str(QSqlQuery.lastError(query).text()),
                module_name,
                Qgis.Critical)
            return

        topics = []
        record = query.record()
        while query.next():
            topic = {"topic": str(query.value(record.indexOf("topic")))}

            tables = []
            for table in str(query.value(record.indexOf("tables"))).split(
                    ","):
                tables.append(table)
            topic["tables"] = tables

            geometry_columns = []
            for geometry_column in str(
                    query.value(record.indexOf("geometry_columns"))).split(
                    ","):
                geometry_columns.append(geometry_column)
            topic["geometry_columns"] = geometry_columns

            class_names = []
            for class_name in str(
                    query.value(record.indexOf("class_names"))).split(","):
                class_names.append(class_name)
            topic["class_names"] = class_names

            primary_keys = []
            for primary_key in str(
                    query.value(record.indexOf("primary_keys"))).split(","):
                primary_keys.append(primary_key)
            topic["primary_keys"] = primary_keys

            topics.append(topic)

        db.close()
        del db

        return topics

    except Exception as e:
        message = "Something went wrong catching the topics tables list " \
                  "from the database."
        QgsMessageLog.logMessage(tr(message), module_name,
                                 Qgis.Critical)
        QgsMessageLog.logMessage(str(e), module_name,
                                 Qgis.Critical)
        return

def get_baselayers(module_name):
    """Reads all baselayer definitions from a yaml file.

    Returns
      A list of dictionaries with all baselayer definitions. Otherwise
      False.
    """
    filename = os.path.join(
        get_modules_dir(),
        module_name,
        "baselayer",
        "baselayer.yml")
    try:
        baselayers = yaml_load_file(filename)
        return baselayers
    except Exception as e:
        QgsMessageLog.logMessage(str(e), module_name,
                                 Qgis.Critical)
        return

def get_check_topics(module_name):
    """Get all check topics (aka groups).

    Different languages are support. See the yaml file how to deal with it.

    Returns:
      A ordered dictionary with the topic name and corresponding check
      files (python). False if something went wrong.
    """

    topics_dir = os.path.join(
        get_modules_dir(), module_name, 'checks')

    checks = []
    for topic_dir in get_subdirs(topics_dir):
        topic_file = os.path.join(topics_dir, topic_dir, 'topic.yml')
        if os.path.isfile(topic_file):
            try:
                topic = yaml_load_file(topic_file)
                topic['topic_dir'] = topic_dir
                checks.append(topic)
            except VerisoError:
                raise
    try:
        locale = QSettings().value('locale/userLocale')[0:2]
    except TypeError:
        locale = 'de'
    try:
        topics = OrderedDict()
        checks = sorted(checks,
                        key=lambda k: k['topic'][locale])
        for check in checks:
            topic = check["topic"]
            topic_dir = check["topic_dir"]

            # Check, if yaml file is multilingual.
            try:
                if topic in topics:
                    continue
                topics[topic] = check
                # TODO control this whe using checks_from_files
                # yaml is *not* multilingual.
            except:
                # yaml is multilingual.
                # If the language set in QGIS is not available in the
                # yaml file, the first language will be chosen

                # dinamically get the checks based on the available files
                checks_from_files = get_checks_from_files(
                    module_name, topic_dir)
                try:
                    my_topic = topic[locale]
                    my_check = OrderedDict()
                    my_check["topic"] = my_topic
                    # my_check["checks"] = check["checks"]
                    my_check["checks"] = checks_from_files
                    my_check["topic_dir"] = topic_dir
                    topics[my_topic] = my_check
                    # language found

                except:
                    # language *not* found
                    my_check = OrderedDict()
                    my_check["topic"] = list(topic.values())[0]
                    # my_check["checks"] = check["checks"]
                    my_check["checks"] = checks_from_files
                    my_check["topic_dir"] = topic_dir
                    topics[my_check["topic"]] = my_check
        return topics
    except Exception as e:
        print(str(e))
        raise VerisoError(str(e), e, tag=module_name)

def get_checks_from_files(module_name, topic_dir, modules_dir=None):
    """

    :param module_name:
    :param topic_dir:
    :param modules_dir:
    :return:
    """

    if modules_dir is None:
        modules_dir = get_modules_dir()
    path = os.path.join(modules_dir, module_name, 'checks', topic_dir)
    package = 'veriso.modules.%s.checks.%s' % (module_name, topic_dir)
    checks = []

    files = os.listdir(path)
    # alpha-numeric sorting to assure the same order in the menus
    # see http://stackoverflow.com/a/2669523/1193450
    # files = sorted(files, key=lambda item: (
    #    int(item.partition(' ')[0]) if item[0].isdigit() else float('inf'),
    #    item))
    try:
        locale = QSettings().value('locale/userLocale')[0:2]
    except TypeError:
        locale = 'de'

    for f in files:
        check = {}
        if f.endswith(".py") and f != '__init__.py':
            filename = f[:-3]
            module = '%s.%s' % (package, filename)
            try:
                module = dynamic_import(module)
                check['id'] = filename
                check['file'] = filename
                check['name'] = module.ComplexCheck.get_name()
                if check['name'] is not None:
                    # name is defined in the class
                    check['shortcut'] = module.ComplexCheck.get_shortcut()
                else:
                    # let's see if there is a yaml file as our last resort
                    yaml_path = os.path.join(path, filename + '.yml')
                    check['name'], check['shortcut'] = get_info_from_yaml(
                        yaml_path)

                # if we made it to here, it's all good
                checks.append(check)
            except:
                continue
        elif f.endswith('_separator'):
            check['name'] = 'separator'
            # checks.append(check)
    checks = sorted(checks, key=lambda k: k["name"][locale])
    return checks

def get_info_from_yaml(path):
    try:
        data = yaml_load_file(path)
        name = data['name']
    except Exception as e:
        raise VerisoError('error parsing %s' % path, e)
    try:
        shortcut = data['shortcut']
    except KeyError:
        shortcut = ''

    return name, shortcut


from flask import Flask, request, redirect, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import cgi

app = Flask(__name__)
app.config['DEBUG'] = True      # displays runtime errors in the browser, too
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://build-a-blog:blogpassword@localhost:8889/build-a-blog'
app.config['SQLALCHEMY_ECHO'] = True

db = SQLAlchemy(app)

class BlogPost(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(120))
    post_txt = db.Column(db.String(1000))
    post_datetime = db.Column(db.TIMESTAMP,default=datetime.utcnow)
    def __init__(self, title, post_txt):
        self.title = title
        self.post_txt = post_txt

def isvalidpost(title,newpost):
    title_error = ''
    blog_error = ''
    if not title:
        title_error = 'Please fill in the title'
    if not newpost:
        blog_error = 'Please fill in the body'
    return (title_error, blog_error)

@app.route('/newpost', methods=['POST', 'GET'])
def newpost():
    error = request.args.get("error")
    if request.method == 'POST':
        title = request.form['title']
        newpost = request.form['newpost']
        title_error, blog_error = isvalidpost(title,newpost)
        if (title_error or blog_error):
            return render_template('newpost.html', page_title='Add a Blog Entry', title_error=title_error, blog_error=blog_error, title=title, newpost=newpost)
        new_blog_post = BlogPost(title, newpost)
        db.session.add(new_blog_post)
        db.session.commit()
        return redirect('/blog?id={}'.format(new_blog_post.id))
    return render_template('newpost.html', page_title='Add a Blog Entry', error=error)

@app.route("/blog")
def blog():
    id = request.args.get("id")
    if id:
        the_blogs = BlogPost.query.filter_by(id=id).first()
        if the_blogs:
            title=the_blogs.title
            return render_template('1blog.html', page_title=title, post=the_blogs)
        return redirect('/') # there was no db return with the requested id.
    the_blogs = BlogPost.query.order_by('post_datetime DESC').all()
    return render_template('blog.html', page_title='Build a Blog', posts=the_blogs)

@app.route("/")
def index():
    return redirect('/blog')

if __name__ == "__main__":
    app.run()


#ADD thư viện cần sử dụng
import numpy as np
import cv2
#Tìm đường viền
img = cv2.imread('D:\\Python_XLA\\phathiendoituong\\imgs.png')
imgGry = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)          #Chuyển ảnh xám thành ảnh grayscale
#img1 = img.copy()
hsv_frame = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)        #Chuyển ảnh xám thành ảnh grayscale
ret,thrash = cv2.threshold(imgGry, 240, 255, cv2.CHAIN_APPROX_NONE)     #Nhị phân hóa bức ảnh bằng cách đặt ngưỡng, với giá trị của ngưỡng là 240
contours, hierachy = cv2.findContours(thrash, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)     #Tìm contour
#Bắt đầu vòng lặp tìm contour từng hình
for contour in contours:
    M = cv2.moments(contour)        # Tính toán trung tâm của đường viền
    cX = int(M['m10']/M['m00'])
    cY = int(M['m01']/M['m00'])

    approx = cv2.approxPolyDP(contour, 0.01 * cv2.arcLength(contour, True), True)       #Tính xấp xỉ đường viền để xác định hình
    cv2.drawContours(img, [approx], 0, (0, 0, 0), 5)  #Vẽ lại ảnh contour vào ảnh gốc
    x = approx.ravel()[0]
    y = approx.ravel()[1] - 5
    if len(approx) == 3:            #Hình tam giác có 3 đỉnh
        cv2.putText(img, "Tam Giac", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 4:      #Hình chữ nhật, hình vuông có 4 đỉnh
        x, y, w, h = cv2.boundingRect(approx)           #Tính toán giới hạn của đường bao và tỉ lệ khung hình để xác đinh hình vuông hay hình chữ nhật
        AspectRatio = float(w) / h      #Tính tỉ lệ khung hình
        if AspectRatio >= 0.95 and AspectRatio < 1.05:   #Hình vuông tỉ lệ khung hình gần bằng 1, ngược lại là hình chữ nhật
            cv2.putText(img, "Hinh Vuong", (x, y-10), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))     #Viết một chuỗi kỹ tự lên bức hình
        else:
            cv2.putText(img, "Hinh Chu Nhat", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 5:      #Hình ngũ giác có 5 đỉnh
        cv2.putText(img, "Ngu Giac", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 10:        #Hình ngôi sao 10 đỉnh
        cv2.putText(img, "Ngoi Sao", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))       #Viết một chuỗi kỹ tự lên bức hình
    elif len(approx) == 7:      #Hình mũi tên có 7 đỉnh
        cv2.putText(img, "Mui Ten", (x-90, y-60), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) == 11:   #Hình tia sét có 11 đỉnh
        cv2.putText(img, "Tia Set", (x, y-30), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    elif len(approx) > 11 and len(approx) < 13 :    #Hình tròn
        cv2.putText(img, "Hinh Tron", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))
    else:    #Hình trái tim
        cv2.putText(img, "Heart", (x, y), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0))

    pixel_center = hsv_frame[cY, cX]       #Tọa độ trung tâm
    hue_value = pixel_center[0]     #Giá trị tông màu HUE

    color = 'undefined'
    if hue_value <10:
        color = "DO"
    elif hue_value <22:
        color = "CAM"
    elif hue_value <33:
        color = "VANG"
    elif hue_value < 80:
        color = "LUC"
    elif hue_value <100:
        color = "XANH DA TROI"
    elif hue_value <150:
        color = "LAM"
    elif hue_value <170:
        color = "TIM"
    elif hue_value <171:
        color = "HONG"
    else:
        color = "DO"

    #pixel_center_bgr = img[cY, cX]
    #b, g, r = int(pixel_center_bgr[0]), int(pixel_center_bgr[1]), int(pixel_center_bgr[2])
    cv2.putText(img, color, (cX+10, cY+10), cv2.FONT_HERSHEY_COMPLEX, 0.5, (0, 0, 0), 1)        #Viết một chuỗi ký tự name color
    cv2.circle(img, (cX,cY),3,(255,255,255),-1)     #Vẽ đường viền
cv2.imshow('image',img)
cv2.waitKey(0)


import base64
import ctypes
import os

import mock
import pytest  # type: ignore
from requests.packages.urllib3.util.ssl_ import create_urllib3_context  # type: ignore
import urllib3.contrib.pyopenssl  # type: ignore

from google.auth import exceptions
from google.auth.transport import _custom_tls_signer

urllib3.contrib.pyopenssl.inject_into_urllib3()

FAKE_ENTERPRISE_CERT_FILE_PATH = "/path/to/enterprise/cert/file"
ENTERPRISE_CERT_FILE = os.path.join(
    os.path.dirname(__file__), "../data/enterprise_cert_valid.json"
)
INVALID_ENTERPRISE_CERT_FILE = os.path.join(
    os.path.dirname(__file__), "../data/enterprise_cert_invalid.json"
)

def test_load_offload_lib():
    with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()):
        lib = _custom_tls_signer.load_offload_lib("/path/to/offload/lib")

    assert lib.ConfigureSslContext.argtypes == [
        _custom_tls_signer.SIGN_CALLBACK_CTYPE,
        ctypes.c_char_p,
        ctypes.c_void_p,
    ]
    assert lib.ConfigureSslContext.restype == ctypes.c_int

def test_load_signer_lib():
    with mock.patch("ctypes.CDLL", return_value=mock.MagicMock()):
        lib = _custom_tls_signer.load_signer_lib("/path/to/signer/lib")

    assert lib.SignForPython.restype == ctypes.c_int
    assert lib.SignForPython.argtypes == [
        ctypes.c_char_p,
        ctypes.c_char_p,
        ctypes.c_int,
        ctypes.c_char_p,
        ctypes.c_int,
    ]

    assert lib.GetCertPemForPython.restype == ctypes.c_int
    assert lib.GetCertPemForPython.argtypes == [
        ctypes.c_char_p,
        ctypes.c_char_p,
        ctypes.c_int,
    ]

def test__compute_sha256_digest():
    to_be_signed = ctypes.create_string_buffer(b"foo")
    sig = _custom_tls_signer._compute_sha256_digest(to_be_signed, 4)

    assert (
        base64.b64encode(sig).decode() == "RG5gyEH8CAAh3lxgbt2PLPAHPO8p6i9+cn5dqHfUUYM="
    )

def test_get_sign_callback():
    # mock signer lib's SignForPython function
    mock_sig_len = 10
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.SignForPython.return_value = mock_sig_len

    # create a sign callback. The callback calls signer lib's SignForPython method
    sign_callback = _custom_tls_signer.get_sign_callback(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # mock the parameters used to call the sign callback
    to_be_signed = ctypes.POINTER(ctypes.c_ubyte)()
    to_be_signed_len = 4
    returned_sig_array = ctypes.c_ubyte()
    mock_sig_array = ctypes.byref(returned_sig_array)
    returned_sign_len = ctypes.c_ulong()
    mock_sig_len_array = ctypes.byref(returned_sign_len)

    # call the callback, make sure the signature len is returned via mock_sig_len_array[0]
    assert sign_callback(
        mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len
    )
    assert returned_sign_len.value == mock_sig_len

def test_get_sign_callback_failed_to_sign():
    # mock signer lib's SignForPython function. Set the sig len to be 0 to
    # indicate the signing failed.
    mock_sig_len = 0
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.SignForPython.return_value = mock_sig_len

    # create a sign callback. The callback calls signer lib's SignForPython method
    sign_callback = _custom_tls_signer.get_sign_callback(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # mock the parameters used to call the sign callback
    to_be_signed = ctypes.POINTER(ctypes.c_ubyte)()
    to_be_signed_len = 4
    returned_sig_array = ctypes.c_ubyte()
    mock_sig_array = ctypes.byref(returned_sig_array)
    returned_sign_len = ctypes.c_ulong()
    mock_sig_len_array = ctypes.byref(returned_sign_len)
    sign_callback(mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len)

    # sign callback should return 0
    assert not sign_callback(
        mock_sig_array, mock_sig_len_array, to_be_signed, to_be_signed_len
    )

def test_get_cert_no_cert():
    # mock signer lib's GetCertPemForPython function to return 0 to indicts
    # the cert doesn't exit (cert len = 0)
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.GetCertPemForPython.return_value = 0

    # call the get cert method
    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        _custom_tls_signer.get_cert(mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH)

    assert excinfo.match("failed to get certificate")

def test_get_cert():
    # mock signer lib's GetCertPemForPython function
    mock_cert_len = 10
    mock_signer_lib = mock.MagicMock()
    mock_signer_lib.GetCertPemForPython.return_value = mock_cert_len

    # call the get cert method
    mock_cert = _custom_tls_signer.get_cert(
        mock_signer_lib, FAKE_ENTERPRISE_CERT_FILE_PATH
    )

    # make sure the signer lib's GetCertPemForPython is called twice, and the
    # mock_cert has length mock_cert_len
    assert mock_signer_lib.GetCertPemForPython.call_count == 2
    assert len(mock_cert) == mock_cert_len

def test_custom_tls_signer():
    offload_lib = mock.MagicMock()
    signer_lib = mock.MagicMock()

    # Test load_libraries method
    with mock.patch(
        "google.auth.transport._custom_tls_signer.load_signer_lib"
    ) as load_signer_lib:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.load_offload_lib"
        ) as load_offload_lib:
            load_offload_lib.return_value = offload_lib
            load_signer_lib.return_value = signer_lib
            signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE)
            signer_object.load_libraries()
    assert signer_object._cert is None
    assert signer_object._enterprise_cert_file_path == ENTERPRISE_CERT_FILE
    assert signer_object._offload_lib == offload_lib
    assert signer_object._signer_lib == signer_lib
    load_signer_lib.assert_called_with("/path/to/signer/lib")
    load_offload_lib.assert_called_with("/path/to/offload/lib")

    # Test set_up_custom_key and set_up_ssl_context methods
    with mock.patch("google.auth.transport._custom_tls_signer.get_cert") as get_cert:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.get_sign_callback"
        ) as get_sign_callback:
            get_cert.return_value = b"mock_cert"
            signer_object.set_up_custom_key()
            signer_object.attach_to_ssl_context(create_urllib3_context())
    get_cert.assert_called_once()
    get_sign_callback.assert_called_once()
    offload_lib.ConfigureSslContext.assert_called_once()

def test_custom_tls_signer_failed_to_load_libraries():
    # Test load_libraries method
    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        signer_object = _custom_tls_signer.CustomTlsSigner(INVALID_ENTERPRISE_CERT_FILE)
        signer_object.load_libraries()
    assert excinfo.match("enterprise cert file is invalid")

def test_custom_tls_signer_fail_to_offload():
    offload_lib = mock.MagicMock()
    signer_lib = mock.MagicMock()

    with mock.patch(
        "google.auth.transport._custom_tls_signer.load_signer_lib"
    ) as load_signer_lib:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.load_offload_lib"
        ) as load_offload_lib:
            load_offload_lib.return_value = offload_lib
            load_signer_lib.return_value = signer_lib
            signer_object = _custom_tls_signer.CustomTlsSigner(ENTERPRISE_CERT_FILE)
            signer_object.load_libraries()

    # set the return value to be 0 which indicts offload fails
    offload_lib.ConfigureSslContext.return_value = 0

    with pytest.raises(exceptions.MutualTLSChannelError) as excinfo:
        with mock.patch(
            "google.auth.transport._custom_tls_signer.get_cert"
        ) as get_cert:
            with mock.patch(
                "google.auth.transport._custom_tls_signer.get_sign_callback"
            ):
                get_cert.return_value = b"mock_cert"
                signer_object.set_up_custom_key()
                signer_object.attach_to_ssl_context(create_urllib3_context())
    assert excinfo.match("failed to configure SSL context")


import sys
import os
from dotenv import load_dotenv
import importlib.util

class Config:

    def __init__(self):
        self._data = {}
        self.load_env()
        self.load_configs()

    @staticmethod
    def load_env():
        try:
            load_dotenv('.env')  # Cargamos el archivo env
        except Exception as e:
            print("Error: No fue posible cargar el archivo .env")
            print(e)
            sys.exit(1)

    def load_configs(self):
        path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), os.getenv("DIR_CONFIGURATIONS"))
        files = os.listdir(path)
        for file in files:
            # Ignorar archivos que no son configuraciones
            if not file.endswith(".py"):
                continue
            # Importar la configuracion
            module_name = file[:-3]  # Quitar la extensión .py
            module_path = os.path.join(path, file)
            spec = importlib.util.spec_from_file_location(module_name, module_path)
            module = importlib.util.module_from_spec(spec)
            spec.loader.exec_module(module)
            variables = module.__dict__
            for variable_name, variable_value in variables.items():
                if not variable_name.startswith("__") and not variable_name == "Tools":  # Ignorar variables especiales
                    self._data[variable_name] = variable_value

    def get(self,config,prop):
        try:
         return self._data[config][prop]
        except (Exception,):
            return None


import datetime
from flask import Flask, render_template, request, redirect, url_for
from flask_login import LoginManager, login_user, login_required, logout_user, current_user
from werkzeug.security import check_password_hash

# looks not good, better to have DataBase class with all those methods.
from database_handlers import get_assignment_from_base, get_task_from_base, get_tasks_from_base, \
    delete_task_from_base, add_task, stop_channel, stop_task, start_new_loop, \
    get_user_by_login
from config import SECRET_KEY, host, port
from utils2 import string_to_list
from user_login import UserLogin

app = Flask(__name__)
app.config['SECRET_KEY'] = SECRET_KEY
login_manager = LoginManager(app)
process = None
app.permanent_session_lifetime = datetime.timedelta(days=1)

@login_manager.unauthorized_handler
def unauthorized():
    return redirect('/login')

@login_manager.user_loader
def load_user(user_id):
    print('load_user')
    return UserLogin().from_db(user_id)

@app.route('/login', methods=["POST", "GET"])
def login():
    if request.method == "POST":
        user = get_user_by_login(request.form['username'])
        if user and check_password_hash(user.password, request.form['password']):
            user_login = UserLogin().create(user)
            login_user(user_login)
            return redirect(url_for('start_page'))
        else:
            return "Mistake"
    return render_template('login.html')

@app.route('/')
@login_required
def start_page():
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    tasks = get_assignment_from_base()
    return render_template('main.html', tasks=tasks)

@app.route('/task_list<int:channel>')
@login_required
def task_list(channel):
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    if channel:
        title = "task"
    else:
        title = "tasks"
    if channel:
        task = get_task_from_base(channel)
        h1 = f"{channel} channel task list:"
    else:
        task = get_tasks_from_base()
        h1 = f"Full task list:"

    time = datetime.datetime.now()
    context = {"title": title,
               "task": task,
               "h1": h1,
               "time": time}

    return render_template('task_list.html', context=context)

@app.route('/add_task', methods=['GET', 'POST'])
@login_required
def task_form():
    if request.method == "POST":
        try:
            channel = int(request.form['channel'])
            working_time = int(request.form['working-time'])
            pause_time = int(request.form['pause-time'])
            subchannels = str(request.form['subchannels'])
            assert isinstance(channel, int)
            assert isinstance(working_time, int)
            assert isinstance(pause_time, int)
            assert isinstance(subchannels, str)
            delete_task_from_base(channel)
            subchannels = string_to_list(subchannels)
            add_task(*subchannels, main_channel=channel, working_time=working_time, pause_time=pause_time)
            return redirect(url_for('task_list', channel=channel))
        except Exception as ER:
            return render_template('error.html', error_message=f"Ошибка {ER} попробуйте ещё", task_form=url_for('task_form'))
    else:
        return render_template('add_task.html')

@app.route('/kill_process<int:channel>')
@login_required
def kill_process(channel):
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    if channel:
        delete_task_from_base(channel)
        stop_channel(channel)
        return redirect(url_for('start_page'))
    else:
        return redirect(url_for('start_page'))

@app.route('/stop_process<int:channel>')
@login_required
def stop_process(channel):
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    if channel:
        stop_task(channel)
        stop_channel(channel)
        return redirect(url_for('start_page'))
    else:
        return redirect(url_for('start_page'))

@app.route('/start_process<int:channel>')
@login_required
def start_process(channel):
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    if channel:
        start_new_loop(channel)
    return redirect(url_for('start_page'))

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('login'))

if __name__ == "__main__":
    app.run(host=host, port=port,debug=True)


# -*- coding: utf-8 -*-
# April 2020
# Author: Dimbi

from zato.server.service import Service
from contextlib import closing
import datetime
import json

class DateTimeEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime) or isinstance(obj, datetime.date):
            encoded_object = obj.strftime("%Y%m%d%H%M%S%z")
        else:
            encoded_object = json.JSONEncoder.default(self, obj)
        return encoded_object

class SqlToRedisServiceFinal(Service):
    name = 'Sql.To.Redis.Service.Final'

    class SimpleIO:
        input_required = ('query', 'out_name', 'output_dict_name', 'output_dict_key')
        input_optional = ('operation_name', 'table_name')

    def handle(self):
        query = self.request.input.query
        outName = self.request.input.out_name
        tableName = self.request.input.table_name
        outputDictName = self.request.input.output_dict_name
        outputDictKey = self.request.input.output_dict_key
        operationName = self.request.input.operation_name

        log_msg_head = """{} -- Stockage des donnees de la table '{}' dans Redis \n""".format(operationName, tableName)
        log_warn_head = """{} -- Erreur lors du stockage des donnees de la table '{}' dans Redis\n""".format(operationName, tableName)
        log_msg = log_warn = ""
        try:
            # Etape 1
            etape = "Etape 1"
            operation = """Selection dans la table '{}'""".format(tableName)
            inputVariable = {"query": query,
                             "out_name": outName,
                             "operation": "select"}
            response = self.invoke("Request.Sql.Service.Final", inputVariable)
            result = response.get("response").get("result")
            log_msg += """{} -- {}: terminee \n""".format(etape, operation)
            # Etape 2
            etape = "Etape 2"
            operation = """Stockage dans Redis""".format(tableName)
            self.kvdb.conn.delete(outputDictName)
            for i in range(len(result)):
                row = json.dumps(result[i], cls=DateTimeEncoder)
                dictKey = result[i].get(outputDictKey)
                self.kvdb.conn.hset(outputDictName, dictKey, row)
            log_msg += """{} -- {}: termine \n""".format(etape, operation)
            self.logger.info(log_msg_head + log_msg)
        except Exception as es:
            log_warn += log_msg
            log_warn += """{} -- {} -- Erreur : {} \n""".format(etape, operation, es)
            log_warn += """ ================== Erreur \n"""
            self.logger.warn(log_warn_head + log_warn)