from __future__ import annotations

import enum
from math import log
from typing import Final, Optional, Tuple

from numpy.random import randint

from .running.config import config
from .universal import SimulatedObject

class Resource(SimulatedObject):
    """Subclass of SimulatedObject:
        Inanimated objects used as resources by entities

    Attributes:
        quantity (int): collectible amount
    """
    DEFAULTY_EXPIRY: Final[int] = config['Simulation']['Resource']['expiry_date']
    def __init__(self,
                 resource_id: int,
                 position: Tuple[int, int],
                 appearance: str = "",
                 quantity: int = 0,
                 expiry: int = DEFAULTY_EXPIRY,
                 owner_id: Optional[int] = None,
                 size: Optional[int] = None,
                 ):
        """Super constructor:
            Get the necessary information for a resource

        Args:
            resource_id (int):          unique identifier
            position (Tuple[int, int]): coordinates in the world
            appearance (str, optional): path to the image file. Defaults to "".
            quantity (int, optional):   collectible amount. Defaults to 0.
        """

        self.quantity: int = quantity or randint(10,100) # collectible amount of resources
        size: int = size or int(1 + log(quantity, 2))
        self.age: int = 0
        self.expiry: int = expiry

        self.owner: Optional[int] = owner_id # unique identifier of owner

        appearance = "models/resources/" + appearance
        super().__init__(sim_obj_id=resource_id,
                         position=position,
                         size=size,
                         appearance=appearance)

    def update(self, environment) -> None:
        """Public method:
            Increase the life time of 1 cycle,
            remove if reached expiry date

        Args:
            environment (Environment): energy's environment
        """
        self.age += 1
        if self.age >= self.expiry:
            environment.remove_resource(resource=self)

class EnergyType(enum.Enum):
    """Enum:
        Type of energy, BLUE or RED
    """
    BLUE = "blue energy"
    RED = "red energy"

class Energy(Resource):
    """Subclass of Resource:
        Super class for energies

    Attributes:
        type (EnergyType):  BLUE or RED
        owner_id (int):     unique identifier of owner
    """
    def __init__(self,
                 energy_id: int,
                 energy_type: EnergyType,
                 position: Tuple[int,int],
                 quantity: int = 10,
                 appearance: str = "",
                 owner_id: Optional[int] = None,
                 expiry: int = Resource.DEFAULTY_EXPIRY,
                 tree_planter: Optional[int] = None
                 ):
        """Super constructor:
            Get the necessary information for an energy

        Args:
            energy_id (int):                    unique identifier
            energy_type (EnergyType):           BLUE or RED
            position (Tuple[int,int]):          coordinates in the world
            quantity (int, optional):           collectible amount. Defaults to 10.
            appearance (str, optional):         path to image file. Defaults to "".
            owner_id (Optional[int], optional): unique identifier of owner. Defaults to 0.
        """

        appearance = "energies/" + appearance
        super().__init__(resource_id=energy_id,
                         position=position,
                         appearance=appearance,
                         quantity=quantity,
                         expiry=expiry,
                         owner_id=owner_id)

        self._type: EnergyType = energy_type    # BLUE or RED
        self.tree_planter: int = tree_planter   # Planter id from which the energy comes from

    def __repr__(self) -> str:
        return f'{self._type.value.title()} {self.id}: {self.quantity}'

    @property
    def type(self) -> EnergyType:
        """Property:
            Return the type of Energy

        Returns:
            EnergyType: type of Energy
        """
        return self._type

class RedEnergy(Energy):
    """Subclass of Energy:
        Energy for complex actions, used to prosper
    """
    def __init__(self,
                 position: Tuple[int,int],
                 energy_id: int = 0,
                 quantity: int = 10,
                 owner_id: Optional[int] = 0,
                 expiry: int = Resource.DEFAULTY_EXPIRY,
                 tree_planter: Optional[int] = None):
        """Constructor:
            Create a red energy

        Args:
            position (Tuple[int,int]):          coordinates in the world
            energy_id (int, optional):          unique identifier. Defaults to 0.
            quantity (int, optional):           collectible amount. Defaults to 10.
            owner_id (Optional[int], optional): unique identifier of the owner. Defaults to 0.
        """

        super().__init__(energy_id=energy_id,
                         position=position,
                         quantity=quantity,
                         appearance="red_energy.png",
                         energy_type=EnergyType.RED,
                         owner_id=owner_id,
                         expiry=expiry,
                         tree_planter=tree_planter)

class BlueEnergy(Energy):
    """Subclass of Energy:
        Energy for simple actions, used to survive
    """
    def __init__(self,
                 position: Tuple[int,int],
                 energy_id: int = 0,
                 quantity: int = 10,
                 owner_id: Optional[int] = 0,
                 expiry: int = Resource.DEFAULTY_EXPIRY,
                 tree_planter: Optional[int] = None,
                 ):
        """Constructor:
            Create a blue energy

        Args:
            position (Tuple[int,int]):          coordinates in the world
            energy_id (int, optional):          unique identifier. Defaults to 0.
            quantity (int, optional):           collectible amount. Defaults to 10.
            owner_id (Optional[int], optional): unique identifier of the owner. Defaults to 0.
        """

        super().__init__(energy_id=energy_id,
                         position=position,
                         quantity=quantity,
                         appearance="blue_energy.png",
                         energy_type=EnergyType.BLUE,
                         owner_id=owner_id,
                         expiry=expiry,
                         tree_planter=tree_planter)


def capture_stderr():
    """This ``Context Manager`` redirects STDERR to a ``StringIO`` objects
    which is returned from the ``Context``.  On exit STDERR is restored.

    Example:

    .. code-block:: python

        with capture_stderr() as capture:
            print('foo')

        # got here? => capture.getvalue() will now have "foo\\n"
    """
    stderr = sys.stderr
    try:
        capture_out = StringIO()
        sys.stderr = capture_out
        yield capture_out
    finally:
        sys.stderr = stderr


from django.shortcuts import render
from django.http import JsonResponse
from ..models import Type, Category

def getTypeByCategory(request):
    category_id = request.GET['category_id']
    category = Category.objects.get(pk=category_id)
    types = Type.objects.filter(category=category)
    res = []

    for t in types:
        res.append((t.id, t.name))
    return JsonResponse({'types': res})


#meine Notizen für die Funktionen siehe Zeile 3
#clinically_nonfunctioning():
    #had_hormonactive (in OP) = 0 OR
    #had_hormonactive (in hist) = 0 OR
    #'hormoninaktiv' in comment
    #Frage an Dr. Lindner: welche Grenzwerte im Labor gelten zur Unterscheidung hormonaktiv / hormoninaktiv?
    #Prolaktin: Frau vor Menopause: ca. 400mU/L
    #           Frau nach Menopause und Mann: ca. 600mU/L
    #Cortisol: max. ca 620nmol/L
    #TSH: zwischen 0,40 und 4,0 mU/l
    #freies T4: zwischen 7 und 14,8 ng/l
    #IGF-1: 70-290ng/ml
    #GH: 0-8 ng/ml
    #Testosteron: Männer: 3,5–11,5 ng/ml (12–40 nmol/l)
    #             Frauen: 0,15–0,6 ng/ml (0,5–2,0 nmol/l)
    #LH: Männer: 1,7 - 8,6 U/l
    #    Frauen: zyklisch schwankend
    #FSH: Männer: 2 bis 10 IU/ml
    #     Frauen: zyklisch schwankend

        #MAKROADENOM:
        #imaging_size_kk  >= 10 OR
        #imaging_size_ll  >= 10 OR
        #imaging_size_ap  >= 10 OR
        # imaging_micro_or_macro  = 1 OR
        #'Makroadenom' in comment

                #KLINISCHE AUFFÄLLIGKEITEN:
                #'Oligo/Amenorrhoe/Libidoverlust', 'Galaktorrhoe',
                #'Augenmuskelparesen', 'Diabetes insipidus', 'Neuropathie', 'Osteoporose',
                #'Potenzverlust', 'Rhinoliquorrhoe', 'Sehstörungen' in clinic_abnormalities    OR

                #BILDGEBENDE AUFFÄLLIGKEITEN:
                #'Verschiebung Chiasma optikum', 'Ummantelung ACI', 'suprasellär',
                #'parasellär', 'Infiltration S. cavernosus' in imaging_local                    OR

                #OPHTHALMOLOGIE:
                #has_chiasmasyndrom == 1

                    #--> OP

                #KLINISCH UNAUFFÄLLIG:

                    #--> wait and scan

        #MIKROADENOM:
        # imaging_micro_or_macro  = 2
        #imaging_size_kk  <= 10 OR
        #imaging_size_ll  <= 10 OR
        #imaging_size_ap  <= 10 OR
        #'Mikroadenom' in comment

            #--> wait and scan

#clinically_functioning():
    #had_hormonactive (in OP) = 1 OR
    #had_hormonacive (in hist) = 1 OR
    #'produzierend' in comment
    #'Akrenwachstum','Stammfettsucht', 'Striae rubra' in clinic_abnormalities

        #PROLAKTINOM
        #'Prolaktinom','prolaktin',  in comment
        #adenom_classification == "Adenom ja - Prolaktinom"
        #labor_prolactine_mug_l >= 94 (alternativ 35, 50, ...?)

            #--> kausal medikamentös

        #ANDERER HORMONPRODUZIERENDER TUMOR
        #Else:

            #--> OP  m

def hormonaktivität(op_had_hormonactive, patient_comment, clinic_abnormalities):

    if(
        op_had_hormonactive==0 or
        'hormoninaktiv' in patient_comment):

            return "nonfunctioning adenoma"

    elif(
        op_had_hormonactive==1 or
        'produzierend' in patient_comment or
        'Akrenwachstum','Stammfettsucht', 'Striae rubra' in clinic_abnormalities):

            return 'functioning adenoma'

    else:
        return 'keine Vorhersage möglich'

def mikro_makro(imaging_size_kk, imaging_size_ll, imaging_size_ap, imaging_micro_or_macro, patient_comment):

    if(
        imaging_size_kk  >= 10 or
        imaging_size_ll  >= 10 or
        imaging_size_ap  >= 10 or
        imaging_micro_or_macro == 1 or
        'Makroadenom' in patient_comment):

           return "macroadenoma"

    elif (imaging_size_kk  <= 10 and
        imaging_size_ll  <= 10 and
        imaging_size_ap  <= 10 or
        'Mikroadenom' in patient_comment or
        imaging_micro_or_macro == 2):

           return "microadenoma"

    else:
        return 'keine Vorhersage möglich'

def hormon_type(labor_prolactine_mug_l, adenom_classification, patient_comment):

    if(
        'Prolaktinom' or 'prolaktin' in patient_comment or
        adenom_classification == "Adenom ja - Prolaktinom" or
        labor_prolactine_mug_l >= 94):

           return "prolactinoma"

    else:
           return "other hyperfunctioning adenoma"

def mass_symptoms(clinic_abnormalities, imaging_local, ophthalmology_has_chiasma_syndrome):

    if(
        'Oligo/Amenorrhoe/Libidoverlust' or 'Galaktorrhoe' or
        'Augenmuskelparesen' or 'Diabetes insipidus' or 'Neuropathie' or 'Osteoporose' or
        'Potenzverlust' or 'Rhinoliquorrhoe' or 'Sehstörungen' in clinic_abnormalities or

        'Verschiebung Chiasma optikum' or 'Ummantelung ACI' or 'suprasellär' or
        'parasellär' or 'Infiltration S. cavernosus' in imaging_local or

        ophthalmology_has_chiasma_syndrome == 1):

           return "symptomatic mass effects"

    else:
           return "not symptomatic"

