from __future__ import annotations

from datetime import datetime, timezone
from typing import Any, Mapping, Sequence, Union
from warnings import warn

from pkg_resources import resource_string
from typing_extensions import Literal
from yaml import safe_load

ALWAYS_DICTS = {'definitions', 'properties'}

def make_schemaless_object(data, always_dicts = set(), key = None):
    if isinstance(data, dict):
        processed_data = {k: make_schemaless_object(v, always_dicts, k) for k, v in data.items()}
        return SchemalessObject(processed_data) if key not in always_dicts else processed_data
    elif isinstance(data, list):
        return [make_schemaless_object(v, always_dicts) for v in data]
    else:
        return data

class SchemalessObject:
    def __init__(self, data):
        self._data = data

    def __getattr__(self, attr):
        try:
            return self._data[attr]
        except KeyError as e:
            raise AttributeError(attr) from e

    def __str__(self):
        return str(self._data)

    def __repr__(self):
        return repr(self._data)

class Undefined:
    def __repr__(self):
        return 'undefined'

class SchemaDocument:
    def __init__(self, schema: Schema):
        self.document = schema
        if isinstance(self.document.definitions, SchemalessObject):
            self.document.definitions = self.document.definitions._data

    def to_type(self, schema: Schema, override_type = None):
        assert not isinstance(schema, dict)
        undefined = Undefined()

        ref = getattr(schema, '$ref', undefined)
        if ref is not undefined:
            if ref == '#':
                # TODO Recursion
                return Any

            assert ref.startswith('#/definitions/')
            def_name = ref[len('#/definitions/'):]
            return self.to_type(self.document.definitions[def_name])

        if schema == True:
            return Any

        const = getattr(schema, 'const', undefined)
        if const is not undefined:
            if const is None:
                return type(None)
            else:
                return Literal[const]

        anyOf = getattr(schema, 'anyOf', undefined)
        if anyOf is not undefined:
            return Union[tuple(self.to_type(subschema) for subschema in anyOf)]

        schema_type = override_type or getattr(schema, 'type', undefined)

        if isinstance(schema_type, list):
            return Union[tuple(self.to_type(schema, override_type = single_type) for single_type in schema_type)]

        if schema_type == 'null':
            return type(None)
        if schema_type == 'boolean':
            return bool
        if schema_type == 'integer':
            return int
        if schema_type == 'number':
            return float
        if schema_type == 'string':
            format = getattr(schema, 'format', None)
            if format == 'date-time':
                return datetime
            return str

        if schema_type == 'object':
            properties = getattr(schema, 'properties', undefined)
            additionalProperties = getattr(schema, 'additionalProperties', undefined)

            if properties is not undefined and additionalProperties is not undefined:
                raise NotImplementedError('Handling both properties and additionalProperties on a single object is not implemented.')

            if properties is not undefined:
                if isinstance(properties, SchemalessObject):
                    properties = properties._data
                property_types = dict()
                default_values = dict()
                for prop_name, prop_schema in properties.items():
                    property_types[prop_name] = self.to_type(prop_schema)
                    default = getattr(prop_schema, 'default', undefined)
                    if default is not undefined:
                        default_values[prop_name] = default

                def __init__(self, **kwargs):
                    unknown_kwargs = set(kwargs.keys()) - set(type(self).__annotations__.keys())
                    if unknown_kwargs != set():
                        raise TypeError(f'{type(self).__name__} got unexpected properties: {", ".join(unknown_kwargs)}')

                    for prop_name, prop_type in type(self).__annotations__.items():
                        if prop_name in kwargs:
                            setattr(self, prop_name, kwargs[prop_name])

                def __str__(self):
                    return f'{type(self).__name__} {self.__dict__}'

                Patch = type((schema.title or '') + 'Patch', (), dict(
                    __annotations__ = property_types,
                    __resttest_plain__ = True,
                    __resttest_schema__ = schema,
                    __init__ = __init__,
                    __str__ = __str__,
                    __repr__ = __str__,
                ))

                Full = type(schema.title or '', (Patch,), dict(
                    Patch = Patch,
                    **default_values,
                ))

                def __init__(self, **kwargs):
                    missing_kwargs = set(type(self).__annotations__.keys()) - set(kwargs.keys()) - set(type(self).__dict__.keys())
                    if missing_kwargs != set():
                        raise TypeError(f'{type(self).__name__} missing required properties: {", ".join(missing_kwargs)}')

                    super(Full, self).__init__(**kwargs)

                Full.__init__ = __init__

                return Full

            if additionalProperties is not undefined:
                return Mapping[str, self.to_type(additionalProperties)]

            warn(f"Untyped object: {schema}", UserWarning, 2)
            return dict

        if schema_type == 'array':
            items = getattr(schema, 'items', undefined)

            if items is not undefined:
                if isinstance(items, list):
                    raise NotImplementedError('Handling pre-set list items is not implemented.')

                return Sequence[self.to_type(items)]

            warn(f"Untyped array: {schema}", UserWarning, 2)
            return list

        warn(f"Untyped value: {schema}", UserWarning, 2)
        return Any

def schema_to_type(top_level_schema: Schema, chosen_schema: Schema = None):
    return SchemaDocument(top_level_schema).to_type(chosen_schema or top_level_schema)

Schema = schema_to_type(make_schemaless_object(safe_load(resource_string(__name__, 'schema.yaml'))))

def unserialize(Object, data):
    if Object == Schema:
        # TODO delete after this becomes strong enough to interpret JSON Schema schema correctly
        return make_schemaless_object(data, ALWAYS_DICTS)

    if Object == type(None):
        if data is not None:
            raise ValueError(Object)
        return data

    if getattr(Object, '__origin__', None) == Literal:
        const = Object.__args__[0]
        if data != const:
            raise ValueError(Object)
        return data

    if Object == bool:
        if not isinstance(data, bool):
            raise ValueError(Object)
        return data

    if Object == int:
        if not isinstance(data, int):
            raise ValueError(Object)
        return data

    if Object == float:
        if not isinstance(data, float):
            raise ValueError(Object)
        return data

    if Object == str:
        if not isinstance(data, str):
            raise ValueError(Object)
        return data

    if Object == datetime:
        if not isinstance(data, str):
            raise ValueError(Object)
        if not data.endswith('Z'):
            raise NotImplementedError('Parsing dates with non-Z timezones is not supported.')
        return datetime.fromisoformat(data[:-1]).replace(tzinfo = timezone.utc)

    if getattr(Object, '__resttest_plain__', False):
        if not isinstance(data, dict):
            raise ValueError(Object)

        unknown_data = set(data.keys()) - set(Object.__annotations__.keys())
        if unknown_data != set():
            warn(f'{Object.__name__} has unknown properties: {", ".join(unknown_data)}', UserWarning, 2)

        missing_data = set(Object.__annotations__.keys()) - set(data.keys()) - set(Object.__dict__.keys())
        if missing_data != set():
            raise TypeError(f'{Object.__name__} is missing required properties: {", ".join(missing_data)}')

        kwargs = dict()
        for prop_name, prop_type in Object.__annotations__.items():
            if prop_name in data:
                kwargs[prop_name] = unserialize(prop_type, data[prop_name])

        return Object(**kwargs)

    if getattr(Object, '__origin__', None) == Union:
        results = []

        for arg in Object.__args__:
            try:
                results.append(unserialize(arg, data))
            except ValueError as e:
                pass

        if len(results) > 1:
            raise NotImplementedError('Matching multiple options from anyOf is not implemented.')

        if len(results) == 1:
            return results[0]

        raise ValueError(Object)

    if Object == dict:
        if not isinstance(data, dict):
            raise ValueError(Object)
        return data

    if issubclass(getattr(Object, '__origin__', type(None)), Sequence):
        if not isinstance(data, list):
            raise ValueError(Object)
        item_type = Object.__args__[0]
        return [unserialize(item_type, item) for item in data]

    if Object == list:
        if not isinstance(data, list):
            raise ValueError(Object)
        return data

    if Object == Any:
        return data

    raise ValueError(Object)

def serialize(obj):
    if obj is None or isinstance(obj, bool) or isinstance(obj, int) or isinstance(obj, float) or isinstance(obj, str):
        return obj

    if isinstance(obj, datetime):
        return obj.isoformat().replace('+00:00', 'Z')

    if getattr(type(obj), '__resttest_plain__', False):
        return serialize(obj.__dict__)

    if isinstance(obj, dict):
        return {k: serialize(v) for k, v in obj.items()}

    if isinstance(obj, list):
        return [serialize(v) for v in obj]

    raise ValueError()


"""test_action_indexsettings"""
# pylint: disable=missing-function-docstring, missing-class-docstring, protected-access, attribute-defined-outside-init
from unittest import TestCase
from mock import Mock
from curator.actions import IndexSettings
from curator.exceptions import ActionError, ConfigurationError, MissingArgument
from curator import IndexList
# Get test variables and constants from a single source
from . import testvars

class TestActionIndexSettings(TestCase):
    VERSION = {'version': {'number': '8.0.0'} }
    def builder(self):
        self.client = Mock()
        self.client.info.return_value = self.VERSION
        self.client.cat.indices.return_value = testvars.state_one
        self.client.indices.get_settings.return_value = testvars.settings_one
        self.client.indices.stats.return_value = testvars.stats_one
        self.client.indices.exists_alias.return_value = False
        self.ilo = IndexList(self.client)
    def test_init_raise_bad_index_list(self):
        self.assertRaises(TypeError, IndexSettings, 'invalid')
    def test_init_no_index_settings(self):
        self.builder()
        _ = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertRaises(MissingArgument, IndexSettings, self.ilo, {})
    def test_init_bad_index_settings(self):
        self.builder()
        _ = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertRaises(ConfigurationError, IndexSettings, self.ilo, {'a':'b'})
    def test_init(self):
        self.builder()
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertEqual(self.ilo, iso.index_list)
        self.assertEqual(self.client, iso.client)
    def test_static_settings(self):
        static = [
            'number_of_shards',
            'shard',
            'codec',
            'routing_partition_size',
        ]
        self.builder()
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertEqual(static, iso._static_settings())
    def test_dynamic_settings(self):
        self.builder()
        dynamic = [
            'number_of_replicas',
            'auto_expand_replicas',
            'refresh_interval',
            'max_result_window',
            'max_rescore_window',
            'blocks',
            'max_refresh_listeners',
            'mapping',
            'merge',
            'translog',
        ]
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertEqual(dynamic, iso._dynamic_settings())
    def test_settings_check_raises_with_opened(self):
        self.builder()
        self.ilo.get_index_state()
        self.ilo.get_index_settings()
        iso = IndexSettings(self.ilo, {'index':{'codec':'best_compression'}})
        self.assertRaises(ActionError, iso._settings_check)
    def test_settings_check_no_raise_with_ignore_unavailable(self):
        self.builder()
        iso = IndexSettings(
            self.ilo, {'index':{'codec':'best_compression'}}, ignore_unavailable=True
        )
        self.assertIsNone(iso._settings_check())
    def test_settings_check_no_raise_with_dynamic_settings(self):
        self.builder()
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertIsNone(iso._settings_check())
    def test_settings_check_no_raise_with_unknown(self):
        self.builder()
        iso = IndexSettings(self.ilo, {'index':{'foobar':'1s'}})
        self.assertIsNone(iso._settings_check())
    def test_settings_dry_run(self):
        self.builder()
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertIsNone(iso.do_dry_run())
    def test_settings_do_action(self):
        self.builder()
        self.client.indices.put_settings.return_value = {"acknowledged":True}
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertIsNone(iso.do_action())
    def test_settings_do_action_raises(self):
        self.builder()
        self.client.indices.put_settings.side_effect = testvars.fake_fail
        iso = IndexSettings(self.ilo, {'index':{'refresh_interval':'1s'}})
        self.assertRaises(Exception, iso.do_action)


