import numpy as np
import pickle

def get_phones(alphabet='arpabet'):
    if alphabet == 'arpabet':
        vowels = ['aa', 'ae', 'eh', 'ah', 'ea', 'ao', 'ia', 'ey', 'aw', 'ay', 'ax', 'er', 'ih', 'iy', 'uh', 'oh', 'oy', 'ow', 'ua', 'uw']
        consonants = ['el', 'ch', 'en', 'ng', 'sh', 'th', 'zh', 'w', 'dh', 'hh', 'jh', 'em', 'b', 'd', 'g', 'f', 'h', 'k', 'm', 'l', 'n', 'p', 's', 'r', 't', 'v', 'y', 'z'] + ['sil']
        phones = vowels + consonants
        return phones
    if alphabet == 'graphemic':
        vowels = ['a', 'e', 'i', 'o', 'u']
        consonants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z'] + ['sil']
        phones = vowels + consonants
        return phones
    raise ValueError('Alphabet name not recognised: ' + alphabet)

def get_vects(obj, phones, max_len_frames, num_spk):
    n = len(obj['plp'][0][0][0][0][0]) # dimension of mfcc vector

    # Define the tensors required by spectral attack model
    p_vects = np.zeros((num_spk, int((len(phones)-1)*(len(phones)-2)*0.5) , max_len_frames, n))
    q_vects = np.zeros((num_spk, int((len(phones)-1)*(len(phones)-2)*0.5) , max_len_frames, n))
    num_phones_mask = np.zeros((num_spk, int((len(phones)-1)*(len(phones)-2)*0.5)))
    p_mask = np.zeros((num_spk, int((len(phones)-1)*(len(phones)-2)*0.5), max_len_frames, n))
    q_mask = np.zeros((num_spk, int((len(phones)-1)*(len(phones)-2)*0.5), max_len_frames, n))

    for spk in range(num_spk):
        print("On speaker " + str(spk) + " of " + str(num_spk))
        Xs = np.zeros((len(phones) - 1, max_len_frames, n))
        N = np.zeros(len(phones) - 1)

        for utt in range(len(obj['plp'][spk])):
            for w in range(len(obj['plp'][spk][utt])):
                for ph in range(len(obj['plp'][spk][utt][w])):
                    # n.b. this is iterating through the phones that occur sequentially in a word
                    for frame in range(len(obj['plp'][spk][utt][w][ph])):
                        num_frames = N[obj['phone'][spk][utt][w][ph]]
                        if num_frames >= max_len_frames:
                            continue
                        N[obj['phone'][spk][utt][w][ph]] += 1
                        X = np.array(obj['plp'][spk][utt][w][ph][frame])
                        curr_pos = N[obj['phone'][spk][utt][w][ph]] - 1
                        curr_pos = int(curr_pos.item())
                        Xs[obj['phone'][spk][utt][w][ph]][curr_pos] = X

        # Consturct every unique pairing of phones, related mfcc vectors
        k = 0
        for i in range(len(phones) - 1):
            for j in range(i + 1, len(phones) - 1):
                if N[i] == 0 or N[j] == 0:
                    # define Gaussian distribution that has 0 kl div
                    # later the mask will be used to make these features "-1"
                    num_phones_mask[spk][k] = 0
                    # Store length as 1 (in reality 0), to prevent division by 0 later on
                    p_mask[spk][k][0] = np.ones(n)
                    q_mask[spk][k][0] = np.ones(n)
                else:
                    num_phones_mask[spk][k] = 1
                    for frame in range(int(N[i])):
                        p_mask[spk][k][frame] = np.ones(n)
                    for frame in range(int(N[j])):
                        q_mask[spk][k][frame] = np.ones(n)

                p_vects[spk][k] = Xs[i].squeeze()
                q_vects[spk][k] = Xs[j].squeeze()

                k += 1

    return p_vects, q_vects, p_mask, q_mask, num_phones_mask

# pkl_file = '/home/alta/BLTSpeaking/exp-vr313/data/mfcc13/GKTS4-D3/grader/BLXXXgrd02/BLXXXgrd02.pkl'
# #pkl_file = '/home/alta/BLTSpeaking/exp-vr313/data/mfcc13/GKTS4-D3/grader/BLXXXeval3/BLXXXeval3.pkl'
# pkl = pickle.load(open(pkl_file, "rb"))
#
# print("loaded pkl")
#
# # get the phones
# phones = get_phones()
#
# # get the mfcc vects as  [batch_size x 1128 x max_mfccs_per_phone x mfcc_dim] split into p and q groups (for doing kl)
# max_num_mfccs_length = 4000
# p_vects, q_vects, p_mask, q_mask, mask = get_vects(pkl, phones, max_num_mfccs_length)
#
# # get output labels
# y = (pkl['score'])
# y = np.array(y)
#
# # write to output file
# output_file = 'BLXXXgrd02_pqvects.npz'
# #output_file = 'BLXXXeval3_pqvects.npz'
# #pkl_obj = [p_vects.tolist(), q_vects.tolist(),  p_lengths.tolist(), q_lengths.tolist(), mask.tolist(), y.tolist()]
# #pickle.dump(pkl_obj, open(output_file, "wb"))
# np.savez(output_file, p_vects, q_vects, p_lengths, q_lengths, mask, y)


import os
import time
import urllib.request
import urllib.parse
import json
import jinja2

from city import City
from config import gmaps