# =============================================================================
# # Vorschlag von Daniel
# # diese Funktion spiegelt den eigentlichen Entscheidungsbaum wider.
#
# def apply_guideline(patient_data: pd.Series):
#     hormonactive = hormonaktivität(
#         op_had_hormonactive=patient_data[''],
#         had_hormonactive_hist=...,
#         patient_comment=...,
#         clinic_abnormalities=...
#     )
#     if hormonactive == '':
#         micro_macro = mikro_makro(
#             imaging_size_kk=...,
#             imaging_size_ll=...,
#             imaging_size_ap=...,
#             imaging_micro_or_macro=...,
#             patient_comment=...
#         )
#     else:
#         ...
#
#     return therapy
# =============================================================================

def main():                     # das ist die Hauptfunktion, die nur auf alles andere zurückgreift

    # load dataframe
    # aggregate data
    for patient in data.iterrows():
        therapy = apply_guideline(patient)
        print(patient.name, therapy)

if __name__ == '__main__':      # per Definition wird so bei Start des Programms zuerst dieser Teil ausgeführt
    main()


def post_cleanup(self):
        """\
        remove any divs that looks like non-content,
        clusters of links, or paras with no gusto
        """
        parse_tags = ['p']
        if self.config.parse_lists:
            parse_tags.extend(['ul', 'ol'])
        if self.config.parse_headers:
            parse_tags.extend(['h1', 'h2', 'h3', 'h4', 'h5', 'h6'])

        target_node = self.article.top_node
        node = self.add_siblings(target_node)
        for elm in self.parser.getChildren(node):
            e_tag = self.parser.getTag(elm)
            if e_tag not in parse_tags:
                if (self.is_highlink_density(elm) or self.is_table_and_no_para_exist(elm) or
                        not self.is_nodescore_threshold_met(node, elm)):
                    self.parser.remove(elm)
        return node


# redis docker build: https://www.runoob.com/docker/docker-install-redis.html
import redis
import json
import os

def createRedisClient(host, port):
    try:
        redisClient = redis.Redis(host=host, port=port)
        pingTest = redisClient.ping()

        if (pingTest == True):
            print("Connected To Redis!")
            return redisClient
        else:
            print("Could not connect to Redis!")
    except Exception as ex:
        print("Could not connect to redis! See Message Below")
        print(ex)
    return False

# cache flow:
# try to get redis cache data
# acquire a lock for data
# try again to get redis cache data
# if not found, use DB
# release lock

# cache flow is used to prevent simultaneously acquire a data

# get cache by transform string back to object

def getRedisValueByKey(key: str):
    output = redisClient.get(key)
    if output == None:
        with redisClient.lock('lock_' + key):
            output = redisClient.get(key)

    if output != None:
        output = json.loads(output)

    return output

# cache object with jsonify string

def setRedisKeyAndValue(key: str, value):
    value = json.dumps(value)
    output = redisClient.set(key, value)
    redisClient.expire(key, 180) # set 3 min data expiration time
    return output

redisClient = createRedisClient('localhost', 6379) if os.getenv("FROM") == 'LOCAL' else createRedisClient('redis', 6379)


# Problem
# =====================================================================================================================
# Given a string s and an integer array indices of the same length.
#
# The string s will be shuffled such that the character at the ith position moves to indices[i] in the shuffled string.
#
# Return the shuffled string.
#
#
#
# Example 1:
#
#
# Input: s = "codeleet", indices = [4,5,6,7,0,2,1,3]
# Output: "leetcode"
# Explanation: As shown, "codeleet" becomes "leetcode" after shuffling.
# Example 2:
#
# Input: s = "abc", indices = [0,1,2]
# Output: "abc"
# Explanation: After shuffling, each character remains in its position.
# Example 3:
#
# Input: s = "aiohn", indices = [3,1,4,2,0]
# Output: "nihao"
# Example 4:
#
# Input: s = "aaiougrt", indices = [4,0,2,6,7,3,1,5]
# Output: "arigatou"
# Example 5:
#
# Input: s = "art", indices = [1,0,2]
# Output: "rat"
#
#
# Constraints:
#
# s.length == indices.length == n
# 1 <= n <= 100
# s contains only lower-case English letters.
# 0 <= indices[i] < n
# All values of indices are unique (i.e. indices is a permutation of the integers from 0 to n - 1).

# Solution
# ====================================================================================================================
# Solution ~ 52 ms
class Solution:
    def restoreString(self, s, indices):
        word_len = len(s)
        result = []
        final_word = ""
        for i in range(word_len):
            result.append([])

        for i in range(word_len):
            result[indices[i]] = s[i]

        for letter in result:
            final_word += letter

        return final_word

# Solution v2 ~ 48 ms: Using List comprehension and .join function
class Solution:
    def restoreString(self, s: str, indices: List[int]) -> str:
        word_len = len(s)
        result = [[] for x in range(word_len)]

        for i in range(word_len):
            result[indices[i]] = s[i]

        return "".join(result)

# Input
# =====================================================================================================================
obj = Solution()
print(obj.restoreString("codeleet", [4, 5, 6, 7, 0, 2, 1, 3]))


"""A script that contains the class that calculates the IDs that define con."""

import numpy as np

class ConnectionNodes:
    """A class for the calculation of the connection nodes."""

    def __init__(self, parameters, x_y_z, n_spars, n_stringers):

        # Initialize matrices for LE and TE storing
        self.LE_IDs = np.zeros((3, parameters.N_ribs, 1))
        self.TE_IDs_u = np.zeros((3, parameters.N_ribs, 1))
        self.TE_IDs_l = np.zeros((3, parameters.N_ribs, 1))

        # Define their values
        self.calculate_le_te_ids(parameters)
        # Put the other node ids in the curve arrays
        self.put_in_arrays(parameters, x_y_z, n_spars, n_stringers)
        # Insert the TE and LE ids to curve arrays
        self.insert_le_te(n_spars, n_stringers, parameters.N_ribs)

    def put_in_arrays(self, parameters, x_y_z, n_spars, n_stringers):
        # Insert them to the arrays
        self.Curve_IDs_Upper =\
            np.zeros((3, parameters.N_ribs,
                      3 * n_spars + n_stringers))
        self.Curve_IDs_Lower =\
            np.zeros((3, parameters.N_ribs,
                      3 * n_spars + n_stringers))

        for i in range(0, parameters.N_ribs):
            for k in range(0, 3):
                self.Curve_IDs_Upper[k, i, :] =\
                    - np.sort(- np.concatenate((
                        x_y_z.Spar_ID_Upper[k, i, :],
                        x_y_z.Spar_Cap_ID_Upper_Left[k, i, :],
                        x_y_z.Spar_Cap_ID_Upper_Right[k, i, :],
                        x_y_z.stringer_id_upper[k, i, :]
                        )))
                self.Curve_IDs_Lower[k, i, :] =\
                    np.sort(np.concatenate((
                        x_y_z.Spar_ID_Lower[k, i, :],
                        x_y_z.Spar_Cap_ID_Lower_Left[k, i, :],
                        x_y_z.Spar_Cap_ID_Lower_Right[k, i, :],
                        x_y_z.stringer_id_lower[k, i, :]
                        )))
        self.Curve_IDs_Upper = self.Curve_IDs_Upper.astype(int)
        self.Curve_IDs_Lower = self.Curve_IDs_Lower.astype(int)

    def calculate_le_te_ids(self, parameters):

        for i in range(0, parameters.N_ribs):
            for k in range(0, 3):
                self.LE_IDs[k, i, 0] = ((2 * i + 1) * parameters.n) + parameters.N_ribs * 240 * k
                self.TE_IDs_u[k, i, 0] = ((2 * i) * parameters.n + 1) + parameters.N_ribs * 240 * k
                self.TE_IDs_l[k, i, 0] = ((2 * i + 2) * parameters.n) + parameters.N_ribs * 240 * k

    def insert_le_te(self, n_spars, n_stringers, n_ribs):
        Curve_IDs_Upper_all =np.zeros((3, n_ribs, 3 * n_spars + n_stringers + 2))
        Curve_IDs_Lower_all =np.zeros((3, n_ribs, 3 * n_spars + n_stringers + 2))

        for k in range(0, 3):
            Curve_IDs_Upper =\
                np.insert(self.Curve_IDs_Upper[k, :, :],
                          3 * n_spars + n_stringers, self.TE_IDs_u[k, :, 0], axis=1)
            Curve_IDs_Upper =\
                np.insert(Curve_IDs_Upper, 0, self.LE_IDs[k, :, 0], axis=1)

            Curve_IDs_Lower =\
                np.insert(self.Curve_IDs_Lower[k, :, :],
                          3 * n_spars + n_stringers, self.TE_IDs_l[k, :, 0], axis=1)
            Curve_IDs_Lower =\
                np.insert(Curve_IDs_Lower, 0, self.LE_IDs[k, :, 0], axis=1)

            Curve_IDs_Upper_all[k, :, :] = Curve_IDs_Upper
            Curve_IDs_Lower_all[k, :, :] = Curve_IDs_Lower

        # Make them integers
        self.Curve_IDs_Upper = Curve_IDs_Upper_all.astype(int)
        self.Curve_IDs_Lower = Curve_IDs_Lower_all.astype(int)


def ohlcDF(symbol, token='', version=''):
    '''Returns the official open and close for a give symbol.

    https://iexcloud.io/docs/api/#news
    9:30am-5pm ET Mon-Fri

    Args:
        symbol (string); Ticker to request
        token (string); Access token
        version (string); API version

    Returns:
        DataFrame: result
    '''
    o = ohlc(symbol, token, version)
    if o:
        df = pd.io.json.json_normalize(o)
        _toDatetime(df)
    else:
        df = pd.DataFrame()
    return df


'''
  @ Date: 2022-09-20 20:55:05
  @ Author: Qing Shuai
  @ Mail: s_q@zju.edu.cn
  @ LastEditors: Qing Shuai
  @ LastEditTime: 2022-09-21 12:03:47
  @ FilePath: /EasyMocapPublic/easymocap/blender/read_smpl.py
'''
import os
import json
import numpy as np
from os.path import join

def read_json(path):
    with open(path) as f:
        data = json.load(f)
    return data

def read_smpl(outname):
    assert os.path.exists(outname), outname
    datas = read_json(outname)
    outputs = []
    if isinstance(datas, dict):
        datas = datas['annots']
    for data in datas:
        for key in ['Rh', 'Th', 'poses', 'shapes']:
            data[key] = np.array(data[key])
        outputs.append(data)
    return outputs

def merge_params(param_list, share_shape=True):
    output = {}
    for key in ['poses', 'shapes', 'Rh', 'Th', 'expression']:
        if key in param_list[0].keys():
            output[key] = np.vstack([v[key] for v in param_list])
    if share_shape:
        output['shapes'] = output['shapes'].mean(axis=0, keepdims=True)
    return output

def load_smpl_params(path):
    from glob import glob
    filenames = sorted(glob(join(path, '*.json')))
    motions = {}
    for filename in filenames:
        infos = read_smpl(filename)
        for data in infos:
            pid = data['id']
            if pid not in motions.keys():
                motions[pid] = []
            motions[pid].append(data)
    keys = list(motions.keys())
    # BUG: not strictly equal: (Rh, Th, poses) != (Th, (Rh, poses))
    for pid in motions.keys():
        motions[pid] = merge_params(motions[pid])
        if motions[pid]['poses'].shape[1] == 69:
            motions[pid]['poses'] = np.hstack([np.zeros((motions[pid]['poses'].shape[0], 3)), motions[pid]['poses']])
        # motions[pid]['poses'][:, :3] = motions[pid]['Rh']
        # motions[pid]['poses'][:, :3] = 0
    return motions