import collections
import csv
import random

# Example of data structure
my_data = [['slashdot', 'USA', 'yes', 18, 'None'],
           ['google', 'France', 'yes', 23, 'Premium'],
           ['digg', 'USA', 'yes', 24, 'Basic'],
           ['kiwitobes', 'France', 'yes', 23, 'Basic'],
           ['google', 'UK', 'no', 21, 'Premium'],
           ['(direct)', 'New Zealand', 'no', 12, 'None'],
           ['(direct)', 'UK', 'no', 21, 'Basic'],
           ['google', 'USA', 'no', 24, 'Premium'],
           ['slashdot', 'France', 'yes', 19, 'None'],
           ['digg', 'USA', 'no', 18, 'None'],
           ['google', 'UK', 'no', 18, 'None'],
           ['kiwitobes', 'UK', 'no', 19, 'None'],
           ['digg', 'New Zealand', 'yes', 12, 'Basic'],
           ['slashdot', 'UK', 'no', 21, 'None'],
           ['google', 'UK', 'yes', 18, 'Basic'],
           ['kiwitobes', 'France', 'yes', 19, 'Basic']]

# Loads file in CSV format and processes its data
def loadCsv(filename):
    lines = csv.reader(open(filename, "rb"))
    dataset = list(lines)
    for i in range(len(dataset)):  # Convert all data from string to int
        dataset[i] = [float(x) for x in dataset[i]]
    return dataset

# split the data into a training dataset to make predictions and a test dataset
# that we can use to evaluate the accuracy of the model. Splits the data set randomly into train
# and datasets with a ratio of for example 67% train and 33% test (this is a common ratio for testing
# an algorithm on a dataset)
def splitDataset(dataset, splitRatio):
    trainSize = int(len(dataset) * splitRatio)
    trainSet = []
    copy = list(dataset)
    while len(trainSet) < trainSize:
        index = random.randrange(len(copy))
        trainSet.append(copy.pop(index))
    return [trainSet, copy]

# Removes every row that has blank data in order not to bias the algorithm
def normalizeDataset(dataSet):
    rowLength = len(dataSet[0])
    dataSetLength = len(dataSet)
    lineIndex = 0
    for lineNumber in range(0, dataSetLength):
        line = dataSet[lineIndex]
        deletedLine = False
        for col in range(0, rowLength):
            if (line[col] == ''):
                del dataSet[lineIndex]
                deletedLine = True
            if deletedLine: break
        if not deletedLine: lineIndex += 1
    return dataSet

# Removes entire column from the dataset by index, columnIndex starts at 0
def removeColumn(dataSet, columnIndex):
    for row in dataSet:
        del row[columnIndex]

# Moves one column in the dataset to the last of the dataset
def postponeColumn(rows, columToPostpone):
    columToPostpone = columToPostpone - 1
    for row in rows:
        row.append(row[columToPostpone])
        del row[columToPostpone]

def printDataSet(dataSet):
    print("DATASET:")
    print('')
    for line in dataSet:
        print(line)

# Splits a dataset randomly into a number of datasets
def randomSplit(dataSet, subsetQuantity):
    startingIndex = 0
    dataSets = []
    subsetLength = int(round(len(dataSet) / subsetQuantity))
    random.shuffle(dataSet)
    for i in range(0, subsetQuantity):
        dataSets.append(dataSet[startingIndex: startingIndex + subsetLength])
        startingIndex += subsetLength
    return dataSets

def getTestSet(dataSet, column, divisionPercentage=30):
    columnList = [row[column] for row in dataSet]
    ocurrences = collections.Counter(columnList)
    percentages = {}

    # The percentages dictionary contains the quantites of each attribute class we need to take
    # in order to get a well balanced test set
    for var in ocurrences:
        percentages[var] = (ocurrences[var] * divisionPercentage) / 100
    # We shuffle randomly the dataset in order to get always a different testset
    print(percentages)
    random.shuffle(dataSet)
    testSet = []
    for row in dataSet:
        value = row[column]
        if (percentages[value] > 0):
            testSet.append(row)
            percentages[value] -= 1
    return testSet


from mrjob.job import MRJob
from mrjob.step import MRStep

class StarWarsSims(MRJob):

    def steps(self):
        return [

            MRStep(mapper=self.mapper_movies, ##Mapper and Reducer functions of 1st step of the MapReduce job i.e to create movie rating pair by user
                    reducer=self.reducer_movies)
          ]

    def mapper_movies(self, key, line):
        (movieName, value) = line.split('\t')
        if (movieName == '"Batman & Robin (1997)"'):
            (bracket, simName, values) = value.split('"')
            (empty, score, coraters) = values.split(',')
            cleanCoraters = coraters.split(']')
            numCoraters = int(cleanCoraters[0])
            if (numCoraters > 15):
                yield float(score), (simName, numCoraters)

    def reducer_movies(self, key, values):
        for value in values:
            yield key, value

if __name__ == '__main__':
    StarWarsSims.run()


# -*- coding: utf-8 -*-
"""
-------------------------------------------------
  @Time : 2019/11/30 9:43
  @Auth : 可优
  @File : payment.py
  @IDE  : PyCharm
  @Motto: ABC(Always Be Coding)
  @Email: keyou100@qq.com
  @Company: 湖南省零檬信息技术有限公司
  @Copyright: 柠檬班
-------------------------------------------------
"""
import requests

class Payment:
    """
    定义第三方支付类
    """
    @staticmethod
    def auth(card_num, amount):
        """
        请求第三方支付接口
        :param card_num:
        :param amount:
        :return:
        """
        url = "http://第三方支付接口.com"  # 第三方的支付接口, 不能请求
        data = {"card_num": card_num, "amount": amount}
        res = requests.post(url, data=data)
        return res.status_code

    def pay(self, user_id, card_num, amount):
        """
        支付方法
        :param user_id:
        :param card_num:
        :param amount:
        :return:
        """
        try:
            status_code = self.auth(card_num, amount)
        except TimeoutError:
            status_code = self.auth(card_num, amount)

        if status_code == 200:
            print(f"【{user_id}】支付【{amount}】成功!!! 进行扣款并登记支付记录!")
            return "Success"
        elif status_code == 500:
            print(f"【{user_id}】支付【{amount}】失败!!! 不进行扣款!")
            return "Fail"


"""This script runs the Ca/Backbone prediction CNN with a single protein's pre-processed mrc file

The script accomplished the following:
1. Load the pre-processed protein from an .MRC file
2. Restore the saved prediction model from file.
3. Runs the protein through the network using a splitting function for proteins larger than 64^3 in size.
4. Prints the SS prediction maps, backbone prediction map, and Ca prediction map to file.
5. Uses graph theory to improve the final backbone trace.
6. Print the final traces to file.
"""

import tensorflow as tf
import numpy as np
import mrcfile
from copy import deepcopy
import math
import cnn.map_splitter as ms
from collections import deque
import os
import prediction as pre

__author__ = 'Moritz Spencer'

def update_paths(paths):
    paths['loops_confidence'] = paths['output'] + 'loops_confidence.mrc'
    paths['sheet_confidence'] = paths['output'] + 'sheet_confidence.mrc'
    paths['helix_confidence'] = paths['output'] + 'helix_confidence.mrc'
    paths['backbone_confidence'] = paths['output'] + 'backbone_confidence.mrc'
    paths['ca_confidence'] = paths['output'] + 'ca_confidence.mrc'