class GMapsManager:

    @staticmethod
    def get_cities_from_database():
        data = None
        try:
            database = open(gmaps['DATABASE_PATH'], 'r', encoding='utf-8')
            try:
                data = database.readlines()
            finally:
                database.close()
        except IOError:
            print('IOError: Can\'t open file or read data')

        if data:
            cities = list()
            for line in data:
                name, lat, lng = line.split(', ')
                lat, lng = float(lat[1:]), float(lng[:-2])
                cities.append(City(name, lat, lng))
            return cities

        return list()

    @staticmethod
    def write_cities_to_database(cities):
        if cities:
            try:
                database = open(gmaps['DATABASE_PATH'], 'a', encoding='utf-8')
                try:
                    database.write('\n'.join([str(city) for city in cities]))
                    database.write('\n')
                finally:
                    database.close()
            except IOError:
                print('IOError: Can\'t write data')

    @staticmethod
    def get_city_from_gmaps(city_name):
        parameters = {
            'address': city_name,
            'sensor': 'false'
        }

        param_string = urllib.parse.urlencode(parameters)
        req = urllib.request.Request(gmaps['URL'] + param_string)
        response = urllib.request.urlopen(req).read()
        json_data = json.loads(response.decode('utf-8'))
        city_pos = json_data['results'][0]['geometry']['location']

        new_city = City(city_name, float(city_pos['lat']), float(city_pos['lng']))
        print('Just add new city: ', new_city)
        return new_city

    @staticmethod
    def get_cities(cities_names):
        existing_cities = GMapsManager.get_cities_from_database()
        existing_names = [city.name for city in existing_cities]

        new_cities = list()
        for city_name in cities_names:
            if city_name not in existing_names:
                new_cities.append(GMapsManager.get_city_from_gmaps(city_name))
                time.sleep(1)

        GMapsManager.write_cities_to_database(new_cities)
        return existing_cities + new_cities

    @staticmethod
    def make_gmaps_webpage(tour, iter_counter):
        env = jinja2.Environment(loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
        template = env.get_template('templates/template.html')

        tour_lats = [city.lat for city in tour]
        tour_lngs = [city.lng for city in tour]

        center_lat = (max(tour_lats) + min(tour_lats)) / 2
        center_lng = (max(tour_lngs) + min(tour_lngs)) / 2

        gmaps_content = template.render({
            'center_lat': center_lat,
            'center_lng': center_lng,
            'tour': tour,
            'iter_counter': iter_counter
        })

        try:
            webpage = open(gmaps['WEBMAP_PATH'], 'w', encoding='utf-8')
            try:
                webpage.write(gmaps_content)
            finally:
                webpage.close()
        except IOError:
            print('IOError: Can\'t write data')


import copy

from PyQt5.QtCore import QObject, pyqtSignal

from src.utils.global_registration_util import do_fgr_registration

class FGRRegistrator(QObject):
    signal_finished = pyqtSignal()
    signal_registration_done = pyqtSignal(object, object)

    def __init__(self, pc1, pc2, init_transformation,
                 voxel_size, division_factor, use_absolute_scale, decrease_mu, maximum_correspondence,
                 max_iterations, tuple_scale, max_tuple_count, tuple_test):
        super().__init__()

        self.pc1 = copy.deepcopy(pc1)
        self.pc2 = copy.deepcopy(pc2)
        self.pc1.transform(init_transformation)

        self.voxel_size = voxel_size
        self.division_factor = division_factor
        self.use_absolute_scale = use_absolute_scale
        self.decrease_mu = decrease_mu
        self.maximum_correspondence = maximum_correspondence
        self.max_iteration = max_iterations
        self.tuple_scale = tuple_scale
        self.max_tuple_count = max_tuple_count
        self.tuple_test = tuple_test

    def do_registration(self):
        results = do_fgr_registration(self.pc1, self.pc2, self.voxel_size,
                                      self.division_factor,
                                      self.use_absolute_scale,
                                      self.decrease_mu,
                                      self.maximum_correspondence,
                                      self.max_iteration,
                                      self.tuple_scale,
                                      self.max_tuple_count,
                                      self.tuple_test)

        self.signal_registration_done.emit(results, None)
        self.signal_finished.emit()


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

# In[11]:

import numpy as np
from utils import draw3d, read_obj, draw2d, get_projection

def Projection_3Dto2D(points_3d, P):
    points_3d_homo = np.concatenate([points_3d, np.ones((points_3d.shape[0], 1))], axis=1)
    points_2d_homo = np.dot(points_3d_homo, P.T)
    vertices2d = points_2d_homo[:, :2] / points_2d_homo[:, 2:]
    return vertices2d

if __name__ == "__main__":
    # Parameters
    ax = 1                      # scale factor
    ay = 1                      # scale factor
    x0 = 0                      # principal point
    y0 = 0                      # principal point
    skew = 0                    # skew parameter
    roll = 0                   # rotation
    pitch = 0                   # rotation
    yaw = 0                     # rotation
    translation = [0, 0, 500]     # translation : camera location

    projection = get_projection(ax, ay, x0, y0, skew, roll, pitch, yaw, translation)

    vertices3d, faces = read_obj("cat.obj")

    draw3d(vertices3d, faces)

    vertices2d = Projection_3Dto2D(vertices3d, projection)

    draw2d(vertices2d, faces)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2018/10/25 20:20
# @Author  : WeidongLi
# @Email   : weidonghappy@163.com
# @File    : looooggggg.py
# @Software: PyCharm
import logging
import datetime

logging.basicConfig(level=logging.DEBUG, format='%(levelname)s %(module)s line:%(lineno)d %(asctime)s %(message)s',
                    datefmt='%H:%M:%S')
formatter = logging.Formatter('%(levelname)s %(module)s line:%(lineno)d %(asctime)s %(message)s')
filehdlr = logging.FileHandler('log-' + datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S'))
# datetime.now().strftime('%Y-%m-%d %I:%M:%S.%f %p')
filehdlr.setLevel(logging.DEBUG)
filehdlr.setFormatter(formatter)
logging.getLogger().addHandler(filehdlr)
# filehadler = logging.FileHandler('log-' + datetime.datetime.now().strftime('%Y-%m-%d %H-%M-%S'))
# filehadler.setFormatter(formatter)
# filehadler.setLevel(logging.DEBUG)
logging.info('hehe'*100)


from collections import OrderedDict
from pymongo.response import Response
from rest_framework.pagination import PageNumberPagination

class StandarPagination(PageNumberPagination):
    page_size = 20  # 默认每页显示条数配置
    page_query_param = 'page'  # “页数”的请求参数名称, 默认是page
    page_size_query_param = 'page_size'  # “分页大小”的请求参数名称

    # 进入父类 PageNumberPagination 可看响应体返回字段.
    #  def get_paginated_response(self, data):
    #  return Response(OrderedDict([
    #    ('count', self.page.paginator.count),
    #    ('next', self.get_next_link()),
    #    ('previous', self.get_previous_link()),
    #    ('results', data)
    #  ]))

    # 觉得不适用, 那就拷贝出来,重载函数, 自己多加几个字段.
    # (可通过官方文档或直接调试得知从哪些属性获取正确的值.)
    def get_paginated_response(self, data):
        return Response(OrderedDict([
            ('count', self.page.paginator.count),
            ('next', self.get_next_link()),
            ('previous', self.get_previous_link()),
            ('page', self.page.number),
            ('total_page', self.page.paginator.num_pages),
            ('page_size', self.page.paginator.per_page),
            ('results', data)
        ]))

# class Pagination(object):
#     """自定义分页（Bootstrap版）"""
#
#     def __init__(self, current_page, total_count, base_url, per_page=10, max_show=11):
#         """
#         :param current_page: 当前请求的页码
#         :param total_count: 总数据量
#         :param base_url: 请求的URL
#         :param per_page: 每页显示的数据量，默认值为10
#         :param max_show: 页面上最多显示多少个页码，默认值为11
#         """
#         try:
#             self.current_page = int(current_page)
#         except Exception as e:
#             # 取不到或者页码数不是数字都默认展示第1页
#             self.current_page = 1
#         # 定义每页显示多少条数据
#         self.per_page = per_page
#         # 计算出总页码数
#         total_page, more = divmod(total_count, per_page)
#         if more:
#             total_page += 1
#         self.total_page = total_page
#         # 定义页面上最多显示多少页码(为了左右对称，一般设为奇数)
#         self.max_show = max_show
#         self.half_show = max_show // 2
#         self.base_url = base_url
#
#     @property
#     def start(self):
#         return (self.current_page - 1) * self.per_page
#
#     @property
#     def end(self):
#         return self.current_page * self.per_page


import glob
import subprocess
import yaml
import sys

def yosys_script(name, files):
    files = " ".join([f"{name}/src/{fn}" for fn in files])

    return f"read_verilog -sv {files}; synth -flatten -top toplevel_chip; setundef -undriven -zero; setundef -zero; async2sync; synth -top toplevel_chip; rename toplevel_chip {name}; write_verilog -attr2comment {name}/flattened.v; check; stat;"

def run_yosys(name, files):
    out = subprocess.check_output(["yosys", "-p", yosys_script(name, files)]).decode()
    out = out.split("Printing statistics.")[-1].split("End of script")[0].split("Warnings")[0].strip()
    with open(f"{name}/flattened_stats.txt", "w+") as f:
        f.write(out+"\n")

def write_wrapper(name, topname):
    wrapper = """
        module toplevel_chip (
            input [13:0] io_in,
            output [13:0] io_out
        );

            CHIPNAME mchip (
                .io_in(io_in[7:0]),
                .io_out(io_out[7:0])
            );

        endmodule
    """.replace("CHIPNAME", topname)

    with open(f"{name}/src/wrapper.v", "w+") as f:
        f.write(wrapper)

def write_wrapper_clocked(name, topname):
    wrapper = """
        module toplevel_chip (
            input [13:0] io_in,
            output [13:0] io_out
        );

            // CLOCKED
            CHIPNAME mchip (
                .io_in({io_in[7:1], io_in[12]}),
                .io_out(io_out[7:0])
            );

        endmodule
    """.replace("CHIPNAME", topname)

    with open(f"{name}/src/wrapper.v", "w+") as f:
        f.write(wrapper)

if len(sys.argv) > 1:
    g = sys.argv[1]
else:
    g = "d*"

for des in sorted(list(glob.glob(g))):
    with open(f"{des}/info.yaml") as f:
        data = yaml.load(f, Loader=yaml.Loader)

    if "tt02_fmt" in data["project"] and data["project"]["tt02_fmt"] == "clocked":
        print("Processing OLD (clocked)", des)
        sources = data["project"]["source_files"] + ["wrapper.v"]

        write_wrapper_clocked(des, data["project"]["top_module"])
        run_yosys(des, sources)

    elif "tt02_fmt" in data["project"] and data["project"]["tt02_fmt"]:
        print("Processing OLD (async)", des)
        sources = data["project"]["source_files"] + ["wrapper.v"]

        write_wrapper(des, data["project"]["top_module"])
        run_yosys(des, sources)

    else:
        print("Processing NEW", des)
        assert data["project"]["top_module"] == "toplevel_chip"
        sources = data["project"]["source_files"]

        run_yosys(des, sources)


from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedSmoothNodeAI import DistributedSmoothNodeAI

from toontown.catalog import CatalogItem
from toontown.estate import HouseGlobals

class DistributedFurnitureItemAI(DistributedSmoothNodeAI):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFurnitureItemAI')

    def __init__(self, air, house, furnitureMgr, catalogItem):
        DistributedSmoothNodeAI.__init__(self, air)
        self.house = house
        self.furnitureMgr = furnitureMgr
        self.catalogItem = catalogItem
        self.mode = 0
        self.avId = 0

    def announceGenerate(self):
        DistributedSmoothNodeAI.announceGenerate(self)
        self.b_setPosHpr(*self.catalogItem.posHpr)

    def getItem(self):
        return [self.furnitureMgr.doId, self.catalogItem.getBlob(store=CatalogItem.Customization)]

    def requestPosHpr(self, final, x, y, z, h, p, r, t):
        senderId = self.air.getAvatarIdFromSender()
        posHpr = (x, y, z, h, p, r)
        if senderId != self.house.avatarId:
            # Hey! What are you doing!?
            self.notify.warning('%d tried to move furniture of house owned by %d!' % (senderId, self.house.ownerId))
            return

        if not final and self.mode != HouseGlobals.FURNITURE_MODE_START:
            self.b_setMode(HouseGlobals.FURNITURE_MODE_START, senderId)
        elif final and self.mode == HouseGlobals.FURNITURE_MODE_START:
            self.b_setMode(HouseGlobals.FURNITURE_MODE_STOP, senderId)
            self.b_setMode(HouseGlobals.FURNITURE_MODE_OFF, senderId)
            self.b_setPosHpr(*posHpr)

        self.catalogItem.posHpr = posHpr
        self.sendUpdate('setSmPosHpr', [x, y, z, h, p, r, t])

    def setMode(self, mode, avId):
        self.mode = mode
        self.avId = avId

    def d_setMode(self, mode, avId):
        self.sendUpdate('setMode', [mode, avId])

    def b_setMode(self, mode, avId):
        self.setMode(mode, avId)
        self.d_setMode(mode, avId)

    def getMode(self):
        return self.mode, self.avId


'''
Problem Solving Baekjoon 1347
Author: Injun Son
Date: October 26, 2020
'''
import sys
import math

'''
순차적인 아이디어:
1. 큰 2차원 배열을 만들고 직접 이동하는 것들을 시뮬레이션하면되지 않을까
2. 그 2차원 배열을 미리 '#', 즉 벽으로 채워놓으면 되지 않을까
3. 그런데 큰 2차원 배열에서 정답에 해당하는 부분만 어떻게 찾아내지? -> 발상 못함
4. 모든 행과 열에는 적어도 하나의 이동할 수 있는 칸이 있다고 했으니,
제일 왼쪽 행, 제일 위 열, 제일 오른쪽 행, 제일 아래쪽 열을 구하면된다!
'''
#방향: 남 서 북 동
dx = [0, -1, 0, 1]
dy = [1, 0, -1, 0]
graph = [ ['#']*111 for _ in range(111)]
dir = 0
N = int(input())
command_list = input()
cur_y, cur_x = 50, 50
graph[cur_y][cur_x]='.'

leftmost_x, rightmost_x = 111, -1
highest_y, lowest_y = 111,-1

for command in command_list:
    if command == 'R':
        dir = (dir+1)%4

    elif command == 'L':
        if dir >=1:
            dir -=1
        elif dir==0:
            dir = 3
    else:
        cur_y += dy[dir]
        cur_x += dx[dir]
        graph[cur_y][cur_x] = '.'

for i in range(111):
    for j in range(111):
        if graph[i][j]=='.':
            if j < leftmost_x:
                leftmost_x = j

            if i < highest_y:
                highest_y = i

            if j > rightmost_x:
                rightmost_x = j

            if i > lowest_y:
                lowest_y = i

for i in range(highest_y, lowest_y+1):
    for j in range(leftmost_x, rightmost_x +1):
        print(graph[i][j], end="")
    print()


start_id = 1

class DataBlock(object):
    def __init__(self, id, security, type, faction, level):
        self.id = id
        self.security = security
        self.type = type
        self.faction = faction
        self.level = level
        self.item_quantity = {}

    def set_item_quantity(self, item_quantity):
        self.item_quantity = item_quantity
        self.item_quantity = dict(
            sorted(self.item_quantity.items(), key=lambda item: item[0])
        )

    def __str__(self):
        output = ""
        for key in self.item_quantity.keys():
            output = output + str(self.id) + "$"
            output = output + self.security + "$"
            output = output + self.type + "$"
            output = output + self.faction + "$"
            output = output + self.level + "$"
            output = output + key + "$"
            output = output + str(self.item_quantity[key]) + "\n"

        output = output[:-1]
        return output

with open("data.txt", "r") as file:
    summer = {}
    new_id = start_id
    previous_id = -1
    for line in file:
        words = line.split("\t")
        current_id, security, type, faction, level, item, quantity = words
        if previous_id != current_id:
            if summer:
                block.set_item_quantity(summer)
                print(block)
                summer = {}
            block = DataBlock(new_id, security, type, faction, level)
            new_id += 1
        previous_id = current_id
        if summer.get(item):
            summer[item] += int(quantity)
        else:
            summer[item] = int(quantity)

    if summer:
        block.set_item_quantity(summer)
        print(block)


import matplotlib.pyplot as plt
import numpy as np

# Albedos from file:
with open("F:/olafd/s3snow/from_alex/20181126/comp_albedo_spectral_clean_polluted.csv") as f:
    data = f.read()
data = data.split('\n')

wvl = [row.split(' ')[0] for row in data]
alb_polluted = [row.split(' ')[1] for row in data]
alb_clean = [row.split(' ')[2] for row in data]

# t2 = np.arange(0.4, 2.39, 0.01)
plt.plot(wvl, alb_polluted, 'b')
plt.plot(wvl, alb_clean, 'g')

# plot properties and legends
line1, = plt.plot(wvl, alb_polluted, 'b', label='polluted')
line2, = plt.plot(wvl, alb_clean, 'g', label='clean')
data_legend = plt.legend(handles=[line1,line2], loc=0, prop={'size': 10})
data_legend.legendHandles[0].set_linewidth(2.0)

plt.text(1250.0, 0.6, 'S3A_OL_1_EFR____20180424T100524\n'
                     r''                             '\n'
                     r'                               Lautaret Site' '\n'
                     r'                               45.04N, 6.41E',
         style='italic', bbox={'facecolor': 'green', 'alpha': 0.2, 'pad': 5})

plt.ylim([0.0, 1.0])
plt.xlabel('Wavelength (nm)')
plt.ylabel('Albedo (dl)')
plt.title('Planar spectral albedo from clean and polluted snow algorithm')
plt.grid(True)
plt.savefig("comp_albedo_spectral_clean_polluted.png")

plt.show()


from django.urls import path
from . import views

urlpatterns = [
    path('',views.pollshome,name='pollshome'),
    path('createpolls/',views.createPolls,name='createpolls'),
    path('createpublicpoll/',views.createPublicPoll,name='createpublicpoll'),
    path('createprivatepoll/',views.createPrivatePoll,name='createprivatepoll'),
    path('privateinvite/<int:poll_id>',views.privateinvite,name='privateinvite'),
    path('publicpolls/',views.publicPolls,name='publicpolls'),
    path("polldetails/<int:poll_id>", views.publicpolldetails, name="polldetails"),
    path("polldetails/<int:poll_id>/editpublicpoll", views.editpublicpoll, name="editpublicpoll"),
    path("polldetails/<int:poll_id>/deletepublicpoll", views.deletepublicpoll, name="deletepublicpoll"),
    path("privatepolldetails/<int:poll_id>/deleteprivatepoll", views.deleteprivatepoll, name="deleteprivatepoll"),
    path('privatepolls/',views.privatePolls,name='privatepolls'),
    path("privatepolldetails/<int:poll_id>", views.privatepolldetails, name="privatepolldetails"),
    path("privatepolldetails/<int:poll_id>/editprivatepoll", views.editprivatepoll, name="editprivatepoll"),
    path('polldetails/<int:poll_id>/vote/', views.public_vote, name='publicvote'),
    path('polldetails/<int:poll_id>/results/', views.public_results, name='publicresults'),
    path('privatepolldetails/<int:poll_id>/vote/', views.private_vote, name='privatevote'),
    path('privatepolldetails/<int:poll_id>/userinvite/', views.private_userinvite, name='privateuserinvite'),
    path('invitations/', views.privateinvitations, name='privateinvitations'),
    path('invitations/acceptedinvites', views.acceptedinvites, name='acceptedinvites'),
    path('invitations/<int:poll_id>/invitechoice', views.invitechoice, name='invitechoice'),
    path('privatepolldetails/<int:poll_id>/results/', views.private_results, name='privateresults'),
    path('votinghistory/', views.votingHistory, name='votinghistory'),
    path('api/publicresultdata/<int:poll_id>', views.publicResultData, name='publicresultdata'),
    path('api/privateresultdata/<int:poll_id>', views.privateResultData, name='privateresultdata'),
]


"""
ABossBattle.py
"""

import Main_Battle as Battle
import pygame
from GlobalVar import *
import pyAnimation
import ATextBox
import ASequence

def a_DoBoss(screen, playerInfo):

    # Difficulty
    diff = playerInfo.Beated(False)["bosslevel"]

    # Counter for the boss
    counter = -1
    battleResults = "win"

    if diff == 3:
        LightName = True
    else:
        LightName = False

    # Initiate bossInfo, Pass in boss information
    bossInfo = ABoss.Boss()
    BattleClass = Battle.AdventureBattle(screen, diff,
                                         playerInfo, bossInfo, BattleGraphics=DefaultBattleWallpaper[diff],
                                         LightName = LightName)

    pyAnimation.EnterFade(screen, BattleClass.Fade, CentralClock, GameFPS)

    BattleClass.Dialogue("Narrator", "You travelled through the world to beat Mathematicians\n" +
                         "Here and now, you will face the man of your dreams.")

    # Loop for incrementing the boss
    while counter <= 2:

        if battleResults == "escape":
            return
        elif battleResults == "lose":
            return
        elif battleResults == "draw":
            BattleClass.FightContinues()
        elif battleResults == "win":
            if counter != -1:
                BattleClass.EndDialogue()
            if counter + 1 <= 1:
                # Increment counter
                counter += 1

                # Pass in new boss info
                bossInfo = BossDatabase[diff][counter]
                BattleClass.Reinitialize(bossInfo, diff = diff + (3 if counter == 1 else 0), round = counter + 1)

                # Display boss
                BattleClass.BossAppears("Final Boss" if counter == 1 else "Mathematician")
                BattleClass.StartDialogue()
            else:
                break

        # Battle sequence
        battleResults = BattleClass.Main()

    # Reads player info
    playerInfoDict = playerInfo.Beated(0)

    # Rewards will not be given if the player has beaten the boss once before
    if playerInfoDict["beat"]:

        # Asks whether the player would like to watch the epilogue again
        popUp = ATextBox.PopUp(screen)
        popUp.TextBox.InsertText("Would you like to watch the Epilogue again?", "center", True)
        nah = popUp.TextBox.InsertMenu("No")
        ya = popUp.TextBox.InsertMenu("Yes")
        popUp.TextBox.Finalize()

        popUp.Start()

        run = True
        while run:

            for event in pygame.event.get():
                Quit(event)
                result = popUp.TextBox.Event(event, popUp.Offset())
                if result == nah:
                    epilogue = False
                    run = False
                elif result == ya:
                    epilogue = True
                    run = False

            popUp.Blit()
            LoopBundle()
    # If the player hasn't beat the boss before
    else:
        BattleClass.Rewards()
        if playerInfoDict["bosslevel"] == 3:
            epilogue = True
        else:
            epilogue = False

    playerInfo.Beated(1)

    # The player has defeated all three bosses
    if epilogue:
        playerInfo.BeatFlag()
        return ASequence.Epilogue(screen)
    else:
        return False

def main():
    import APlayer
    screen = pygame.display.set_mode((1280, 800))
    playerInfo = APlayer.LoadSave("TestPlayer.txt")
    a_DoBoss(screen, playerInfo)

if __name__ == "__main__":
    main()


# button.py
# Written by Alexander Sfakianos
# October 4th, 2016
# Creates button class for factory.py and blackjack.py

from graphics import *
from math import *

class Buttons:
   """Allows buttons to be created on demand with location and text."""

   def __init__(self, win, center, width, height, label):
      self.xMod, self.yMod = width / 2, height / 2
      self.xC, self.yC = center.getX(), center.getY()
      self.xMin = self.xC - self.xMod
      self.xMax = self.xC + self.xMod
      self.yMin = self.yC - self.yMod
      self.yMax = self.yC + self.yMod
      pt1 = Point(self.xMin, self.yMin)
      pt2 = Point(self.xMax, self.yMax)
      self.outline = Rectangle(pt1, pt2)
      self.outline.setFill('lightgray')
      self.outline.draw(win)
      self.label = Text(center, label)
      self.label.draw(win)
      self.deactivate()

   def clicked(self, pt):
      wasClicked = False
      if self.xMin <= pt.getX() and self.xMax >= pt.getX():
         if self.yMin <= pt.getY() and self.yMax >= pt.getY():
            if self.active == True:
               wasClicked = True
      return wasClicked

   def getLabel(self):
      return self.label.getText()

   def setLabel(self, label):
      self.label.setText(label)

   def activate(self):
      self.label.setFill('black')
      self.outline.setWidth(2)
      self.active = True

   def deactivate(self):
      self.label.setFill('darkgrey')
      self.outline.setWidth(1)
      self.active = False

   def remove(self):
      """Undraws the given button"""
      self.outline.undraw()
      self.label.undraw()

   def buttonMove(self, pt):
      """Moves the button to the given point"""
      newX, newY = pt.getX(), pt.getY()
      moveX, moveY = newX - self.xC, newY - self.yC
      self.outline.move(moveX, moveY)
      self.label.move(moveX, moveY)
      self.xC, self.yC = newX, newY
      self.xMin = self.xC - self.xMod
      self.xMax = self.xC + self.xMod
      self.yMin = self.yC - self.yMod
      self.yMax = self.yC + self.yMod


import datetime as datetime
import os
import warnings

import numpy as np
import pandas as pd
import statsmodels.api as sm
import yfinance as yf
from scipy.stats import multivariate_normal, norm, t

warnings.filterwarnings("ignore")
from math import *

from arch import arch_model
from pypfopt import HRPOpt, risk_models
from pypfopt.efficient_frontier import EfficientFrontier
from scipy.optimize import minimize
from sklearn.decomposition import PCA

# from maxt import multskewt

os.chdir("/home/sahil/diss")
k = pd.read_csv("djia.csv")
# Convert string to datetime datatype consisting of only dates and not time
k["Date"] = pd.to_datetime(k.Date).apply(lambda x: x.date())

def multivariate_t_distribution(x, mu, Sigma, df, d):
    """
    Multivariate t-student density:
    output:
        the density of the given element
    input:
        x = parameter (d dimensional numpy array or scalar)
        mu = mean (d dimensional numpy array or scalar)
        Sigma = scale matrix (dxd numpy array)
        df = degrees of freedom
        d: dimension
    """
    Num = gamma(1.0 * (d + df) / 2)
    Denom = (
        gamma(1.0 * df / 2)
        * pow(df * pi, 1.0 * d / 2)
        * pow(np.linalg.det(Sigma), 1.0 / 2)
        * pow(
            1
            + (1.0 / df)
            * np.dot(np.dot((x - mu), np.linalg.inv(Sigma)), (x - mu)),
            1.0 * (d + df) / 2,
        )
    )
    d = 1.0 * Num / Denom
    return d

def likelihood_skew_t(y, alpha, beta, omega, skew, v, init_vol):
    # Dimension of data
    d = y.shape[1]

    def minimizer(params):
        v = params[120]
        loglike = []
        for j in range(d):
            vol = [init_vol[j]]
            for i in range(1, len(y)):
                alpha = params[j]
                beta = params[30 + j]
                omega = params[60 + j]
                skew = params[90 + j]
                cond_vol = beta * vol[i - 1] + alpha * y[i - 1][j] ** 2 + omega
                if (alpha + beta > 1) and omega < 0:
                    return 1000
                if cond_vol <= 0:
                    return 1000
                vol.append(cond_vol)
                pdf = np.float(
                    multskewt(
                        y[i],
                        0,
                        cond_vol,
                        skew,
                        v,
                    )
                )

                loglike.append(-np.log(pdf))
        return np.array(loglike).mean()

    res = minimize(
        minimizer,
        alpha + beta + omega + skew + [v],
        method="nelder-mead",
        bounds=((0.01, 1),) * 60
        + ((0.005, 1),) * 30
        + ((-1, 1),) * 30
        + ((2.1, 100)),
        tol=1e-6,
    )
    return res

def gen_ret(df):
    assets = [
        i for i in df.columns if i != "Date"
    ]  # Extracting Column names of all assets

    for asset in assets:
        df[asset + "_logret"] = (
            np.log(df[asset] / df[asset].shift(1)) * 100
        )  # Calculating log returns for an asset
        # df[asset + "_perret"] = (
        #    df[asset].pct_change() * 100
        # )  # Calculating percentage Returns for an asset
    # perret_cols = [i for i in df.columns if "_perret" in i]
    return df

def cov_est(pvar, w, lamb):
    # var = np.diag(list(pvar[0:3]))
    # # var = np.diag(pvar[0:3])
    # w_trans = w[3:]
    # w_left = w[:][3:]

    return w.T * np.diag(pvar) * w

def predict(y, omega, alpha, beta):
    y = np.array(y)
    vol = [0]
    for i in range(1, len(y)):
        cond_vol = beta * vol[i - 1] + alpha * y[i - 1] ** 2 + omega
        vol.append(cond_vol)
    return vol

k = gen_ret(k)
k = k.dropna()
lnret = [i for i in k.columns if "_logret" in i]

pca = PCA(n_components=len(lnret))
krets = k[lnret + ["Date"]]
ktrain = krets[krets.Date < datetime.date(2019, 6, 1)]
ktest = krets[krets.Date > datetime.date(2019, 6, 1)]
# Store lenght of training set
tlen = len(ktrain)
# Column names of principal components
pcols = ["p" + str(i + 1) for i in range(29)]
# Column names of Garch volatility of principal components
pcolsvar = [f"p{i+1}_vol" for i in range(29)]
# Extract the principal components from train set and
# do the transformation on the entire set using eigenvectors
# obtained from the training set
pca = pca.fit(ktrain[lnret])
k[pcols] = pca.transform(k[lnret])
ktrain[pcols] = k[pcols].iloc[0:tlen]
ktest[pcols] = k[pcols].iloc[tlen:]
# Extract the eigenvectors
w = np.matrix(pca.components_)
# Get the eigenvalues
lamb = pca.explained_variance_
loglike = 0
for i in range(29):
    model = arch_model(
        ktrain[pcols[i]],
        mean="Zero",
        vol="GARCH",
        p=1,
        o=0,
        q=1,
    )
    mod = model.fit()
    loglike = loglike + mod.loglikelihood
    ktrain[pcolsvar[i]] = mod.conditional_volatility ** 2
    alpha = mod.params["alpha[1]"]
    beta = mod.params["beta[1]"]
    omega = mod.params["omega"]
    preds = predict(k[pcols[i]], omega, alpha, beta)
    k[pcolsvar[i]] = preds
    ktrain[f"{pcolsvar[i]}_nonlib"] = preds[:tlen]
    ktest[pcolsvar[i]] = preds[tlen:]
print(f"Normal Loglikelihood={loglike/(len(ktrain))}")
# Extracting time varying covariance matrix

k["cov_t"] = k[pcolsvar].apply(lambda row: cov_est(row, w, lamb), axis=1)

# Save for further processing
k.to_pickle("returns_pca.pkl")

ktrain["cov_t"] = ktrain[pcolsvar].apply(
    lambda row: cov_est(row, w, lamb), axis=1
)

ktest["cov_t"] = ktest[pcolsvar].apply(
    lambda row: cov_est(row, w, lamb), axis=1
)

ktrain["log_t"] = ktrain.apply(
    lambda row: multivariate_normal.logpdf(
        row[lnret], [0] * len(pcols), row["cov_t"]
    ),
    axis=1,
)
ktest["log_t"] = ktest.apply(
    lambda row: multivariate_normal.logpdf(
        row[lnret], [0] * len(pcols), row["cov_t"]
    ),
    axis=1,
)

v = 8.9
ktrain["log_t_tdist"] = ktrain.apply(
    lambda row: np.log(
        multivariate_t_distribution(
            row[lnret],
            [0] * len(pcols),
            row["cov_t"],
            v,
            len(pcols),
        )
    ),
    axis=1,
)
ktest["log_t_tdist"] = ktest.apply(
    lambda row: np.log(
        multivariate_t_distribution(
            row[lnret],
            [0] * len(pcols),
            row["cov_t"],
            v,
            len(pcols),
        )
    ),
    axis=1,
)

print(ktrain.log_t.mean())
print(ktrain.log_t_tdist.mean())


add = 0
for i in range(1, 11):
	add = add + i
print('1 - 10 까지의 합 : ', add)

# 1~10 까지 홀수합 출력 !!
odd = 0
for i in range(1, 11, 2):
	odd = odd + i
print(' 1~10 까지 홀수 합 : ', odd)

# 1~10까지 짝수 합 출력 !!
even = 0
for i in range(2, 11, 2):
	even = even + i
print(' 1~10 까지 짝수 합 : ', even)


import sys
from PyQt5.QtWidgets import QApplication, \
    QWidget, QInputDialog, QLineEdit, QMainWindow
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets, QtCore
import PyQt5
from PyQt5 import QtGui

class MainWindow ( QMainWindow ):

    def __init__(self):
        super().__init__( )

        dlgi = QInputDialog()
        text, ok = dlgi.getText(self, 'InputDialog', 'EnterYourName = ')

        if ok:
            print( "PRint from input are", text )
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    app.exec_()
    print ("process doen")


import json
import csv

def json_to_csv(json_data):
  keys = list(json_data.keys())
  header = sorted(keys)
  csv_data = []
  for k in header:
    csv_data.append(json_data[k])
  return csv_data, header

# filename = "NAS_feedback_state"
# filename = "NAS_learning_outcomes_state"
# filename = "NAS_participation_state"
filename = "NAS_performance_percentage_state"

with open(filename + ".json", 'r') as f:
  json_data = json.loads(f.read())

list_size = len(json_data["state 1"])

header = ["state_name"]
csv_data = []
for x in range(1, 38):
  state_key = "state " + str(x)
  for y in range(0, list_size-1):
    parsed_csv, parsed_header = json_to_csv(json_data[state_key][y])
    if y == 0 and x == 1:
      header.extend(parsed_header)
    temp = [json_data[state_key][list_size-1]["state_name"]]
    temp.extend(parsed_csv)
    csv_data.append(temp)

with open(filename + ".csv", 'w+') as csvfile:
  csv_writer = csv.writer(csvfile, delimiter=';')
  csv_writer.writerow(header)
  for row in csv_data:
    csv_writer.writerow(row)


from telegram import Update
from telegram.ext import CallbackContext
from telegram import ReplyKeyboardMarkup
from telegram import ReplyKeyboardRemove

from .admin import admin

from ...states import States
from ...data import text
from ...database import db_session

def pick_deal(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    deals = db_session.get_deals_list()

    reply_markup = []

    for deal in deals:
        deal = f"{deal[0]}) - {deal[1]}"
        reply_markup.append([deal])

    if reply_markup == []:
        context.bot.send_message(
            chat_id=chat_id,
            text=text["no_deals_for_now"],
        )
        return States.ADMIN_MENU

    reply_markup.append([text["back"]])

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["choose_deal"],
        reply_markup=markup,
    )
    return States.ADMIN_DEAL_CHOSEN

def get_deal(option, deals):
    for deal in deals:
        if option == deal[0]:
            print(deal)
            return deal
    return None

def deal_feedback(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id
    msg = update.message.text

    try:
        msg = msg.split(")")
        option = int(msg[0])
    except ValueError:
        context.bot.send_message(chat_id=chat_id, text=text["err_unexpected_type"])
        return pick_deal(update, context)

    deals = db_session.get_deals_list()
    deal = get_deal(option, deals)
    if deal != None:
        context.user_data["chosen_deal"] = deal
    else:
        return pick_deal(update, context)

    reply_markup = [
        [text["yes"]],
        [text["no"]],
        [text["back"]]
    ]

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["has_deal_been"],
        reply_markup=markup,
    )
    return States.HAS_DEAL_BEEN

def deal_no(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_no_admin"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_NO_DESCRIPTION

def send_deal_description(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id
    msg = update.message.text

    chosen_deal = context.user_data["chosen_deal"]
    db_session.delete_deal(chosen_deal)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_no_admin_descr_thx"],
    )

    context.bot.send_message(
        chat_id=chosen_deal[2],
        text=text["deal_no_lead"] + msg + "\"",
        #reply_markup=ReplyKeyboardRemove()
    )
    context.user_data.pop("chosen_deal")
    return admin(update, context)

def deal_yes(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_summ"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_YES_SUMM

def deal_yes_summ(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    mssg = update.message.text

    context.user_data["deal_summ"] = mssg

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_percent"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_YES_PERCENT

def deal_yes_percent(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    mssg = update.message.text

    deal_percent = context.user_data["deal_percent"] = mssg

    chosen_deal = context.user_data["chosen_deal"]
    leadgen_id = chosen_deal.leadgen_id
    leadgen = db_session.get_user(leadgen_id)
    leadgen_full_name = f"{leadgen.first_name} {leadgen.last_name}"
    linkedin = chosen_deal.linkedin
    deal_summ = context.user_data["deal_summ"]

    leadgen_get = round(int(deal_summ) / 100 * int(deal_percent))
    context.user_data["leadgen_get"] = leadgen_get

    reply_markup = [
        [text["yes"]],
        [text["cancel"]]
    ]

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_approve"].format(leadgen_full_name, linkedin, deal_summ, deal_percent, leadgen_get),
        reply_markup=markup
    )

    return States.DEAL_YES_APPROVE

def deal_yes_approve(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_yes_admin_thanks"],
    )

    chosen_deal = context.user_data["chosen_deal"]
    deal_summ = context.user_data["deal_summ"]
    deal_percent = context.user_data["deal_percent"]
    leadgen_get = context.user_data["leadgen_get"]
    # print(chosen_deal)
    db_session.deal_done(chosen_deal, leadgen_get)

    context.bot.send_message(
        chat_id=chosen_deal[2],
        text=text["deal_yes_lead_thanks"].format(leadgen_get),
    )
    context.user_data.pop("chosen_deal")
    context.user_data.pop("deal_summ")
    context.user_data.pop("deal_percent")
    context.user_data.pop("leadgen_get")
    return admin(update, context)


import os
from datetime import datetime
from glob import glob
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, validator
import uvicorn

from gmail import email_with_attachment

app = FastAPI()

class DateTimeModeMixin(BaseModel):
    # To add timestamp script executed, https://pydantic-docs.helpmanual.io/usage/validators/
    created_at: datetime = None

    @validator("created_at", pre=True, always=True)
    def default_datetime(cls, value:datetime) -> datetime:
        return value or datetime.now()

class Job(DateTimeModeMixin):
    name: str
    description: Optional[str]

jobs = []

def job_email_with_attachment():
    to_email = os.getenv("TO_EMAIL").split(';')
    attachments = glob('data/*.csv')
    email_with_attachment(header='header...', recipient=to_email, body='body...', attachments=attachments)

@app.get('/jobs')
async def get_jobs():
    return jobs

@app.post('/jobs', status_code=201)
async def add_job(job: Job):
    jobs.append(job)
    job_email_with_attachment()
    return jobs

if __name__ == '__main__':
    uvicorn.run(app)


from flask import Flask, request, render_template
import cycle_time
import lead_time_for_change
import call_commit_id
import deployment_freq

app = Flask(__name__, template_folder='template')

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

@app.route("/cycle_time", methods=["POST"])
def get_details():
    project_key = request.form["project_key"]
    start_date = request.form["start_date"]
    end_date = request.form["end_date"]
    res_cycle = cycle_time.cycle_time(project_key, start_date, end_date)
    res_lead = lead_time_for_change.cycle_time_lead(project_key, start_date, end_date)
    res_mean = call_commit_id.cycle_time_failover(project_key, start_date, end_date)
    res_deploy = deployment_freq.deployment_freq(project_key, start_date, end_date)
    print(f"{res_cycle}\n {res_lead}\n {res_mean}\n {res_deploy}")
    return render_template("result.html")  # cycle_time=res_cycle, mean_time=res_mean, lead_time=res_lead


"""
Problem: LeetCode 10 - Regular Expression Matching

Key Idea:
The key idea is to use dynamic programming to solve this problem. We create a 2D table 'dp' where dp[i][j] represents whether the first 'i' characters in the string 's' match the first 'j' characters in the pattern 'p'. We fill this table based on the characters in 's' and 'p' and previous results.

Time Complexity:
The time complexity is O(m * n), where 'm' is the length of the string 's' and 'n' is the length of the pattern 'p'. We have a nested loop that iterates through the characters in 's' and 'p'.

Space Complexity:
The space complexity is O(m * n) as we use a 2D table 'dp' of size m x n to store the results of subproblems.
"""

class Solution:
    def isMatch(self, s: str, p: str) -> bool:
        m, n = len(s), len(p)

        # Create a 2D table dp to store whether s[:i] matches p[:j].
        dp = [[False] * (n + 1) for _ in range(m + 1)]

        # Base case: empty string matches empty pattern.
        dp[0][0] = True

        # Fill the first row of dp based on '*' in the pattern.
        for j in range(2, n + 1):
            if p[j - 1] == "*":
                dp[0][j] = dp[0][j - 2]

        # Fill the dp table based on characters in s and p.
        for i in range(1, m + 1):
            for j in range(1, n + 1):
                if p[j - 1] == s[i - 1] or p[j - 1] == ".":
                    dp[i][j] = dp[i - 1][j - 1]
                elif p[j - 1] == "*":
                    dp[i][j] = dp[i][j - 2] or (
                        dp[i - 1][j] and (s[i - 1] == p[j - 2] or p[j - 2] == ".")
                    )

        return dp[m][n]


# coding=utf-8
from __future__ import absolute_import, print_function
import argparse
import os
import json
import torch
import shutil
import time
import numpy as np
import pandas as pd
from sklearn import metrics
from glob import glob
from torch.nn import DataParallel
from torchsummary import summary
import torchvision.models as models

from DataSet.dataset import get_iwildcam_loader, data_prefetcher
from Utils.train_utils import cross_entropy, focal_loss, cb_loss, get_optimizer, set_logs, load_ckpt
from Utils.train_utils import AverageMeter, ProgressMeter, accuracy
from Utils.train_utils import mixup_data, mixup_criterion
from Utils.default import _C as cfg
from Utils.default import update_config
from Models.model_factory import create_model

import click
import warnings
warnings.filterwarnings("ignore")
from torch.utils.tensorboard import SummaryWriter

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
if torch.cuda.device_count() > 1:
	print("Use Device Number: {}".format(torch.cuda.device_count()))

def evaluate(model, data_loader, criterion, use_onehot=True):
	y_pred, y_true, losses=[],[],[]
	with torch.no_grad():
		inputs, labels, ids = data_loader.next()
		while inputs is not None:
			if use_onehot:
				targets = np.argmax(labels.cpu().detach().numpy(), axis=1)
			else:
				targets = labels.cpu().detach().numpy()
			y_true.extend(targets)
			output = model(inputs)
			# loss = criterion(output, labels)
			y_pred.extend(np.argmax(output.cpu().detach().numpy(), axis=1))
			# losses.append(loss.cpu().detach().numpy())

			inputs, labels, ids = data_loader.next()

	acc = metrics.accuracy_score(y_true, y_pred)
	f1 = metrics.f1_score(y_true, y_pred, average='macro')
	# loss_val=np.mean(losses)
	# return loss_val, acc, f1
	return acc, f1

def validate(val_loader, model, criterion, cfg, label_type, use_onehot):
	batch_time = AverageMeter('Time', ':6.3f')
	# losses = AverageMeter('Loss', ':.4e')
	val_acc = AverageMeter('Acc', ':6.2f')
	val_f1 = AverageMeter('F1', ':6.2f')
	# progress = ProgressMeter(
	# 	len(val_loader),
	# 	[batch_time, val_acc, val_f1],
	# 	prefix="Test: ")

	model.eval()
	data_loader = data_prefetcher(val_loader, label_type)
	i = 0
	inputs, labels, ids = data_loader.next()
	with torch.no_grad():
		end = time.time()
		while inputs is not None:
			output = model(inputs)
			acc, f1 = accuracy(output, labels, use_onehot)
			# losses.update(loss.item(), inputs.size(0))
			val_acc.update(acc, inputs.size(0))
			val_f1.update(f1, inputs.size(0))

			inputs, labels, ids = data_loader.next()
			i += 1

	return val_acc.avg, val_f1.avg

def train(train_data_loader, model, criterion, optimizer, epoch, cfg, label_type, use_onehot):
	batch_time = AverageMeter('Time', ':6.3f')
	data_time = AverageMeter('Data', ':6.3f')
	losses = AverageMeter('Loss', ':.4e')
	train_acc = AverageMeter('Acc', ':6.2f')
	train_f1 = AverageMeter('F1', ':6.2f')
	progress = ProgressMeter(
		len(train_data_loader),
		[batch_time, data_time, losses, train_acc, train_f1],
		prefix="Epoch: [{}]".format(epoch))

	model.train()
	train_loader = data_prefetcher(train_data_loader, label_type)
	i = 0
	end = time.time()
	inputs, labels, ids = train_loader.next() # ids没有用到
	while inputs is not None:
		data_time.update(time.time() - end)

		mixup_now = np.random.random() < cfg.AUG.AUG_PROBA # 0.5 一半的概率mixup
		if cfg.AUG.MIXUP and mixup_now: # True & 一半的概率
			inputs, labels_a, labels_b, lam = mixup_data(inputs, labels, cfg.AUG.MIXUP_ALPHA)

		output = model(inputs)
		if cfg.AUG.MIXUP and mixup_now:
			loss = mixup_criterion(criterion, output, labels_a, labels_b, lam) # mixup之后的图片也要根据mixup的obj算loss
		else:
			if cfg.LOSS.CLASS_WEIGHT:
				# loss = CE(output, labels.max(axis=1)[1])
				loss = criterion(output, labels.max(axis=1)[1])
			else:
				loss = criterion(output, labels)

		# acc/f1
		acc, f1 = accuracy(output, labels, use_onehot)
		losses.update(loss.item(), inputs.size(0))
		train_acc.update(acc, inputs.size(0))
		train_f1.update(f1, inputs.size(0))

		optimizer.zero_grad()
		loss.backward()
		optimizer.step()

		# measure elapsed time
		batch_time.update(time.time() - end)
		end = time.time()

		if i % cfg.PRINT_STEP == 0:
			progress.display(i)

		inputs, labels, ids = train_loader.next()
		i += 1

	return losses.avg, train_acc.avg, train_f1.avg

def main(cfg, kcross=-1, K=-1):
	tensorboard_dir = os.path.join(cfg.SAVE_DIR, "tb_event")
	if not os.path.exists(cfg.SAVE_DIR):
		os.makedirs(cfg.SAVE_DIR)
	else:
		print("This directory has already existed, Please remember to modify your configs")
		if not click.confirm(
			"\033[1;31;40mContinue and override the former directory?\033[0m",
			default=False,
			):
			exit(0)
		if tensorboard_dir is not None and os.path.exists(tensorboard_dir):
			shutil.rmtree(tensorboard_dir)
	print("=> output model will be saved in {}".format(cfg.SAVE_DIR))
	tb_writer = SummaryWriter(tensorboard_dir)

	model = create_model(
		cfg.NET.TYPE,
		pretrained=cfg.NET.PRETRAINED,
		num_classes=cfg.NUM_CLASSES,
		drop_rate=cfg.NET.DROP_RATE,
		global_pool='avg',
		bn_tf=False,
		bn_momentum=0.99,
		bn_eps=1e-3,
		checkpoint_path=cfg.INIT_MODEL if cfg.INIT_MODEL != "" else None,
		in_chans=3)
	print(model)

	optimizer = get_optimizer(cfg, model)
	# use torchvision.models
 	# model = models.__dict__[params['Net']](num_classes=params['num_classes'])

	param_num = sum([p.data.nelement() for p in model.parameters()])
	print("=> Number of model parameters: {} M".format(param_num / 1024 / 1024))

	model = model.cuda()
	# summary(model, (3, cfg.INPUT_SIZE[0], cfg.INPUT_SIZE[1]))
	model = DataParallel(model)

	train_data_loader, dev_data_loader = get_iwildcam_loader(cfg, mode=cfg.MODE) # train/eval的dataloader

	if cfg.TRAIN.LR_SCHEDULE == 'Step':# True
		scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=cfg.TRAIN.LR_DECAY_EPOCHS, gamma=0.2)
	elif cfg.TRAIN.LR_SCHEDULE == 'Cosine':
		scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=(cfg.TRAIN.EPOCHS // 9) + 1, eta_min=1e-06)
	else:
		raise NotImplementedError("Only Support lr_schdule(step, cosine)")

	best_acc, best_f1, best_epoch, start_epoch = 0, 0, 0, 1
	# ------ Begin Resume -------
	if cfg.RESUME:
		load_ckpt(cfg.SAVE_DIR) # read history parameters from json
		ckpt = torch.load(cfg.INIT_MODEL, map_location="cuda") # already specify in load_params()
		print('=> Load checkpoint from ', cfg.INIT_MODEL)
		model.load_state_dict(ckpt['state_dict'])
		optimizer.load_state_dict(ckpt['optimizer'])
		scheduler.load_state_dict(ckpt['scheduler'])
		start_epoch = ckpt['epoch'] + 1
		# best_acc = ckpt['best_acc']
		best_f1 = ckpt['best_f1']
		best_epoch = ckpt['best_epoch']

	if cfg.LOSS.LOSS_TYPE == 'CE':
		criterion = cross_entropy(func_type='softmax').to(device)
		if cfg.LOSS.WEIGHT_PER_CLS:
			CE = torch.nn.CrossEntropyLoss(weight=torch.from_numpy(cfg.LOSS.WEIGHT_PER_CLS).float().to(device))
		label_type = 'float'
	elif cfg.LOSS.LOSS_TYPE == 'Sigmoid_CE':
		criterion = cross_entropy(func_type='sigmoid').to(device)
		label_type = 'float'
	elif cfg.LOSS.LOSS_TYPE == 'Focal':
		criterion = focal_loss(gamma=1.0, alpha=1.0).to(device)
		label_type = 'long'
	elif cfg.LOSS.LOSS_TYPE == 'CB_loss': # FIXME: this is unsure implementation, low score
		criterion = cb_loss(cfg.LOSS.SAMPLES_PER_CLS, cfg.NUM_CLASSES, 'softmax').to(device)
		label_type = 'float'
	else:
		raise NotImplementedError("Not accessible loss type for: {}".format(cfg.LOSS.LOSS_TYPE))

	t0 = time.time()
	t1 = time.time()
	print('[INFO]Begin to train')
	use_onehot = cfg.LOSS.LOSS_TYPE != 'Focal'
	for epoch in range(start_epoch, cfg.TRAIN.EPOCHS + 1):
		print('=> Current Lr {:.5e}'.format(optimizer.param_groups[0]['lr']))
		if cfg.TRAIN.LR_SCHEDULE:
			scheduler.step()

		if cfg.LOSS.CLASS_WEIGHT:
			train_loss, train_acc, train_f1 = \
				train(train_data_loader, model, CE, optimizer, epoch, cfg, label_type, use_onehot)
		else:
			train_loss, train_acc, train_f1 = \
				train(train_data_loader, model, criterion, optimizer, epoch, cfg, label_type, use_onehot)

		val_acc, val_f1 = validate(dev_data_loader, model, criterion, cfg, label_type, use_onehot)
		# TODO: this should also be done with the ProgressMeter
		print('=> [Epoch-{}] * Acc {:.3f} F1 {:.3f}'.format(epoch, val_acc, val_f1))

		is_best = val_f1 > best_f1
		best_f1 = max(val_f1, best_f1)
		best_epoch = epoch if is_best else best_epoch

		tb_writer.add_scalar('train_loss', train_loss, epoch)
		tb_writer.add_scalar('val_metrics/val_acc', val_acc, epoch)
		tb_writer.add_scalar('val_metrics/val_f1-score', val_f1, epoch)

		save_model_path= os.path.join(cfg.SAVE_DIR, 'model_{:03d}.pkl'.format(epoch))
		torch.save({
			'state_dict': model.state_dict(),
			'scheduler': scheduler.state_dict(),
			'optimizer': optimizer.state_dict(),
			'epoch': epoch,
			# 'best_acc': best_acc,
			'best_f1': best_f1,
			'best_epoch': best_epoch,
			}, save_model_path)
		print('=> save model to', save_model_path)

	print("=> Train is over, Time cost: {:.1f} hours...".format((time.time() - t0) / 3600))

	source = 'model_{:03d}.pkl'.format(best_epoch)
	source_path = os.path.join(cfg.SAVE_DIR, source)
	target = 'model_best.pkl'
	target_path = os.path.join(cfg.SAVE_DIR, target)
	try:
		shutil.copy(source_path, target_path)
		print("Save best model to {}: [Epoch: {:d} / f1-score: {:.4f}]".format(target_path, best_epoch, best_f1))
	except IOError as e:
		print("Unable to copy file. %s" % e)
	except:
		print("Unexpected error:", sys.exc_info())

	# ---- Delete Useless ckpt
	ckpts = sorted(name for name in os.listdir(cfg.SAVE_DIR) if name.startswith('model'))
	ckpts = ckpts[:-1]
	print("=> Start to clean checkpoint from {} to {}".format(ckpts[0], ckpts[-1]))
	for name in ckpts:
		os.remove(os.path.join(cfg.SAVE_DIR, name))

	if cfg.CROSS_VALIDATION:
		ksave_path = os.path.join(cfg.SAVE_DIR, 'kcross_model')
		if not os.path.exists(ksave_path):
			os.makedirs(ksave_path)
		kmodel_path = os.path.join(ksave_path, 'kcross_{}.pkl'.format(kcross))
		shutil.copy(target_path, kmodel_path)
		print("=> Save K-best model to {}...".format(kmodel_path))

if __name__ == '__main__':
	parser = argparse.ArgumentParser()
	parser.add_argument('--config', '-cfg', default='input yaml path')
	local_args = parser.parse_args()
	cfg = update_config(cfg, local_args)
	cfg.SAVE_DIR = os.path.join("/data/iwildcam_output", os.path.basename(local_args.config))
	set_logs(cfg)
	print("=" * 40)
	print(cfg)
	print("=" * 40)
	if cfg.CROSS_VALIDATION:
		K = 5 # K-cross validation
		for i in range(K):
			# update params for K-cross
			cfg.DATASET.TRAIN_JSON = '/Kcross' + '/train_K{}.json'.format(i)
			cfg.DATASET.VAL_JSON = '/KCross' + '/val_K{}.json'.format(i)
			main(cfg, i, K)
			print("---- {}/{} Finished ---- ".format(i+1, K))
	else:
		main(cfg)


import numpy as np
import seaborn
from pandas import read_csv
from pandas.plotting import register_matplotlib_converters
from matplotlib.pyplot import subplots, savefig, show
from ds_charts import get_variable_types, HEIGHT

register_matplotlib_converters()
filename = '../../data/air_quality_tabular.csv'
data = read_csv(filename, index_col='FID', parse_dates=True, infer_datetime_format=True)
data.pop('GbCity')
data.pop('GbProv')
data.pop('Field_1')
numeric_vars = get_variable_types(data)['Numeric']
numeric_vars.append('ALARM')
if [] == numeric_vars:
    raise ValueError('There are no numeric variables.')

rows, cols = len(numeric_vars) - 1, len(numeric_vars) - 1
fig, axs = subplots(rows, cols, figsize=(cols * HEIGHT, rows * HEIGHT), squeeze=False)

colors = np.where(data["ALARM"] == "Safe", 'g', 'r')

for i in range(len(numeric_vars)):
    var1 = numeric_vars[i]
    for j in range(i + 1, len(numeric_vars)):
        var2 = numeric_vars[j]
        axs[i, j - 1].set_title("%s x %s" % (var1, var2))
        axs[i, j - 1].set_xlabel(var1)
        axs[i, j - 1].set_ylabel(var2)
        #axs[i, j - 1].scatter(data[var1], data[var2], c=colors, cmap='winter')
        seaborn.stripplot(y=data[var1].astype(str), x=data[var2].astype(str), jitter=0.35, edgecolor='gray', alpha=.25,
                          ax=axs[i, j - 1], palette=colors)
print("Saving figure")
savefig(f'../DataSparsity_Set2/images/sparsity_study_numeric_better.png')
# show()
print("Done")


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn import preprocessing
import seaborn as sns

def viz(df, scaled_df1, scaled_df2, scaled_df3):
    fig, (ax1, ax2, ax3, ax4) = plt.subplots(ncols=4, figsize=(12, 5))

    ax1.set_title('Before Scaling')
    sns.kdeplot(df['x1'], ax=ax1)
    sns.kdeplot(df['x2'], ax=ax1)
    sns.kdeplot(df['x3'], ax=ax1)

    ax2.set_title('After Standard Scaler')
    sns.kdeplot(scaled_df1['x1'], ax=ax2)
    sns.kdeplot(scaled_df1['x2'], ax=ax2)
    sns.kdeplot(scaled_df1['x3'], ax=ax2)

    ax3.set_title('After Min-Max Scaler')
    sns.kdeplot(scaled_df2['x1'], ax=ax3)
    sns.kdeplot(scaled_df2['x2'], ax=ax3)
    sns.kdeplot(scaled_df2['x3'], ax=ax3)

    ax4.set_title('After Robust Scaler')
    sns.kdeplot(scaled_df3['x1'], ax=ax4)
    sns.kdeplot(scaled_df3['x2'], ax=ax4)
    sns.kdeplot(scaled_df3['x3'], ax=ax4)

    plt.show()

def get_guassian_data():
    return pd.DataFrame({
            'x1': np.random.normal(0, 2, 10000),
            'x2': np.random.normal(5, 3, 10000),
            'x3': np.random.normal(-5, 5, 10000)
            })

def get_mixed_data1():
    return pd.DataFrame({
            # positive skew
            'x1': np.random.chisquare(8, 1000),
            # negative skew
            'x2': np.random.beta(8, 2, 1000) * 40,
            # no skew
            'x3': np.random.normal(50, 3, 1000)
            })

def get_mixed_data2():
    return pd.DataFrame({
            # Distribution with lower outliers
            'x1': np.concatenate([np.random.normal(20, 1, 1000), np.random.normal(1, 1, 25)]),
            # Distribution with higher outliers
            'x2': np.concatenate([np.random.normal(30, 1, 1000), np.random.normal(50, 1, 25)]),
             # Distribution with no outliers
            'x3': np.concatenate([np.random.normal(20, 1, 1000), np.random.normal(20, 1, 25)]),
            })

def get_transformed_data(df):
    scaler1 = preprocessing.StandardScaler()
    scaled_df1 = scaler1.fit_transform(df)
    scaled_df1 = pd.DataFrame(scaled_df1, columns=['x1', 'x2', 'x3'])

    scaler2 = preprocessing.MinMaxScaler()
    scaled_df2 = scaler2.fit_transform(df)
    scaled_df2 = pd.DataFrame(scaled_df2, columns=['x1', 'x2', 'x3'])

    scaler3 = preprocessing.RobustScaler()
    scaled_df3 = scaler3.fit_transform(df)
    scaled_df3 = pd.DataFrame(scaled_df3, columns=['x1', 'x2', 'x3'])

    return scaled_df1, scaled_df2, scaled_df3

np.random.seed(1)

df = get_guassian_data()
scaled_df1, scaled_df2, scaled_df3 = get_transformed_data(df)
viz(df, scaled_df1, scaled_df2, scaled_df3)

df = get_mixed_data1()
scaled_df1, scaled_df2, scaled_df3 = get_transformed_data(df)
viz(df, scaled_df1, scaled_df2, scaled_df3)

df = get_mixed_data2()
scaled_df1, scaled_df2, scaled_df3 = get_transformed_data(df)
viz(df, scaled_df1, scaled_df2, scaled_df3)


#Aqui começa a Etapa 1

import math
import matplotlib.pyplot as plt

def evoluir_populacao_cenouras(Pce, Rce, Pcemax, Mce, Pco):
    """Calcula o crescimento de Cenouras
    Requires: Pce,Rce,Pcemax,Mce,Pco que sejam inteiros e onde Pcemax não pode ser zero
    Ensures: O número de cenouras depois de um mês
    """
    PceAfter = Pce + Rce * Pce * (1 - (Pce / Pcemax)) - (Mce * Pco)
    return round(PceAfter)

#Aqui começa a Etapa 2
def evoluir_populacao_coelhos(Pco, Pce, Mce, Pcomax, Mco, Plo):
    """Calcula o aumento da população de coelhos
    Requires: Pco,Pce,Mce,Pcomax,Mco,Plo que sejam inteiros onde Mce, Pco e Pcomax não podem ser igual a zero
    Ensures: O número de coelhos depois de um mês
    """
    Nco = Pce / (Mce * Pco)
    PcoAfter = Pco + Nco * (1 - (Pco / Pcomax)) - (Mco * Plo)
    return round(PcoAfter)

#Aqui começa a Etapa 3
def evoluir_populacao_lobos(Plo, Pco, Mco, Plomax, Mlo):
    """Calcula o aumento da população de lobos
    Requires: Pco,Mlo,Plomax,Mco,Plo que sejam inteiros onde Mco, Plo e Plomax não podem ser igual a zero
    Ensures: O número de lobos depois de um mês
    """
    Nlo = Pco / (Mco * Plo)
    PloAfter = Plo + Nlo * (1 - (Plo / Plomax)) - (Mlo * Plo)
    return round(PloAfter)

#Aqui começa a Etapa 4
def simular_populacoes(num_meses, param, t):
    """ Calcula o número Cenouras Coelhos e Lobos após Um número de meses inserido pelo utilizador
    Requires: num_meses que deve ser um inteiro positivo, e um dicionário que contem as variáveis necessárias p'ra as fun~es utilizadas p'ra calcular o número de seres vivos
    Ensures: A string com o número de meses e os respectivos números de cada espéciede ser vivo.E depois 3 listas em que cada lista contem a quantidade em cada mês de cada espécie de ser vivo, as listas são respectivamente de Cenouras, Coelhos e Lobos.
    """
    Rce = int(param["Rce"])
    PceMax = int(param["Pcemax"])
    Mce = int(param["Mce"])
    PcoMax = int(param["Pcomax"])
    Mco = int(param["Mco"])
    PloMax = int(param["Plomax"])
    Mlo = int(param["Mlo"])

    listaPce = []
    listaPco = []
    listaPlo = []

    if t == 0:
        print('Mês {} : {} cenouras, {} coelhos, {} lobos'.format(0, param["Pce0"], param["Pco0"], param["Plo0"]))

    for It in range(0, t + num_meses + 1):
        PopCe = param.get("Pce" + str(It), None)
        PopCo = param.get("Pco" + str(It), None)
        PopLo = param.get("Plo" + str(It), None)
        if PopCe == None or PopCo == None or PopLo == None:
            # Cria dados para mes = It
            AntPopCe = int(param["Pce" + str(It - 1)])
            AntPopCo = int(param["Pco" + str(It - 1)])
            AntPopLo = int(param["Plo" + str(It - 1)])
            PopCe = evoluir_populacao_cenouras(AntPopCe, Rce, PceMax, Mce, AntPopCo)
            PopCo = evoluir_populacao_coelhos(AntPopCo, AntPopCe, Mce, PcoMax, Mco, AntPopLo)
            PopLo = evoluir_populacao_lobos(AntPopLo, AntPopCo, Mco, PloMax, Mlo)
            param["Pce" + str(It)] = PopCe
            param["Pco" + str(It)] = PopCo
            param["Plo" + str(It)] = PopLo
            print('Mês {} : {} cenouras, {} coelhos, {} lobos'.format(It, PopCe, PopCo, PopLo))
        listaPce.append(int(PopCe))
        listaPco.append(int(PopCo))
        listaPlo.append(int(PopLo))

    return listaPce, listaPco, listaPlo

#Aqui começa a Etapa 5
def menu():
    """Através do input que pede ao utilizador simula o crescimento da população ou mostra um gráfico de uma espécie que o utilizador escolhe
    Requires: A função não requer quaisquer parâmetros
    Ensures: Calcula o número de cada espécie apôs um número específico de meses introduzido pelo utilizador ou constroí um gráfico com a evolução do ser vivo escolhido pelo utilizador do mês zero até ao mês introduzido pelo utilizador
    """
    print('(s)imular, (d)esenhar gráfico')
    Resposta = input()
    Resposta = Resposta.lower()
    if Resposta == 's':
        return simular()
    elif Resposta == 'd':
        return draw()
    elif Resposta == 'q':
        return Resposta
    else:
        print('Caracter inválido!')
        return menu()

#Aqui começa a Etapa 6
def obter_parametros(nome_ficheiro):
    """Constroí um dicionário com as variáveis que estão apresentadas no ficheiro (nome_ficheiro)
    Requires: O ficheiro (nome_ficheiro) que contem as variáveis necessárias à função simular_populacoes (num_meses,param)
    Ensures:Um dicionário com o nome das variáveis como chave e como valor a quantidade numérica da respectiva variável que tem como chave
    """
    ficheiro = open(nome_ficheiro, 'r')
    parametros = {}
    nome = []
    valor = []
    for linha in ficheiro:
        n,v = linha.split('=')
        nome.append(n.strip())
        valor.append(eval(v.strip()))
    for i in range(0, len(nome)):
        parametros.update({nome[i]:valor[i]})
    return parametros

#Aqui começa a Etapa 7
def simulador(nome_ficheiro):
    """Simula o crescimento das espécies de seres vivos do ecosistema
    Requires: Um ficheiro (nome_ficheiro) com as variáveis necessárias p'ra simular cada espécie
    Ensures: Uma string com o mês e o número de cada ser vivo p'ra cada espécie e em cada mês
    """
    parametros = obter_parametros(nome_ficheiro)
    mesAtual = 0
    Op = menu()
    while Op != 'q':
        if Op == 'c':
            grafico_populacao(mesAtual, parametros, 0)
        elif Op == 'r':
            grafico_populacao(mesAtual, parametros, 1)
        elif Op == 'w':
            grafico_populacao(mesAtual, parametros, 2)
        elif Op.isdigit():
            simular_populacoes(int(Op), parametros, mesAtual)
            mesAtual += int(Op)
        Op = menu()
    listasGuardar = simular_populacoes(mesAtual, parametros, 0)
    gravar_resultado_simulacao('resultados.csv', listasGuardar[0], listasGuardar[1], listasGuardar[2])
    print('Simulador Terminado')

def simular():
    print('Quantos meses pretende simular?')
    sims = input()
    sims = sims.lower()
    if sims == 'q' or (sims.isdigit() and int(sims) > 0):
        return sims
    elif sims == 'a':
        return menu()
    else:
        print('Caracter inválido!')
        return simular()

def draw():
    print('Qual a população que deseja representar?')
    print('C -> cenouras, R -> coelhos, W -> lobos')
    resposta = input()
    resposta = resposta.lower()
    if resposta == 'q' or resposta == 'c' or resposta == 'r' or resposta == 'w':
        return resposta
    elif resposta == 'a':
        return menu()
    else:
        print('Caracter inválido!')
        return draw()

def grafico_populacao(meses, parametros, pop_indice):
    lista = simular_populacoes(meses, parametros, 0)[pop_indice]
    descricao = 'Número de '
    color = ''
    if pop_indice == 0:
        descricao += "Cenouras"
        color = 'orange'
    elif pop_indice == 1:
        descricao += "Coelhos"
        color = 'c'
    elif pop_indice == 2:
        descricao += "Lobos"
        color = 'b'

    plt.plot(lista, linestyle='-', marker='o', color = color)
    plt.xlabel('Número de Meses')
    plt.ylabel(descricao)
    plt.title('Simulação de Ecossistema')
    plt.show()

#Aqui começa a Etapa 9
def gravar_resultado_simulacao(nome_ficheiro, lista_pop_cenouras, lista_pop_coelhos, lista_pop_lobos):
    """Grava os resultados do número de cada ser vivo em cada mês num formato(.csv)
    Requires:Um ficheiro (nome_ficheiro), uma lista com o número de cenouras em cada mês em que é efectuado a simulação(lista_pop_cenouras),uma lista com o número de coelhos em cada mês em que é efectuado a simulação(lista_pop_coelhos),uma lista com o número de lobos em cada mês em que é efectuado a simulação(lista_pop_lobos)
    Ensures: Um ficheiro .csv com cada mês e o respectivo número de cada ser vivo
    """
    ResFich = open(nome_ficheiro, 'w')
    for mes in range(0, len(lista_pop_lobos)):
        ResFich.write('{};{};{};{}\n'.format(mes, lista_pop_cenouras[mes], lista_pop_coelhos[mes], lista_pop_lobos[mes]))

simulador("configuracao.txt")


# ---
# jupyter:
#   jupytext:
#     cell_metadata_filter: ExecuteTime,collapsed,code_folding,incorrectly_encoded_metadata,tags,jp-MarkdownHeadingCollapsed,-autoscroll
#     formats: ipynb,py:percent
#     notebook_metadata_filter: all,-widgets,-varInspector
#     text_representation:
#       extension: .py
#       format_name: percent
#       format_version: '1.3'
#       jupytext_version: 1.14.6
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
#   language_info:
#     codemirror_mode:
#       name: ipython
#       version: 3
#     file_extension: .py
#     mimetype: text/x-python
#     name: python
#     nbconvert_exporter: python
#     pygments_lexer: ipython3
#     version: 3.9.13
#   latex_envs:
#     LaTeX_envs_menu_present: true
#     autoclose: false
#     autocomplete: true
#     bibliofile: biblio.bib
#     cite_by: apalike
#     current_citInitial: 1
#     eqLabelWithNumbers: true
#     eqNumInitial: 1
#     hotkeys:
#       equation: Ctrl-E
#       itemize: Ctrl-I
#     labels_anchors: false
#     latex_user_defs: false
#     report_style_numbering: false
#     user_envs_cfg: false
# ---

# %% [markdown]
# # Micro- and Macroeconomic Implications of Very Impatient Households
#
#
Generator: QuARK-make/notebooks_byname

#
# [![badge](https://img.shields.io/badge/Launch%20using%20-Econ--ARK-blue)](https://econ-ark.org/materials/micro-and-macro-implications-of-very-impatient-hhs#launch)

# %% [markdown] jp-MarkdownHeadingCollapsed=true
# ## Introduction
#
# Buffer stock saving models of the kind implemented in $\texttt{ConsIndShockType}$ say that, if a standard ['Growth Impatience Condition'](https://econ-ark.github.io/BufferStockTheory/#GICRaw), holds:
#
# \begin{eqnarray}
# \newcommand{\Rfree}{\mathsf{R}}\newcommand{\DiscFac}{\beta}\newcommand{\PermGroFac}{\Gamma}\newcommand{\PermShk}{\psi}\newcommand{\CRRA}{\rho}
# \left(\frac{(\Rfree\DiscFac)^{1/\CRRA}\mathbb{E}[\PermShk^{-1}]}{\PermGroFac}\right) & < & 1
# \end{eqnarray}
#
# then the _ratio_ of asets $\newcommand{\aLev}{\mathbf{a}}\aLev$ to permanent income $\newcommand{\pLev}{\mathbf{p}}\pLev$, $a=\aLev/\pLev$, has a target value $\newcommand{\aTarg}{\check{a}}\aTarg$ that depends on the consumer's preferences (relative risk aversion $\CRRA$, time preference $\DiscFac$) and circumstances (interest factor $\Rfree$, growth factor $\PermGroFac$, uncertainty about permanent income shocks $\sigma^{2}_{\PermShk}$).
#
# If everyone had identical preferences and everyone were at their target $\check{a}$, then inequality in the level of $\aLev$ would be exactly the same as inequality in $\pLev$.
#
# ["The Distribution of Wealth and the Marginal Propensity to Consume"](https://www.econ2.jhu.edu/people/ccarroll/papers/cstwMPC) (Carroll, Slacalek, Tokuoka, and White 2017; hereafter: "cstwMPC") shows that, when such a model is simulated and agents draw their idiosyncratic shocks (so, agents are _ex post_ heterogeneous -- see the definition in [Intro-To-HARK](http://github.com/econ-ark/PARK/tree/master/Intro-To-HARK.pdf)) -- asset inequality is indeed close to $\pLev$ inequality even though everyone is not always at exactly their target $a$.
#
# But a large body of evidence shows that _actual_ inequality in assets is much greater than _actual_ inequality in permanent income.  Thus, to make a model that qualifies as what cstwMPC call a 'serious' microfounded macro model of consumption (one that matches the key facts _theory says_ should be first-order important), the model must be modified to incorporate some form of _ex ante_ heterogeneity: That is, there must be differences across people in $\DiscFac$ or $\Rfree$ or $\CRRA$ or $\PermGroFac$ or $\sigma^{2}_{\PermShk}$.
#
# The most transparent and simplest of these to change is the time preference factor $\beta$.  So that is what the paper does.  The main results are:
#
# 1. The distribution of $\beta$ need not be particularly wide to match the extreme concentration of wealth: roughly 0.91 to 0.98 (annual); that is, the most impatient person discounts the future about 6 percentage points more per year than the most patient agent agent
# 2. With such a distribution of $\beta$, simulated agents' (annual) marginal propensity to consume (MPC) from transitory income shocks to income matches large body of microeconomic evidence that typically finds evidence of MPC's in the range of 0.2 to 0.6.  This is much better than RA macro models that typically yield MPC's in the range of 0.01 to 0.05.
#
# While the most impatient agents in the cstwMPC model have fairly high MPCs (~0.6 annual), there is microeconomic evidence that a significant fraction of households have *even higher* MPCs than the model predicts, especially at the quarterly frequency.  This group of households is commonly referred to as "hand-to-mouth" -- they consume most of their transitory shocks to income not too long after they receive them (mostly within a quarter).  There are several reasons why a household could be hand-to-mouth, but one plausible explanation is that these households are *even more impatient* than estimated by cstwMPC for the most impatient agent.
#

# %% code_folding=[25]
# This cell does some setup and imports generic tools used to produce the figures

from HARK.utilities import get_lorenz_shares, get_percentiles
from HARK.datasets import load_SCF_wealth_weights
from HARK.distribution import Uniform
from HARK.ConsumptionSaving.ConsIndShockModel import IndShockConsumerType
from copy import deepcopy
import warnings
from distutils.spawn import find_executable
import matplotlib.pyplot as plt
from IPython import get_ipython  # In case it was run from python instead of ipython
from tqdm import tqdm

import numpy as np
from copy import deepcopy

Generator = False  # Is this notebook the master or is it generated?
# Import related generic python packages

# Set how many digits past the decimal point should be printed?

def mystr(number):
    return "{:.4f}".format(number)

def decfmt4(number):
    return "{:.4f}".format(number)

def decfmt3(number):
    return "{:.3f}".format(number)

def decfmt2(number):
    return "{:.2f}".format(number)

def decfmt1(number):
    return "{:.1f}".format(number)

# This is a jupytext paired notebook that autogenerates BufferStockTheory.py
# which can be executed from a terminal command line via "ipython BufferStockTheory.py"
# But a terminal does not permit inline figures, so we need to test jupyter vs terminal
# Google "how can I check if code is executed in the ipython notebook"

def in_ipynb():
    try:
        if (
            str(type(get_ipython()))
            == "<class 'ipykernel.zmqshell.ZMQInteractiveShell'>"
        ):
            return True
        else:
            return False
    except NameError:
        return False

# Determine whether to make the figures inline (for spyder or jupyter)
# vs whatever is the automatic setting that will apply if run from the terminal
if in_ipynb():
    # # %matplotlib inline generates a syntax error when run from the shell
    # so do this instead
    get_ipython().run_line_magic("matplotlib", "inline")
else:
    get_ipython().run_line_magic("matplotlib", "auto")

# Import the plot-figure library matplotlib

# In order to use LaTeX to manage all text layout in our figures, we import rc settings from matplotlib.

plt.rc("font", family="serif")

# LaTeX is huge and takes forever to install on mybinder
# so if it is not installed then do not use it

iflatexExists = False
if find_executable("latex"):
    iflatexExists = True

plt.rc("text", usetex=iflatexExists)

# The warnings package allows us to ignore some harmless but alarming warning messages

warnings.filterwarnings("ignore")

# %% [markdown]
# ## Calibrating a Basic Version of cstwMPC
#
# To get started, let's reproduce a simplified version of the main results from cstwMPC.
#
# In cstwMPC, the authors calibrated nearly all of the model parameters-- risk aversion, income shock process, etc-- to commonly used or previously estimated values.  The only parameter to be estimated is the distribution of $\beta$.  cstwMPC assumed that $\beta$ is uniformly distributed on $[\grave{\beta}-\nabla,\grave{\beta}+\nabla]$, approximated by a seven point distribution.
#
# Their estimation procedure seeks the values of $\grave{\beta}$ and $\nabla$ that generate a simulated distribution of wealth that best matches empirical U.S. data.  Their definition of "best match" has two aspects:
#
# 1. The simulated aggregate capital-to-income ratio matches the true U.S. value.
# 2. The sum of squared distances between the simulated and empirical Lorenz curves (at the 20th, 40th, 60th, and 80th percentiles) is minimized (conditional on item 1).
#
# cstwMPC's target empirical moments are a capital-to-income ratio of 10.26 and cumulative wealth shares as given in the table below.  Yes, you are reading the table correctly: The "poorest" 80 percent of households own 17.5 percent of wealth.
#
# | Net worth percentile | Cumulative wealth share |
# |:---:|:---:|
# |  20th  | -0.2% |
# |  40th  | 1.0% |
# |  60th  | 5.5% |
# |  80th  | 17.5% |
#
# To reproduce their basic results, we must import an $\texttt{AgentType}$ subclass and define a dictionary with calibrated parameters identical to those in the paper.

# %% code_folding=[0, 4]
# Import IndShockConsumerType

# Define a dictionary with calibrated parameters
cstwMPC_calibrated_parameters = {
    "CRRA": 1.0,  # Coefficient of relative risk aversion
    "Rfree": 1.01 / (1.0 - 1.0 / 160.0),  # Survival probability,
    # Permanent income growth factor (no perm growth),
    "PermGroFac": [1.000**0.25],
    "PermGroFacAgg": 1.0,
    "BoroCnstArt": 0.0,
    "CubicBool": False,
    "vFuncBool": False,
    "PermShkStd": [
        (0.01 * 4 / 11) ** 0.5
    ],  # Standard deviation of permanent shocks to income
    "PermShkCount": 5,  # Number of points in permanent income shock grid
    "TranShkStd": [
        (0.01 * 4) ** 0.5
    ],  # Standard deviation of transitory shocks to income,
    "TranShkCount": 5,  # Number of points in transitory income shock grid
    "UnempPrb": 0.07,  # Probability of unemployment while working
    "IncUnemp": 0.15,  # Unemployment benefit replacement rate
    "UnempPrbRet": 0.07,
    "IncUnempRet": 0.15,
    "aXtraMin": 0.00001,  # Minimum end-of-period assets in grid
    "aXtraMax": 40,  # Maximum end-of-period assets in grid
    "aXtraCount": 32,  # Number of points in assets grid
    "aXtraExtra": [None],
    "aXtraNestFac": 3,  # Number of times to 'exponentially nest' when constructing assets grid
    "LivPrb": [1.0 - 1.0 / 160.0],  # Survival probability
    "DiscFac": 0.97,  # Default intertemporal discount factor; dummy value, will be overwritten
    "cycles": 0,
    "T_cycle": 1,
    "T_retire": 0,
    # Number of periods to simulate (idiosyncratic shocks model, perpetual youth)
    "T_sim": 1200,
    "T_age": 400,
    "IndL": 10.0 / 9.0,  # Labor supply per individual (constant),
    "aNrmInitMean": np.log(0.00001),
    "aNrmInitStd": 0.0,
    "pLvlInitMean": 0.0,
    "pLvlInitStd": 0.0,
    "AgentCount": 10000,
}

# %% [markdown]
# * Start with importing the predefined dictionaries for agent types from the HARK toolkit. Then only show the parameters that are actually different from the imported dictionary.

# %% [markdown]
# # Creating an ex-ante distribution of heterogeneous agents
#
# Now let's make several instances of our class of agents and give them different values of $\beta$, following cstwMPC's estimated distribution.  In our specification of interest, we will use $\grave{\beta}=0.9855583$ and $\nabla = 0.0085$.
#
# NB: Reported parameter estimates in cstwMPC use a model with aggregate shocks and wage and interest rates determined dynamically (a heterogeneous agents DSGE model); this is the $\texttt{AggShockConsumerType}$ in HARK.  The estimated parameters are slightly different in this exercise, as we are ignoring general equilibrium aspects and only using the $\texttt{IndShockConsumerType}$
#
# ### Method 1: "Brute force" approach
#
# There are two methods for accomplishing this. The first is a more "brute force" approach: We specify a uniform distribution and discretize it for the number of household types we would like to see in the model. From there, We place each of the household types with a different time preference factor in a list. Finally, a for-loop is used to compute the solution for each household's optimization problem.

# %%
# This cell constructs seven instances of IndShockConsumerType with different discount factors

BaselineType = IndShockConsumerType(**cstwMPC_calibrated_parameters)

# Specify the distribution of the discount factor
num_types = 7  # number of types we want
DiscFac_mean = 0.9855583  # center of beta distribution
DiscFac_spread = 0.0085  # spread of beta distribution

# Here's how to use the tools to create time preference heterogeneity manually

DiscFac_dstn = (
    Uniform(DiscFac_mean - DiscFac_spread, DiscFac_mean + DiscFac_spread)
    .discretize(num_types)
    .atoms.flatten()
)

MyTypes = []  # initialize an empty list to hold our consumer types
for nn in range(num_types):
    # Now create the types, and append them to the list MyTypes
    NewType = deepcopy(BaselineType)
    NewType.DiscFac = DiscFac_dstn[nn]
    NewType.seed = nn  # give each consumer type a different RNG seed
    MyTypes.append(NewType)

# %% [markdown]
# ### Method 2: The new `AgentPopulation` class
#
# The second approach incorporates a new class defined in the  HARK toolkit: `AgentPopulation`. This class will create a new iterable object `AgentPopulation`, which takes two arguments. The first is the dictionary which defines the AgentType. The second is a distribution over the parameter value for which the user would like to see ex-ante heterogeneity in. From there, the `approx_distributions` method is called on the object to discretize the distribution given the specified number of discrete points. Finally, the `create_distributed_agents` method is called to create the distribution of agents, for which the standard solution method calls can be used to solve each agents problem.

# %%
# This cell constructs seven instances of IndShockConsumerType with different discount factors

from HARK.core import AgentPopulation

# Specify the distribution of the discount factor
num_types = 7  # number of types we want
DiscFac_mean = 0.9855583  # center of beta distribution
DiscFac_spread = 0.0085  # spread of beta distribution

cstwMPC_calibrated_parameters["DiscFac"] = Uniform(
    DiscFac_mean - DiscFac_spread, DiscFac_mean + DiscFac_spread
)

SubPops = AgentPopulation(IndShockConsumerType, cstwMPC_calibrated_parameters)
SubPops.approx_distributions({"DiscFac": num_types})
SubPops.create_distributed_agents()

# %% [markdown]
# ## Solving and Simulating the Baseline Agents
#
# Now let's solve and simulate each of our types of agents.  If you look in the parameter dictionary (or at any of the agent objects themselves), you will see that each one has an $\texttt{AgentCount}$ attribute of 10000. That is, these seven ex ante heterogeneous types each represent ten thousand individual agents that will experience ex post heterogeneity when they draw different income (and mortality) shocks over time.
#
# In the code block below, fill in the contents of the loop to solve and simulate each agent type for many periods.  To do this, you should invoke the methods $\texttt{solve}$, $\texttt{initialize_sim}$, and $\texttt{simulate}$ in that order.  Simulating for 1200 quarters (300 years) will approximate the long run distribution of wealth in the population.
#
# After solving the model, we will check that the aggregate level of capital (total assets held by all households) to income ratio equals what we expected it would be. This will serve as a verification that the code is written correctly. To do this, we combine the asset holdings of all types, take the mean, and compare it to the desired capital to income ratio of 10.26.
#
# NB: Because there is no permanent income growth in this model, all shocks are mean one and idiosyncratic, and we have many agents, aggregate or average income is 1.0.
#
# ### 1. Solution for the "brute force" approach
#
# Here is the output for the solution to the first approach to the problem, as well as a computation of the mean level of assets across the agent types. As you can see, the model does a good job of matching the aggregate capital-to-output ratio found in the data, as cited by Carroll et al. (2017).

# %%
# Progress bar keeps track interactively of how many have been made
for ThisType in tqdm(MyTypes):
    ThisType.solve()
    ThisType.initialize_sim()
    ThisType.simulate()

# %%
aLvl_all = np.concatenate([ThisType.state_now["aLvl"] for ThisType in MyTypes])
print(
    "The ratio of aggregate capital to permanent income is "
    + decfmt2(np.mean(aLvl_all))
)

# %% [markdown]
# ### 2. Solution using the `AgentPopulation` class
#
# We now conduct the same exercise for the new tool implemented in HARK. As you can see, both the out for the solution and the mean level of assets are nearly identical to the output when using the "brute force" approach.
#
# Note: As an aside, the working theory for why these two approaches give nearly-but-not-perfectly-identical solution outputs is that, the "brute force" approach requires the user to specify the random seed when creating the discretized distribution of agents. The approach using `AgentPopulation`, on the other hand, specifies the random seed for the user during the implementation of the code. As you may know from the basics of programming in Python, the random seed's main function is for reproducibility of results when using random number generators. In order for this theory to be tested, the `AgentPopulation` tool in HARK must be updated to allow for users to fix the random seed in this way.

# %%
SubPops.solve()
SubPops.initialize_sim()
SubPops.simulate()

# time this second solution method

# %%
aLvl_all_ap = np.concatenate([ThisSubPop.state_now["aLvl"] for ThisSubPop in SubPops])
print(
    "The ratio of aggregate capital to permanent income is "
    + decfmt2(np.mean(aLvl_all_ap))
)

# %% [markdown]
# ## Plotting the Lorenz Curve
#
# Next, we conduct the exercise of matching the inequality in the observable distribution of wealth using the distribution of assets that arises from the model we've constructed with ex-ante heterogeneity in the time preference factor. As you can see from the plots below, the matching exercise is again nearly identical from the two approaches.

# %%
# Compute Lorenz shares using the brute force approach

SCF_wealth, SCF_weights = load_SCF_wealth_weights()

pctiles = np.linspace(0.001, 0.999, 200)
sim_wealth = np.concatenate([ThisType.state_now["aLvl"] for ThisType in MyTypes])
SCF_Lorenz_points = get_lorenz_shares(
    SCF_wealth, weights=SCF_weights, percentiles=pctiles
)
sim_Lorenz_points = get_lorenz_shares(sim_wealth, percentiles=pctiles)

# Compute Lorenz shares using the `AgentPopulation` approach

sim_wealth_ap = np.concatenate([ThisSubPop.state_now["aLvl"] for ThisSubPop in SubPops])
SCF_Lorenz_points_ap = get_lorenz_shares(
    SCF_wealth, weights=SCF_weights, percentiles=pctiles
)
sim_Lorenz_points_ap = get_lorenz_shares(sim_wealth_ap, percentiles=pctiles)

# Plot Lorenz curves for model with uniform distribution of time preference using both methods

plt.subplot(1, 2, 1)
plt.plot(pctiles, SCF_Lorenz_points, "--k")
plt.plot(pctiles, sim_Lorenz_points, "-b")
plt.title("Brute force approach")
plt.xlabel("Percentile of net worth")
plt.ylabel("Cumulative share of wealth")

plt.subplot(1, 2, 2)
plt.plot(pctiles, SCF_Lorenz_points, "--k")
plt.plot(pctiles, sim_Lorenz_points_ap, "-b")
plt.title("Using AgentPopulation class")
# plt.xlabel("Percentile of net worth")
# plt.ylabel("Cumulative share of wealth")

plt.tight_layout()
plt.show(block=False)

# %% [markdown]
# ## Calculating the Lorenz Distance at Targets
#
# Now we want to construct a function that calculates the Euclidean distance between simulated and actual Lorenz curves at the four percentiles of interest: 20, 40, 60, and 80.
#
# NB: For some reason, this step is not completed in the code. We leave this cell here, as this exercise should probably be performed as well.

# %% [markdown]
# ## The Distribution Of the Marginal Propensity to Consume
#
# For many macroeconomic purposes, the distribution of the MPC $\kappa$ is more important than the distribution of wealth.  Ours is a quarterly model, and MPC's are typically reported on an annual basis; we can compute a (very) approximate annual MPC from the quraterly ones as $\kappa_{Y} \approx 1.0 - (1.0 - \kappa_{Q})^4$
#
# In the cell below, we retrieve the MPCs from our simulated consumers and show that the 10th percentile in the MPC distribution is only about 6 percent, while at the 90th percentile it is almost 0.5
#
# ### 1. MPC distribution from the "brute force" approach
#
# Again, we first show the computation from the "brute force approach". This is done in the following code block.

# %%
# Retrieve the MPC's
percentiles = np.linspace(0.1, 0.9, 9)
MPC_sim = np.concatenate([ThisType.MPCnow for ThisType in MyTypes])
MPCpercentiles_quarterly = get_percentiles(MPC_sim, percentiles=percentiles)
MPCpercentiles_annual = 1.0 - (1.0 - MPCpercentiles_quarterly) ** 4

print(
    "The MPC at the 10th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[0]))
)
print(
    "The MPC at the 50th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[4]))
)
print(
    "The MPC at the 90th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[-1]))
)

# %% [markdown]
# ### 2. MPC distribution from the `AgentPopulation` approach
#
# Next, we compare this distribution of marginal propensities to consume with the one from the analogous computation when the `AgentPopulation` class is used. Notably, the distribution of MPCs in this case is nearly identical, with the only difference being at the 90th percentile.

# %%
# Retrieve the MPC's
percentiles = np.linspace(0.1, 0.9, 9)
MPC_sim_ap = np.concatenate([ThisSubPop.MPCnow for ThisSubPop in SubPops])
MPCpercentiles_quarterly_ap = get_percentiles(MPC_sim_ap, percentiles=percentiles)
MPCpercentiles_annual_ap = 1.0 - (1.0 - MPCpercentiles_quarterly_ap) ** 4

print(
    "The MPC at the 10th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[0]))
)
print(
    "The MPC at the 50th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[4]))
)
print(
    "The MPC at the 90th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[-1]))
)

# %% [markdown]
# ## Adding Very Impatient Households
#
# Now that we have some tools for examining both microeconomic (the MPC across the population) and macroeconomic (the distribution and overall level of wealth) outcomes from our model, we are all set to conduct our experiment.
#
# In this exercise, we are going to add very impatient households to the economy in a very direct way: by replacing the *most impatient consumer type* with an *even more impatient type*.  Specifically, we will have these agents have a discount factor of $\beta = 0.80$ at a quarterly frequency, which corresponds to $\beta \approx 0.41$ annual.
#
# In the code block below, we:
#
# 1. Replicate the list of agents using $\texttt{deepcopy}$.
# 2. Set the $\beta$ of the most impatient type to $0.80$ (for the copied set of agents).
# 3. Solve and simulate the most impatient type (for the copied set of agents).
#
# We conduct this exercise for both approaches again. The code is essentially identical, other than the naming conventions used for variables in each case. Notice that the output from each of the final two code blocks are exactly identical!

# %%
# Follow the instructions above to make another list of agents that includes *very* impatient households.
NewTypes = deepcopy(MyTypes)
NewTypes[0].DiscFac = 0.8
NewTypes[0].solve()
NewTypes[0].initialize_sim()
NewTypes[0].simulate()

# Retrieve the MPC's
percentiles = np.linspace(0.1, 0.9, 9)
MPC_sim = np.concatenate([ThisType.MPCnow for ThisType in NewTypes])
MPCpercentiles_quarterly = get_percentiles(MPC_sim, percentiles=percentiles)
MPCpercentiles_annual = 1.0 - (1.0 - MPCpercentiles_quarterly) ** 4

print(
    "The MPC at the 10th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[0]))
)
print(
    "The MPC at the 50th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[4]))
)
print(
    "The MPC at the 90th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual[-1]))
)

# these last two slides need an edit if this is the wealth distribution.

# %%
# Follow the instructions above to make another list of agents that includes *very* impatient households.
NewSubPops = deepcopy(SubPops)
NewSubPops[0].DiscFac = 0.8
NewSubPops[0].solve()
NewSubPops[0].initialize_sim()
NewSubPops[0].simulate()

# Retrieve the MPC's
percentiles = np.linspace(0.1, 0.9, 9)
MPC_sim_ap = np.concatenate([ThisSubPop.MPCnow for ThisSubPop in NewSubPops])
MPCpercentiles_quarterly_ap = get_percentiles(MPC_sim_ap, percentiles=percentiles)
MPCpercentiles_annual_ap = 1.0 - (1.0 - MPCpercentiles_quarterly_ap) ** 4

print(
    "The MPC at the 10th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[0]))
)
print(
    "The MPC at the 50th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[4]))
)
print(
    "The MPC at the 90th percentile of the distribution is "
    + str(decfmt2(MPCpercentiles_annual_ap[-1]))
)


# https://www.acmicpc.net/problem/1629
import sys

def powWithMode(base, exp, mod):
  ret = 1
  while exp:
    if exp & 1:
      ret = (ret * base) % mod
    base = (base * base) % mod
    exp >>= 1

  return ret

a,b,c = map(int, sys.stdin.readline().split())

print(powWithMode(a, b, c))


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

class solution:

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

    def compute(self):
        s=1
        for v in range(1,self.n+1):
            s*=v

        str_res=str(s)
        res=0
        for digit in str_res:
            res+= int(digit)
        return res

if __name__ == "__main__":
    import sys
    if len(sys.argv)==2:
        n=int(sys.argv[1])
    else:
        n=100
    s=solution(n)
    print(s.compute())