import logging

from django.conf import settings

class LoggingMiddleware(object):
    """
    Middleware para gerar um log completo da api
    """
    _initial_http_body = None

    def __init__(self, get_response):
        self.get_response = get_response
        self.response = None
        # One-time configuration and initialization.

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        response = self.get_response(request)

        self.go_log(request, response)

        self.response = response

        # Code to be executed for each request/response after
        # the view is called.

        return response

    def process_request(self, request):
        self._initial_http_body = request.body

    def go_log(self, request, response):
        """
        Adicionando log de request e response
        """
        if request.path.startswith('/feiras/') and \
            (request.method == "POST" and
                request.META.get('CONTENT_TYPE') == 'application/json' or
                request.method == "GET"):

            settings.REQUEST_LOGGER.log(
                logging.DEBUG,
                "GET: {}. body: {} response code: {}. "
                "response "
                "content: {}".format(
                    request.GET,
                    self._initial_http_body,
                    response.status_code,
                    response.content),
                extra={'tags': {'url': request.build_absolute_uri()}})
        return response


from django.urls import path
from todo import views

urlpatterns = [
    path('add-todo/', views.add_todo, name='add-todo'),
    path('all-todos/', views.show_all_todos, name='show-all-todos'),
    path('edit-todo/<todo_id>/', views.edit_todo, name='edit-todo'),
    path('delete-todo/<todo_id>/', views.delete_todo, name='delete-todo'),
    path('',views.home , name='home'),
]


#!/usr/bin/python
# 给你一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c
# 使得 a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组

def threeSum(nums: list):
    res = []
    n = len(nums)
    nums.sort()
    for i in range(n):
        if nums[i] > 0:
            return res
        if i > 0 and nums[i] == nums[i - 1]:
            continue

        j = i + 1
        k = n - 1

        while j < k:
            sum = nums[i] + nums[j] + nums[k]
            if sum > 0:
                k -= 1
            elif sum < 0:
                j += 1
            else:
                res.append([nums[i], nums[j], nums[k]])
                j += 1
                k -= 1
                while j < k and nums[j] == nums[j - 1]:
                    j += 1
                while j < k and nums[k] == nums[k + 1]:
                    k -= 1
    return res

def main():
    nums = [-1, 0, 1, 2, -1, -4]
    print(threeSum(nums))

if __name__ == '__main__':
    main()


import os

import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import Formatter, LogFormatter

import utils.utils as utilities

class ConciseScientificNotationFormatter(Formatter):
    def __call__(self, x, pos=None):
        # if exponent is 0, don't bother with scientific notation
        if 1 <= x < 10:
            return str(x).rstrip('0').rstrip('.')
        else:
            # get python's string formatter version of scientific notation
            verbose = '%E' % x

            # strip off trailing zeros that might be on the mantissa, and if it's an integer, the decimal point too
            mantissa = verbose.split('E')[0]
            mantissa = mantissa.rstrip('0').rstrip('.')

            # omit the exponent's sign if it's positive and strip leading zeros off
            exponent = verbose.split('E')[1]
            exponent_sign = '-' if '-' in exponent else ''
            exponent = exponent[1:].lstrip('0')
            return mantissa + 'e' + exponent_sign + exponent

def loss_rank_overlay(loss, rank, left_ax, title, correlation, font_size=18):
    correlation_message = "correlation = {0}".format(np.round(correlation, 2))
    color1 = [c / 255 for c in (20, 46, 120)]
    color2 = [c / 255 for c in (255, 87, 20)]

    l1 = left_ax.plot(loss, color=color1, label='loss')
    left_ax.set_title(title, fontsize=font_size)
    left_ax.set_yscale('log', basey=10)
    left_ax.set_ylabel("loss", color=color1, fontsize=font_size)
    left_ax.set_ylim(top=1)
    left_ax.tick_params('y', colors=color1, which='both', labelsize=font_size)
    left_ax.tick_params('x', labelsize=font_size)

    left_ax.text(.5, .85, correlation_message, bbox=dict(facecolor='black', alpha=0.2), horizontalalignment='center',
                 fontsize=font_size, transform=left_ax.transAxes)
    left_ax.yaxis.set_major_formatter(LogFormatter())
    left_ax.yaxis.set_minor_formatter(LogFormatter())
    left_ax.minorticks_off()

    right_ax = left_ax.twinx()
    l2 = right_ax.plot(rank, color=color2, label='rank', linestyle='dashed')
    right_ax.set_yscale('log', basey=10)
    right_ax.set_ylabel("rank", color=color2, fontsize=font_size)
    right_ax.tick_params('y', colors=color2, which='both', labelsize=font_size)
    right_ax.yaxis.set_major_formatter(LogFormatter())
    right_ax.yaxis.set_minor_formatter(LogFormatter())
    # right_ax.minorticks_off()
    right_ax.set_ylim(bottom=1)

    left_ax.legend(l1 + l2, [l.get_label() for l in (l1 + l2)], loc=1, fontsize=font_size)

def mean_rank_per_epoch(train, val, n_categories, ax, title="Mean Rank vs. Epoch", xlabel='epoch'):
    ax.plot(train, color='blue', label='training')
    ax.plot(val, color='orange', label='validation', linestyle='dotted')
    if n_categories:
        ax.axhline(y=n_categories / 2, linestyle='dashed', color='magenta', label='random chance')

    ax.set_ylabel("Mean Rank")
    ax.set_xlabel(xlabel)

    ax.set_ylim(0, n_categories)

    ax.set_title(title)

    ax.legend()

def mrr_per_epoch(train, val, ax, title="MRR vs. Epoch", xlabel='epoch', n_categories=None):
    ax.plot(train, color='blue', label='training')
    ax.plot(val, color='orange', label='validation', linestyle='dotted')
    if n_categories:
        ax.axhline(y=mrr_random_chance(n_categories), linestyle='dashed', color='magenta', label='random chance')

    ax.set_ylabel("MRR")
    ax.set_xlabel(xlabel)
    ax.set_ylim(0, 1)

    ax.set_title(title)

    ax.legend()

def loss_per_epoch(train, val, ax, title="Loss vs. Epoch", log=True):
    ax.plot(train, color='blue', label='training')
    ax.plot(val, color='orange', label='validation', linestyle='dotted')

    ax.set_ylabel("loss")
    ax.set_xlabel("epoch")

    if log:
        ax.set_yscale('log', basey=10)
        title += " (Log)"
    else:
        y_tick_interval = .1
        y_max = max(2, max(train) + .5, max(val) + .5)
        ax.set_yticks(np.arange(0, y_max + y_tick_interval, y_tick_interval))
        ax.set_ylim(0, y_max)

    ax.set_title(title)

    ax.legend()

def accuracy_per_epoch(train, val, ax, title="Accuracy vs. Epoch"):
    ax.plot(train, color='blue', label='training')
    ax.plot(val, color='orange', label='validation', linestyle='dotted')

    ax.set_ylabel("accuracy")
    ax.set_xlabel("epoch")
    ax.set_ylim(0, 1)

    ax.set_title(title)
    ax.legend()

def title_to_filename(title, suffix):
    if suffix:
        file = suffix + '_' + title
    else:
        file = title
    file = file.replace(' ', '_').replace('.', '').replace(',', '')
    file += '.png'
    file = file.lower()
    return os.path.join('./output', str(utilities.get_trial_number()), file)

def mrr_random_chance(n_categories):
    return np.mean([1 / n for n in np.random.randint(low=1, high=n_categories + 1, size=99999)])

def correlation_boxplot(directory, data, p_value):
    # Multiple box plots on one Axes
    fig, ax = plt.subplots()
    fig.set_size_inches(9.5, 6)
    d = ax.boxplot(data)
    n = len(data)
    ax.set_xticklabels(["Pairwise", "Triplet"], fontsize=18)
    ax.tick_params('y', labelsize=18)
    medians = [median.get_xydata() for median in d['medians']]
    ax.text(.5, .25, "p = {0}".format(np.round(p_value, 6)), horizontalalignment='center', transform=ax.transAxes,
            fontsize=18)
    ax.text(.5, .15, "n = {0}".format(n), horizontalalignment='center', transform=ax.transAxes, fontsize=18)
    for median in medians:
        x_right = median[1][0]
        y = median[0][1]
        ax.text(x_right + .01, y, "{0}".format(np.round(y, 2)), horizontalalignment='left', verticalalignment='center',
                fontsize=18)
    ax.set_ylim(-.25, 1)
    ax.set_title("Correlation between loss over time and rank over time", fontsize=18)
    ax.set_ylabel("Pearson's correlation coefficient", fontsize=18)
    ax.set_xlabel("Loss", fontsize=18)
    plt.savefig(os.path.join(directory, "correlation_boxplot.pdf"))
    plt.close()

def num_canonical_memorized(memorized_var, n_memorized, evaluated_epochs, num_categories):
    plt.plot(evaluated_epochs, n_memorized, color='b', label='performance')
    plt.axhline(y=num_categories, color='magenta', label='# categories')
    plt.ylabel('# of categories memorized')
    plt.xlabel('epoch')
    plt.title("# of Categories Memorized vs. Time")
    plt.savefig('n_memorized.png')
    plt.close()

    plt.plot(evaluated_epochs, memorized_var, color='b', label='variance across imitations')
    plt.ylabel("variance")
    plt.xlabel('epoch')
    plt.title("Variance across Imitations vs. Time")
    plt.savefig("variance.png")
    plt.close()


import random
import re
import sys
from time import sleep

# This list of acceptable quit responses needs to be accessible globally
quit_responses = ['quit', 'quit game']

# This quit_game() function needs to be accessible globally
def quit_game():
    print("Sorry to see you go!")
    sys.exit()