def execute(paths):
    with pre.prediction.semaphore:
        with tf.Session() as sess:
            module_path = os.path.dirname(os.path.abspath(__file__)) + '/saved_module/5-7A_Full_SS_Combo/'
            saver = tf.train.import_meta_graph(module_path + 'saved_model.ckpt.meta')
            saver.restore(sess, module_path + 'saved_model.ckpt')  # Load the saved CNN.
            normalized_map = mrcfile.open(paths['normalized_map'], mode='r')
            full_image = deepcopy(normalized_map.data)

            manifest = ms.create_manifest(full_image) # Create a 'manifest' to run through the CNN.

            # Tensors to be restored in the CNN. These tensors will hold the final output from each stage.
            graph = tf.get_default_graph()
            x = graph.get_tensor_by_name("protein_maps:0")
            y = graph.get_tensor_by_name("ss_labels:0")
            loops_op = graph.get_tensor_by_name('loops_prediction:0')
            sheet_op = graph.get_tensor_by_name('sheet_prediction:0')
            helix_op = graph.get_tensor_by_name('helix_prediction:0')
            ss_op = graph.get_tensor_by_name('ss_logits/BiasAdd:0')
            backbone_op = graph.get_tensor_by_name('backbone_logits/BiasAdd:0')
            ca_op = graph.get_tensor_by_name('ca_logits/BiasAdd:0')

            # Placeholders for prediction maps that will be output from the CNN.
            loops_image = np.zeros((np.shape(manifest)))
            sheet_image = np.zeros((np.shape(manifest)))
            helix_image = np.zeros((np.shape(manifest)))
            loops_confidence = np.zeros((np.shape(manifest)))
            sheet_confidence = np.zeros((np.shape(manifest)))
            helix_confidence = np.zeros((np.shape(manifest)))
            backbone_image = np.zeros((np.shape(manifest)))
            ca_image = np.zeros((np.shape(manifest)))

            # Run the protein through the CNN and save the output in a local placeholder.
            for index in range(math.ceil(len(manifest) / 10)):
                loops_output, sheet_output, helix_output, ss_output, backbone_output, ca_output = \
                    sess.run([loops_op, sheet_op, helix_op, ss_op, backbone_op, ca_op],
                             feed_dict={
                                 x: manifest[index * 10: (index + 1) * 10],
                                 y: manifest[index * 10: (index + 1) * 10]
                             })
                loops_image[index * 10: (index + 1) * 10] = loops_output
                sheet_image[index * 10: (index + 1) * 10] = sheet_output
                helix_image[index * 10: (index + 1) * 10] = helix_output
                loops_confidence[index * 10: (index + 1) * 10] = ss_output[:, :, :, :, 0]
                sheet_confidence[index * 10: (index + 1) * 10] = ss_output[:, :, :, :, 1]
                helix_confidence[index * 10: (index + 1) * 10] = ss_output[:, :, :, :, 2]
                backbone_image[index * 10: (index + 1) * 10] = np.subtract(backbone_output[:, :, :, :, 1],
                                                                           backbone_output[:, :, :, :, 0])
                ca_image[index * 10: (index + 1) * 10] = np.subtract(ca_output[:, :, :, :, 1], ca_output[:, :, :, :, 0])

            # Add an arbitrary constant for improved viewing in Chimera.
            backbone_image += 4  # Used 4 for sim maps.
            ca_image += 10

            # Reconstruct each 64^3 image into the full protein shape.
            loops_confidence = ms.reconstruct_map(loops_confidence, np.shape(full_image))
            sheet_confidence = ms.reconstruct_map(sheet_confidence, np.shape(full_image))
            helix_confidence = ms.reconstruct_map(helix_confidence, np.shape(full_image))
            backbone_image = ms.reconstruct_map(backbone_image, np.shape(full_image))
            ca_image = ms.reconstruct_map(ca_image, np.shape(full_image))

            # Clean up predicted images by zeroing out space outside in input map.
            input_mask = np.where(full_image > 0, 1, 0)
            loops_confidence = np.where(input_mask == 1, loops_confidence, 0)
            sheet_confidence = np.where(input_mask == 1, sheet_confidence, 0)
            helix_confidence = np.where(input_mask == 1, helix_confidence, 0)
            ss_image = np.stack((loops_confidence, sheet_confidence, helix_confidence), axis=3)
            backbone_image = np.where(input_mask == 1, backbone_image, 0)
            backbone_image[backbone_image < 0] = 0
            ss_image = ss_nearest_neighbor(ss_image, input_mask)  # Post-Processing Step to clean up SS predictions.

            loops_image = np.where(ss_image == 0, 1, 0)
            sheet_image = np.where(ss_image == 1, 1, 0)
            helix_image = np.where(ss_image == 2, 1, 0)
            loops_image = np.where(input_mask == 1, loops_image, 0)
            sheet_image = np.where(input_mask == 1, sheet_image, 0)
            helix_image = np.where(input_mask == 1, helix_image, 0)

            remove_small_chunks(backbone_image)
            ca_image = np.where(input_mask == 1, ca_image, 0)
            ca_image = np.array(ca_image, dtype=np.float32)

            # Print the loops image
            with mrcfile.new(paths['loops_confidence'], overwrite=True) as mrc:
                mrc.set_data(np.array(loops_image, dtype=np.float32))
                mrc.header.origin = normalized_map.header.origin.item(0)
                mrc.update_header_stats()
                mrc.close()

            # Print the sheet image
            with mrcfile.new(paths['sheet_confidence'], overwrite=True) as mrc:
                mrc.set_data(np.array(sheet_image, dtype=np.float32))
                mrc.header.origin = normalized_map.header.origin.item(0)
                mrc.update_header_stats()
                mrc.close()

            # Print the helix image
            with mrcfile.new(paths['helix_confidence'], overwrite=True) as mrc:
                mrc.set_data(np.array(helix_image, dtype=np.float32))
                mrc.header.origin = normalized_map.header.origin.item(0)
                mrc.update_header_stats()
                mrc.close()

            # Print the backbone confidence image
            with mrcfile.new(paths['backbone_confidence'], overwrite=True) as mrc:
                mrc.set_data(backbone_image)
                mrc.header.origin = normalized_map.header.origin.item(0)
                mrc.update_header_stats()
                mrc.close()

            # Print the ca-confidence image
            with mrcfile.new(paths['ca_confidence'], overwrite=True) as mrc:
                mrc.set_data(ca_image)
                mrc.header.origin = normalized_map.header.origin.item(0)
                mrc.update_header_stats()
                mrc.close()

            normalized_map.close()

# Post-Processing step used to remove classification outliers in the secondary structure
# prediction image. This function examines each voxel in the image and reassigns it to
# the secondary structure represented by the weighted average of its neighbors.
def ss_nearest_neighbor(ss_confidence, input_mask):
    box_size = np.shape(input_mask)
    output_prediction = np.zeros(box_size)
    sphere_radius = 2
    for x in range(1, box_size[0] - 1):
        for y in range(1, box_size[1] - 1):
            for z in range(1, box_size[2] - 1):
                if input_mask[x][y][z] > 0:
                    loops_weight = 0
                    sheet_weight = 0
                    helix_weight = 0
                    for z_n in range(-sphere_radius + z, sphere_radius + z):
                        for y_n in range(-sphere_radius + y, sphere_radius + y):
                            for x_n in range(-sphere_radius + x, sphere_radius + x):
                                if (0 <= z_n < box_size[2] and 0 <= y_n < box_size[1] and
                                                0 <= x_n < box_size[0] and input_mask[x_n][y_n][z_n] > 0 and
                                            distance(z, z_n, y, y_n, x, x_n) <= sphere_radius):
                                    loops_weight += ss_confidence[x_n][y_n][z_n][0]
                                    sheet_weight += ss_confidence[x_n][y_n][z_n][1]
                                    helix_weight += ss_confidence[x_n][y_n][z_n][2]
                    if loops_weight > sheet_weight and loops_weight > helix_weight:
                        output_prediction[x][y][z] = 0
                    elif sheet_weight > helix_weight:
                        output_prediction[x][y][z] = 1
                    else:
                        output_prediction[x][y][z] = 2
    return output_prediction

def remove_small_chunks(input_image):
    """A method used to remove small disjoint regions in a 3D image

    This was primarily used to clean up the backbone prediction .MRC file
    however it may not be necessary
    """
    min_chuck_size = 25
    box_size = np.shape(input_image)
    visited = np.zeros(box_size)
    for x in range(1, box_size[0] - 1):
        for y in range(1, box_size[1] - 1):
            for z in range(1, box_size[2] - 1):
                if input_image[x, y, z] > 0 and visited[x, y, z] == 0:
                    chunk_list = list()
                    queue = deque()
                    queue.append([x, y, z])
                    chunk_list.append([x, y, z])
                    while len(queue) > 0:
                        cur_position = queue.popleft()
                        visited[cur_position[0], cur_position[1], cur_position[2]] = 1
                        offsets = [[0, 0, -1], [0, 0, 1], [0, -1, 0], [0, 1, 0], [-1, 0, 0], [1, 0, 0]]
                        for index in range(len(offsets)):
                            x_new = cur_position[0] + offsets[index][0]
                            y_new = cur_position[1] + offsets[index][1]
                            z_new = cur_position[2] + offsets[index][2]
                            if 0 <= x_new < box_size[0] and 0 <= y_new < box_size[1] and 0 <= z_new < box_size[2]:
                                if input_image[x_new, y_new, z_new] > 0 and visited[x_new, y_new, z_new] == 0:
                                    queue.append([x_new, y_new, z_new])
                                    visited[x_new, y_new, z_new] = 1
                                    chunk_list.append([x_new, y_new, z_new])
                    if len(chunk_list) < min_chuck_size:
                        for voxel in chunk_list:
                            input_image[voxel[0], voxel[1], voxel[2]] = 0

def distance(z1, z2, y1, y2, x1, x2):
    """Calculates Euclidean distance between two points"""
    z_diff = z1 - z2
    y_diff = y1 - y2
    x_diff = x1 - x2
    sum_squares = math.pow(z_diff, 2) + math.pow(y_diff, 2) + math.pow(x_diff, 2)
    return math.sqrt(sum_squares)


import re
import threading
import time
import winsound

import numpy as np
import pandas as pd
import requests

API_KEY = 'xxx'
thread_lock = threading.Lock()
AUCTION_DATA = {}
last_updated_old = 0

def human_format(num):
    num = float('{:.3g}'.format(num))
    magnitude = 0
    while abs(num) >= 1000:
        magnitude += 1
        num /= 1000.0
    return '{}{}'.format('{:f}'.format(num).rstrip('0').rstrip('.'), ['', 'K', 'M', 'B', 'T'][magnitude])

def get_number_of_auctions_pages_and_if_updated():
    api_auctions_url = 'https://api.hypixel.net/skyblock/auctions'
    response = requests.get(api_auctions_url)
    response = response.json()
    number_of_pages = response["totalPages"]
    if number_of_pages > 120:
        raise Exception("Abusing hypixel Api")
    last_updated = response["lastUpdated"]
    return number_of_pages, last_updated

def get_last_updated():
    api_auctions_url = 'https://api.hypixel.net/skyblock/auctions'
    response = requests.get(api_auctions_url)
    response = response.json()
    last_updated = response["lastUpdated"]
    return last_updated

def get_auctions(item_name: str, price: int, page: int, reforges_list, matches, lore='', flipper_mode=True):
    api_auctions_url = 'https://api.hypixel.net/skyblock/auctions'
    parameters = {"page": page}
    response = requests.get(api_auctions_url, params=parameters).json()
    for auction in response["auctions"]:
        if not flipper_mode:
            if item_name in auction["item_name"].lower() and not auction["claimed"] \
                    and lore in auction["item_lore"]:
                try:
                    if auction["bin"]:
                        if auction["starting_bid"] < price:
                            print(print(item_name), " price: " + str(auction['starting_bid']))
                            for i in range(1, 10):
                                winsound.Beep(i * 100, 200)
                except KeyError as k:
                    continue
        else:
            try:
                if auction["bin"]:
                    item_name = auction["item_name"].lower()
                    item_name = re.sub(r'(\[\w*\s\d*\])', '', item_name)  # [lvl xx]
                    item_name = re.sub(r'\s\s+', ' ', item_name)  # double spaces to one
                    item_name = re.sub(r'([^\w\s]\W*$)', '', item_name, re.MULTILINE)  # *** at the end of the name
                    item_name = re.sub(r'(^\W\s)', '', item_name,
                                       re.MULTILINE)  # this weird umbrella ect at the beginning
                    reforges_regex = re.compile(r'\b(?:' + r'|'.join(reforges_list) + r")\b", re.MULTILINE)
                    item_name = re.sub(reforges_regex, '', item_name)  # deleting reforges
                    item_name = item_name.strip()
                    if item_name == "enchanted book":
                        lore = auction['item_lore']
                        book_names = lore.split('\n')[0].split(',')
                        legendary_enchantment = False
                        for names in book_names:
                            enchantments = names.split('9')
                            for enchantment in enchantments:
                                if "§l" in enchantment:
                                    item_name = enchantment.strip('§d§l§7§l,').split('\n')[0]
                                    legendary_enchantment = True
                            if not legendary_enchantment:
                                if len(enchantments) > 1:
                                    item_name = enchantments[1].strip('§9§d§l§7§l,').split('\n')[0]
                                else:
                                    item_name = enchantments[0].strip('§9§d§l§7§l,').split('\n')[0]
                        if "Use this on" in item_name or len(item_name) < 2:
                            continue
                        item_name = item_name.strip(" \n")
                    # item_name = rename_to_similar(item_name, matches) #too slow - maybe i'll optimize in the future
                    with thread_lock:
                        global AUCTION_DATA
                        if item_name.lower() not in AUCTION_DATA.keys():
                            AUCTION_DATA[item_name.lower()] = [
                                str(auction['starting_bid']) + '|' + str(auction['uuid'])]
                        else:
                            AUCTION_DATA[item_name.lower()].append(
                                str(auction['starting_bid']) + '|' + str(auction['uuid']))
            except KeyError as k:
                continue

def rename_to_similar(item_name, matches_df):
    similar_words = pd.DataFrame()
    similar_words["index_left"] = matches_df["left_side"].isin([item_name])
    similar_words["index_right"] = matches_df["right_side"].isin([item_name])
    if similar_words["index_left"].sum() != 0:
        return matches_df[similar_words["index_left"][0]]
    elif similar_words["index_right"].sum() != 0:
        return matches_df[similar_words["index_right"][0]]
    else:
        return item_name

def auction_finder(reforges_list, matches, item_name: str = '', price: int = 0, lore=''):
    threads = []
    number_of_pages, last_updated = get_number_of_auctions_pages_and_if_updated()
    global last_updated_old
    if last_updated == last_updated_old:
        return None
    for page in range(0, number_of_pages):
        x = threading.Thread(target=get_auctions, args=(item_name, price, page, reforges_list, matches, lore))
        threads.append(x)
        x.start()
    for thread in threads:
        thread.join()
    last_updated_old = last_updated

def MAD_Z_Score(data, consistency_correction=1.4826):
    if np.sum(data) == 0:
        return np.array([]), 0
    median = np.median(data)
    mean = np.mean(data)
    deviation_from_med = np.abs(np.array(data) - median)
    deviation_from_mean = np.abs(np.array(data) - mean)
    MeanAD = np.mean(deviation_from_mean)
    MAD = np.median(deviation_from_med)
    if MAD != 0:
        MAD_zscore = deviation_from_med / (consistency_correction * MAD)
        return MAD_zscore, MAD
    else:
        MeanAD_zscore = deviation_from_mean / (np.mean(deviation_from_mean) * 1.253314)
        return MeanAD_zscore, MeanAD

def find_items_to_flip(data: pd.DataFrame()):
    flip_items = {}
    for index, row in data.iterrows():
        product = row.drop(columns=row[0]).to_numpy()
        products_uuid = None
        with np.nditer([product, products_uuid], ['refs_ok'], [['readwrite'], ['writeonly', 'allocate']]) as it:
            while not it.finished:
                if it[0] == None:
                    it.iternext()
                    continue
                it[1] = str(it[0]).split('|')[1]
                it[0] = float(str(it[0]).split('|')[0])
                it.iternext()
            product = it.operands[0]
            products_uuid = it.operands[1]
        product = product[~np.isnan(product.astype(float))].astype(float)
        if product.max() - product.min() == 0:
            continue
        product_normalize = (product - product.min()) / (product.max() - product.min())
        if len(product) > 1:
            mad_zscore, mad = MAD_Z_Score(product_normalize)
            product_median = np.median(product)
            product_anomalies = (mad_zscore > 3)
            if 0 < np.sum(product_anomalies) < 3:
                product_sorted = sorted(product)
                for idx, anom in enumerate(product_anomalies):
                    if anom and product[idx] < product_median:
                        outlier = product[idx]
                        product_sorted.remove(product[idx])
                        cheapest = product_sorted[0]
                        expected_profit = cheapest - outlier
                        flip_items[str(index)] = [outlier, cheapest, expected_profit, len(product), products_uuid[idx]]
    items_to_flip_dataset = pd.DataFrame.from_dict(flip_items, orient="index",
                                                   columns=["Hunted Price", "LBin", "Expected Profit",
                                                            "Items on market", "Auction uuid"])
    items_to_flip_dataset.sort_values(by="Expected Profit", ascending=False, inplace=True)
    print(items_to_flip_dataset)
    global AUCTION_DATA
    AUCTION_DATA = {}

def check_auctions(reforges_list, matches: list, id: int):
    auction_finder(reforges_list, matches)
    data = pd.DataFrame.from_dict(AUCTION_DATA, orient='index')
    find_items_to_flip(data)
    print("Thread #" + str(id) + " has finished its job")

if __name__ == '__main__':
    last_updated = 0
    path = "auction_objects_data.csv"
    reforges_list = ((pd.read_csv("reforges.csv"))["reforges"]).to_list()
    reforges_list_lower = []
    for reforge in reforges_list:
        reforges_list_lower.append(reforge.lower())
    reforges_list = reforges_list + reforges_list_lower
    start = time.time()
    agents = []
    thread_counter = 0
    while True:
        print("Creating new thread")
        thread_counter += 1
        s1 = threading.Thread(target=check_auctions, args=[reforges_list, [], thread_counter])
        s1.start()
        agents.append(s1)
        agents[-1].join()
        time.sleep(35)
        end = time.time()
        if end - start % 145 == 0:
            thread_to_kill = agents.pop(0)


import torch

def get_horizontal_wave(height, width, freq, amplitude):
    xx, yy = torch.linspace(-1, 1, width), torch.linspace(-1, 1, height)
    gridy, gridx = torch.meshgrid(yy, xx)  # create identity grid
    grid = torch.stack([gridx, gridy], dim=-1)
    dy = amplitude * torch.cos(freq * grid[:, :, 0])  # calculate dy
    grid[:, :, 1] += dy
    return grid.unsqueeze(0)  # unsqueeze(0) since the grid needs to be 4D.


# coding: utf-8

# In[1]:

LIVENOTEBOOK = False
import cv2
cv2.__version__

# In[2]:

LIVENOTEBOOK = True

# In[3]:

import numpy as np
import matplotlib.pyplot as plt
from skimage.measure import compare_ssim
def imshow(img):  plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

if LIVENOTEBOOK:
    get_ipython().magic(u'matplotlib inline')
    img = cv2.imread("../reference/frame17978.png")
    # test plotting
    imshow(img)

# In[4]:

def tightbluemask(image, clean=True):
    """Returns a mask (grayscale image) which is >0 in the area of the blue grid."""
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
    threshold  = np.array([[103,95,30],[120,240,125]])
    mask = cv2.inRange(hsv, threshold[0,:], threshold[1,:])

    if clean:
        # close gaps
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (15, 15))
        mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)
        # remove speckles
        kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
        mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)

    return mask

# In[5]:

# step 1, extract the right kind of blue
if LIVENOTEBOOK:
    image = img
    mask = tightbluemask(img)
    bluewhite = img.copy()
    bluewhite[mask==0,:] = (255,255,255)
    imshow(bluewhite)

# In[6]:

# step 2 :extract raw contours
if LIVENOTEBOOK:
    dst = np.zeros(image.shape, np.uint8)
    dst[:]=(240,240,240)
    cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
    print("Found %d outer contours" % len(cnts))
    cv2.drawContours(dst, cnts, -1, (0,255,0), 3)
    plt.imshow(dst)

# In[7]:

# simplify contours, find one that is a rectangle
def find_outer_rect(cnts, img=None):
    """Find the one large rectangle in a list of contours, returns an approximated contour
    and optionally an image of the contour

    If an optional image is passed, this routine will return a filled 3-channel image of the found contour.
    In channel 0, the area inside the outer rect is 0, 255 elsewhere."""

    if not img is None:
        dst = np.zeros(img.shape, np.uint8)
        dst[:] = (255,240,240)
    else:
        dst = None
    for c in cnts:
        peri = 0.01 * cv2.arcLength(c, True)  # approximate such that points are never > 0.01*perimeter away
        approx = cv2.approxPolyDP(c, peri, True)
        print ("Found shape with sides: %d" % len(approx))
        if len(approx) == 4:
                approx = np.reshape(approx,[4,2]) # drop 2nd dimension
                xsize = approx[:,0].max() - approx[:,0].min()
                ysize = approx[:,1].max() - approx[:,1].min()
                if xsize > 300 and ysize > 150:
                    print ("-- Found: %d x %d" % (xsize, ysize))
                    if not img is None:
                        cv2.drawContours(dst, [approx], -1, (0,255,0), cv2.FILLED)
                    break
                else:
                    print ("-- Rejected rectangle: %d x %d" % (xsize, ysize))
    else:
        raise ValueError("No outer rectangle found")
    return approx, dst

# step 3: get outer rectangle
if LIVENOTEBOOK:
    (outerRectangle, filledMask) = find_outer_rect(cnts, img)
    imshow(filledMask)

# In[8]:

# step 4: remove area outside of outer rectangle from mask (ie set to 0)
if LIVENOTEBOOK:
    mask[filledMask[:,:,0]>0]=0
    plt.imshow(mask)

# In[9]:

def find_inner_rectangles(img):
    # find inner rectangles
    _, cnts, hier = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    contours = []
    for i in range(len(cnts)):
        contour = cnts[i]
        _,_,w,h = cv2.boundingRect(contour)
        if w>100 and h>50:
            contours.append(contour)
        else:
            hier[0, i, -1] = -2 # mark for deletion

    hier = np.delete(hier, np.where(hier[0,:,-1] == -2)[0], 1)

    assert len(contours) == 5, "there should be five contours: found %d" % len(contours)
    assert hier[0,0,-1] == -1, "first contour should be the outer one, ie it has no parent"
    assert np.all(hier[0,1:5,-1] == 0), "all other contours should have the first contour as their parent"
    hier = np.delete(hier, 0, 1) # remove parent from list of hier
    contours = contours[1:] # remove parent from contours
    contours.sort(key=lambda a: a[:,0,1].min()) # sort contours by minimum y value (top down)
    return contours, hier

# step 5: find inner rectangles
if LIVENOTEBOOK:
    contours, hier = find_inner_rectangles(mask)
    assert len(contours) == 4, "Expected four inner rectangles, found %d " % len(contours)

# In[10]:

hier

# In[11]:

# http://www.pyimagesearch.com/2014/08/25/4-point-opencv-getperspective-transform-example/