class Board:
    def __init__(self):
        # restart_game variable will be set to True if user wants to edit dim/no. of bombs during the game
        self.restart_game = False

        # Initialize dimension & number of bombs to None and we'll run set_dim_size() and set_num_bombs() at the top of
        # the restart loop so user can adjust dim/bombs without completely resetting any symbol changes
        self.dim_size = None
        self.num_bombs = None

        # Set game symbols. All symbols must be len 3 for __str__ function printing.
        # 'no surrounding bombs' is the symbol that prints when a spot is dug up but there aren't any surrounding bombs.
        # You could also just print the spot's 'bombs' value like you would for any other spot--which would be 0--but
        # you'll have to edit __str__ if you want 0 spots to print 0 instead of the 'no surrounding bombs' symbol.
        self.symbols = {'bomb': ' X ', 'undug spot': ' - ', 'no surrounding bombs': '   ', 'flag': ' • '}

        # Initialize board to None and we'll run Board.make_new_board() at the top of each game so a new board is
        # created each time.
        self.board = None

        # Initialize a set to keep track of which locations have been dug using (row, col) tuples.
        # I didn't set 'is dug' as one of the keys in each 'spot' because the game needs to be able to compare the
        # length of Board.dug to (board size - num. bombs) to check if the player has dug up all of the safe spots.
        self.dug = set()  # if we dig at 0,0, then self.dug = {(0,0)}

    def set_dim_size(self):
        print("\nWhat size square board would you like to play on? (e.g. enter '10' for a 10x10 board).")
        while True:
            dimension_input = input("> ").lower().strip()
            try:
                # Check if user wants to quit
                if dimension_input in quit_responses:
                    quit_game()

                # Otherwise, check that the input is a valid dimension size
                dim = int(dimension_input)
                if dim <= 0:  # Dim needs to be greater than 0
                    raise ValueError

                # If no errors are raised, set board dim_size dim
                self.dim_size = dim
                break

            except ValueError:
                print("Please enter an integer that is greater than 0 and less than 1000.")

    def set_num_bombs(self):
        # Level suggestions: Easy: 10-15% of the board is bombs, Med: 15-25%, Hard: 25-35%
        print(f"\nHow many bombs would you like to have on your board?"
              f"\n  For an easy game, I'd suggest: "
              f"{(self.dim_size ** 2) * 1 // 10} - {(self.dim_size ** 2) * 15 // 100} bombs."
              f"\n  For a medium game, I'd suggest: "
              f"{((self.dim_size ** 2) * 15 // 100) + 1} - {(self.dim_size ** 2) * 25 // 100} bombs."
              f"\n  For a hard game, I'd suggest: "
              f"{((self.dim_size ** 2) * 25 // 100) + 1} - {(self.dim_size ** 2) * 35 // 100} bombs.")
        while True:
            bombs_input = input("> ").lower().strip()
            try:
                # Check if user wants to quit
                if bombs_input in quit_responses:
                    quit_game()

                # Otherwise, check that bomb input is a valid integer
                bombs = int(bombs_input)
                if bombs <= 0 or bombs >= self.dim_size ** 2:
                    raise ValueError

                # If no errors are raised, return the number of bombs
                self.num_bombs = bombs
                break

            except ValueError:
                print(f"Please enter an integer that is greater than 0 but less than {self.dim_size ** 2}.")

    # Call this function at the start of each game to create a new board
    def make_new_board(self):
        # Construct a new board based on the dim size & num bombs.
        # We should construct a list of lists here (or whatever representation you prefer, but since we have a 2D
        # board, list of lists is more natural).

        # Each element in the innermost list (so, each 'spot') is a 3-element dictionary where 'is bomb' tracks whether
        # the spot is a bomb, 'surrounding bombs' holds the number of surrounding bombs (if spot isn't a bomb), and
        # 'flagged' tracks whether the spot has been flagged or not.
        board = [[{'is bomb': False, 'surrounding bombs': None,
                   'flagged': False} for i in range(self.dim_size)] for j in range(self.dim_size)]

        # Plant bombs
        bombs_planted = 0
        while bombs_planted < self.num_bombs:
            spot = random.randint(0, self.dim_size ** 2 - 1)
            row = spot // self.dim_size
            col = spot % self.dim_size

            if board[row][col]['is bomb']:
                continue
            board[row][col]['is bomb'] = True
            bombs_planted += 1

        # Assign the created board to self.board
        self.board = board
        # Now assign values to each spot on the board
        self.assign_values_to_board()

    # Helper for make_new_board to assign values to each spot (values 0-8 for bombs, nothing if spot['is_bomb'] == True)
    def assign_values_to_board(self):

        # Go through each spot on the board
        for r in range(self.dim_size):
            for c in range(self.dim_size):

                # If spot contains a bomb, don't waste time assigning it a 'surrounding bombs' value
                if self.board[r][c]['is bomb']:
                    continue

                # Otherwise, assign the value of the num of surrounding bombs
                self.board[r][c]['surrounding bombs'] = self.get_num_surrounding_bombs(r, c)

    # Helper for assign_value_to_board that counts the number of bombs surrounding a specific spot
    def get_num_surrounding_bombs(self, row, col):
        # Initialize counter for number of bombs
        bomb_count = 0

        # For each of the 8 squares around that spot, if there's a bomb, increment counter by +1.
        # We don't want the range to go below 0 or above dim size (since range will go up to dim size - 1).
        for surrounding_row in range(max(0, row - 1), min(self.dim_size, (row + 1) + 1)):
            for surrounding_col in range(max(0, col - 1), min(self.dim_size, (col + 1) + 1)):

                # We don't want to count the spot itself--just its surrounding spots
                if surrounding_row == row and surrounding_col == col:
                    continue
                if self.board[surrounding_row][surrounding_col]['is bomb']:
                    bomb_count += 1

        return bomb_count

    def dig_spot(self, row, col):
        # First, let's add this spot to our set of dug places as a tuple
        self.dug.add((row, col))

        # Then we have 3 scenarios:
        # 1) There's a bomb where we dig => return False
        if self.board[row][col]['is bomb']:
            return False
        # 2) We dig a spot that's next to a bomb => we stop digging
        elif self.board[row][col]['surrounding bombs'] > 0:
            return True

        # 3) We dig a spot that's not next to a bomb and must keep digging.
        # To decide how to keep digging, we'll use the same pattern we used for checking for bombs;
        # however, we'll use recursion to dig up a bunch of spots since we're doing the same thing over and over
        for surrounding_row in range(max(0, row-1), min(self.dim_size, (row+1)+1)):
            for surrounding_col in range(max(0, col-1), min(self.dim_size, (col+1)+1)):
                if (surrounding_row, surrounding_col) in self.dug:  # If we hit a spot we've already dug, jump over it
                    continue
                else:
                    self.dig_spot(surrounding_row, surrounding_col)

        # At some point, the dig will finish out the for loops, and so we'll want to return True when that's all done
        return True

    def flag_spot(self, row, col):
        self.board[row][col]['flagged'] = True
        return True

    def __str__(self):
        # Let's make the board that we want the player to see!
        first_row = "   |"  # We're going to make a string of column numbers along the first row
        horizontal_line = "————"  # Make a string of dashes to underline the title column

        for c in range(self.dim_size):
            # Concat each column number + "|" divider onto the first_row string. Note that numbers may have dif lengths
            if len(str(c)) == 1:  # Center-align col numbers that are of length 1
                first_row += " " + str(c) + " |"
            elif len(str(c)) == 2:  # Left-align col numbers that are of length 2
                first_row += str(c) + " |"
            elif len(str(c)) == 3:
                first_row += str(c) + "|"

            # For each additional column, we also want to extend the horizontal line
            horizontal_line += "————"

        # Initialize the list that'll hold all of the strings that represent each row of the board
        board_values = [first_row, horizontal_line]
        # Now create a list of strings of row values for each row
        for r in range(self.dim_size):
            # Initialize string var that will hold all the values from each row in one string
            row_values = ""

            # Start each row with the row number.
            # Again, be mindful that '3' and '124' would take up diff amounts of space
            if len(str(r)) == 1:  # Center-align row numbers that are of length 1
                row_values = str(r) + "  |"
            elif len(str(r)) == 2:  # Left-align row numbers that are of length 2
                row_values = str(r) + " |"
            elif len(str(r)) == 3:
                row_values = str(r) + "|"

            # Now add the values of each spot in that row onto the row_values string
            for c in range(self.dim_size):

                # If the spot hasn't been dug yet, we don't want its value showing
                if (r, c) not in self.dug:
                    # If the spot has been flagged, we want to show the flag symbol
                    if self.board[r][c]['flagged']:
                        row_values += self.symbols['flag'] + "|"
                    else:
                        row_values += self.symbols['undug spot'] + "|"

                # elif the spot was dug and it's a bomb, show the bomb symbol
                elif self.board[r][c]['is bomb']:
                    row_values += self.symbols['bomb'] + "|"

                # elif the spot was dug and it's a 0, show the 'no surrounding bombs' symbol
                elif self.board[r][c]['surrounding bombs'] == 0:
                    row_values += self.symbols['no surrounding bombs'] + "|"

                # otherwise, the spot was dug and it's not a bomb or a 0 (it has a non-zero 'surrounding bombs' value)
                else:
                    row_values += " " + str(self.board[r][c]['surrounding bombs']) + " |"

            # Add that string of row values to the list of board values
            board_values += [row_values]

        # Put a horizontal line at the very bottom of the board for aesthetics
        board_values += [horizontal_line]

        # Since this function needs to return a string, we'll have to concatenate all of the row_values in the list
        # into one single string, using \n to break the lines
        string_board = "\n"
        for row in board_values:
            string_board += row + "\n"

        return string_board

    # --- Change Settings
    def general_settings(self):
        # Ask user what setting they want to change
        print(f"\nWhat would you like to change? You can enter something like '3' or 'Symbols' to edit game "
              f"settings, or enter 'quit' to quit the game."
              f"\n  1. Board dimensions or number of bombs "
              f"(currently a {self.dim_size}x{self.dim_size} board with {self.num_bombs} bombs)"
              f"\n  2. Symbols (e.g. bomb symbol, flag symbol, etc.)"
              f"\n  3. Exit settings menu")
        # Check input is valid
        while True:
            user_input = input("> ").lower().strip()

            # If user wants to change dimensions/bombs, just restart the game
            if user_input in ["1", "board", "dimension", "dimensions", "dim", "board dimensions", "board dim",
                              "board dims", "board dimension", "board and bombs", "dim and bombs", "dim & bombs",
                              "board & bombs", "bombs", "num", "number of bombs", "num bombs", "num of bombs"]:
                self.restart_game = True
                break
            # If they want to change symbols, move into symbol_settings()
            elif user_input in ['2', 'symbols', 'sym', 'symbol', 'syms', 'symbs', 'symb']:
                self.symbol_settings()
                break
            # If user wants to exit or quit, do so
            elif user_input in ['3', 'exit', 'exit menu', 'exit settings', 'exit settings menu']:
                break
            elif user_input in quit_responses:
                quit_game()
            else:
                print('Please enter a valid choice, such as "3" or "Symbols".')

        # Unless the user is restarting the game, print the board after settings have been adjust/after they exit so
        # that when the game loops back to asking where they want to play/if they want to dig or flag, they can easily
        # reference the board
        if not self.restart_game:
            sleep(0.5)
            print(self)

    # This function gets user's input on what symbol they want to change and what they want the new symbol to be,
    # and it checks that the input is valid and that the 'new symbol' is not already in use
    def symbol_settings(self):
        # Set exit_settings variable so the function doesn't execute change_symbol() if the user tries to exit
        exit_settings = False
        # Initialize variables to hold name of symbol that user wants to change & the new symbol that they want to use
        symbol_name, new_symbol = None, None

        print(f'\nWhat symbol would you like to change?'
              f'\n  1. Flag: "{self.symbols["flag"]}"'
              f'\n  2. Bomb: "{self.symbols["bomb"]}"'
              f'\n  3. Undug spot: "{self.symbols["undug spot"]}"'
              f'\n  4. Spot with no surrounding bombs: "{self.symbols["no surrounding bombs"]}"'
              f'\n  5. Exit settings menu')

        # Check option selection input is valid & assign symbol_name
        while True:
            user_input = input('> ').lower().strip()

            # Let user input the actual symbol to identify the symbol name, as long as
            # self.symbols[symbol].lower().strip() != '', b/c the function would accept the user accidentally pressing
            # enter.
            # So, if self.symbols[symbol].lower().strip() == '', don't include it in the list of acceptable responses.
            if user_input in ['1', 'flag', 'flag symbol',
                              self.symbols["flag"].lower().strip() if self.symbols["flag"].lower().strip() != '' else None]:
                symbol_name = 'flag'
                break
            elif user_input in ['2', 'bomb', 'bomb symbol',
                                self.symbols["bomb"].lower().strip() if self.symbols["bomb"].lower().strip() != '' else None]:
                symbol_name = 'bomb'
                break
            elif user_input in ['3', 'undug', 'undug spot', 'undug symbol', 'undug spot symbol',
                                self.symbols["undug spot"].lower().strip() if self.symbols["undug spot"].lower().strip() != '' else None]:
                symbol_name = 'undug spot'
                break
            elif user_input in ['4', 'spot with no surrounding bombs', 'no surrounding bombs', 'no bombs',
                                self.symbols["no surrounding bombs"].lower().strip() if self.symbols["no surrounding bombs"].lower().strip() != '' else None]:
                symbol_name = 'no surrounding bombs'
                break
            elif user_input in ['5', 'exit', 'exit menu', 'exit settings', 'exit settings menu']:
                exit_settings = True
                break
            elif user_input in quit_responses:
                quit_game()
            else:
                print('Please enter a valid choice, such as "1" or "Flag".')

        # If user hasn't exited settings, ask for their new symbol
        if not exit_settings:
            print(f'\nThe current "{symbol_name}" symbol is: "{self.symbols[symbol_name]}". What would you like the '
                  f'new symbol to be? The new symbol can be anywhere from 1-3 characters long.')

            # Check new symbol input is valid
            while True:
                new_symbol = input("> ")  # Don't want to lower().strip() input bc user might want to use spaces

                if new_symbol.lower().strip() in ['exit', 'exit menu', 'exit settings', 'exit settings menu']:
                    break
                elif new_symbol.lower().strip() in quit_responses:
                    quit_game()
                # The actual symbol has to be len == 3, so check that len(input) <= 3, and then convert it to len == 3
                elif len(new_symbol) == 1:  # Center-align symbols of len 1
                    new_symbol = " " + new_symbol + " "
                elif len(new_symbol) == 2:  # Left-align symbols of len 2
                    new_symbol = new_symbol + " "
                elif len(new_symbol) == 3:
                    pass
                else:
                    print(f'Please enter a new symbol to use for the {symbol_name} that is 1-3 characters long. For '
                          f'example, "F" or "~~~".')
                    continue

                # Check that the new symbol is not already in use
                if new_symbol in self.symbols.values():
                    print('That symbol is already in use. Please enter a different symbol or enter "Exit" to exit '
                          'the settings menu.')
                    continue
                else:
                    self.change_symbol(symbol_name, new_symbol)
                    print(f'\nThe {symbol_name} symbol has been changed to: "{new_symbol}"')
                    break

    # This function actually changes the symbol
    def change_symbol(self, symbol_name, new_symbol):
        self.symbols[symbol_name] = new_symbol

    # Call this function at end of each game to reset board values so they can be created anew when the next game starts
    def reset_board(self):
        self.restart_game = False
        self.board = None
        self.dug = set()