def order_points(pts):
    rect = np.zeros((4, 2), dtype = "float32")
    s = pts.sum(axis = 1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis = 1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

def four_point_transform(image, pts, wh):
    """Given a source image and a list of 4 contour points, return a perspective warped image
    of dimension WxH"""
    rect = order_points(pts)

    if not wh:
        (tl, tr, br, bl) = rect

        widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
        widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
        maxWidth = max(int(widthA), int(widthB))

        heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
        heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
        maxHeight = max(int(heightA), int(heightB))
        wh = (maxWidth, maxHeight)

    dst = np.array([
        [0, 0],
        [wh[0] - 1, 0],
        [wh[0] - 1, wh[1] - 1],
        [0, wh[1] - 1]], dtype = "float32")

    M = cv2.getPerspectiveTransform(rect, dst)
    warped = cv2.warpPerspective(image, M, wh)

    return warped, wh

# In[77]:

imshow(four_point_transform(bluewhite, outerRectangle, (400,555))[0])

# In[12]:

class Box(object):
    "data class for image of the four squares (boxes) on our white board"
    def __init__(self, **kwargs):
            self.__dict__.update(kwargs)
    def __str__(self):
        return "Box< %r >" % self.__dict__

# In[88]:

# TODO this all assumes the first box is the largest one, which we don't test or ensure

def get_inner_rect_contents(contours, image):
    """for each inner rectangle in 'contours', extract a standard size rectange with
    the (masked) contents of this rectangle from 'image'.  Returns a list of cropped images. """

    boxes = []
    wh = (475, 100) # scaled from what we have
    kernel =  np.ones((5,5), np.uint8)
    for contour in contours:
        # compute mask from contour by filling
        mask = np.zeros(image.shape[:2], np.uint8)
        cv2.drawContours(mask, [contour], -1, 255, cv2.FILLED)
        # make mask about 5px smaller on all sides
        mask = cv2.erode(mask, kernel)
        peri = cv2.arcLength(contour, True)  # approximate such that points are never > 0.05*perimeter away
        approx = cv2.approxPolyDP(contour, 0.05 * peri, True)
        # create white box and copy image in where mask is true
        box = Box(img=np.zeros_like(image), perimeter=peri, contour=contour, approx=approx)
        box.img.fill(255)
        box.img[mask == 255] = image[mask == 255]
        # find simpler contour
        print ("Found shape with sides: %d" % len(approx))
        box.img, wh = four_point_transform(box.img, approx[:,0,:], wh)
        boxes.append(box)
    return boxes

# step 6: get contents of inner rectangles (boxes)
if LIVENOTEBOOK:
    boxes = get_inner_rect_contents(contours, img)
    plt.imshow(np.concatenate([x.img for x in boxes]))

# In[23]:

def get_contents(imagepath):
    img = cv2.imread(imagepath)

    # step 1, extract the right kind of blue
    # image = img
    mask = tightbluemask(img)
    bluewhite = img.copy()
    bluewhite[mask==0,:] = (255,255,255)

    # step 2 :extract raw contours
    dst = np.zeros(img.shape, np.uint8)
    dst[:]=(240,240,240)
    cnts = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
    print("Found %d outer contours" % len(cnts))
    cv2.drawContours(dst, cnts, -1, (0,255,0), 3)

    # step 3: get outer rectangle
    (outerRectangle, filledMask) = find_outer_rect(cnts, img)

    # step 4: remove area outside of outer rectangle from mask (ie set to 0)
    mask[filledMask[:,:,0]>0]=0

    # step 5: find inner rectangles
    contours, hier = find_inner_rectangles(mask)
    assert len(contours) == 4, "Expected four inner rectangles, found %d " % len(contours)

    # step 6: get contents of inner rectangles (boxes)
    boxes = get_inner_rect_contents(contours, img)
    return boxes

# # Full or empty?
# Given code that can extract the contents of the inner rectangles (boxes), we can determine whether the
# contents have changed _and_ whether the box is empty or not.
#

# In[90]:

# we have this nice code for shrinking contours but it not necessary anymore...
h,w = boxes[0].img.shape[:2]
for box in boxes:
    box.template = cv2.cvtColor(box.img[10:h-10, 30:w-30], cv2.COLOR_BGR2GRAY)

plt.imshow(np.concatenate([x.template for x in boxes]), cmap="gray")

# In[25]:

[ x.template.shape for x in boxes ]

# In[26]:

# In[27]:

tt = boxes[1].template
tt = cv2.Canny(tt,10,200)
cnts = cv2.findContours(box.template.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
plt.imshow(tt, cmap="gray")

# In[52]:

namefound = cv2.cvtColor(cv2.imread('./namefound50.png'), cv2.COLOR_BGR2GRAY)
namemissing = cv2.cvtColor(cv2.imread('./namemissing50.png'), cv2.COLOR_BGR2GRAY)
print(namefound.shape, namemissing.shape)
plt.imshow(namemissing, cmap="gray")

# In[53]:

# using Otsu binarization, assumes histo with two peaks (white-black)
tt = boxes[1].template
blur = cv2.GaussianBlur(tt, (5,5), 0)
otsu, tt = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
tt[20:66,-60:-10] = namefound
plt.imshow(tt, cmap="gray")

# In[54]:

# using adaptive thresholding
tt = boxes[1].template
blur = cv2.GaussianBlur(tt, (5,5), 0)
tt = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
tt[20:66,-60:-10] = namemissing
plt.imshow(tt, cmap="gray")

# In[91]:

namefound = cv2.cvtColor(cv2.imread('./namefound50.png'), cv2.COLOR_BGR2GRAY)
namemissing = cv2.cvtColor(cv2.imread('./namemissing50.png'), cv2.COLOR_BGR2GRAY)

for b in boxes:
    #image = cv2.Canny(b.template,10,200)
    blur = cv2.GaussianBlur(b.template, (5,5), 0)
    bg = cv2.adaptiveThreshold(blur, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    dst = np.dstack([bg, bg, bg])
    image = cv2.Canny(bg, 10, 200)
    cnts = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[1]
    cnts = [ c for c in cnts if cv2.contourArea(c) >= 20 ]
    b.hascontent = len(cnts) > 1
    if b.hascontent:
        color = (255,0,0)
        icon = namefound
    else:
        color = (0,0,255)
        icon = namemissing
    cv2.drawContours(dst, cnts, -1, color, 3)
    dst[20:66,-60:-10,:] = np.dstack([icon, icon, icon])
    b.contentdetection = dst

if LIVENOTEBOOK:
    print([b.hascontent for b in boxes])
    imshow(np.concatenate([b.contentdetection for b in boxes]))

# In[100]:

bluestraight = four_point_transform(bluewhite, outerRectangle, (480,550))[0]
bluestraight[30:(30+80),26:(26+415)] = boxes[0].contentdetection
bluestraight[180:(180+80),26:(26+415)] = boxes[1].contentdetection
bluestraight[290:(290+80),26:(26+415)] = boxes[2].contentdetection
bluestraight[430:(430+80),26:(26+415)] = boxes[3].contentdetection

imshow(bluestraight)

# In[94]:

boxes[0].approx

# In[ ]:

# In[ ]:

# In[ ]:

# In[ ]:


from ast import Delete
from http.client import REQUEST_URI_TOO_LONG
from urllib import request
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

from api.serializers.habit_serializer import *
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view

@api_view(['GET', 'POST', 'DELETE'])
def habits_list(request, user_id):
    if request.method == 'GET':
        habits = Habit.objects.filter(user_id = user_id)
        serializer = HabitSerializer(habits, many=True)
        return Response(serializer.data, status=200)

    elif request.method == 'POST':
        serializer = HabitSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)

@api_view(['GET', 'PUT', 'DELETE'])
def about_habit(request, habit_id):
    try:
        habit = Habit.objects.get(id=habit_id)
    except Habit.DoesNotExist as err:
        return Response({'message': str(err)}, status=400)

    if request.method == 'GET':
        serializer = HabitSerializer(habit)
        return Response(serializer.data, status=200)

    elif request.method == 'PUT':
        serializer = HabitSerializer(data=request.data, instance=habit)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=200)

    elif request.method == 'DELETE':
        habit.delete()
        return Response({'message': 'delete company ' + str(habit)})


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

import torch_geometric as tg
import torch_geometric.nn as tgnn

servings = {
    "GCN": None, # graph convolutional network
    "GIN": None, # graph isomorphism network
    "ESAN": None, # equivariant subgraph aggregation network
    "2-IGN": None, # 2-invariant graph network
    "2-IGN+": None, # provably powerful graph networks
    "P-GNN": None, # position-aware graph neural networks
    "k-GNN": None, # k-WL graph neural network
    "MPNN": None # message passing neural network
}

class GCN(nn.Module):
    def __init__(self, indim, hidden, outdim):
        super().__init__()
        self.conv1 = tgnn.GraphConv(indim, hidden)
        self.conv2 = tgnn.GraphConv(hidden, hidden)
        self.conv3 = tgnn.GraphConv(hidden, outdim)

    def forward(self, x, edge_idx):
        x = torch.relu(self.conv1(x, edge_idx))
        x = torch.relu(self.conv2(x, edge_idx))
        out = torch.softmax(self.conv3(x, edge_idx), 1)

        return out

class GAT(nn.Module):
    def __init__(self, indim, hidden, outdim):
        super().__init__()
        self.conv1 = tgnn.GATConv(indim, hidden)
        self.conv2 = tgnn.GATConv(hidden, hidden)
        self.conv3 = tgnn.GATConv(hidden, outdim)

    def forward(self, x, edge_idx):
        x = torch.relu(self.conv1(x, edge_idx))
        x = torch.relu(self.conv2(x, edge_idx))
        out = torch.softmax(self.conv3(x, edge_idx), 1)

        return out

class GIN(nn.Module):
    def __init__(self, indim, hidden, outdim):
        super().__init__()
        self.l1 = nn.Linear()
        self.conv1 = tgnn.GINConv(nn, )
        self.conv2 = tgnn.GraphConv(hidden, hidden)
        self.conv3 = tgnn.GraphConv(hidden, outdim)

    def forward(self, x, edge_idx):
        x = torch.relu(self.conv1(x, edge_idx))
        x = torch.relu(self.conv2(x, edge_idx))
        out = torch.softmax(self.conv3(x, edge_idx), 1)

        return out


import warnings
from .stats import find_repeats, _contains_nan
from . import distributions
from collections import namedtuple
import numpy as np
from scipy import stats
from numpy import (isscalar, r_, log, around, unique, asarray,
                   zeros, arange, sort, amin, amax, any, atleast_1d,
                   sqrt, ceil, floor, array, compress,
                   pi, exp, ravel, count_nonzero, sin, cos, arctan2, hypot)

class Wilcoxon:
    def __init__(self):
        pass

    def r_plus(self):
        count_r_plus = 1
        return count_r_plus

    def r_minus(self):
        count_r_plus = 2
        return count_r_plus

    def first_validation(self,zero_method,alternative):
        if zero_method not in ["wilcox", "pratt", "zsplit"]:
            raise ValueError("Zero method should be either 'wilcox' "
                             "or 'pratt' or 'zsplit'")

        if alternative not in ["two-sided", "less", "greater"]:
            raise ValueError("Alternative must be either 'two-sided', "
                             "'greater' or 'less'")

    WilcoxonResult = namedtuple('WilcoxonResult', ('statistic', 'pvalue'))

    def wilcoxon(self,x, y=None, zero_method="wilcox", correction=False,
                 alternative="two-sided"):

        self.first_validation(zero_method, alternative)
        distr = self.check_y(y)

        n_zero = self.zero_wilcox_pratt(distr, zero_method)

        if zero_method == "wilcox":
            # Keep all non-zero differences
            distr = compress(np.not_equal(distr, 0), distr, axis=-1)

        count = len(distr)
        if count < 10:
            warnings.warn("Sample size too small for normal approximation.")

        rankdata = stats.rankdata(abs(distr))
        r_plus = np.sum((distr > 0) * rankdata, axis=0)
        r_minus = np.sum((distr < 0) * rankdata, axis=0)

        if zero_method == "zsplit":
            r_zero = np.sum((distr == 0) * rankdata, axis=0)
            r_plus += r_zero / 2.
            r_minus += r_zero / 2.

        T_val = self.set_t_val(alternative, r_minus, r_plus)
        mn = count * (count + 1.) * 0.25
        se = count * (count + 1.) * (2. * count + 1.)

        mn, rankdata, se = self.zero_method_pratt(distr, mn, n_zero, rankdata, se, zero_method)

        replist, repnum = find_repeats(rankdata)
        if repnum.size != 0:
            # Correction for repeated elements.
            se -= 0.5 * (repnum * (repnum * repnum - 1)).sum()

        se = sqrt(se / 24)

        distr = self.set_distr(T_val, alternative, correction, distr, mn)

        # compute statistic and p-value using normal approximation
        z_stat = (T_val - mn - distr) / se
        prob = self.count_p_val(alternative, z_stat)

        return WilcoxonResult(T_val, prob)

    def set_distr(self, T_val, alternative, correction, distr, mn):
        # apply continuity correction if applicable
        distr = 0
        if correction:
            if alternative == "two-sided":
                distr = 0.5 * np.sign(T_val - mn)
            elif alternative == "less":
                distr = -0.5
            else:
                distr = 0.5
        return distr

    def set_t_val(self, alternative, r_minus, r_plus):
        # return min for two-sided test, but r_plus for one-sided test
        # the literature is not consistent here
        # r_plus is more informative since r_plus + r_minus = count*(count+1)/2,
        # i.e. the sum of the ranks, so r_minus and the min can be inferred
        # (If alternative='pratt', r_plus + r_minus = count*(count+1)/2 - r_zero.)
        # [3] uses the r_plus for the one-sided test, keep min for two-sided test
        # to keep backwards compatibility
        if alternative == "two-sided":
            T_val = min(r_plus, r_minus)
        else:
            T_val = r_plus
        return T_val

    def zero_method_pratt(self, distr, mn, n_zero, rankdata, se, zero_method):
        if zero_method == "pratt":
            rankdata = rankdata[distr != 0]
            # normal approximation needs to be adjusted, see Cureton (1967)
            mn -= n_zero * (n_zero + 1.) * 0.25
            se -= n_zero * (n_zero + 1.) * (2. * n_zero + 1.)
        return mn, rankdata, se

    def count_p_val(self, alternative, z_stat):
        if alternative == "two-sided":
            prob = 2. * distributions.norm.sf(abs(z_stat))
        elif alternative == "greater":
            # large T_val = r_plus indicates x is greater than y; i.e.
            # accept alternative in that case and return small p-value (sf)
            prob = distributions.norm.sf(z_stat)
        else:
            prob = distributions.norm.cdf(z_stat)
        return prob

    def zero_wilcox_pratt(self, distr, zero_method):
        if zero_method in ["wilcox", "pratt"]:
            n_zero = np.sum(distr == 0, axis=0)
            if n_zero == len(distr):
                raise ValueError("zero_method 'wilcox' and 'pratt' do not work if "
                                 "the x - y is zero for all elements.")
        return n_zero

    def check_y(self, y):
        if y is None:
            distr = asarray(x)
            if distr.ndim > 1:
                raise ValueError('Sample x must be one-dimensional.')
        else:
            x, y = map(asarray, (x, y))
            if x.ndim > 1 or y.ndim > 1:
                raise ValueError('Samples x and y must be one-dimensional.')
            if len(x) != len(y):
                raise ValueError('The samples x and y must have the same length.')
            distr = x - y
        return distr


import openai
from decouple import config

# custom functions
from functions.db import get_recent_messages

# retrieving env variables
openai.organization = config("OPEN_AI_ORG")
openai.api_key = config("OPEN_AI_KEY")

# using whisper part of openAI
# convert audio to text
def convert_audio_to_text(audio_file):
    try:
        textFromAud = openai.Audio.transcribe("whisper-1",audio_file)
        msg_text = textFromAud
        return msg_text
    except Exception as e:
        print(e)
        return

# openai - chat-gpt
# getting resposnes from chatgpt
def get_chat_response(message_input):
    messages = get_recent_messages()
    user_messages = {"role":"user","content":message_input}
    messages.append(user_messages)
    print(messages)

    try:
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=messages
        )
        # print(response)
        messages_text = response["choices"][0]["message"]["content"]
        return messages_text
    except Exception as e:
        print(e)
        return