# play the game
def play():
    # Initialize game_board
    game_board = Board()

    print("\nWelcome to Minesweeper!"
          "\nInput 'quit' any time to quit the game.")

    # Create lists of responses that need to be used multiple times in this function
    settings_responses = ['settings', 'setting', 'set']

    # This loop is so that if Board.restart_game = True, the game will restart/jump back to the very top
    while True:
        # Set board dimensions & number of bombs
        game_board.set_dim_size()
        game_board.set_num_bombs()

        # This loop makes each game go right into the next game with the same dimensions & no. of bombs
        while True:

            sleep(0.5)
            print("\n\n**************************"
                  "\n  **********************"
                  "\n         NEW GAME         "
                  "\n  **********************"
                  "\n**************************\n")
            sleep(0.5)

            print("Input 'settings' any time to change the game settings.")
            sleep(0.5)

            # Create a new board for this game
            game_board.make_new_board()

            safe = True  # Used to indicate whether the player is safe after they've dug a spot
            col, row = None, None

            # as long as the number of spaces dug is less than the number of spaces available, keep playing this game
            while len(game_board.dug) < game_board.dim_size**2 - game_board.num_bombs:
                # First, show user the current board
                sleep(0.5)
                print(game_board)

                # Ask user where they want to dig and make sure the input is acceptable
                while not game_board.restart_game:
                    # Don't need \n at the start of this message b/c the printed game board has an extra \n underneath
                    user_input = input("Where would you like to dig/flag? Input as col, row:\n> ").lower().strip()
                    try:
                        # If user asked to quit, quit
                        if user_input in quit_responses:
                            quit_game()
                        # Elif user wants to adjust settings, open up the settings
                        elif user_input in settings_responses:
                            game_board.general_settings()
                            # After adjusting settings, loop back to asking user where they want to play.
                            # If Board.restart_game was set to True during settings, the game will break out of loop
                            continue
                        # Elif user only inputs something like "1" or "1,", or if they don't put the comma, raise error
                        elif len(user_input) < 3 or "," not in user_input:
                            raise ValueError

                        # Split the input into two values to be assigned to col & row.
                        # sometimes re.split has fluff in middle, so ensure you're taking the last value by using [-1].
                        user_input = re.split(',(\\s)*', user_input)
                        col, row = int(user_input[0]), int(user_input[-1])

                        # Throw up an error if the input is out of dimension range
                        if row < 0 or row >= game_board.dim_size or col < 0 or col >= game_board.dim_size:
                            raise ValueError

                        # If the user has already dug at that spot, ask them to pick a new spot
                        if (row, col) in game_board.dug:
                            print("Please pick a spot where you haven't dug yet.")
                            continue

                        break  # Can only get here if there are no errors and Board.restart_game is False

                    except ValueError:
                        print(f"Please enter 2 integers between 0 and {game_board.dim_size - 1} in col, row form "
                              f"(for example: 2, 3.), enter 'settings' to adjust game settings, or enter 'quit' to "
                              f"quit the game.")

                # Check that user inputs D or F
                while not game_board.restart_game:
                    print(f"\nWould you like to dig (D) or flag (F) spot ({col}, {row})?")
                    user_action = input("> ").lower().strip()

                    if user_action in quit_responses:
                        quit_game()
                    elif user_action in settings_responses:
                        game_board.general_settings()
                        # After adjusting settings, loop back to asking user whether they want to dig or flag.
                        # If Board.restart_game was set to True during settings, the game will break out of loop.
                        continue
                    elif user_action in ["f", "flag"]:
                        safe = game_board.flag_spot(row, col)
                        break
                    elif user_action in ["d", "dig"]:
                        safe = game_board.dig_spot(row, col)
                        break
                    else:
                        print(f"Please enter 'D' to dig in spot ({col}, {row}), 'F' to flag that spot,"
                              f"'settings' to adjust game settings, or 'quit' to quit the game.")

                # If user dug a bomb or is restarting game to adjust variables, break out of this current game loop
                if not safe or game_board.restart_game:
                    break

            # 3 ways to end loop: restarting game to change dim/bombs, ran out of space (safe!), dug a bomb (not safe)
            if game_board.restart_game:
                game_board.reset_board()
                break
            elif safe:
                sleep(1)
                print("CONGRATULATIONS!!! YOU WON!!")
            else:
                sleep(1)
                print("Oof magoof. You died")

            # let's reveal the whole board
            sleep(1)
            game_board.dug = [(r, c) for r in range(game_board.dim_size) for c in range(game_board.dim_size)]
            print(game_board)
            sleep(1)

            # Reset the game_board values before jumping into the next game
            game_board.reset_board()

if __name__ == '__main__':
    play()


############################################################################################################################################
# COPYRIGHT (C) 2016 Razvan Petre
# * Licensed under the Apache License, Version 2.0 (the "License");
# * you may not use this file except in compliance with the License.
# * You may obtain a copy of the License at
# *
# * http://www.apache.org/licenses/LICENSE-2.0
# *
# * Unless required by applicable law or agreed to in writing, software
# * distributed under the License is distributed on an "AS IS" BASIS,
# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# * See the License for the specific language governing permissions and
# * limitations under the License.

# This library is based on code developed by Dragos Iosub, Bucharest 2015. http://itbrainpower.net,original code link below:
# http://itbrainpower.net/micro-GSM-shield-module-cuGSM/GSM-micro-shield-board-module-RaspberryPI-Arduino-c-uGSM-features-code-examples
#
# NAME: Phonebook.py
# PROJECT: SMSGate
# DESCRIPTION: This module contains the definition of Phonebook class

############################################################################################################################################
from globalPara import *

import json

class Phonebook:
    """
    self.people  -> is a list of dictionaries
                 -> each dictionary in people has the following keys: ID Name PhoneNo Email and Group
                 -> for the latter, Group is a list, beacuse a person can be part of multiple groups
    self.gropups -> list of groups in the phonebook
    """

    people = []
    groups = []

    def __init__(self):
        self.people = []
        self.groups = []
        if self.setup() is True:
            Logger.error('Error while opening/reading phonebook.json')

    def setup(self):
        """
        setup the people dictionary and groups list with new information from the XML file

        @return: True if an error occurred while reading json or None otherwise
        """
        try:

            with open(phonebook_path + 'phonebook.json') as data_file:
                data = json.load(data_file)

            self.people = data['employees']
            self.groups = data['groups'].keys()

            for employee in self.people:
                employee.update({'Group':[]})
                for group in data['groups']:
                    if int(employee['ID']) in data['groups'][group]:
                        employee['Group'].append(group)

        except:
            return True

        return None

    def getGroups(self):
        return self.groups

    def getGroupConts(self, group, option):
        """
        It is the duty of the callee function to give the group without spaces in corners and ALL LOWERNAMES

        @param option:
            -   if it is PhoneNo return numbers of the group members
            -   if it is Email return email of the group members
        @param group:
            -   the group whose member's phone numbers are wanted,
            -   can take spaces in the right or left eg. '  Admins  '
            -   is not case sensitive ' Admins ' is the same as 'admIns'
        @return: None if not found, list of Phone No. if option is PhoneNo of list of e-mails if option is Email
        """
        numbers = []
        emails = []
        if group in self.groups:
            for employee in self.people:
                if group in employee['Group']:
                    numbers.append(employee['PhoneNo'])
                    emails.append(employee['Email'])
            if option == 'PhoneNo':
                return numbers
            else:
                return emails
        else:
            Logger.warning('Group %s not found!' % group)
            return None

    def getName(self, phoneno):
        """
        It is the duty of the callee function to give the phoneno without spaces in corners and without +4..

        @param phoneno: phone number for what is wanted the owner
        @return: the owner's name from database or None
        """
        for employee in self.people:
            if employee['PhoneNo'] == phoneno:
                return employee['Name']
        return None

    def checkPhoneNo(self, phoneno):
        """
        Checks if a Phone Number is in the PhoneBook and return True if so and False if not

        It is the duty of the callee function to give the phoneno without spaces in corners and without +4..

        @param phoneno: Phone NUmber to be checked
        @return: True or False
        """
        for employee in self.people:
            if employee['PhoneNo'] == phoneno:
                return True
        return False

    def checkEmail(self, email):
        """
        Checks if an Email address is in the PhoneBook and return True if so and False if not

        It is the duty of the callee function to give the email without spaces in corners

        @param email: email address to be checked
        @return: True or False
        """
        for employee in self.people:
            if employee['Email'] == email:
                return True
        return False

#Class objects
phonebook = Phonebook()


# --------------------------------------------------------
# Tensorflow TIN
# Licensed under The MIT License [see LICENSE for details]
# --------------------------------------------------------

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

import _init_paths
import tensorflow as tf
import numpy as np
import argparse
import pickle
import json
import ipdb
import os

# for error of 'ImportError: No module named pycocotools.coco'
from ult.config_vcoco import cfg
import sys
sys.path.append(cfg.ROOT_DIR + '/Data/v-coco/coco/PythonAPI')

from pycocotools.coco import COCO # for test
from ult.vsrl_eval_output_txt import VCOCOeval
from models.test_VCOCO_D_pose_pattern_naked import test_net

from networks.TIN_VCOCO import ResNet50