# --------------
#import libraries
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv(path)

data.columns

data.shape

data.rename(columns={'Total':'Total_Medals'},inplace=True)

data.head(10)

data[(data['Total_Winter']>0)& (data['Total_Summer']==0)]

data['Better_Event'] = np.where(data['Total_Summer'] > data['Total_Winter'] , 'Summer', 'Winter')
data['Better_Event'] =np.where(data['Total_Summer'] ==data['Total_Winter'],'Both',data['Better_Event'])

# better_event = data['Better_Event'].value_counts()
data['Better_Event'].value_counts()
better_event = 'Summer'

# top_countries.drop(146,inplace=True)
top_countries = data[['Country_Name','Total_Summer', 'Total_Winter','Total_Medals']]
top_countries = top_countries[:-1]

def top_ten(df,col_na):
    """ Presenting the top ten conutries in the dataframe
    This function accepts the dataframe and column name

    keyword arguments
    df - dataframe of country names and medals
    col_na  - column name is country_name and medals

    returns  - top 10 country list

    """
    country_list = []

    a = df.nlargest(10,col_na)
    country_list = list(a['Country_Name'])
    return country_list

top_10_summer = (top_ten(top_countries,'Total_Summer'))
print(top_10_summer)
top_10_winter = list(top_ten(top_countries,'Total_Winter'))

top_10 = top_ten(top_countries,'Total_Medals')

common = set(top_10).intersection(top_10_summer,top_10_winter)

top_df = data[data['Country_Name'].isin(top_10)]
summer_df = data[data['Country_Name'].isin(top_10_summer)]
winter_df = data[data['Country_Name'].isin(top_10_winter)]

summer_df.plot(kind='bar',x='Country_Name',y='Total_Summer')
plt.xlabel('Country Name')
plt.ylabel('Counts')
plt.title('Summer')
plt.show()

def bar_graph(df,col_1,col_2):
    """
    Plotting bar plot for above column
    parameters :
    df -  dataframe
    col_1 -  column from dataframe at x axis
    col_2 - column from dataframe at y axis
    """
    df.plot(kind='bar',x=col_1,y=col_2)
    plt.xlabel(col_1)
    plt.ylabel('Counts')
    plt.title(col_1)
    plt.show()

bar_graph(summer_df,'Country_Name','Total_Summer')

bar_graph(winter_df,'Country_Name','Total_Winter')

bar_graph(top_df,'Country_Name','Total_Medals')

# summer_df['Gold_Ratio'] = (summer_df['Gold_Summer']/summer_df['Total_Summer'])

summer_df.columns

# gold_max = pd.DataFrame(summer_df.groupby(['Country_Name','Gold_Ratio'])['Gold_Summer'].count()).reset_index()

# g_max = summer_df['Gold_Ratio'].max()

# summer_df.loc[summer_df['Gold_Ratio']==g_max,'Country_Name'].iloc[0]

# gr = gold_max['Gold_Ratio'].max()

# gold_max.loc[gold_max['Gold_Ratio']==gr,'Country_Name'].iloc[0]

def gold_countries(df,df_type,c_name,g_type,total):
        """
        finding the countries which has highest gold ratio
        parameters:
        df : dataframe
        col_1 : is the Gold ratio column
        col_2 : Country name in data frame
        """
        dataframes = {'Summer':summer_df,'Winter':winter_df,'Top':top_df}
        df1 = dataframes[df_type]
        df1['Gold_Ratio'] = round((df1[g_type]/df1[total])*100,3)

        gold_max_ratio = df1['Gold_Ratio'].max()
#         print(gold_max_ratio)

        country_gold =  df1.loc[ df1['Gold_Ratio']==gold_max_ratio,c_name].iloc[0]
        print(country_gold)
        return round(gold_max_ratio,2),country_gold

summer_gold_ratio, summer_country_gold = gold_countries(summer_df,'Summer','Country_Name','Gold_Summer','Total_Summer')

winter_gold_ratio, winter_country_gold = gold_countries(winter_df,'Winter','Country_Name','Gold_Winter','Total_Summer')

top_df.columns

top_max_ratio, top_country_gold = gold_countries(top_df,'Top','Country_Name','Gold_Total','Total_Medals')
top_max_ratio =0.40
data_1 = data.drop(146)

data_1.head()

data_1['Gold_Total'].map(lambda x : x*3)

def points(df):
    df['Gold_Points'] = df['Gold_Total'].map(lambda x : x*3)
    df['Silver_Points'] = df['Silver_Total'].map(lambda x : x*2)
    df['Bronze_Points'] = df['Bronze_Total']
    df['Total_Points'] = df['Gold_Points']+df['Silver_Points']+df['Bronze_Points']

    return df

points(data_1)

def best_country(df,col_1):
    max_p = df['Total_Points'].max()

    best_c =  df.loc[ df['Total_Points']==max_p,col_1].iloc[0]
    return max_p,best_c

most_points,best_country = best_country(data_1,'Country_Name')

most_points,best_country

best = data[ data['Country_Name']==best_country]

best =best[['Gold_Total','Silver_Total','Bronze_Total']]

best.plot(kind='bar',stacked=True)
plt.xlabel('United States')
plt.ylabel('Meadals Tally')
plt.xticks(rotation=45)
plt.show()


# -*- coding: utf-8 -*-
# @Author: jadesauve
# @Date:   2021-01-06
"""
find the area of a grid south of 31S and the avg depth of each cells using ETOPO data

data dowload: 2021-01-03

"""

## Import modules
import pandas as pd
# pd.set_option("display.precision", 8)
import numpy as np
# import scipy.interpolate
import gsw
# import matplotlib.pyplot as plt
import xarray as xr
import datetime
from dateutil.relativedelta import relativedelta
# from shapely.geometry import Point
# from shapely.geometry.polygon import Polygon
import os
import sys
pht = os.path.abspath('/Users/jadesauve/Documents/Python/scripts/python_tools/')
if pht not in sys.path:
    sys.path.append(pht)