os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' # use GPU 0, 1

def parse_args():
    parser = argparse.ArgumentParser(description='Test an TIN on VCOCO')
    parser.add_argument('--num_iteration', dest='iteration',
            help='Specify which weight to load',
            default=6000, type=int)
    parser.add_argument('--model', dest='model',
            help='Select model',
            default='TIN_VCOCO', type=str)
    parser.add_argument('--prior_flag', dest='prior_flag',
            help='whether use prior_flag or not',
            default=3, type=int)
    parser.add_argument('--object_thres', dest='object_thres',
            help='Object threshold',
            default=0.4, type=float)
    parser.add_argument('--human_thres', dest='human_thres',
            help='Human threshold',
            default=0.6, type=float)

    args = parser.parse_args()
    return args

# prior flag: see ROOT/lib/ult/apply_prior.py for more detail
#     apply_prior   prior_mask
# 0        -             -
# 1        Y             -
# 2        -             Y
# 3        Y             Y

if __name__ == '__main__':

    args = parse_args()

    Test_RCNN      = pickle.load( open( cfg.DATA_DIR + '/' + 'Test_Faster_RCNN_R-50-PFN_2x_VCOCO_with_pose.pkl', "rb" ) )
    prior_mask     = pickle.load( open( cfg.DATA_DIR + '/' + 'prior_mask.pkl', "rb" ) )
    Action_dic     = json.load(   open( cfg.DATA_DIR + '/' + 'action_index.json'))
    Action_dic_inv = {y:x for x,y in Action_dic.iteritems()}

    vcocoeval      = VCOCOeval(cfg.DATA_DIR + '/' + 'v-coco/data/vcoco/vcoco_test.json', cfg.DATA_DIR + '/' + 'v-coco/data/instances_vcoco_all_2014.json', cfg.DATA_DIR + '/' + 'v-coco/data/splits/vcoco_test.ids')

    weight = cfg.ROOT_DIR + '/Weights/' + args.model + '/HOI_iter_' + str(args.iteration) + '.ckpt'
    print ('Human thres = ' + str(args.human_thres) + ', Object thres = ' + str(args.object_thres) + ', iter = ' + str(args.iteration) + ', path = ' + weight )

    output_file = cfg.ROOT_DIR + '/-Results/' + str(args.iteration) + '_' + args.model + '_' + str(args.human_thres) + '_' + str(args.object_thres) + '_naked.pkl'

    # init session
    tfconfig = tf.ConfigProto(allow_soft_placement=True)
    tfconfig.gpu_options.allow_growth=True
    sess = tf.Session(config=tfconfig)

    net = ResNet50()
    net.create_architecture(False)

    saver = tf.train.Saver()
    saver.restore(sess, weight)

    print('Pre-trained weights loaded.')

    test_net(sess, net, Test_RCNN, prior_mask, Action_dic_inv, output_file, args.object_thres, args.human_thres, args.prior_flag)
    sess.close()

    os.system("python tools/Vcoco_lis_nis.py --prior_flag 3 --mode best --input_S " + output_file)


from typing import TypeVar, Generic

from graph_searcher import GraphSearcher
from vertex import Vertex

T = TypeVar("T")

class DFS(GraphSearcher, Generic[T]):
    def __search__(self, node: Vertex[T]) -> tuple[bool, int]:
        stack = self.__buffer__
        current = stack.pop()
        visited = self.__visited__
        vertices = self.__vertices__[current]

        if current not in visited:
            visited[current] = True

        for vertex in vertices:
            if vertex == node:
                visited[vertex] = True
                return True, 0
            if vertex not in visited:
                stack.append(vertex)

        return False, 0


import click

from flask import current_app, Blueprint
from flask.cli import with_appcontext

@click.command('me')
@click.option('--name', prompt='Enter your name')
@with_appcontext
def command_about_me(name):
    click.echo(f"Your name: {name}")

def init_blueprint_cli(blueprint: Blueprint) -> None:
    blueprint.cli.add_command(command_about_me)


import streamlit as st

from front import js_map
from front.model_controller import get_recommend_call_location

def after_work_page(picker_coord, default_current_time):
    st.header("기사님 수요밀집 지역 추천")
    st.image('resources/after_work_flow.png')
    img_col1, img_col2 = st.columns([3, 5])
    with img_col1:
        st.image('resources/situation2.png')
    with img_col2:
        col1, col2 = st.columns([5, 5])
        with col1:
            picker_lat = st.text_input("픽커 lat", picker_coord[0])
            current_time = st.text_input("시간 설정", default_current_time)
        with col2:
            picker_lon = st.text_input("픽커 lat", picker_coord[1])
        # 버튼 클릭 여부 확인
        if st.button("모델 예측", key="coord"):
            with st.spinner("Loading..."):
                recommend_result = get_recommend_call_location(lat=picker_lat, lon=picker_lon,
                                                               current_time=current_time)
                st.write(recommend_result)
                js_map.getMapWithPicker((picker_lat, picker_lon))


import fileinput
import os
import sys

# Check that a directory was provided as a command-line argument
if len(sys.argv) < 2:
    print('Usage: python patch-ics.py <directory>')
    sys.exit(1)

# Get the directory from the command-line argument
directory = sys.argv[1]

# Specify the replacement value for X-WR-TIMEZONE
replacement = """BEGIN:VTIMEZONE
TZID:Europe/Paris
BEGIN:STANDARD
DTSTART:19710101T030000
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
END:STANDARD
END:VTIMEZONE"""

# Loop over each file in the directory
for filename in os.listdir(directory):
    # Check that the file has a .ics extension
    if filename.endswith('.ics'):
        # Open the file for in-place editing
        with fileinput.FileInput(os.path.join(directory, filename), inplace=True) as file:
            # Loop over each line in the file
            for line in file:
                # Replace the X-WR-TIMEZONE property with the replacement value
                if line.startswith('X-WR-TIMEZONE:'):
                    print(replacement)
                else:
                    print(line, end='')


import matplotlib.pyplot as plt
import numpy as np
import os
import random
import tensorflow as tf

from keras import backend as K
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.metrics import fowlkes_mallows_score, silhouette_score

from ml import dense
from constants_multi_clusters import *
from mnist17 import dataset, poisonings

NUM_ITER = 5
MAX_NUM_CL = 10

COLOURS = ['royalblue', 'salmon', 'seagreen', 'magenta', 'turquoise', 'darkviolet', 'gold', 'lime', 'pink', 'coral', 'darkred', 'blue']

def plot_metrics_by_num_clusters(exp_dir, epoch_metrics):
    assert epoch_metrics[0][-1].shape[0] == NUM_EPOCHS
    xvalues = np.arange(MAX_NUM_CL) + 1

    for epoch_idx in range(NUM_EPOCHS):
        plt.title('Clustering metrics by number of clusters - epoch {}'.format(epoch_idx + 1))
        plt.xlabel('Number of clusters')
        plt.ylabel('Metric value')
        plt.xticks(xvalues)
        for i, (metric_name, values) in enumerate(epoch_metrics):
            metric_mean = values[epoch_idx].mean(axis=1)
            metric_std = values[epoch_idx].std(axis=1)
            plt.plot(xvalues, metric_mean, label=metric_name, c=COLOURS[i])
            plt.plot(xvalues, metric_mean - metric_std, c=COLOURS[i], linestyle='dashed')
            plt.plot(xvalues, metric_mean + metric_std, c=COLOURS[i], linestyle='dashed')
        plt.legend()
        plt.savefig(os.path.join(exp_dir, 'cluster_metrics_epoch{}'.format(epoch_idx + 1)), dpi=150)
        plt.gcf().clear()

# def plot_mmap_pca(mmap_pca, epoch, num_cl, cluster_labels, comp_x, comp_y, plot_dir, true=False):
#     plt.title('Mmap PCA - components {} and {} - epoch {}'
#               .format(comp_x + 1, comp_y + 1, epoch + 1))
#     plt.xlabel('Component {}'.format(comp_x + 1))
#     plt.ylabel('Component {}'.format(comp_y + 1))
#     for i in range(num_cl):
#         c_mask = cluster_labels == i
#         plt.scatter(mmap_pca[c_mask, comp_x], mmap_pca[c_mask, comp_y],
#                     c=COLOURS[i], marker='o', s=1, label='Cluster {}'.format(i + 1))
#     plt.legend()
#     file_path = os.path.join(plot_dir,
#                              'cl{}_epoch{}_{}_mmap_pca_{}-{}.png'.format(
#                                  num_cl, epoch + 1, 'true' if true else 'pred', comp_x + 1, comp_y + 1))
#     plt.savefig(file_path, dpi=150)
#     plt.gcf().clear()

def mnist17_cl_02(poisoning_type):  # E.g. 'c_noise'
    exp_name = 'mnist17_cl_02{}'.format(poisoning_type)
    os.makedirs(exp_name, exist_ok=False)

    # Reported metrics, by epoch: (epoch index, number of clusters - 1, iteration index) -> value
    silhouette_by_num_cl = np.zeros(shape=(NUM_EPOCHS, MAX_NUM_CL, NUM_ITER))
    fowlkes_mallows_by_num_cl = np.zeros(shape=(NUM_EPOCHS, MAX_NUM_CL, NUM_ITER))

    for iter_ in range(NUM_ITER):
        print('Iteration', iter_)
        # _set_seed(iter_)

        iter_dir = os.path.join(exp_name, 'iter{}'.format(iter_))
        os.makedirs(iter_dir, exist_ok=False)

        train_x, train_y, test_x, test_y, train_batch_id = dataset.basic_train_test()
        if poisoning_type == 'a_base':
            train_x, train_y, true_batch_labels = poisonings.base(train_x, train_y)
        elif poisoning_type == 'b_flip':
            train_x, train_y, true_batch_labels = poisonings.flip_poisoning(train_x, train_y)
        elif poisoning_type == 'c_noise':
            train_x, train_y, true_batch_labels = poisonings.noise_poisoning(train_x, train_y, plot_dir=iter_dir, plot=True)
        # elif poisoning_type == 'd_merge':
        #     pass
        else:
            raise ValueError('Unknown poisoning type: {}'.format(poisoning_type))

        dense_nn = dense.DenseNN(parent_dir=iter_dir,
                                 name=iter_dir,
                                 input_dim=INPUT_DIM, h1_dim=H1_DIM, h2_dim=H2_DIM,
                                 classes=(1, 7), batch_size=BATCH_SIZE,
                                 mmap_normalise=False)

        for epoch in range(NUM_EPOCHS):
            dense_nn.fit(train_x, train_y,
                         validation_data=(test_x, test_y), batch_size=BATCH_SIZE, num_epochs=1, continue_training=True)
            # Model is loaded during fit(). Start from scratch every time.
            assert len(dense_nn.epoch_mmaps) == epoch + 1

            mmap, _, _ = dense_nn.epoch_mmaps[-1]  # mmap mush already be demeaned here.
            assert mmap.shape[0] == NUM_TRAIN_BATCHES

            # Clusterise.
            pca = PCA(n_components=3)
            mmap_pca = pca.fit_transform(mmap)

            zero_labels = np.zeros(shape=(NUM_TRAIN_BATCHES,))
            fowlkes_mallows_by_num_cl[epoch, 0, iter_] = fowlkes_mallows_score(true_batch_labels, zero_labels)

            for n_clusters in range(2, MAX_NUM_CL + 1):
                kmeans = KMeans(n_clusters=n_clusters, random_state=iter_).fit(mmap_pca)

                # 2 first PCs are enough.
                # plot_mmap_pca(mmap_pca, epoch, n_clusters, kmeans.labels_, 0, 1, iter_dir, true=False)
                # TODO n_clusters
                # plot_mmap_pca(mmap_pca, epoch, n_clusters, true_batch_labels, 0, 1, iter_dir, true=True)

                # Compute Silhouette.
                silhouette_by_num_cl[epoch, n_clusters - 1, iter_] = silhouette_score(mmap_pca, kmeans.labels_)
                # Compute Fowlkes-Mallows index.
                fowlkes_mallows_by_num_cl[epoch, n_clusters - 1, iter_] = fowlkes_mallows_score(true_batch_labels, kmeans.labels_)

    # Report metric.
    plot_metrics_by_num_clusters(exp_name,
                                 [
                                     ('Silhouette score', silhouette_by_num_cl),
                                     ('Fowlkes-Mallows index', fowlkes_mallows_by_num_cl)
                                 ])

def main():
    # _set_seed(0)

    # mnist17_cl_02(poisoning_type='a_base')
    # mnist17_cl_02(poisoning_type='b_flip')
    mnist17_cl_02(poisoning_type='c_noise')

# def _set_seed(seed_value):
#     os.environ['PYTHONHASHSEED'] = str(seed_value)
#     random.seed(seed_value)
#     np.random.seed(seed_value)
#     tf.random.set_random_seed(seed_value)
#     tf.set_random_seed(seed_value)
#     tf.compat.v1.set_random_seed(seed_value)
#     session_conf = tf.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
#     sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
#     K.set_session(sess)
#     session_conf = tf.compat.v1.ConfigProto(intra_op_parallelism_threads=1, inter_op_parallelism_threads=1)
#     sess = tf.compat.v1.Session(graph=tf.compat.v1.get_default_graph(), config=session_conf)
#     tf.compat.v1.keras.backend.set_session(sess)

if __name__ == '__main__':
    main()


from battle.simulate import rand
import itertools

from battle import log

class FrontCollection(object):
    it = None
    avangard = None
    leftFlang = None
    rightFlang = None
    rear = None
    location = None

    def __init__(self, inDefence):
        self.inDefence = inDefence

    def get(self, name):
        """
        :rtype: Front
        """
        if name == Front.TYPE_AVANGARD:
            return self.avangard
        elif name == Front.TYPE_LEFT_FLANG:
            return self.leftFlang
        elif name == Front.TYPE_RIGHT_FLANG:
            return self.rightFlang
        elif name == Front.TYPE_REAR:
            return self.rear

    def parseAction(self, sequence, enemyFrontCollection, myFront):
        """
        :type sequence: tuple
        :type enemyFrontCollection: FrontCollection
        :type myFront: Front
        """

        if myFront.getMeleeCount() == 0:
            return False

        if type(sequence) is tuple:
            for direction in sequence:
                if enemyFrontCollection.get(direction).getUnitsCount():
                    targetFront = enemyFrontCollection.get(direction)
                    isClose = False
                    if targetFront.getTarget() == myFront:
                        isClose = targetFront.currentWaitToMove

                    myFront.setTarget(targetFront, isClose)
                    log.front('`%s` set target `%s`' % (targetFront.it, myFront.it))
                    return True

            return False
        else:
            for myDirection in sequence:
                # print(self.it, myDirection, sequence, sequence[myDirection])
                if self.get(myDirection).getUnitsCount() == 0:
                    return self.parseAction(sequence[myDirection], enemyFrontCollection, myFront)

    def getNextTarget(self, frontName, enemyFrontCollection):
        """
        :type frontName: string
        :type enemyFrontCollection: FrontCollection
        """
        myFront = self.get(frontName)
        if myFront and myFront.getTarget() and myFront.getTarget().getUnitsCount():
            log.front('`%s` has target `%s`' % (myFront.it, myFront.getTarget().it))
            return
        else:
            if self.inDefence:
                sequence = self.location.getSequenceOfStrategicActionsDefender()
            else:
                sequence = self.location.getSequenceOfStrategicActionsAttacker()

            self.parseAction(sequence[frontName], enemyFrontCollection, myFront)

    def getArcheryTarget(self):
        """Used by enemy"""
        avangardSize = self.avangard.getUnitsCount()
        leftFlang = self.leftFlang.getUnitsCount()
        rightFlang = self.rightFlang.getUnitsCount()
        target = None
        count = 0

        if avangardSize >= count and not self.avangard.isBussy():
            target = self.avangard
            count = avangardSize

        if leftFlang >= count and not self.leftFlang.isBussy():
            target = self.leftFlang
            count = leftFlang

        if rightFlang >= count and not self.rightFlang.isBussy():
            target = self.rightFlang

        return target

    def iterateAll(self):
        for i in [self.avangard, self.leftFlang, self.rightFlang, self.rear]:
            yield i

    def getArmySize(self):
        armySize = 0
        for front in Front.TYPES:
            armySize += self.get(front).getUnitsCount()

        return armySize

    def setAvangard(self, front):
        """
        :type front: Front
        """
        front.setInDefence(self.inDefence)
        self.avangard = front

    def setLeftFlang(self, front):
        """
        :type front: Front
        """
        self.leftFlang = front

    def setRightFlang(self, front):
        """
        :type front: Front
        """
        self.rightFlang = front

    def setRear(self, front):
        """
        :type front: Front
        """
        self.rear = front

    def setLocation(self, location):
        self.location = location
        self.avangard.setLocation(location)
        self.leftFlang.setLocation(location)
        self.rightFlang.setLocation(location)
        self.rear.setLocation(location)

class Front(object):
    it = None

    TYPE_AVANGARD = 1
    TYPE_LEFT_FLANG = 2
    TYPE_RIGHT_FLANG = 3
    TYPE_REAR = 4

    TYPES = (1, 2, 3, 4, )

    location = None
    inDefence = None

    currentFrontTarget = None
    currentWaitToMove = 0

    def __init__(self, frontDirection):
        self._type = frontDirection
        self.groups = []

    def move(self):
        if self.currentWaitToMove:
            self.currentWaitToMove -= 1

        log.front('`%s` move left %i' % (self.it, self.currentWaitToMove))
        for group in self.groups:
            group.move()

    def getType(self):
        return self._type

    def addGroup(self, group):
        self.groups.append(group)

    def archersFire(self, target):
        if self.inDefence:
            bonus = self.location.getArcheryBonusDefender()
        else:
            bonus = self.location.getArcheryBonusAttacker()

        log.front('`%s` archery fire to `%s`' % (self.it, target.it, ))

        for group in self.groups:
            group.archersFire(target, bonus)

    def meleeFire(self):
        targetFront = self.getTarget()

        if targetFront is None:
            return

        if not targetFront or self.currentWaitToMove != 0:
            return

        if targetFront.getMeleeCount():
            units = targetFront.getMeleeGroups(False)
        elif targetFront.getRangeCount():
            units = targetFront.getRangeGroups(False)
        else:
            return False

        generator = itertools.cycle(units)

        for group in self.groups:
            if group.getTarget():
                continue

            targetGroup = None

            for i in range(targetFront.getUnitsCount()):
                tmp = next(generator)
                if targetFront.hasGroup(tmp):
                    targetGroup = tmp
                    break

            if targetGroup is None:
                return

            group.setTarget(targetGroup)

        for group in self.groups:
            group.meleeAttack()

    def getMeleeGroups(self, ignoreWithTarget=True):
        groups = []

        for group in self.groups:
            if group.getCount() and group.getMeleeCount() and \
                ((ignoreWithTarget is True and not group.getTarget()) or ignoreWithTarget is False):
                    groups.append(group)

        return groups

    def getRangeGroups(self, ignoreWithTarget=True):
        groups = []

        for group in self.groups:
            if group.getCount() and group.getRangeCount() and \
                ((ignoreWithTarget is True and not group.getTarget()) or ignoreWithTarget is False):
                    groups.append(group)

        return groups

    def getGroups(self):
        return self.groups

    def getUnitsCount(self):
        frontSize = 0
        for group in self.groups:
            frontSize += group.getCount()

        return frontSize

    def getMeleeCount(self):
        frontSize = 0
        for group in self.groups:
            frontSize += group.getMeleeCount()

        return frontSize

    def getRangeCount(self):
        frontSize = 0
        for group in self.groups:
            frontSize += group.getRangeCount()

        return frontSize

    def isBussy(self):
        """Is this front in local battle"""
        return self.currentFrontTarget and self.currentWaitToMove != 0

    def getRandomGroup(self):
        """
        used by enemy
        :rtype: battle.structure.group.Group
        """
        return self.groups[ rand.randint(0, len(self.groups) - 1) ]

    def setLocation(self, location):
        """
        :type location: battle.places.abstract.AbstractPlace
        """
        self.location = location

    def setInDefence(self, inDefence):
        self.inDefence = inDefence

    def getTarget(self):
        """
        :rtype: Front
        """
        return self.currentFrontTarget

    def setTarget(self, targetFront, isClose=False):
        self.currentFrontTarget = targetFront
        self.setGroupsTargets(targetFront)

        if type(isClose) is int:
            self.currentWaitToMove = isClose
        else:
            self.currentWaitToMove = self.location.timeToAttack()

    def hasGroup(self, group):
        return group in self.groups

    def setGroupsTargets(self, targetFront):
        pass


# Task1:
#Create a recursive function named countdown with a single integer input
# argument that prints a countdown starting from the given number.

def countdown(my_number):
    number = int(my_number)
    for i in range(number, 0, -1):   # counting from number to 0 but not including 0
        print(i)
    return 0

print(countdown(5))

# Task2:
# Create a recursive function named factorial that returns the factorial of a number
# (the number multiplied by every integer lower than the number and greater than 0).
# example: factorial 10 = print(10*9*8*7*6*5*4*3*2*1)

def factorial(my_num):
    number = int(my_num)
    my_sum = 1
    for i in range(1, number+1):
        my_sum = my_sum * i
    return my_sum

print(factorial(10))

# Task3:
# Create a function called harmonic_sum that requires an integer as an argument.
# The function will return the harmonic sum of the integer.
# The harmonic sum is the sum of reciprocals of the positive integers. The harmonical sum of 2 is:
# 1/1 + 1/2 = 1.5

def harmonic_sum(number):
    my_number = int(number)
    result = 0
    for i in range(1,my_number+1):
        result += (1/i)
    return result

print(harmonic_sum(4))


#!/usr/bin/env python3
# Author: Armit
# Create Time: 2023/07/20

# implementation of one-pass OC-VQE, combining OC-VQE and SS-VQE

from .common import *

from mindspore.common.parameter import Parameter
from mindquantum.framework import MQAnsatzOnlyLayer
from mindquantum.simulator.utils import GradOpsWrapper
from mindquantum.core.circuit import add_prefix

# save current reg term for check
punish_f: float = None

# ↓↓↓ mindquantum/simulator/mqsim.py ↓↓↓

from mindquantum.simulator.mqsim import MQSim

MQSim.get_expectation_with_grad