from toolbox_float import *

#### Parameters ####

directory_relief = '/Users/jadesauve/Coding/data/'

file_relief = 'ETOPO1_Ice_g_gmt4.grd'

# to save
directory_out =  '/Users/jadesauve/Coding/output/'
file_out_depth = 'ETOPO1_ocean_depth_26S.pkl'
file_out_area = 'grid_cell_area_26S.pkl'

######################

# open the files
ds_rel = xr.open_dataset(directory_relief + file_relief)

# convert to 0-360 from -180-180
ds_rel = ds_rel.assign_coords(x=ds_rel.x%360)
ds_rel = ds_rel.sortby('x')

# select data south of 30S
ds_rel = ds_rel.sel(y=slice(-90,-25))

## make a grid
# set a step size
dl = 0.5

# make a vector for coordinates - center of the cell
latc = np.arange(-90+(dl/2),-26,dl)
lonc = np.arange(dl/2,360-(dl/2),dl)

# Make a grid
lonc,latc = np.meshgrid(lonc,latc)

# vector for the corners of the cell
lat1 = latc-(dl/2)
lat2 = latc+(dl/2)
lon1 = lonc-(dl/2)
lon2 = lonc+(dl/2)

# find the area of each cell
area = areaquad(lat1,lon1,lat2,lon2)

# make a df
df_area = pd.DataFrame(index=latc[:,0],columns=lonc[0,:],data=area)

# find the mean depth of each cell
depth = np.empty(area.shape)
depth[:] = np.NaN

# print('Finding depth - 127')
for i in range(depth.shape[0]): # latitude - 118
	print(i)
	for j in range(depth.shape[1]): # longitude - 719
		# select the depth for the proper cells
		z = ds_rel.sel(x=slice(lon1[i,j],lon2[i,j]),y=slice(lat1[i,j],lat2[i,j]))
		# get the avg depth
		depth[i,j] = z.mean(['x','y']).to_array()

# make a df
df_depth = pd.DataFrame(index=latc[:,0],columns=lonc[0,:],data=depth)

#save
df_depth.to_pickle(directory_out+file_out_depth)
df_area.to_pickle(directory_out+file_out_area)

# plot
directory_in  = '/Users/jadesauve/Coding/output/'
file_depth = 'ETOPO1_ocean_depth_31S.pkl'
file_area ='grid_cell_area_31S.pkl'

df_ga = pd.read_pickle(directory_in + file_area)
df_depth = pd.read_pickle(directory_in + file_depth)

plt.figure()
cmap=plt.cm.seismic
cmap.set_bad('white',1.)
norm=mpl.colors.Normalize(vmin=-8000,vmax=8000)
plt.pcolormesh(df_depth.columns,df_depth.index,df_depth,cmap=cmap,norm=norm)
plt.colorbar()
plt.show()

plt.figure()
plt.pcolormesh(df_ga.columns,df_ga.index,df_ga)
plt.colorbar()
plt.show()


import flask
from flask import Flask, jsonify,request, render_template, Response, redirect, url_for, request, session, abort
import json
import pickle
import numpy as np

app = Flask(__name__)

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/get_end_predictions', methods=['post'])
def get_prediction_result():
    try:
        d1=float(request.json["Vertical_input"])
        d2=float(request.json["Diagonal_input"])
        d3=float(request.json["Cross_input"])
        d4=float(request.json["Height_input"])
        d5=float(request.json["Width_input"])
        input_data=np.array([d1,d2,d3,d4,d5]).reshape(1, -1)
        print(input_data)
        file = open("fish_model.pickle",'rb')
        model=pickle.load(file)
        pre_weight=model.predict(input_data)
        print("weight",pre_weight)
        return app.response_class(response=json.dumps(pre_weight[0]), status=200, mimetype='application/json')
    except Exception as error:
        err = str(error)
        print(err)
        return app.response_class(response=json.dumps(pre_weight[0]), status=500, mimetype='application/json')

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', use_reloader=False)


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

class Robot:

    def __init__(self, arena_size, robot_radius, lin_speed, ang_speed):

        self.arena_size = arena_size
        self.robot_radius = robot_radius
        self.position = np.array([arena_size/2, arena_size/2])
        self.direction = np.array([1.0, 0.0])
        self.lin_speed = lin_speed
        self.ang_speed = ang_speed

        self.rot = 0
        self.turning = False
        self.turninit = False
        self.rot_angle = 0

    def move(self):

        # Move or turn the robot depending on the state
        if (not self.turning):
            self.position += self.direction * self.lin_speed
        else:
            # Initialize the random angle
            if (not self.turninit):
                self.turninit = True
                self.rot_angle = np.random.uniform(0.25*2*np.pi, 0.75*2*np.pi)
                self.rot_angle += self.rot

            # Turn the robot until it reaches the random angle
            if (self.rot < self.rot_angle):
                self.rot += self.ang_speed
                self.direction = np.array([np.cos(self.rot), np.sin(self.rot)])
            else:
                self.turning = False
                self.turninit = False

        # Handle the boundary conditions considering the robot radius
        if self.position[0] < self.robot_radius:
            self.position[0] = self.robot_radius
            self.turning = True
        elif self.position[0] > self.arena_size - self.robot_radius:
            self.position[0] = self.arena_size - self.robot_radius
            self.turning = True

        if self.position[1] < self.robot_radius:
            self.position[1] = self.robot_radius
            self.turning = True
        elif self.position[1] > self.arena_size - self.robot_radius:
            self.position[1] = self.arena_size - self.robot_radius
            self.turning = True

class BrownianRobotSimulation:

    def __init__(self, arena_size, lin_speed, ang_speed):

        self.robot = Robot(arena_size, 1, lin_speed, ang_speed)

        self.fig, self.ax = plt.subplots()
        self.ax.set_xlim([0, arena_size])
        self.ax.set_ylim([0, arena_size])
        self.ax.set_aspect('equal')

        self.robot_circle = plt.Circle(self.robot.position, radius=1, color='r')
        self.arrow = plt.arrow(self.robot.position[0], self.robot.position[1], self.robot.direction[0], self.robot.direction[1], color='b', width=0.3)
        self.ax.add_artist(self.robot_circle)

    def update(self, i):

        # Move the robot
        self.robot.move()

        # Update the robot circle
        self.robot_circle.center = self.robot.position

        # Update the arrow
        self.arrow.remove()
        self.arrow = plt.arrow(self.robot.position[0], self.robot.position[1], self.robot.direction[0], self.robot.direction[1], color='b', width=0.3)
        self.ax.add_artist(self.arrow)

        return [self.robot_circle, self.arrow]

    def simulate(self, num_steps):
        ani = FuncAnimation(self.fig, self.update, frames=num_steps, interval=50, blit=True)
        plt.show()

if __name__ == '__main__':
    rsim = BrownianRobotSimulation(50, 0.5, 0.2)
    rsim.simulate(200)


import pandas as pd
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn import preprocessing
from sklearn.model_selection import cross_val_score

data = pd.read_cv("credit_data.csv") #load dataset

features = data[["income", "age", "loan"]] #attributes to be used in the model
target = data.default #labels of dataset

#convert dataframes to np arrays
x = np.array(features).reshape(-1, 3)
y = np.array(target)

# perform normalization
x = preprocessing.MinMaxScaler().fit_transform(x)

# split dataset between training-testing
training_dataset, testing_dataset, training_dataset, testing_target = train_test_split(x, y, test_size=0.3)

# create KNN model
model = KNeighborsClassifier(n_neighbors=7)
fitted_model = model.fit(training_dataset, testing_target)

predict = fitted_model.predict(np.array([[100000, 50, 6000]]))
print(predict)

#many predictions
predictions = fitted_model.predict(testing_dataset)
print(confusion_matrix(testing_target, predictions))
#print(accuracy_matrix)
print(accuracy_score(testing_target, predictions))

#Estudiar
for k in range(1, 100):

    # perform crossvalidation
    knn = KNeighborsClassifier(6)
    scores = cross_val_score(knn, x, y, cv=10, scoring="accuracy")

    print(scores)
    print(np.mean(scores))


import os
import time
import unittest

from appium import webdriver
from pytest_testconfig import config
from selenium.webdriver.common.by import By

class IAppium(unittest.TestCase):
    def setUp(self) -> None:
        desired_caps = {}
        # appium_server_url = config['appium_server_url']
        appium_server_url = config['appium_server_url']
        desired_caps['platformName'] = config['desired_caps']['platformName']
        desired_caps['udid'] = config['desired_caps']['udid']
        desired_caps['deviceName'] = config['desired_caps']['deviceName']
        desired_caps['appPackage'] = config['desired_caps']['appPackage']
        desired_caps['appActivity'] = config['desired_caps']['appActivity']
        desired_caps['automationName'] = config['desired_caps']['automationName']
        desired_caps['noReset'] = config['desired_caps']['noReset']
        desired_caps['app'] = f'{os.path.dirname(os.path.dirname(__file__))}/app/ContactManager.apk'
        self.driver = webdriver.Remote(appium_server_url, desired_caps)

    def tearDown(self) -> None:
        self.driver.quit()

    def test_contact(self):
        self._click_addContact_btn()
        time.sleep(2)
        self._add_Contact_Name("heihei")
        self._add_Contact_Phone("13800000000")
        self._add_Contact_Email("titanmax@163.com")
        self._save_button()
        time.sleep(3)

    def _click_addContact_btn(self):
        ele = self.driver.find_element(By.ID, "com.example.android.contactmanager:id/addContactButton")
        print("-------- 点击 Add Contact ----------")
        ele.click()

    def _add_Contact_Name(self,txt_name):
        ele = self.driver.find_element(By.ID, "com.example.android.contactmanager:id/contactNameEditText")
        print("-------- 输入 Contact Name ----------")
        ele.send_keys(txt_name)

    def _add_Contact_Phone(self,txt_phone):
        ele = self.driver.find_element(By.ID, "com.example.android.contactmanager:id/contactPhoneEditText")
        print("-------- 输入 Contact Phone ----------")
        ele.send_keys(txt_phone)

    def _add_Contact_Email(self, txt_email):
        ele = self.driver.find_element(By.ID, "com.example.android.contactmanager:id/contactEmailEditText")
        print("-------- 输入 Contact Email ----------")
        ele.send_keys(txt_email)

    def _save_button(self):
        ele = self.driver.find_element(By.ID, "com.example.android.contactmanager:id/contactSaveButton")
        print("---- 保存 ------")
        ele.click()


"""MlFlow Launcher."""

from pathlib import Path
from typing import Any
import json
import logging
import tempfile

import fromconfig
import mlflow

LOGGER = logging.getLogger(__name__)

_RUN_ID_ENV_VAR = "MLFLOW_RUN_ID"