def grad_ops_hijack(
  self: MQSim,
  hams: List[Hamiltonian],
  circ_left: Circuit,     # gs
  circ_right: Circuit,    # es
  *inputs: ndarray,
):
  # gs, es
  inputs0, inputs1 = inputs

  if not 'check <φ0|φ1>':
    qs0 = circ_left .get_qs(pr=inputs0)
    qs1 = circ_right.get_qs(pr=inputs1)
    ip = qs0 @ qs1
    print('ip:', ip)

  L_ansatz_params_name = circ_left .all_ansatz.keys()
  R_ansatz_params_name = circ_right.all_ansatz.keys()
  param_names = L_ansatz_params_name + R_ansatz_params_name
  param_values = np.concatenate([inputs0, inputs1], axis=0)

  f_g = self.sim.get_expectation_with_grad_non_hermitian_multi_multi(
    [i.get_cpp_obj() for i in hams],
    [i.get_cpp_obj(hermitian=True) for i in hams],
    circ_left.get_cpp_obj(),
    circ_left.get_cpp_obj(hermitian=True),
    circ_right.get_cpp_obj(),
    circ_right.get_cpp_obj(hermitian=True),
    np.array([[]]),
    param_values,
    [],
    param_names,
    self.sim,
    1,
    1,
  )

  res = np.squeeze(np.array(f_g))
  f, g = res[0], res[1:]
  return f, g

# ↑↑↑ mindquantum/simulator/mqsim.py ↑↑↑

def run(mol:MolecularData, ham:Ham, config:Config) -> Tuple[float, float]:
  # Declare the simulator
  sim, HAM_NULL = get_sim(mol, ham, ret_null_ham=True)

  # Construct state ansatz circuit: |ψ(λj)>
  gs_circ, init_amp0 = get_ansatz(mol, config['ansatz'], config)
  es_circ, init_amp1 = get_ansatz(mol, config['ansatz'], config)
  gs_circ = add_prefix(gs_circ, 'gs') ; len_gs = len(gs_circ.all_paras)
  es_circ = add_prefix(es_circ, 'es') ; len_es = len(es_circ.all_paras)

  # Initialize amplitudes
  if init_amp0 is not None and init_amp1 is not None:
    init_amp = np.concatenate([init_amp0, init_amp1], axis=0)
  else:
    init_amp = init_randu(len_gs + len_es)

  # Get the expectation and gradient calculating function: <ψ(λj)|H|ψ(λj)>
  gs_grad_ops = sim.get_expectation_with_grad(ham, gs_circ)
  es_grad_ops = sim.get_expectation_with_grad(ham, es_circ)
  ip_grad_ops = lambda *inputs: grad_ops_hijack(sim.backend, [HAM_NULL], gs_circ, es_circ, *inputs)

  # Define the objective function to be minimized
  def func(x:ndarray, gs_grad_ops:Callable, es_grad_ops:Callable, ip_grad_ops:Callable, hparams:Config) -> Tuple[float, ndarray]:
    beta: float = hparams['beta']
    w:    float = hparams['w']

    x0 = x[:len_gs]
    x1 = x[-len_es:]
    f0, g0 = gs_grad_ops(x0)
    f1, g1 = es_grad_ops(x1)
    f0, f1, g0, g1 = [np.squeeze(x) for x in [f0, f1, g0, g1]]
    f_sum = f0 + w * f1
    g_cat = np.concatenate([g0, w * g1], axis=0)

    global punish_f
    f_, g_ = ip_grad_ops(x0, x1)
    punish_f = beta * np.abs(f_) ** 2
    punish_g = beta * (np.conj(g_) * f_ + g_ * np.conj(f_))

    if DEBUG: print('gs:', f0.real, 'es:', f1.real, 'reg:', punish_f)
    return np.real(f_sum + punish_f), np.real(g_cat + punish_g)

  # Get optimized result
  opt = config.get('opt', 'scipy')
  if opt == 'scipy':
    params = optim_scipy(func, init_amp, (gs_grad_ops, es_grad_ops, ip_grad_ops), config)

  elif opt == 'mindspore':
    def grad_ops(x):
      f, g = func(x, gs_grad_ops, es_grad_ops, ip_grad_ops, config)
      f = np.expand_dims(np.expand_dims(f, 0), 0)
      g = g[None, None, :]
      return f, g

    grad_ops_wrapper = GradOpsWrapper(
      grad_ops,
      [ham],
      es_circ,
      gs_circ,
      gs_circ.all_encoder.keys() + es_circ.all_encoder.keys(),
      gs_circ.all_ansatz .keys() + es_circ.all_ansatz .keys(),
      None,
    )

    pqc = MQAnsatzOnlyLayer(grad_ops_wrapper)
    pqc.weight = Parameter(ms.Tensor(init_amp, pqc.weight.dtype))
    params = optim_mindspore(pqc, config)

  else: raise ValueError(f'unknown optim lib: {opt}')

  # Get the energyies
  sim.reset() ; f0 = run_expectaion(sim, ham, gs_circ, params[:len_gs])
  sim.reset() ; f1 = run_expectaion(sim, ham, es_circ, params[-len_es:])

  if PEEK:
    print('E0 energy:', f0)
    print('E1 energy:', f1)
    print('reg_term:', punish_f)
  return f0, f1

def opocvqe_solver(mol:MolecularData, config:Config) -> float:
  ham = get_ham(mol, config)

  # Find the lowest two energies by min. U|φ0> + w*U|φ1> + β*<φ0|U'U|φ1>
  if 'optims' in config:
    for optim in config['optims']:
      assert 0.0 < optim['w'] < 1.0
  else:
    assert 0.0 < config['w'] < 1.0
  gs_ene, es_ene = run(mol, ham, config)

  return es_ene


""" Replace this text with your name please"""

class Fixture(object):
    def __init__(self, name):
        self.name = name

    def describe(self):
        print('\t' + self.name)

class Venue(object):
    def __init__(self, name):
        self.name = name
        self.additions = []

    def build(self, a_new_bit):
        self.additions.append(a_new_bit)

    def map(self):
        print(self.name)
        for addition in self.additions:
            if type(addition) == Fixture:
                addition.describe()
            elif type(addition) == Venue:
                addition.map()

if __name__ == '__main__':
    park = Venue('AMI Stadium')
    stand1 = Venue('Tui Stand')
    stand2 = Venue('Paul Kelly Motor Company Stand')
    stand3 = Venue('Hadlee Stand')

    park.build(stand1)
    park.build(stand2)
    park.build(stand3)

    stand1.build(Fixture('Toilets'))
    stand1.build(Fixture('Box 18'))
    stand1.build(Fixture('Box 19'))
    stand1.build(Fixture('Box 20'))
    stand1.build(Fixture('Box 21'))

    stand2.build(Fixture('Toilets'))
    for box in range(1, 18):
        stand2.build(Fixture('Box ' + str(box)))

    stand3.build(Fixture('Main Office'))

    park.map()

'''
expected output:

AMI Stadium
Tui Stand
    Toilets
    Box 18
    Box 19
    Box 20
    Box 21
Paul Kelly Motor Company Stand
    Toilets
    Box 1
    Box 2
    Box 3
    Box 4
    Box 5
    Box 6
    Box 7
    Box 8
    Box 9
    Box 10
    Box 11
    Box 12
    Box 13
    Box 14
    Box 15
    Box 16
    Box 17
Hadlee Stand
    Main Office
'''


#!/bin/python3
#
# Complete the 'stones' function below.
#
# The function is expected to return an INTEGER_ARRAY.
# The function accepts following parameters:
#  1. INTEGER n
#  2. INTEGER a
#  3. INTEGER b
#

def stones(n, a, b):
    # Write your code here
    permutations = []
    permutations.append(a * (n - 1))
    for i in range(n - 1):
        permutations.append(a * (n - 2 - i) + b * (i + 1))
    return sorted(set(permutations))

if __name__ == '__main__':

    T = int(input())

    for T_itr in range(T):
        n = int(input().strip())
        a = int(input().strip())
        b = int(input().strip())

        result = stones(n, a, b)

        print(' '.join(map(str, result)))


#llamamos nuestro modulo y lo ejecutamos en el main:
import utils2
import readCSV2
import graficas2
import pandas as pd

def run():

    while True:
        data = readCSV2.readCsv("./data2.csv")
        country = input("Type Country => ")

        result = utils2.populationsByCountry(data, country)

        if len(result) > 0:
            countryDictionary = result[0]
            labels, values = utils2.getPopulations(countryDictionary)
            graficas2.generateBarChart(country, labels, values)
            print(f"Se generó imagen de la grafica de la poblacion el country: {country}, en la carpeta imgs/country")
            break
        else:
            print("EL country ingresado no es valido, favor ingresar el country nuevamente: ")

    while True:
        continent = input("Ingresar el continente que deseas graficar su población => ")
        #data = readCSV2.readCsv("./data2.csv")#informacion del csv en formato dictionary
        #data = list(filter(lambda x : x["Continent"] == continent, data))#podemos filtrar por continente

        if len(data) > 0:
            #columnCountries = list(map(lambda x : x["Country"], data)) #sacamos la columna de cada uno de los paises de la data2 con map
            #columnPorcentages = list(map(lambda x : x["World Population Percentage"], data))#sacamos el porcentaje de la columna de porcentajes de la data2

            #utilizamos libreria -----PANDAS----- para leer nuestro data2.csv:
            df = pd.read_csv("data2.csv")
            df = df[df["Continent"] == continent]

            #optener la columnas paises y columna porcentajes:
            columnCountries = df["Country"].values
            columnPorcentages = df["World Population Percentage"].values

            graficas2.generatePieChart(continent, columnCountries, columnPorcentages)
            print(f"Se generó imagen de la grafica de la poblacion del continent: {continent}, en la carpeta imgs/continent")
            break
        else:
            print("Continente no encontrado. Por favor, ingrese un continente válido.")

#con el siguiente if podemos ejecutar el archivo desde otro module o desde la terminal llamando al main:
if __name__ == '__main__':
    run()


import os
from ingredienttojson import parse_number_of_serve
from ingredienttojson import ingredient_div_to_array
from ingredienttojson import ingredients_to_dict

_LOG_DIR = './weekcook_web/ingredient'

def test_ingedient_div_to_array():
    sample_file = 'weekcook_sample.txt'
    strings = ingredient_div_to_array(_LOG_DIR, sample_file)
    print('test_ingredient_div_to_array')
    print(strings)
    expected = ['材料4人分', 'アボカド', '2個', '塩鮭', '4切れ', '生クリーム', '200ml', 'チーズ（ピザ用）', '40g', '塩', '少々', 'ブラックペッパー', '少々']

    assert strings == expected

def test_parse_number_of_serve():
    sample_text = '材料4人分'
    serve_dict = parse_number_of_serve(sample_text)
    print('test_parse_number_of_serve')
    print(serve_dict)
    expected = {'材料': '4人分'}

    assert serve_dict == expected

def test_ingredients_to_dict():
    sample_file = 'weekcook_sample.txt'
    strings = ingredient_div_to_array(_LOG_DIR, sample_file)
    ingredients_dict = ingredients_to_dict(strings)
    print('test_ingredient_to_dict')
    print(ingredients_dict)
    expected = {
        "材料": "4人分",
        "アボカド": "2個",
        "塩鮭": "4切れ",
        "生クリーム": "200ml",
        "チーズ（ピザ用）": "40g",
        "塩": "少々",
        "ブラックペッパー": "少々"
    }

    assert ingredients_dict == expected


n1 = float(input('Primeira nota: '))
n2 = float(input('Segunda nota: '))
m = (n1 + n2) / 2
print(f'A media do aluno foi {m:.2f}')

if m >= 7:
    print('Aluno APROVADO')
elif m >=5 and m < 7:
    print('Aluno em RECUPERAÇÃO')
else:
    print('Aluno REPROVADO')


from django import forms
from .models import Twitts

class TwittForm(forms.ModelForm):

    class Meta:
        model = Twitts
        fields = [
            'texto',
        ]

        labels = {
            'texto':'¿ Que estas pensando ?',
        }

        widgets = {
            'texto': forms.Textarea(attrs={'class':'form-control'}),
        }