class MlFlowLauncher(fromconfig.launcher.Launcher):
    """MlFlow Launcher.

    To configure MlFlow, add a `mlflow` entry to your config.

    You can set the following parameters

    - `run_id`: if you wish to restart an existing run
    - `run_name`: if you wish to give a name to your new run
    - `tracking_uri`: to configure the tracking remote
    - `experiment_name`: to use a different experiment than the custom
      experiment
    - `artifact_location`: the location of the artifacts (config files)

    Additionally, if you wish to call the `mlflow` launcher multiple
    times during the launch (for example once before the parser, and
    once after), you need to configure the different launches with the
    special `launches` key (otherwise only the first launch will
    actually log artifacts and parameters).

    The `launches` key should be a list of dictionaries with the
    following parameters

    - `log_artifacts`: if `True` (default), will log the artifacts (the
      config and command given to the launcher)
    - `log_parameters`: if `True` (default) will log a flattened view of
      the parameters
    - `path_config`: if given, will write the config as an artifact with
      that name (default is `config.json`)
    - `path_command`: if given, will write the command as an artifact
      with that name (default is `launch.txt`, using the `.txt`
      extension because you can preview it on MlFlow).
    - `include_keys`: if given, only log flattened parameters that have
      one of these keys as substring. Also shorten the flattened
      parameter to start at the first match. For example, if the config
      is `{"foo": {"bar": 1}}` and `include_keys=("bar",)`, then the
      logged parameter will be `"bar"`.
    - `ignore_keys`: if given, parameters that have at least one of the
      keys as substring will be ignored.

    Example
    -------
    >>> import fromconfig
    >>> config = {
    ...     "run": None,
    ...     "launcher": {"log": ["logging", "mlflow"]},
    ...     "mlflow": {"run_name": "test"}
    ... }
    >>> launcher = fromconfig.launcher.Launcher.fromconfig(config["launcher"])
    >>> launcher(config, "run")
    """

    def __call__(self, config: Any, command: str = ""):
        if mlflow.active_run() is not None:
            LOGGER.info(f"Active run found: {get_url(mlflow.active_run())}")
            self.log_and_launch(config=config, command=command)
        else:
            # Create run from params in config
            params = config.get("mlflow") or {}
            run_id = params.get("run_id")
            run_name = params.get("run_name")
            tracking_uri = params.get("tracking_uri")
            experiment_name = params.get("experiment_name")
            artifact_location = params.get("artifact_location")

            # Setup experiment and general MlFlow parameters
            if tracking_uri is not None:
                mlflow.set_tracking_uri(tracking_uri)
            if experiment_name is not None:
                if mlflow.get_experiment_by_name(experiment_name) is None:
                    mlflow.create_experiment(experiment_name, artifact_location=artifact_location)
                mlflow.set_experiment(experiment_name)

            # Start MlFlow run, log information and launch
            with mlflow.start_run(run_id=run_id, run_name=run_name) as run:
                LOGGER.info(f"Started run: {get_url(run)}")
                config = fromconfig.utils.merge_dict(config, {"mlflow": {"run_id": run.info.run_id}})
                self.log_and_launch(config=config, command=command)

    def log_and_launch(self, config: Any, command: str = ""):
        """Log and launch config

        Parameters
        ----------
        config : Any
            Config
        command : str, optional
            Command
        """
        # Extract params for this launch
        params = config.get("mlflow") or {}
        launches = params.get("launches") or []
        launches = [launches] if not isinstance(launches, list) else launches
        launch = launches[0] if launches else {}
        log_artifacts = launch.get("log_artifacts", True)
        log_parameters = launch.get("log_parameters", True)
        path_config = launch.get("path_config", "config.json")
        path_command = launch.get("path_command", "launch.txt")
        include_keys = launch.get("include_keys")
        ignore_keys = launch.get("ignore_keys")

        # Log artifacts
        if log_artifacts:
            LOGGER.info(f"Logging artifacts {path_config} and {path_command}")
            dir_artifacts = tempfile.mkdtemp()
            with Path(dir_artifacts, path_config).open("w") as file:
                json.dump(config, file, indent=4)
            with Path(dir_artifacts, path_command).open("w") as file:
                file.write(f"fromconfig {path_config} - {command}")
            mlflow.log_artifacts(local_dir=dir_artifacts)

        # Log parameters
        if log_parameters:
            LOGGER.info("Logging parameters")
            params = get_params(config, ignore_keys, include_keys)
            for idx in range(0, len(params), 100):
                mlflow.log_params(dict(params[idx : idx + 100]))

        # Update config (remove used params if successive launches)
        launches = launches[1:] if launches else []
        launches = launches if launches else [{}]
        launches[0] = fromconfig.utils.merge_dict({"log_artifacts": False, "log_parameters": False}, launches[0])
        config = fromconfig.utils.merge_dict(config, {"mlflow": {"launches": launches}})
        self.launcher(config=config, command=command)

def get_params(config, ignore_keys=None, include_keys=None):
    """Log param if coherent with ignore keys and include keys."""
    params = []
    for key, value in fromconfig.utils.flatten(config):
        key = str(key).replace("[", ".").replace("]", "")
        if include_keys and not any(k in key for k in include_keys):
            continue
        if include_keys:
            for k in include_keys:
                index = key.find(k)
                if index != -1:
                    key = key[index:]
        if ignore_keys and any(k in key for k in ignore_keys):
            continue
        params.append((key, value))
    return params

def get_url(run) -> str:
    return f"{mlflow.get_tracking_uri()}/experiments/{run.info.experiment_id}/runs/{run.info.run_id}"


from market import app
from functools import wraps
import jwt
from market.models import User, Shop
from flask import request, g, redirect, url_for

def checkUser(func):
  @wraps(func)
  def checkToken():
    token = request.cookies.get('ezjwt')
    decoded = jwt.decode(token, app.config['SECRET_KEY'], algorithms='HS256')
    id = decoded.get('id')
    existingUser = User.query.filter_by(id=id).first()

    if existingUser:
      g.username = existingUser.username
      g.token = decoded
    else:
      g.username = ''
      g.token = ''

    return func()

  return checkToken

def checkShop(func):
  @wraps(func)
  def checkshopToken():
    token = request.cookies.get('ezjwt')
    decoded = jwt.decode(token, app.config['SECRET_KEY'], algorithms='HS256')
    id = decoded.get('id')
    existingUser = Shop.query.filter_by(id=id).first()

    if existingUser:
      g.name = existingUser.name
      g.token = decoded
      g.id = existingUser.id
    else:
      g.username = ''
      g.token = ''
      return redirect(url_for('login'))

    return func()

  return checkshopToken


#!/usr/bin/env python
from flask import Flask, render_template, Response
import OmniCam as camera
import threading as thread

app = Flask(__name__)
cam = camera.Camera(0)

t = threading.Thread(target=cam.start_recording)
t.start()

@app.route('/')
def index():
    return render_template('index.html')

def gen(camera):
    while True:
        frame = cam.get_jpeg()
        yield (b'--frame\r\n'
               b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route('/login', methods=['POST'])
def login():
    if request.method == 'POST' and request.form['username'] == 'admin' and request.form['passowrd'] == 'password':
        return render_template('camerapage.html')

@app.route('/video_feed')
def video_feed():
    return Response(gen(Camera()),
                    mimetype='multipart/x-mixed-replace; boundary=frame')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)


import numpy as np
from openpyxl import Workbook
def toExcel(arrayStr, yKey, xKey, excelStore):
	wb = Workbook()
	ws = wb.active
	ws.append(["NUMBER", "CONTENT"])
	for i in range(len(arrayStr)):
		if(i == xKey):
			continue
		for j in range(len(arrayStr[0])):
			if(j == yKey or len(arrayStr[i][j]) == 0):
				continue

			if(len(arrayStr[xKey][j]) == 0 and len(arrayStr[i][yKey]) == 0):
				ws.append(["--", arrayStr[i][j]])
			elif(len(arrayStr[xKey][j]) == 0):
				ws.append(["-"+arrayStr[i][yKey], arrayStr[i][j]])
			elif(len(arrayStr[i][yKey]) == 0):
				ws.append([arrayStr[xKey][j]+arrayStr[i][yKey], arrayStr[i][j]])
			else:
				ws.append([arrayStr[xKey][j]+arrayStr[i][yKey], arrayStr[i][j]])
	wb.save(excelStore)
def toExcel2(arrayStr, excelStore):
	wb = Workbook()
	ws = wb.active
	for i, line in enumerate(arrayStr):
		for j, value in enumerate(line):
			ws.cell(row=i+1, column=j+1).value = value
	# print("./"+excelStore)
	wb.save(excelStore)


from django.shortcuts import get_object_or_404
from rest_framework import viewsets
from rest_framework.response import Response

from .serializers import QuestionSerializer, AnswerSerializer
from game.models import Question, Answer
from rest_framework.permissions import AllowAny

class QuestionViewSet(viewsets.ModelViewSet):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer

    # def list(self, request):
    #
    #     print(queryset)
    #     serializer = AnswerSerializer(queryset)
    #     return Response(serializer.data)

    def retrieve(self, request, pk=None):

        queryset = Question.objects.get(pk=pk).answers.all()
        print(queryset)
        question_text = Question.objects.get(pk=pk)
        serializer = QuestionSerializer(question_text)
        return Response({'question': serializer.data, 'answers': queryset.values()})

    def get_permissions(self):
        if self.request.method == 'POST':
            self.permission_classes = (AllowAny,)

        return super(QuestionViewSet, self).get_permissions()

class AnswerViewSet(viewsets.ModelViewSet):
    queryset = Answer.objects.all()
    serializer_class = AnswerSerializer

    def get_permissions(self):
        if self.request.method == 'POST':
            self.permission_classes = (AllowAny,)

        return super(AnswerViewSet, self).get_permissions()


# https://www.acmicpc.net/problem/7576
import sys
from collections import deque

sys.stdin = open('input.txt','r')
input = sys.stdin.readline
M, N = map(int, input().split())
matrix, queue = [], deque()
visited = [[0]*M for _ in range(N)]
for r in range(N):
    line = tuple(input().split())
    matrix.append(line)
    if '1' in line or '-1' in line:
        for c in range(M):
            if line[c] == '1':
                queue.append((r,c))
                visited[r][c] = 1
            elif line[c] == '-1':
                visited[r][c] = 1
while queue:
    r, c = queue.popleft()
    for dx, dy in ((1,0),(0,1),(-1,0),(0,-1)):
        if 0 <= r+dx < N and 0 <= c+dy < M and\
        not visited[r+dx][c+dy] and matrix[r+dx][c+dy] == '0':
            visited[r+dx][c+dy] += visited[r][c] + 1
            queue.append((r+dx, c+dy))
def solve():
    answer = 0
    for r in range(N):
        for c in range(M):
            if visited[r][c] == 0: return -1
            else:
                answer = max(visited[r][c], answer)
    return answer-1
print(solve())