import matplotlib.pyplot as plt
import seaborn as sn
import unicodecsv as csv

from models.topological_compat_matrix import TopologicalCompatMatrix
from utils.constants import LOG_ENTRY_DELIMITER, SENSOR_ID_POS, NOISE_THRESHOLD

class BStep(object):
    def __init__(self):
        """
        Gather the two sets of segments that must be combined to contribute to the validation set.
        """
        self.closed_segments = []  # the segments closed at this B-step.
        self.compat_segments = []  # the segments opened between this B-step and the next that are compatible.
        self.crossing_points =  []
    def add_closed_segment(self, s):
        self.closed_segments.append(s)

    def add_compat_segment(self, s):
        self.compat_segments.append(s)

class SegmentedSensorLog(object):
    def __init__(self, sensor_log=None, top_compat_matrix=None, compat_threshold=None, segments=None,
                 sensor_id_pos=SENSOR_ID_POS, noise_threshold=NOISE_THRESHOLD):
        """
        Segmented version of the given log, built according to the given probabilistic topological compatibility matrix.

        :type sensor_log: file
        :type top_compat_matrix: TopologicalCompatMatrix
        :type compat_threshold: float
        :type segments: list
        :type sensor_id_pos: int
        :type noise_threshold: int
        :param sensor_log: the tab-separated file containing the sensor log.
        :param top_compat_matrix: the topological compatibility matrix of the sensor log.
        :param compat_threshold: the threshold to reach for a direct succession to be significant.
        :param segments: a precomputed list of segments.
        :param sensor_id_pos: the position of the sensor id in the log entry.
        :param noise_threshold: the minimum length of a segment.
        """
        if segments:
            self.segments = segments

        elif sensor_log and top_compat_matrix and compat_threshold:
            self.segments = []
            self.top_compat_matrix = top_compat_matrix
            self.compat_threshold = compat_threshold
            self.noise_threshold = noise_threshold
            self.sensor_id_pos = sensor_id_pos

            self.b_steps = []  # the B-steps performed during the segmentation (to be used in validation).

            self._find_segments(sensor_log)

        else:
            raise ValueError('Not enough inputs provided.')

    def plot_stats(self, distribution=True, time_series=False):
        """
        Visualize segmented sensor log statistics.
        Notice that time-series visualization is significant only when the segments are chronologically ordered.

        :param distribution: whether the distribution visualization must be shown.
        :param time_series: whether the time-series visualization must be shown.
        """
        segments_num = len(self.segments)
        segments_lengths = [len(s) for s in self.segments]

        print('segments num:', segments_num)
        print('min length:  ', len(min(self.segments, key=len)))
        print('max length:  ', len(max(self.segments, key=len)))
        print('avg length:  ', int(sum(segments_lengths) / segments_num))
        print('b-steps num: ', len(self.b_steps))

        if distribution:
            plt.figure()
            sn.distplot(segments_lengths)

        if time_series:
            plt.figure()
            sn.tsplot(segments_lengths)

        plt.show()

    """ UTILITY FUNCTIONS """

    def _find_segments(self, sensor_log):
        """
        Find segments in the given sensor log.

        :type sensor_log: file
        :param sensor_log: the tab-separated file containing the sensor log.
        """
        sensor_log_reader = csv.reader(sensor_log, delimiter=LOG_ENTRY_DELIMITER)
        open_segments = []
        for measure in sensor_log_reader:

            sensor_id = measure[self.sensor_id_pos]
            # find compatible open segments
            compat_segments_idxs = self._get_compat_segments_indices(open_segments, sensor_id)

            # check compatibility results
            if len(compat_segments_idxs) == 1:
                # only one compat segment exists, append the measure
                segment_idx = compat_segments_idxs[0]
                open_segments[segment_idx].append(measure)

            else:
                if len(compat_segments_idxs) > 1:
                    # if many compat segments exist, close them (B-step)
                    self._close_segments(open_segments, compat_segments_idxs)

                # open new segment and append the measure
                new_segment = [measure]
                open_segments.append(new_segment)

                # check whether the new segment is compatible with at least a segment in last B-step
                if self.b_steps:
                    if self._get_compat_segments_indices(self.b_steps[-1].closed_segments, sensor_id):

                        # add new segment to last B-step compatibility list
                        self.b_steps[-1].add_compat_segment(new_segment)
                        #print(str(measure[0])+ "_"+str(sensor_log_reader.line_num))
                        self.b_steps[-1].crossing_points.append(str(measure[0])+ "_"+str(sensor_log_reader.line_num))

        # close remaining open segments
        self._close_segments(open_segments)

    def _get_compat_segments_indices(self, segments, sensor_id):
        """
        Return tho positions of the segments that are compatible (according to the given threshold) with the provided
        sensor identifier.

        :type segments: list
        :param segments: the list of open segments.
        :param sensor_id: the sensor identifier.
        :return: a list containing the indices of the compatible segments.
        """
        compat_segments_idxs = []
        for idx, os in enumerate(segments):
            # consider the sensor id of the last measure in segment
            old_sensor_id = os[-1][self.sensor_id_pos]

            if self.top_compat_matrix.prob_matrix[old_sensor_id][sensor_id] >= self.compat_threshold:
                # the direct succession value is above the threshold -> segment is compatible
                compat_segments_idxs.append(idx)
        return compat_segments_idxs

    def _close_segments(self, open_segments, indices=None):
        """
        Remove the segments identified by the given indices from the open list and add them to close list (if the
        minimum length is matched). If the indices are not provided, then all segments will be closed.

        :type open_segments: list
        :type indices: list
        :param open_segments: the list of open segments.
        :param indices: the positions of the segments to be closed.
        """
        if indices:
            indices = sorted(indices)
        else:
            # build a list of all possible indices to use the same approach for both cases.
            indices = [x for x in range(len(open_segments))]

        # add all segments to be closed to the global segments list and group them in a B-step
        b_step = BStep()
        for idx in reversed(indices):
            closed_segment = open_segments.pop(idx)          # remove segment from open list
            if len(closed_segment) >= self.noise_threshold:  # noise filtering
                self.segments.append(closed_segment)
                b_step.add_closed_segment(closed_segment)
        if b_step.closed_segments:
            self.b_steps.append(b_step)

    """ DEPRECATED FUNCTIONS """

    def _find_segments_old(self, sensor_log):
        """
        Find segments in the given sensor log (old version).

        :type sensor_log: file
        :param sensor_log: the tab-separated file containing the sensor log.
        """
        sensor_log_reader = csv.reader(sensor_log, delimiter=LOG_ENTRY_DELIMITER)

        s0 = next(sensor_log_reader, None)  # consider a sliding window of two events per step
        s1 = next(sensor_log_reader, None)
        segment = [list(s0)]
        while s0 is not None and s1 is not None:
            s0_id = s0[self.sensor_id_pos]
            s1_id = s1[self.sensor_id_pos]

            if self.top_compat_matrix.prob_matrix[s0_id][s1_id] >= self.compat_threshold:
                # the direct succession value is above the threshold
                segment.append(list(s1))  # continue the segment
            else:
                # the direct succession value is under the threshold
                if len(segment) >= self.noise_threshold:  # only segments longer than a threshold are considered
                    self.segments.append(list(segment))   # store a copy of the segment so far
                segment = [list(s1)]                      # start the new segment from the second item in the window

            # prepare next step (slide the window by one position)
            s0 = s1
            s1 = next(sensor_log_reader, None)


"""
@Author         : Ailitonia
@Date           : 2021/09/12 0:09
@FileName       : rate_limiting.py
@Project        : nonebot2_miya
@Description    : 速率限制
@GitHub         : https://github.com/Ailitonia
@Software       : PyCharm
"""

import time
from datetime import datetime, timedelta
from typing import Union, Dict
from nonebot import get_driver, logger
from nonebot.exception import IgnoredException
from nonebot.typing import T_State
from nonebot.adapters.cqhttp.bot import Bot
from nonebot.adapters.cqhttp.event import MessageEvent, GroupMessageEvent
from omega_miya.database import DBBot, DBBotGroup, DBCoolDownEvent

global_config = get_driver().config
SUPERUSERS = global_config.superusers

# 速率限制次数阈值, 触发超过该次数后启用限制
RATE_LIMITING_THRESHOLD: int = 5
# 速率限制时间阈值, 判断连续消息触发的时间间隔小于该值, 单位为秒, 判断依据时间戳为标准
RATE_LIMITING_TIME: float = 1.0
# 启用后判断依据将以处理时的系统时间戳为准, 而不是上报 event 的时间戳
USING_SYSTEM_TIMESTAMP: bool = False
# 记录用户上次消息的时间戳, 作为对比依据
USER_LAST_MSG_TIME: Dict[int, Union[int, float]] = {}
# 记录用户消息在速率限制时间阈值内触发的次数
RATE_LIMITING_COUNT: Dict[int, int] = {}
# 触发速率限制时为用户设置的全局冷却时间, 单位秒
RATE_LIMITING_COOL_DOWN: int = 1800
# 缓存的已被限制的用户id及到期时间, 避免多次查数据库
RATE_LIMITING_USER_TEMP: Dict[int, datetime] = {}
# 群组流控配置冷却时间, 与 plugins.omega_rate_limiting 中配置保持一致
GROUP_GLOBAL_CD_SETTING_NAME: str = 'group_global_cd'

async def preprocessor_rate_limiting(bot: Bot, event: MessageEvent, state: T_State):
    """
    速率限制处理 T_EventPreProcessor
    """
    global USER_LAST_MSG_TIME
    global RATE_LIMITING_COUNT
    global RATE_LIMITING_USER_TEMP

    user_id = event.user_id
    # 忽略超级用户
    if user_id in [int(x) for x in SUPERUSERS]:
        return

    # 检测该用户是否已经被速率限制
    if RATE_LIMITING_USER_TEMP.get(user_id, datetime.now()) > datetime.now():
        logger.info(f'Rate Limiting | User: {user_id} 仍在速率限制中, 到期时间 {RATE_LIMITING_USER_TEMP.get(user_id)}')
        raise IgnoredException('速率限制中')

    # 获取上条消息的时间戳
    last_msg_timestamp = USER_LAST_MSG_TIME.get(user_id, None)

    # 获取当前消息时间戳
    if USING_SYSTEM_TIMESTAMP:
        this_msg_timestamp = time.time()
    else:
        this_msg_timestamp = event.time

    # 更新上次消息时间戳为本次消息时间戳
    if last_msg_timestamp is None:
        USER_LAST_MSG_TIME.update({user_id: this_msg_timestamp})
        # 上次消息时间戳为空则这是第一条消息
        return
    else:
        USER_LAST_MSG_TIME.update({user_id: this_msg_timestamp})

    # 获取速录限制触发计数
    over_limiting_count = RATE_LIMITING_COUNT.get(user_id, 0)

    # 进行速率判断
    if this_msg_timestamp - last_msg_timestamp < RATE_LIMITING_TIME:
        # 小于时间阈值则计数 +1
        over_limiting_count += 1
        logger.info(f'Rate Limiting | User: {user_id} over rate limiting, counting {over_limiting_count}')
    else:
        # 否则重置计数
        over_limiting_count = 0

    # 更新计数
    RATE_LIMITING_COUNT.update({user_id: over_limiting_count})

    # 判断计数大于阈值则触发限制, 为用户设置一个全局冷却并重置计数
    if over_limiting_count > RATE_LIMITING_THRESHOLD:
        RATE_LIMITING_USER_TEMP.update({user_id: datetime.now() + timedelta(seconds=RATE_LIMITING_COOL_DOWN)})
        logger.success(f'Rate Limiting | User: {user_id} 触发速率限制, Upgrade RATE_LIMITING_USER_TEMP completed')

        result = await DBCoolDownEvent.add_global_user_cool_down_event(
            user_id=user_id,
            stop_at=datetime.now() + timedelta(seconds=RATE_LIMITING_COOL_DOWN),
            description='Rate Limiting CoolDown')
        RATE_LIMITING_COUNT.update({user_id: 0})

        if result.error:
            logger.error(f'Rate Limiting | Set rate limiting cool down failed: {result.info}')
        else:
            logger.success(f'Rate Limiting | User: {user_id} 触发速率限制, 已设置 {RATE_LIMITING_COOL_DOWN} 秒全局冷却限制')
        raise IgnoredException('触发速率限制')

async def postprocessor_rate_limiting(bot: Bot, event: MessageEvent, state: T_State):
    """
    速率限制事件后处理 T_EventPostProcessor
    """
    if not state.get('_prefix', {}).get('raw_command') and not state.get('_suffix', {}).get('raw_command'):
        # 限流仅能由命令触发
        logger.debug(f'Rate Limiting | Not command event, ignore global group cool down')
        return

    self_bot = DBBot(self_qq=int(bot.self_id))
    if isinstance(event, GroupMessageEvent):
        group_id = event.group_id
        group = DBBotGroup(group_id=group_id, self_bot=self_bot)
        setting_result = await group.setting_get(setting_name=GROUP_GLOBAL_CD_SETTING_NAME)
        if setting_result.success():
            main, second, extra = setting_result.result
            if main:
                # 配置有效, 为群组设置一个全局冷却
                result = await DBCoolDownEvent.add_global_group_cool_down_event(
                    group_id=group_id,
                    stop_at=datetime.now() + timedelta(seconds=int(main)),
                    description='Rate Limiting Global Group CoolDown')
                if result.error:
                    logger.error(f'Rate Limiting | Set global group cool down failed: {result.info}')
                else:
                    logger.debug(f'Rate Limiting | Set Group: {group_id} global group cool down, times: {main}')
            else:
                logger.error(f'Rate Limiting | Group: {group_id} global group cool down setting not found')
        elif setting_result.error and setting_result.info == 'NoResultFound':
            logger.debug(f'Rate Limiting | Group: {group_id} not set global group cool down, pass')
        else:
            logger.error(f'Rate Limiting | Set global group cool down getting setting failed: {setting_result.info}')

__all__ = [
    'preprocessor_rate_limiting',
    'postprocessor_rate_limiting'
]


import os
import platform

report = []

def getInformation(info, param):
    info = info + str(param)
    print (info)
    report.append(info)

machine = platform.machine()
arch = 'Архитектура системы         : '
if machine == "AMD64":
    machine = "64-Bit"
else:
    machine = "32-Bit"

textList = ['ID текущего процесса        : ',
            'Имя учетной записи          : ',
            'Имя устройства              : ',
            'Операционная система        : ',
            'Версия операционной системы : ',
            'Архитектура системы         : ',
            'Версия сборки               : ',
            'Версия сборки               : ',
            'Процессор                   : ',
            'Версия Python               : ',
            'Версия и дата сборки Python : ']
funcList = [os.getpid(),
            os.getlogin(),
            platform.node(),
            platform.system(),
            platform.release(),
            machine,
            platform.platform(),
            platform.version(),
            platform.processor(),
            platform.python_version(),
            platform.python_build()]

for a in textList:
    for b in funcList:
        qw = textList.pop(0)
        getInformation(qw, b)

print('\nЕсли хотите сохранить информацию в фаил введите : yes или y')

save_txt = input()

if (save_txt == 'yes' or save_txt == 'y'):
    # Запись информации в фаил
    file = open('system_information_report.txt', 'w')         # Открытие файла для записи

    # Цикл записи списка в фаил
    for report in report:
        file.write(report + "\n")

    file.close()                        # Закрытие файла после записи

    print('Фаил сохранен под именем - system_information_report.txt')


import src.core.covariance as cov
import src.core.channel_correlation as correl
import src.core.crosstalk.crosstalk_estimation as crstlk_est
import src.core.radiometry.radiometric_estimation as radio_est
import src.core.radiometry.radiometric_correction as rcal
import src.core.crosstalk.crosstalk_correction as crstlk_cor
import src.error.MNE_estimation as me
import src.error.SNR_estimation as snrc
import testing.dump as td
import src.POA.poa_shift as poa

root_dir = "/media/Cellar/Thesis_Output/"
main_input = root_dir + "/Subset_Main/"
xpol_input = root_dir + "Subset_Xpol/"

radio_dir = root_dir + "Radio_Cal/"

cov_dir_b = root_dir + "Covariance.Before/"

crstlk_q_b = root_dir + "Crosstalk_Q.Before/"
crstlk_q_a = root_dir + "Crosstalk_Q.After/"
crstlk_a_b = root_dir + "Crosstalk_A.Before/"
crstlk_a_a = root_dir + "Crosstalk_A.After/"
crstlk_m_b = root_dir + "Crosstalk_M.Before/"
crstlk_m_a = root_dir + "Crosstalk_M.After/"

logic_out_qb = crstlk_q_b + "Logic_Board"
logic_out_qa = crstlk_q_a + "Logic_Board"

crstlk_qb_rc = root_dir + "Crosstalk_Q_RC.Before/"
crstlk_qa_rc = root_dir + "Crosstalk_Q_RC.After/"
crstlk_ab_rc = root_dir + "Crosstalk_A_RC.Before/"
crstlk_aa_rc = root_dir + "Crosstalk_A_RC.After/"
crstlk_mb_rc = root_dir + "Crosstalk_M_RC.Before/"
crstlk_ma_rc = root_dir + "Crosstalk_M_RC.After/"

out_q = root_dir + "CalOut_Q/"
out_a = root_dir + "CalOut_A/"
out_m = root_dir + "CalOut_M/"

err_q = out_q + "Error"
err_a = out_a + "Error"
err_m = out_m + "Error"

hh_radio = radio_dir + "HH"
hv_radio = radio_dir + "HV"
vh_radio = radio_dir + "VH"
vv_radio = radio_dir + "VV"

cov_dir_q = root_dir + "Covariance_Q/"
cov_dir_a = root_dir + "Covariance_A/"

hh_qcal = out_q + "HH_Cal"
hv_qcal = out_q + "HV_Cal"
vh_qcal = out_q + "VH_Cal"
vv_qcal = out_q + "VV_Cal"

hh_acal = out_a + "HH_Cal"
hv_acal = out_a + "HV_Cal"
vh_acal = out_a + "VH_Cal"
vv_acal = out_a + "VV_Cal"

hh_mcal = out_m + "HH_Cal"
hv_mcal = out_m + "HV_Cal"
vh_mcal = out_m + "VH_Cal"
vv_mcal = out_m + "VV_Cal"

u_qb = crstlk_qb_rc + "u"
v_qb = crstlk_qb_rc + "v"
w_qb = crstlk_qb_rc + "w"
z_qb = crstlk_qb_rc + "z"

u_qa = crstlk_qa_rc + "u"
v_qa = crstlk_qa_rc + "v"
w_qa = crstlk_qa_rc + "w"
z_qa = crstlk_qa_rc + "z"

u_ab = crstlk_ab_rc + "u"
v_ab = crstlk_ab_rc + "v"
w_ab = crstlk_ab_rc + "w"
z_ab = crstlk_ab_rc + "z"

u_aa = crstlk_aa_rc + "u"
v_aa = crstlk_aa_rc + "v"
w_aa = crstlk_aa_rc + "w"
z_aa = crstlk_aa_rc + "z"

u_mb = crstlk_mb_rc + "u"
v_mb = crstlk_mb_rc + "v"
w_mb = crstlk_mb_rc + "w"
z_mb = crstlk_mb_rc + "z"

u_ma = crstlk_ma_rc + "u"
v_ma = crstlk_ma_rc + "v"
w_ma = crstlk_ma_rc + "w"
z_ma = crstlk_ma_rc + "z"

# correl.logicboard(cov_dir=cov_dir_b, out_img=logic_out_qb, threshold=0.3)
# crstlk_est.quegan(cov_dir=cov_dir_b, crosstalk_dir=crstlk_q_b, logic_img=logic_out_qb)
# crstlk_est.range_binning(crstlk_dir=crstlk_q_b, out_dir=crstlk_qb_rc, range_direction=1)

# crstlk_cor.apply_correction(
#     hh_img=hh_radio,
#     hv_img=hv_radio,
#     vh_img=vh_radio,
#     vv_img=vv_radio,
#     params_dir=crstlk_qb_rc,
#     out_dir=out_q,
#     error_map=err_q
# )

# crstlk_est.ainsworth(cov_dir=cov_dir_b, crosstalk_dir=crstlk_a_b)
# crstlk_est.range_binning(crstlk_dir=crstlk_a_b, out_dir=crstlk_ab_rc, range_direction=1)

# crstlk_cor.apply_correction(
#     hh_img=hh_radio,
#     hv_img=hv_radio,
#     vh_img=vh_radio,
#     vv_img=vv_radio,
#     params_dir=crstlk_ab_rc,
#     out_dir=out_a,
#     error_map=err_a
# )

# cov.compute_covar(
#     hh_img=hh_qcal,
#     hv_img=hv_qcal,
#     vh_img=vh_qcal,
#     vv_img=vv_qcal,
#     out_dir=cov_dir_q,
#     winxsize=3,
#     winysize=3
# )

# correl.logicboard(cov_dir=cov_dir_q, out_img=logic_out_qa, threshold=0.3)
# crstlk_est.quegan(cov_dir=cov_dir_q, crosstalk_dir=crstlk_q_a, logic_img=logic_out_qa)
# crstlk_est.range_binning(crstlk_dir=crstlk_q_a, out_dir=crstlk_qa_rc, range_direction=1)

# cov.compute_covar(
#     hh_img=hh_acal,
#     hv_img=hv_acal,
#     vh_img=vh_acal,
#     vv_img=vv_acal,
#     out_dir=cov_dir_a,
#     winxsize=3,
#     winysize=3
# )

# crstlk_est.ainsworth(cov_dir=cov_dir_a, crosstalk_dir=crstlk_a_a)
# crstlk_est.range_binning(crstlk_dir=crstlk_a_a, out_dir=crstlk_aa_rc, range_direction=1)

# me.estimate_mne(
#     u_img=u_qb,
#     v_img=v_qb,
#     w_img=w_qb,
#     z_img=z_qb,
#     mne_img=crstlk_qb_rc + "MNE"
# )

# me.estimate_mne(
#     u_img=u_ab,
#     v_img=v_ab,
#     w_img=w_ab,
#     z_img=z_ab,
#     mne_img=crstlk_ab_rc + "MNE"
# )

# me.estimate_mne(
#     u_img=u_qa,
#     v_img=v_qa,
#     w_img=w_qa,
#     z_img=z_qa,
#     mne_img=crstlk_qa_rc + "MNE"
# )

# me.estimate_mne(
#     u_img=u_aa,
#     v_img=v_aa,
#     w_img=w_aa,
#     z_img=z_aa,
#     mne_img=crstlk_aa_rc + "MNE"
# )

# crstlk_est.ainsworth_mod(cov_dir=cov_dir_b, crosstalk_dir=crstlk_m_b, xoffset=1000, yoffset=1000)
# crstlk_est.range_binning(crstlk_dir=crstlk_m_b, out_dir=crstlk_mb_rc, range_direction=1)
#
# crstlk_cor.apply_correction(
#     hh_img=hh_radio,
#     hv_img=hv_radio,
#     vh_img=vh_radio,
#     vv_img=vv_radio,
#     params_dir=crstlk_mb_rc,
#     out_dir=out_m,
#     error_map=err_m
# )

snrc.estimate_SNR(
    c1_img=vh_radio,
    c2_img=hh_radio,
)


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

from setuptools import setup, find_packages

VAgent_VERSION = '0.0.1'

if __name__ == "__main__":
    setup(
        name = 'src',
        version = VAgent_VERSION,
        packages = find_packages(),
        long_description=__doc__,
        description = 'src common lib',
        include_package_data = True,
        zip_safe = False
    )


# -*- coding: utf-8 -*-
from odoo import api, models, fields

class Edicionmrp(models.Model):
    _inherit = 'mrp.production'

    order_venta_origen = fields.Many2one(
        'sale.order',
        string="Enlace a la orden de venta",
        help="Orden de venta con enlace",
        compute='get_customer',
        readonly=True
    )

    cliente = fields.Many2one(
        'res.partner',
        string=u"Cliente",
        compute='get_customer',
    )

    @api.one
    @api.depends('origin')
    def get_customer(self):
        for record in self:
            order_venta = record.env['sale.order'].search([('name', '=', record.origin)])
            record.order_venta_origen = order_venta
            cliente_id = order_venta.partner_id
            record.cliente = cliente_id


import tensorflow as tf
import numpy as np
tf.set_random_seed(66)

x_data = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=np.float32)
y_data = np.array([[0],[1],[1],[0]], dtype=np.float32)

x = tf.placeholder(tf.float32, shape=[None, 2])
y = tf.placeholder(tf.float32, shape=[None, 1])

w = tf.Variable(tf.zeros([2, 1]), name='weight')
b = tf.Variable(tf.zeros([1]), name='bias')

hypothesis = tf.sigmoid(tf.matmul(x, w) + b)

# sigmoid cost
loss= -tf.reduce_mean(y * tf.log(hypothesis) + (1 - y) * tf.log(1-hypothesis))
train = tf.train.AdamOptimizer(learning_rate = 0.01).minimize(loss)

predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, y), dtype=tf.float32))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(5001):
        cost_val, _ = sess.run([loss,train], feed_dict={x:x_data, y:y_data})

        if step % 200 ==0:
            print(step,cost_val)

    h , c, a = sess.run([hypothesis,predicted,accuracy], feed_dict={x:x_data, y:y_data})

    print("predict value :", h, "original value: ", c, "accuracy: ", a)


# import DIFFICULTY from __init__
# import VERSION from __init__
import hashlib
import time
import json
from Crypto.Hash import SHA256
class block:
    def __init__(self, diffculty, time_stamp, transactions, prev_hash, Nonce):
        self.difficulty = diffculty
        self.time_stamp = time_stamp
        self.transactions = transactions
        self.Nonce = Nonce
        self.prev_hash = prev_hash
        self.current_hash = self.calculate_hash()

    def __str__(self):
        block_str = json.dumps(self, default=lambda o: o.__dict__)
        # print(test_str)
        return block_str

    def calculate_hash(self):
        data = {}
        data['Difficulty'] = self.difficulty
        data['Time_Stamp'] = self.time_stamp
        data['Transactions'] = self.transactions
        data['Nonce'] = self.Nonce
        data['Prev_hash'] = self.prev_hash
        json_data = json.dumps(data)
        hash_val = hashlib.sha256(json_data).hexdigest()
        self.current_hash = hash_val
        return hash_val

    def has_valid_transactions(self):
        for transaction in self.transactions:
            if not transaction.isvalid():
                return false
        return true


import spacy
from chatsenselib.variables import mLangMapDB
from chatsenselib.responses import *
from chatsenselib.parser1sensors import *
from chatsenselib.parser1locations import *

def matchscalarquantityinlist(sr,l):
    answer = False;
    for s in l:
        if (matchscalarquantity(sr,s)):
            answer = True;
        if (matchscalarquantityinlist(sr,s["modifiers"])):
            answer = True;
    return(answer);

def matchlocationinlist(sr,l):
    answer = False;
    for s in l:
        if (matchlocation(sr,s)):
            answer = True;
        if (matchlocationinlist(sr,s["modifiers"])):
            answer = True;
    return(answer);

def matchposandlemma(sr,s,expectedpos,expectedlemma):
    if (s["POS_fine"] == expectedpos and
        s["lemma"].lower() == expectedlemma):
        return(True);
    else:
        return(False);

def matchposandlemmainlist(sr,l,expectedpos,expectedlemma):
    answer = False
    for s in l:
        if (matchposandlemma(sr,s,expectedpos,expectedlemma)):
            answer = True
        matchposandlemmainlist(sr,s["modifiers"],expectedpos,expectedlemma);
    return(answer);

def foundrequestfull(sr,s):
    # print("debug: Found a " + sr["type"] + " for " + sr["quantity"] + " in location " + sr["location"]);
    if (sr["type"] == "request for information"):
        val = str(getSensorValue(sr["quantity"],sr["location"]));
        return("The " + sr["quantity"] + " is " + val + ".");
    else:
        return("Sorry, I cannot do that (yet).");

def foundrequestnolocation(sr,s):
    # print("debug: Found a " + sr["type"] + " for " + sr["quantity"] + " in unspecified location");
    if (sr["type"] == "request for information"):
        return("You would like to get " + sr["quantity"] + ", but for what? Can you specify where?");
    else:
        return("You would like to change something in " + sr["quantity"] + ", but can you specify where?");

def foundrequestnosensor(sr,s):
    # print("debug: Found a " + sr["type"] + " but not clear for what");
    if (sr["location"] == ""):
        return("I'm sorry, you are talking about a " + sr["type"] + " but what for?");
    else:
        return("I'm sorry, you are talking about a " + sr["type"] + " but what for? What do you want to know about the " + sr["location"] + "?");

def foundnorequest(sr,s):
    # print("debug: Found no request");
    return("I'm sorry, I did not understand. What do you want?");

def lookforrequest(s):
    semanticrepr = { "type": "", "quantity": "", "location": "" }
    #print("debug: first pos and lemma: " + s["POS_fine"] + ", " + s["lemma"]);
    #if (len(s["modifiers"]) > 0):
    #   print("debug: second pos and lemma: " + s["modifiers"][0]["POS_fine"] + ", " + s["modifiers"][0]["lemma"]);
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VBZ","be") and
        matchposandlemmainlist(semanticrepr,s["modifiers"],"WP","what")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","show") and
        matchposandlemmainlist(semanticrepr,s["modifiers"],"PRP","me")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","show")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","give") and
        matchposandlemmainlist(semanticrepr,s["modifiers"],"PRP","me")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","give")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","display")):
        semanticrepr["type"] = "request for information";
    if (semanticrepr["type"] == "" and
        matchposandlemma(semanticrepr,s,"VB","set")):
        semanticrepr["type"] = "command to change";
    if (semanticrepr["type"] != ""):
        if (matchscalarquantityinlist(semanticrepr,s["modifiers"])):
            if (matchlocationinlist(semanticrepr,s["modifiers"])):
                return(foundrequestfull(semanticrepr,s));
            else:
                return(foundrequestnolocation(semanticrepr,s));
        else:
            matchlocationinlist(semanticrepr,s["modifiers"])
            return(foundrequestnosensor(semanticrepr,s));
    else:
        return(foundnorequest(semanticrepr,s));

def processrequest(doc):
    result = "";
    # print("debug: Looking for requests in " + doc.text + "...");
    for s in doc.print_tree():
        if (result != ""):
            result = result + " ";
        result = result + lookforrequest(s);
    return(result)


from mesa import Agent, Model
from mesa.time import RandomActivation
from mesa.space import MultiGrid
from mesa.datacollection import DataCollector
from sklearn import svm
import _pickle as pickle
import random
import sys, time, argparse
import numpy as np
import operator

import io
from PIL import Image, ImageDraw

from draw_plane import DrawPlane
from embryo import Embryo

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
import torch.utils.data as utils

parser = argparse.ArgumentParser()
parser.add_argument("--cell", type=str, default='mu_int_r', help="The cell name. choose from [mu_int_r, canl]")
parser.add_argument("--emb", type=int, default=1, help="The index of embryo. choose from [1,2]")

args = parser.parse_args()

if args.cell == 'mu_int_r':
	AI_CELL = 'MSppaapp'	#mu_int_R
	if args.emb == 1:
		START_POINT = 228+25
		END_POINT = 228+80
		PLANE_DRAW = 25
		NUCLEI_DATA_PATH = './data/mu_int_R_CANL_1/'
	elif args.emb == 2:
		START_POINT = 210+25
		END_POINT = 210+80
		PLANE_DRAW = 36
		NUCLEI_DATA_PATH = './data/mu_int_R_CANL_2/'
	else:
		print('Error. Invalid embryo!')
		exit()
elif args.cell == 'canl':
	AI_CELL = 'ABalapaaapa'		#CANL
	if args.emb == 1:
		START_POINT = 250 + 60
		END_POINT = 379 - 9
		PLANE_DRAW = 11		#CANL
		NUCLEI_DATA_PATH = './data/mu_int_R_CANL_1/'
	elif args.emb == 2:
		START_POINT = 236 + 60
		END_POINT = 361 - 5
		PLANE_DRAW = 17		#CANL
		NUCLEI_DATA_PATH = './data/mu_int_R_CANL_2/'
	else:
		print('Error. Invalid embryo!')
		exit()
else:
	print('Error. Invalid cell!')
	exit()

TICK_RESOLUTION = 2

PLANE_THRESHOLD = 3			#draw the cells in the [-2,+2] planes (5 total)

INPUT_PLANE_RANGE = 2 #0

CANVAS_DISPLAY_SCALE_FACTOR = 2		### zoom in/out the size of canvas
FRESH_TIME = 0.02
FRESH_PERIOD = 1

PLANE_RESOLUTION = 4

import torch._utils
try:
    torch._utils._rebuild_tensor_v2
except AttributeError:
    def _rebuild_tensor_v2(storage, storage_offset, size, stride, requires_grad, backward_hooks):
        tensor = torch._utils._rebuild_tensor(storage, storage_offset, size, stride)
        tensor.requires_grad = requires_grad
        tensor._backward_hooks = backward_hooks
        return tensor
    torch._utils._rebuild_tensor_v2 = _rebuild_tensor_v2

class Net(nn.Module):
    def __init__(self, n_input):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(n_input, 20480)
        self.fc2 = nn.Linear(20480, 1024)
        self.fc3 = nn.Linear(1024, 256)
        self.out = nn.Linear(256, 2)

    def forward(self, x):
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        x = F.relu(x)
        x = self.fc3(x)
        x = F.relu(x)
        result = self.out(x)
        return result

class SeqRosModel(Model):
	def __init__(self):
		self.speed_model_plus = Net(4096)
		self.speed_model_plus.load_state_dict(torch.load('./trained_models/TMM.pkl', map_location=lambda storage, loc: storage))
		self.file_path = NUCLEI_DATA_PATH + 't%03d-nuclei'

		print('Parsing the Embryo...')
		self.embryo = Embryo(NUCLEI_DATA_PATH)
		self.embryo.read_data()
		self.embryo.get_embryo_visual_params()

		self.embryo.volume = 2500578

		self.ai_cell = AI_CELL

		self.start_point = START_POINT
		self.end_point = END_POINT

		self.ticks = 0
		self.tick_resolution = TICK_RESOLUTION
		self.end_tick = (self.end_point - self.start_point) * self.tick_resolution
		self.stage_destination_point = self.start_point

		self.plane_resolution = PLANE_RESOLUTION

		self.current_cell_list = []
		self.dividing_cell_overall = []
		self.next_stage_destination_list = {}
		self.state_value_dict = {}
		self.schedule = RandomActivation(self)

		self.init_env()
		self.update_stage_destination()

		self.plane = DrawPlane(width=self.embryo.width,
							height=self.embryo.height,
							w_offset = self.embryo.wid_offset,
							h_offset = self.embryo.hei_offset,
							scale_factor = CANVAS_DISPLAY_SCALE_FACTOR)
		self.canvas = self.plane.canvas
		self.plane_draw = PLANE_DRAW
		self.draw(self.plane_draw)

	def draw(self,n_plane):
		self.canvas.delete("all")
		for cell in self.schedule.agents:
			if cell.cell_name == self.ai_cell:
				center_plane = round(cell.location[2]/5.0)
				n_plane = center_plane

		draw_range = np.arange(center_plane-PLANE_THRESHOLD, center_plane+PLANE_THRESHOLD+1, 1)
		draw_range = draw_range.tolist()
		draw_range.reverse()

		for n in draw_range:
			angle = np.pi *0.5 / (PLANE_THRESHOLD + 1) * np.abs(n - n_plane)
			level = None
			for cell in self.schedule.agents:
				if cell.cell_name == self.ai_cell:
					type = 'AI'
					ai_location = cell.location
					ai_center = cell.location[0:2]
					ai_radius = cell.diameter/2.0*np.cos(angle)
					continue
				else:
					type = 'NUMB'
				if round(cell.location[2]/5.0) == n:
					self.plane.draw_cell(center=cell.location[0:2],
										radius=cell.diameter/2.0*np.cos(angle),
										type=type,
										level=level)
			if round(ai_location[2]/5.0) == n:
				self.plane.draw_cell(center=ai_center,
									radius=ai_radius,
									type='AI',
									level=None)

		self.canvas.pack()
		self.canvas.update()
		time.sleep(FRESH_TIME)

	def radis_ratio(self, cn):
		r=-1
		if cn[0:2]=="AB":
			r=0.55*(0.5**(len(cn)-2))
		elif cn=="P1":
			r=0.45
		elif cn=="EMS":
			r=0.45*0.54
		elif cn=="P2":
			r=0.45*0.46
		elif cn[0:2]=="MS":
			r=0.45*0.54*0.5*(0.5**(len(cn)-2))
		elif cn=="E":
			r=0.45*0.54*0.5
		elif cn[0]=="E" and len(cn)>=2 and cn[1] != "M":
			r=0.45*0.54*0.5*(0.5**(len(cn)-1))
		elif cn[0]=="C":
			r=0.45*0.46*0.53*(0.5**(len(cn)-1))
		elif cn=="P3":
			r=0.45*0.46*0.47
		elif cn[0]=="D":
			r=0.45*0.46*0.47*0.52*(0.5**(len(cn)-1))
		elif cn=="P4":
			r=0.45*0.46*0.47*0.48
		if r == -1:
			return 0.00000001
		return r**(1.0/3)

	def get_radius(self, cell_name):
		if cell_name[0:2]=="AB":
			v=0.55*(0.5**(len(cell_name)-2))
		elif cell_name=="P1":
			v=0.45
		elif cell_name=="EMS":
			v=0.45*0.54
		elif cell_name=="P2":
			v=0.45*0.46
		elif cell_name[0:2]=="MS":
			v=0.45*0.54*0.5*(0.5**(len(cell_name)-2))
		elif cell_name=="E":
			v=0.45*0.54*0.5
		elif cell_name[0]=="E" and len(cell_name)>=2 and cell_name[1] != "M":
			v=0.45*0.54*0.5*(0.5**(len(cell_name)-1))
		elif cell_name[0]=="C":
			v=0.45*0.46*0.53*(0.5**(len(cell_name)-1))
		elif cell_name=="P3":
			v=0.45*0.46*0.47
		elif cell_name[0]=="D":
			v=0.45*0.46*0.47*0.52*(0.5**(len(cell_name)-1))
		elif cell_name=="P4":
			v=0.45*0.46*0.47*0.48
		elif cell_name in ['Z2', 'Z3']:
			v=0.45*0.46*0.47*0.48*0.5
		else:
			print('ERROR!!!!! CELL NOT FOUND IN CALCULATING HER RADIUS!!!!',cell_name)
			print('Use an average value.')
			v=v=0.55*(0.5**(9-2))		#ABarppppa

		radius = pow(self.embryo.volume * v / (4 / 3.0 * np.pi), 1/3.0)
		radius = radius

		return radius

	def get_cell_daughter(self, cell_name, cell_dict):
		daughter = []
		if cell_name == 'P0':
			daughter = ['AB', 'P1']
		elif cell_name == 'P1':
			daughter = ['EMS', 'P2']
		elif cell_name == 'P2':
			daughter = ['C', 'P3']
		elif cell_name == 'P3':
			daughter = ['D', 'P4']
		elif cell_name == 'P4':
			daughter = ['Z2', 'Z3']
		elif cell_name == 'EMS':
			daughter = ['MS', 'E']
		## standard name ###
		else:
			for cell in cell_dict.keys():
				if cell.startswith(cell_name) and len(cell) == len(cell_name) + 1:
					daughter.append(cell)
			daughter = sorted(daughter)
		if daughter == []:
			daughter = ['', '']
		return daughter

	def init_env(self):
		with open(self.file_path % self.start_point) as file:
			for line in file:
				line = line[:len(line)-1]
				vec = line.split(', ')
				id = int(vec[0])
				location = np.array((float(vec[5]), float(vec[6]), float(vec[7])))
				########### add noise to initial location##################
				location_noise = np.random.normal(0, 0.1, 2)
				location[0:2] = location[0:2] + location_noise
				########### add noise to initial location##################
				diameter = float(vec[8])
				cell_name = vec[9]
				if cell_name[0:3] == 'Nuc':
					continue
				if cell_name != '':
					self.current_cell_list.append(cell_name)
					a = CellAgent(id, self, cell_name, location, diameter)
					self.schedule.add(a)

	def set_cell_next_location(self):
		for cell in self.schedule.agents:
			if cell.cell_name in self.next_stage_destination_list:
				cell.next_location = (self.next_stage_destination_list[cell.cell_name][0:3] - cell.location) \
								/ (self.tick_resolution - self.ticks % self.tick_resolution) + cell.location
				cell.diameter = self.next_stage_destination_list[cell.cell_name][3]
			else:
				### new cell born ###
				mother = cell.cell_name
				daughter = self.get_cell_daughter(cell.cell_name, self.next_stage_destination_list)
				if daughter[0] == '':
					self.schedule.remove(cell)
					continue
				cell.cell_name = daughter[0]
				cell.diameter = self.next_stage_destination_list[daughter[0]][3]
				cell.next_location = (self.next_stage_destination_list[daughter[0]][0:3] - cell.location) \
								/ (self.tick_resolution - self.ticks % self.tick_resolution) + cell.location
				new_id = len(self.schedule.agents) + 1
				new_diameter = self.next_stage_destination_list[daughter[1]][3]
				a = CellAgent(new_id, self, daughter[1], cell.location, new_diameter)
				self.schedule.add(a)
				a.next_location = (self.next_stage_destination_list[daughter[1]][0:3] - a.location) \
								/ (self.tick_resolution - self.ticks % self.tick_resolution) + a.location

				self.dividing_cell_overall.append(mother)

	def update_stage_destination(self):
		current_stage_destination_point = self.start_point + 1 + int(self.ticks / self.tick_resolution)
		if self.stage_destination_point == current_stage_destination_point:
			return
		else:
			self.stage_destination_point = current_stage_destination_point
			self.next_stage_destination_list.clear()
			with open(self.file_path % self.stage_destination_point) as file:
				for line in file:
					line = line[:len(line)-1]
					vec = line.split(', ')
					id = int(vec[0])
					loc_and_dia = np.array((float(vec[5]), float(vec[6]), float(vec[7]), float(vec[8])))
					cell_name = vec[9]
					if cell_name != '':
						self.next_stage_destination_list[cell_name] = loc_and_dia

	def render(self):
		if self.ticks % FRESH_PERIOD == 0:
			self.draw(self.plane_draw)

	def reset(self):
		self.ticks = 0

		self.start_point = START_POINT
		self.end_point = END_POINT

		self.end_tick = (self.end_point - self.start_point) * self.tick_resolution
		self.stage_destination_point = self.start_point
		self.current_cell_list = []
		self.dividing_cell_overall = []
		self.next_stage_destination_list = {}
		self.state_value_dict = {}

		del self.schedule.agents[:]
		self.init_env()
		self.update_stage_destination()
		s = self.get_state()

		return s

	def get_state(self):
		s = []
		low_plane = PLANE_DRAW-INPUT_PLANE_RANGE
		if low_plane <=1:
			low_plane = 1
		high_plane = PLANE_DRAW+INPUT_PLANE_RANGE+1
		for p in range(low_plane, high_plane):
			image = Image.new('RGB', (self.embryo.width-self.embryo.wid_offset, self.embryo.height-self.embryo.hei_offset))
			draw = ImageDraw.Draw(image)
			for cell in self.schedule.agents:
				if cell.cell_name == self.ai_cell:
					fill_color = 'red'

				else:
					fill_color = 'green'
				cell_loc = np.array((cell.location[0], cell.location[1], \
								cell.location[2]))
				radius = self.get_radius(cell.cell_name)
				z_diff = cell_loc[2] - p * self.plane_resolution
				if abs(z_diff) < radius:
					radius *= 0.5
					z_diff *= 0.5
					radius_projection = (radius**2 - z_diff**2) ** 0.5
					draw.ellipse((cell_loc[0]-radius_projection-self.embryo.wid_offset,
									cell_loc[1]-radius_projection-self.embryo.hei_offset,
									cell_loc[0]+radius_projection-self.embryo.wid_offset,
									cell_loc[1]+radius_projection-self.embryo.hei_offset),
						fill = fill_color, outline ='black')

			image = image.resize((128,128))
			image_np = np.array(image).astype(np.float32) / 255			#widthxheightx3
			image_np = np.rollaxis(image_np, 2)							#3x2widthxheight

			if s == []:
				s = image_np
			else:
				s = np.concatenate((s, image_np), axis=0)

		return s

	def step(self):
		r = 0
		done = False
		sg_done = False
		if self.ticks > 0 and self.ticks % self.tick_resolution == 0:
			self.update_stage_destination()

		self.set_cell_next_location()
		self.schedule.step()
		self.ticks += 1

		s_ = self.get_state()
		ai_location = np.zeros(3)

		for cell in self.schedule.agents:
			if cell.cell_name == self.ai_cell:
				ai_location = np.array((cell.location[0], cell.location[1], \
								cell.location[2]))

		if self.ticks == self.end_tick:
			done = True

		return s_, r, sg_done, done

class CellAgent(Agent):
	def __init__(self, unique_id, model, name, location, diameter):
		super().__init__(unique_id, model)
		self.cell_name = name
		self.location = location
		self.diameter = diameter
		self.min_dist_list = []
		self.next_location = None

	def move(self):
		speed = np.linalg.norm(self.location[0:2] - self.next_location[0:2])
		location_noise = np.random.normal(0, speed * 0.1, 2)

		self.location = self.next_location
		self.location[0:2] = self.location[0:2] + location_noise
		self.next_location = None

	def step(self):
		self.move()

class CNN_Net(nn.Module):
	def __init__(self, ):
		super(CNN_Net, self).__init__()
		self.conv1 = nn.Sequential(
			nn.Conv2d(N_CHANNEL * N_INPUT, 32, 5, 4, 2),
			nn.ReLU(),
			nn.MaxPool2d(2),
			)                               #output (32x16x16)
		self.conv2 = nn.Sequential(
			nn.Conv2d(32, 64, 3, 1, 1),
			nn.ReLU(),
			nn.MaxPool2d(2),
			)                               #output (64x8x8)
		self.out = nn.Linear(64*8*8, 8)

	def forward(self, x):
		x = self.conv1(x)
		x = self.conv2(x)
		x = x.view(x.size(0),-1)
		actions_value = self.out(x)
		return actions_value

if __name__ == '__main__':
	print('Using cell '+args.cell)
	print('Using Embryo #'+str(args.emb))
	N_CHANNEL = 15
	INPUT_SIZE = 128
	N_INPUT = 1
	if torch.cuda.is_available():
		use_cuda = True
	else:
		use_cuda = False
	FloatTensor = torch.cuda.FloatTensor if use_cuda else torch.FloatTensor
	LongTensor = torch.cuda.LongTensor if use_cuda else torch.LongTensor
	if use_cuda:
		eval_net = CNN_Net().cuda()
	else:
		eval_net = CNN_Net()
	eval_net.load_state_dict(torch.load('./trained_models/hdrl_llmodel.pkl', map_location=lambda storage, loc: storage))

	env = SeqRosModel()
	input_buffer = []
	movement_types = []
	s = env.reset()
	for ni in range(N_INPUT):
		input_buffer.append(s)
	s_all = []
	for ipt in input_buffer:
		if s_all == []:
			s_all = ipt
		else:
			s_all = np.concatenate((s_all, ipt), axis=0)  #s_all shape:(?*128*128)

	ep_r = 0
	counter = 0

	while True:
		env.render()
		x = np.reshape(s_all, (-1,N_CHANNEL*N_INPUT,INPUT_SIZE,INPUT_SIZE))
		if use_cuda:
			x = Variable(torch.FloatTensor(x), 0).cuda()
		else:
			x = Variable(torch.FloatTensor(x), 0)
		for layer, (name, module) in enumerate(eval_net._modules.items()):
			if isinstance(module, torch.nn.Linear):
				x = x.view(x.size(0),-1)
				x = x.data.cpu().numpy()[0]
				break
			x = module(x)

		feature = Variable(torch.Tensor(x).type(FloatTensor))
		pred = env.speed_model_plus(feature)
		pred = pred.data.cpu().numpy()
		movement_type = np.argmax(pred)
		movement_types.append(movement_type)

		s_, r, sg_done, done = env.step()
		del input_buffer[0]
		input_buffer.append(s_)
		s_all_ = []
		for input in input_buffer:
			if s_all_ == []:
				s_all_ = input
			else:
				s_all_ = np.concatenate((s_all_, input), axis=0)

		counter += 1
		ep_r += r

		if done:
			print('Done in', counter, 'steps.')
			print('Movement type:', movement_types)
			break
		s_all = s_all_


import pandas as pd
from selenium import webdriver
from bs4 import BeautifulSoup
import sys
import os
import math
import time
from datetime import datetime
import xlwt

# 입력 받기
input_title = input('1. 크롤링할 영화 제목을 입력하세요: ')

while(True):
    input_num = input('2. 크롤링할 리뷰 건수는 몇 건입니까?: ')
    try:
        input_num = int(input_num)
        break
    except:
        print('다시 입력해주세요.')
        continue

input_path = input('3. 파일을 저장할 폴더명만 쓰세요: ')

if(input_path == '0'):
    input_path = os.getcwd()

# 웹드라이버 실행
driver = webdriver.Chrome(os.getcwd() + "/chromedriver.exe")
url = 'https://movie.naver.com'
driver.get(url)

# 검색어 입력
search_box =  driver.find_element_by_id('ipt_tx_srch')
search_box.send_keys(input_title)
time.sleep(2)

#검색어 클릭
driver.find_element_by_xpath('//*[@class="auto_tx_area"]/div[1]/ul/li[1]/a').click()
time.sleep(2)

#가장 정확도를 내는 코드 (사용X)
#driver.find_element_by_class_name('btn_srch').click()
#time.sleep(2)

# 검색목록에서 맨 첫번째 영화 클릭
#driver.find_element_by_xpath('//*[@id="old_content"]/ul[2]/li[1]/dl/dt/a').click()
#time.sleep(1)

# 평점
driver.find_element_by_xpath('//*[@id="movieEndTabMenu"]/li[5]/a').click()
time.sleep(1)

# 칼럼 리스트 준비
score = []
text = []
user = []
date = []
good = []
bad = []

# iframe 이동
driver.switch_to_default_content()
driver.switch_to_frame('pointAfterListIframe')

# 전체 소스 가져오기
full_html = driver.page_source
soup = BeautifulSoup(full_html, 'html.parser')

# 전체 글 수를 가져와서 입력받은 건수와 비교
total_comment = soup.find('div', class_='score_total').find('strong',class_='total').em.string
total_comment = int(total_comment.replace(",",""))
print('전체 글 수:',total_comment,'건\n')
if(total_comment < input_num):
    print('입력된 건수가 전체 리뷰 수보다 큽니다. 전체 리뷰 수로 대체합니다.')
    input_num = total_comment

# 크롤링한 글 수 카운트
count = 0

# 각 파일경로와 파일이름 설정
f_txt = input_path + '/' + input_title + '_' + '.txt'
f_csv = input_path + '/' + input_title + '_' + '.csv'
f_xls = input_path + '/' + input_title + '_' + '.xls'

while(True):

    # 리뷰 리스트 가져오기
    content_list =  soup.find('div',class_='ifr_area basic_ifr').find('div', class_ = 'score_result').find('ul').find_all('li')

    for li in content_list:

        count += 1

        # 각 요소 가져오기
        tmp_score = li.find('div', class_='star_score').find('em').text
        tmp_text = li.find('div', class_='score_reple').find('p').text
        tmp_user = li.find('div', class_='score_reple').find('dl').find('span').text
        tmp_date = li.find('div', class_='score_reple').find_all('em')[1].text
        tmp_good = li.find('div', class_='btn_area').find_all('strong')[0].text
        tmp_bad = li.find('div', class_='btn_area').find_all('strong')[1].text

        # 칼럼 리스트에 추가
        score.append(tmp_score)
        text.append(tmp_text)
        user.append(tmp_user)
        date.append(tmp_date)
        good.append(tmp_good)
        bad.append(tmp_bad)

        # 확인용 프린트
        print("총 %s 건 중 %s 번째 리뷰 데이터를 수집합니다===================================="%(input_num, count))
        print('1) 별점:', tmp_score)
        print('2) 리뷰내용:', tmp_text)
        print('3) 작성자:', tmp_user)
        print('4) 작성일자:', tmp_date)
        print('5) 공감:', tmp_good)
        print('6) 비공감:',tmp_bad)
        print('\n')

        # txt파일에 저장
        f = open(f_txt, 'a',encoding='UTF-8')
        f.write("총 %s 건 중 %s 번째 리뷰 데이터를 수집합니다===================================="%(input_num, count) + '\n')
        f.write('1) 별점: ' + tmp_score + '\n')
        f.write('2) 리뷰내용: ' + tmp_text + '\n')
        f.write('3) 작성자: ' + tmp_user + '\n')
        f.write('4) 작성일자: ' + tmp_date + '\n')
        f.write('5) 공감: ' + tmp_good + '\n')
        f.write('6) 비공감: ' + tmp_bad + '\n')
        f.write('\n')

        # 만약 현재 글 수가 입력건수에 도달하면 루프 종료
        if(count == input_num):
            break

    if(count == input_num):
        break

    # 아직 입력건수에 도달하지 않았다면 다음 페이지를 열고 루프 계속
    else:
        driver.find_element_by_class_name('pg_next').click()
        time.sleep(1)

        driver.switch_to_default_content()
        driver.switch_to_frame('pointAfterListIframe')

        full_html = driver.page_source
        soup = BeautifulSoup(full_html, 'html.parser')

# 데이터프레임 생성, 각 칼럼 리스트 넣기
df = pd.DataFrame()
df['별점'] = score
df['리뷰내용'] = text
df['작성자'] = user
df['작성일자'] = date
df['공감'] = good
df['비공감'] = bad

# 공백 줄바꿈 제거
for i in range(len(df)):
    df['리뷰내용'][i] = df['리뷰내용'][i].replace("\t","")
    df['리뷰내용'][i] = df['리뷰내용'][i].replace("\n","")

# 엑셀과 csv로 저장
df.to_excel(f_xls,encoding="utf-8-sig",index=True)
df.to_csv(f_csv,encoding="utf-8-sig",index=True)

data = pd.read_csv(f'./{input_title}/{input_path}_.csv')


from django.shortcuts import render
from rest_framework.permissions import IsAuthenticated
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status

from .models import UserProfile
from .serializer import UserProfileSerializer

# Create your views here.

class CustomAuthToken(ObtainAuthToken):
    def post(self, request, *args, **kwargs):
        serializer = self.serializer_class(
            data=request.data, context={"request": request}
        )
        serializer.is_valid(raise_exception=True)
        user = serializer.validated_data["user"]
        token, created = Token.objects.get_or_create(user=user)
        return Response(
            {
                "token": token.key,
                "user_id": user.pk,
                "email": user.email,
                "username": user.username,
            }
        )

class SignupView(APIView):
    def post(self, request):
        serializer = UserProfileSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


import random, timeit
def insertion_sort(array):
    for index in range(1, len(array)):
        if array[index] < array[index-1]:
            for subindex in range(0, index):
                if(array[subindex] > array[index]):
                    array[subindex],array[index]= array[index], array[subindex]

def main():
    array= []
    for number in range(0,10):
        array.append(random.randint(0,100))
    print("before:", array)
    start = timeit.default_timer()
    insertion_sort(array)
    stop = timeit.default_timer()
    print("EXECUTION TIME: ", stop-start)
    print("after:", array)

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
# -*- coding=utf-8 -*-
# 本脚由亁颐堂现任明教教主编写，用于乾颐盾Python课程！
# 教主QQ:605658506
# 亁颐堂官网www.qytang.com
# 教主技术进化论拓展你的技术新边疆
# https://ke.qq.com/course/271956?tuin=24199d8a

import exifread
import re

def FindGPSimage(filepath):
    GPS = {}
    Date = ''
    f = open(filepath, 'rb')
    tags = exifread.process_file(f)
    for tag, value in tags.items():
        if re.match('GPS GPSLatitudeRef', tag):
            GPS['GPSLatitudeRef'] = str(value)
        elif re.match('GPS GPSLongitudeRef', tag):
            GPS['GPSLongitudeRef'] = str(value)
        elif re.match('GPS GPSAltitudeRef', tag):
            GPS['GPSAltitudeRef'] = int(str(value))
        elif re.match('GPS GPSLatitude', tag):
            try:
                match_result = re.match('\[(\w*), (\w*), (\w.*)/(\w.*)\]', str(value)).groups()
                GPS['GPSLatitude'] = int(match_result[0]), int(match_result[1]), int(match_result[2])/int(match_result[3])
            except:
                GPS['GPSLatitude'] = str(value)
        elif re.match('GPS GPSLongitude', tag):
            try:
                match_result = re.match('\[(\w*), (\w*), (\w.*)/(\w.*)\]', str(value)).groups()
                GPS['GPSLongitude'] = int(match_result[0]), int(match_result[1]), int(match_result[2])/int(match_result[3])
            except:
                GPS['GPSLongitude'] = str(value)
        elif re.match('GPS GPSAltitude', tag):
            GPS['GPSAltitude'] = str(value)
        elif re.match('.*Date.*', tag):
            Date = str(value)
    return {'GPS信息': GPS, '时间信息': Date}
    # ttp://www.gpsspg.com/maps.htm

if __name__ == '__main__':
    print(FindGPSimage(r"C:\Users\Administrator\PycharmProjects\Python_Network_2018_HTTP\8_Spider\Photo_Spider\Download_IMG\gps_test_1.jpg"))

# 运行结果
# {'GPS信息': {'GPSLatitudeRef': 'N', 'GPSLatitude': (39, 58, 38.481445), 'GPSLongitudeRef': 'E', 'GPSLongitude': (116, 17, 59.598999), 'GPSAltitudeRef': 1, 'GPSAltitude': '0'}, '时间信息': '2016:05:25 20:43:46'}


"""Provision a machine using rsync."""
from __future__ import absolute_import, division, print_function

import drifter.commands.rsync as base_rsync

def rsync(config, servers, settings, verbose=True):
    """Run the rsync provisioner."""
    local_path = settings.get('local', None)
    remote_path = settings.get('remote', None)
    exclude = settings.get('exclude', None)
    include = settings.get('include', None)
    args = settings.get('args', None)

    base_rsync.do_rsync(config, servers, verbose=verbose,
                        local_path=local_path, remote_path=remote_path,
                        rsync_exclude=exclude, rsync_include=include,
                        rsync_args=args)


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

"""BoardGameGeek hotness spider."""

from datetime import timezone
from pathlib import Path

from pytility import parse_date
from scrapy import Request, Spider

from ..items import GameItem
from ..loaders import GameLoader
from ..utils import now

DATE_FORMAT = "%Y-%m-%dT%H-%M-%S"

class BggHotnessSpider(Spider):
    """BoardGameGeek hotness spider."""

    name = "bgg_hotness"
    allowed_domains = ("boardgamegeek.com",)
    start_urls = ("https://www.boardgamegeek.com/xmlapi2/hot?type=boardgame",)
    item_classes = (GameItem,)

    custom_settings = {
        "DOWNLOAD_DELAY": 0,
        "CONCURRENT_REQUESTS_PER_DOMAIN": 1024,
        "CONCURRENT_REQUESTS_PER_IP": 1024,
        "AUTOTHROTTLE_ENABLED": False,
        "AUTOTHROTTLE_TARGET_CONCURRENCY": 1024,
        "AUTOTHROTTLE_HTTP_CODES": (429, 503, 504),
    }

    def _local_requests(self, path_dir="."):
        path_dir = Path(path_dir).resolve()

        for path_file in path_dir.iterdir():
            if not path_file.is_file():
                continue

            self.logger.info("Processing <%s>", path_file)

            date = parse_date(
                path_file.stem,
                tzinfo=timezone.utc,
                format_str=DATE_FORMAT,
            )

            yield Request(
                url=path_file.as_uri(),
                callback=self.parse,
                meta={"published_at": date},
            )

    def start_requests(self):
        """Initial requests, either locally or from BGG."""

        hotness_dir = self.settings.get("BGG_HOTNESS_DIR")

        if hotness_dir:
            self.logger.info("Loading local files from <%s>", hotness_dir)
            yield from self._local_requests(hotness_dir)

        else:
            yield from super().start_requests()

    def parse(self, response):
        """
        @url https://www.boardgamegeek.com/xmlapi2/hot?type=boardgame
        @returns items 50 50
        @returns requests 0 0
        @scrapes published_at rank bgg_id name year image_url scraped_at
        """

        scraped_at = now()

        for game in response.xpath("/items/item"):
            ldr = GameLoader(item=GameItem(), selector=game, response=response)

            ldr.add_xpath("bgg_id", "@id")
            ldr.add_xpath("rank", "@rank")
            ldr.add_xpath("name", "name/@value")
            ldr.add_xpath("year", "yearpublished/@value")
            ldr.add_xpath("image_url", "thumbnail/@value")

            ldr.add_value("published_at", response.meta.get("published_at"))
            ldr.add_value("published_at", scraped_at)
            ldr.add_value("scraped_at", scraped_at)

            yield ldr.load_item()


import random

class Card:
    """
    A Card is a simple representation of a standard playing card
    that consists of a Suit, Rank, and will default to be face up
    """

    def __init__(self, suit, rank):
        self.suit = suit
        self.rank = rank
        self.faceDown = False

    def __repr__(self):
        if self.faceDown:
            # will return a unicode facedown value
            return '\U0001F0A0' + " "
        return self.rank + self.suit + "  "

class Deck:
    """
    A Deck consists of a collection of standard playing cards that
    each have a suit and rank.
    """
    # unicode represents spades, hearts, diamonds, clubs respectively
    suits = [u'\u2660', u'\u2665', u'\u2666', u'\u2663']
    ranks = ["2", "3", "4", "5", "6",
                  "7", "8", "9", "10", "J", "Q", "K", "A"]
    values = {"2": 2, "3": 3, "4": 4, "5": 5, "6": 6,
              "7": 7, "8": 8, "9": 9, "10": 10, "J": 11, "Q": 12, "K": 13, "A": 14}

    def __init__(self):
        self.cards = []

        for suit in Deck.suits:
            for rank in Deck.ranks:
                card = Card(suit, rank)
                self.cards.append(card)

    def shuffle(self):
        random.shuffle(self.cards)

    def splitDeck(self):
        return self.cards[::2], self.cards[1::2]

    def setDeckFaceup(self):
        for card in self.cards:
            card.faceDown = False

    def __repr__(self):
        toret = ""
        for card in self.cards:
            toret += str(card)
        return toret

def compareCards(card1, card2):
    if Deck.values[card1.rank] > Deck.values[card2.rank]:
        return "win"
    elif Deck.values[card1.rank] < Deck.values[card2.rank]:
        return "lose"
    else:
        return "tie"

def goToWar(playerDeck, opponentDeck, playerCard, opponentCard, name):
    """
    Simulates when war occurs, and will go through the war procedure
    where each player will put a card face down and a card face up.
    Then the player with the winning face up card will take all, but
    in the event of another tie, the procedure is repeated
    """
    playerWarStack, opponentWarStack = [playerCard], [opponentCard]
    turnStatus = compareCards(playerCard, opponentCard)
    faceDownCards = []

    warRound = 1
    while turnStatus == "tie":

        if len(playerDeck) <= 1:
            turnStatus = "lose"
            break
        elif len(opponentDeck) <= 1:
            turnStatus = "win"
            break

        playerFaceDown, opponentFaceDown = playerDeck.pop(), opponentDeck.pop()
        playerFaceDown.faceDown = True
        opponentFaceDown.faceDown = True
        faceDownCards.extend([playerFaceDown, opponentFaceDown])

        playerFaceup, opponentFaceup = playerDeck.pop(), opponentDeck.pop()
        playerWarStack.extend([playerFaceDown, playerFaceup])
        opponentWarStack.extend([opponentFaceDown, opponentFaceup])

        print("\nWar round {0}".format(warRound))
        print("{0}'s war stack: {1} \nOpponent war stack: {2} \n"
              .format(name, playerWarStack, opponentWarStack))

        turnStatus = compareCards(playerFaceup, opponentFaceup)
        warRound += 1
        print("{0} {1}".format(name, turnStatus))

    for card in faceDownCards:
        card.faceDown = False

    if turnStatus == "win":
        playerDeck.extend(playerWarStack)
    else:
        opponentDeck.extend(opponentWarStack)

def playWar(playerDeck, opponentDeck, name):
    """
    Simulates playing the game of war. The user can press (f)
    to flip a card or (q) to stop playing.
    The game will end when either the player or the opponent
    has 0 cards left in the deck.
    """
    while playerDeck and opponentDeck:
        print("\nCurrent scores:")
        print("{0}'s score: {1} \t\t Opponent score: {2} \t\t\n"
              .format(name, len(playerDeck), len(opponentDeck)))
        action = "no action"
        while action != "f" and action != "q":
            action = input("Press (f) to flip or (q) to stop playing ")
        if action == "q":
            break
        playerCard, opponentCard = playerDeck.pop(0), opponentDeck.pop(0)
        print("\n{0}'s card: {1} \t\t Opponent card: {2} \t\t"
              .format(name, playerCard, opponentCard))
        turnStatus = compareCards(playerCard, opponentCard)
        print("\n{0} {1}".format(name, turnStatus))

        if turnStatus == "win":
            playerDeck.extend([playerCard, opponentCard])
        elif turnStatus == "lose":
            opponentDeck.extend([playerCard, opponentCard])
        elif turnStatus == "tie":
            goToWar(playerDeck, opponentDeck, playerCard, opponentCard, name)

def startGame():
    """
    Sets up the game and assigns each player half of the deck
    """
    deck = Deck()
    deck.shuffle()
    print("\n" + 20 * "*" + "\n" + "* Let's go to war! *" + "\n" + 20 * "*" + "\n")

    playerName = input("What's your name? ")

    print("Hello {0} \n".format(playerName))

    deckChoice = "no deck"
    while deckChoice != "1" and deckChoice != "2":
        deckChoice = input("Pick a deck, (1) or (2) ")

    if deckChoice == "1":
        playerDeck, opponentDeck = deck.splitDeck()
    else:
        opponentDeck, playerDeck = deck.splitDeck()

    playWar(playerDeck, opponentDeck, playerName)

    print("Thanks for playing!")

def main():
    startGame()

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
"""
Created on Fri Dec  7 16:10:13 2018

@author: Silence
"""
import tensorflow as tf
from tensorflow.contrib import image
from tensorflow.python.ops import math_ops
import matplotlib.pyplot as plt
import math
import csv
import random
from PIL import Image
PI = math.pi

def getRotatePoint(map_shape, rotate_center, rotate_theta, origin_point):
    """
    实现功能，得到绕旋转中心旋转theta角度后的坐标
    :param map_shape:原始地图的尺寸，因为Image中的坐标原点在图片左上角，需要改变坐标系    Tensor-[height,width,channel]
    :param rotate_center:旋转中心   Tensor-[loc_x,loc_y]
    :param rotate_theta:旋转角度   Tensor-[theta]
    :param origin_point:需要进行旋转操作的点集 Tensor-[loc_x,loc_y]
    :return: rotate_point_list: Tensor-[loc_x,loc_y]
    """
    row = map_shape[0]
    center_x = rotate_center[0]
    center_y = row - rotate_center[1]
    point_x = origin_point[0]
    point_y = row - origin_point[1]

    after_rotate_x = math_ops.round(
        (point_x - center_x) * math_ops.cos(rotate_theta) - (point_y - center_y) * math_ops.sin(
            rotate_theta) + center_x)
    after_rotate_y = row - math_ops.round(
        (point_x - center_x) * math_ops.sin(rotate_theta) + (point_y - center_y) * math_ops.cos(
            rotate_theta) + center_y)
    rotate_point = [after_rotate_x, after_rotate_y]
    rotate_point = tf.reshape(rotate_point, [2])
    return rotate_point

def pointLegalCheck(map_shape, point, box_shape):
    """
    检测旋转后的点是否越界
    :param map_shape: 原始地图大小Tensor-[height,width,channel]
    :param point: 旋转后的点集Tensor-[4,2]
    :param box_shape: 裁剪图片区域的大小Tensor-[2]
    :return: 合法性检测后的点集
    """
    x_move_list = []
    y_move_list = []
    map_shape = tf.cast(map_shape, tf.float32)
    # 依次计算四个顶点与地图边界的偏移大小
    for i in range(4):
        x_move = tf.cond(tf.less(point[i][0], 0.0),
                         true_fn=lambda: 0.0 - point[i][0],  # 若坐标小于零，则需要向正方向移动
                         false_fn=lambda: tf.cond(tf.less(map_shape[1], point[i][0]),
                                                  # 若坐标大于地图边界，则需要向负方向移动
                                                  true_fn=lambda: map_shape[1] - point[i][0],
                                                  false_fn=lambda: 0.0  # 坐标在地图中无需移动
                                                  )
                         )
        y_move = tf.cond(tf.less(point[i][1], 0.0),
                         true_fn=lambda: 0.0 - point[i][1],
                         false_fn=lambda: tf.cond(tf.less(map_shape[0], point[i][1]),
                                                  true_fn=lambda: map_shape[0] - point[i][1],
                                                  false_fn=lambda: 0.0
                                                  )
                         )
        x_move_list.append(x_move)
        y_move_list.append(y_move)

    # 依据四个顶点的偏移，得到坐标的修正值
    x_move = getPixelMove(tf.reshape(x_move_list, [4]))
    y_move = getPixelMove(tf.reshape(y_move_list, [4]))

    # 得到修正后的四个顶点坐标
    point_x = tf.add(point[:, 0], x_move)
    point_y = tf.add(point[:, 1], y_move)
    point = tf.stack([point_x, point_y], 1)
    return point

def getPixelMove(move_list):
    """
    pointLegalCheck的附加函数，返回最大的绝对值位移
    :param move_list: 四个角点与是否越界检测得到的与图片的差值 Tensor-[4]
    :return: max_move 最大位移 Tensor-[1]
    """
    move_max = tf.argmax(move_list)
    move_min = tf.argmin(move_list)
    max_move_index = tf.cond(tf.less(tf.abs(move_min), move_max),
                             true_fn=lambda: move_max,
                             false_fn=lambda: move_min
                             )
    max_move = move_list[max_move_index]
    return max_move

def mapCut(map_data, particle_map_length, old_partcile_states, new_particle_states):
    """
    给定前后坐标，根据运动方向旋转并裁剪地图，得到基于当前坐标的局部地图
    :param map_data: 原始地图数据 Tensor[height,width,channel=3] int
    :param particle_map_length: 局部地图的形状大小，默认正方形 Tensor[1] float32
    :param old_partcile_states: 前一时刻的坐标 Tensor[2](loc_x,loc_y) float32
    :param new_particle_states: 当前时刻的坐标 Tensor[2](loc_x,loc_y) float32
    :return: particle_map 基于运动方向的局部地图 Tensor[height,width,channel=3] float32
    """
    particle_map_length = particle_map_length
    map_shape = tf.shape(map_data)[0:]
    map_shape = tf.cast(map_shape, tf.float32)

    # 计算前后坐标的变化量，并以此计算运动向量的角度temp_theta
    dis = (tf.subtract(new_particle_states[1], old_partcile_states[1]),
           tf.subtract(new_particle_states[0], old_partcile_states[0]))
    temp_theta = tf.to_float(math_ops.atan2(dis[1], dis[0]))

    # 计算围绕在新坐标周围的，没有经过旋转的局部地图的四个顶点坐标
    top_left_point = [new_particle_states[0] - particle_map_length / 2,
                      new_particle_states[1] - particle_map_length / 2]
    top_right_point = [new_particle_states[0] + particle_map_length / 2,
                       new_particle_states[1] - particle_map_length / 2]
    bottom_left_point = [new_particle_states[0] - particle_map_length / 2,
                         new_particle_states[1] + particle_map_length / 2]
    bottom_right_point = [new_particle_states[0] + particle_map_length / 2,
                          new_particle_states[1] + particle_map_length / 2]

    # 计算四个顶点坐标旋转后得到的新坐标
    new_top_left_point = getRotatePoint(map_shape, new_particle_states, temp_theta, top_left_point)
    new_top_right_point = getRotatePoint(map_shape, new_particle_states, temp_theta, top_right_point)
    new_bottom_left_point = getRotatePoint(map_shape, new_particle_states, temp_theta, bottom_left_point)
    new_bottom_right_point = getRotatePoint(map_shape, new_particle_states, temp_theta, bottom_right_point)
    new_point = tf.reshape([new_top_left_point, new_top_right_point, new_bottom_left_point, new_bottom_right_point],
                           [4, 2])

    # 计算四个新坐标的横纵坐标之差的极值，该极值构成了能完整圈住旋转后的局部地图的大矩形的shape
    new_shape_x = tf.cast(new_point[tf.argmax(new_point[:, 0], 0), 0] - new_point[tf.argmin(new_point[:, 0], 0), 0],
                          tf.int32)
    new_shape_y = tf.cast(new_point[tf.argmax(new_point[:, 1], 0), 1] - new_point[tf.argmin(new_point[:, 1], 0), 1],
                          tf.int32)

    # 对四个新坐标的合法性进行判断，使其不会越出地图的边界
    new_point = pointLegalCheck(map_shape, new_point, [new_shape_x, new_shape_y])

    # 计算该大矩形的左上顶点坐标，依据大矩形的左上顶点坐标切割地图
    new_corner_x = tf.cast(new_point[tf.argmin(new_point[:, 0], 0), 0], tf.int32)
    new_corner_y = tf.cast(new_point[tf.argmin(new_point[:, 1], 0), 1], tf.int32)
    map_cut = tf.image.crop_to_bounding_box(map_data, offset_height=new_corner_y,
                                            offset_width=new_corner_x,
                                            target_height=new_shape_y,
                                            target_width=new_shape_x)

    # 反向旋转切割后的地图，使原本的运动方向与坐标轴方向（Y轴正方向）平行
    map_rotate = image.rotate(map_cut, -1.0 * temp_theta)

    # 计算位于居中的，我们最终需要的particle_map_length大小的局部地图的左上顶点，进行第二次切割
    particle_map_length = tf.to_int32(particle_map_length)
    temp_corner_width = tf.cast(tf.div(tf.subtract(new_shape_x, particle_map_length), 2), tf.int32)
    temp_corner_height = tf.cast(tf.div(tf.subtract(new_shape_y, particle_map_length), 2), tf.int32)
    particle_map = tf.image.crop_to_bounding_box(map_rotate, offset_height=temp_corner_height,
                                                 offset_width=temp_corner_width,
                                                 target_height=particle_map_length,
                                                 target_width=particle_map_length)
    return particle_map

origin_path = "map.jpg"
local_map_size = 100.0
ephochs = 10
int_local_map_size = int(local_map_size)
middle = 50
length = 5.0

f = open('label.csv', 'a+', newline='')
data_path = 'data/'
csv_write = csv.writer(f, dialect='excel')

for i in range(ephochs):
    tf.reset_default_graph()
    graph = tf.Graph()
    with graph.as_default() as g:
        file = tf.read_file(origin_path)
        map_data = tf.image.decode_image(file, channels=3)
        map_data = tf.cast(map_data, tf.float64)
        a = random.uniform(290, 570)
        b = random.uniform(288, 2029)
        theta = random.uniform(0.1, 3.0)

        old_particle_state = [a, b]
        new_particle_state = [a + length * math.cos(theta), b + length * math.sin(theta)]
        old_particle_state = tf.convert_to_tensor(old_particle_state)
        new_particle_state = tf.convert_to_tensor(new_particle_state)
        part_map = mapCut(map_data, local_map_size, old_particle_state, new_particle_state)

        with tf.Session(graph=g) as sess:
            index = 100
            trans_image = sess.run(part_map)
            for column in range(int_local_map_size):
                if(trans_image[column][middle][0]+trans_image[column][middle][1]+trans_image[column][middle][2]<600.0):
                    index = column
                    break
            im = Image.fromarray(trans_image.astype('uint8')).convert('RGB')
            im.thumbnail([100, 100])
            im.save('data/'+str(i) + ".png")
            csv_write.writerow([str(i), str(old_particle_state[0].eval()), str(old_particle_state[1].eval()), str(new_particle_state[0].eval()),
                                    str(new_particle_state[1].eval()),str(int(index/10))])
f.close()


"""
    Imhotrack.io @ Imperial College London - Summer 2017
    Project: A Low-Power Motion sensor box with WebApp for Administion.
    Contributors: Pranav Prabhu
    Module: boxtracker
    Description: This file defines the url redirects within the Django Project File to the App (boxtracker)
"""
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^boxtracker/', include('boxtracker.urls')),
    url(r'^admin/', admin.site.urls),
    url(r'^$', include('boxtracker.urls'))
]


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

# # Household Energy Access Assessment in DRC
#
# The objective of this project is to analyze access to energy (electricity and cooking solution) in rural areas of the Democratic Republic of Congo.
#
# The study has been implemented by APIDE, a local NGO working in the regions of Kitutu, Kaituga, and Mwenga, in the eastern part of the country, about 150 km from the border with Burundi and Rwanda.
#
# Data collection, processing, and visualization have been supported by the [HEDERA Impact Toolkit](https://hit.hedera.online)
# This digital report has been created as a [jupyter-book](https://jupyterbook.org/intro).
#
# Relevant information concerning the use, associated costs, and various attributes of access to electricity and cooking solutions has been collected from households APIDE is working with in rural and remote areas, using the HEDERA collect mobile app based on the [OpenDataKit](https://opendatakit.org) open-source framework.
# The HEDERA Impact Toolkit allows institutions to efficiently establish a baseline for monitoring progress towards the Sustainable Development Goals (SDGs) and track the progress thereof, following, for example, the [Multi-tier Framework](https://www.esmap.org/node/55526) (MTF) for SDG7, recently established by The World Bank, and the Progress out of Energy Poverty Index (PEPI) [N. Realpe, PhD Thesis 2017](https://depositonce.tu-berlin.de/handle/11303/6708).
#
#
# ## Methodology
#
# HEDERA provided a mobile application for data collection, as well as digital material for remote training.
# Members of APIDE field staff were trained during a one-day workshop (held by one member of the organization).
# During 10 days, more than 220 data point were collected (household rosters, electricity assessment, cooking solution assessment).
#
# You can also visit the [full report](https://hedera-platform.github.io/report-apide/summary.html) of this case study.
#

# In[1]:

HIT_PATH = '../../../HIT/src/'
institution_id = 7
lang = 'en'
import os,sys, folium
sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(''), HIT_PATH)))
import hedera_types as hedera
import odk_interface as odk

mfi = hedera.mfi(institution_id,setPathBook=True)
mfi.odk_data_name = "../../../ODK_Collect_Data/Apide/Data/SDG7/results.csv"
data = mfi.read_survey(mfi.odk_data_name)
mfi.HH = odk.households(data)

# ## Collection overview
#
# ### Map
# The Map allows to visualize the location of the collected GPS data. Missing data points are displayed with coordinated *(0,0)*

# In[2]:

import matplotlib.pyplot as plt

select = mfi.HH['GPS_Latitude']!=0
HH_with_GPS = mfi.HH[select]

# change plot layout
plt.rcParams.update({'font.size': 20})
#Define initial geolocation
lat_center = HH_with_GPS['GPS_Latitude'].mean()
lon_center = HH_with_GPS['GPS_Longitude'].mean()
max_var = max(HH_with_GPS['GPS_Latitude'].var(),HH_with_GPS['GPS_Longitude'].var())
zoom_start = 9
if max_var>0.1:
    zoom_start -= 1
if max_var>1:
    zoom_start -= 1
initial_location = [lat_center, lon_center]

# create map
map_osm = folium.Map(initial_location, zoom_start=zoom_start)
colors = {0: hedera.tier_color(0), 1 : hedera.tier_color(1), 2 : hedera.tier_color(2),
          3 : hedera.tier_color(3), 4 : hedera.tier_color(4), 5: hedera.tier_color(5)}
HH_with_GPS.apply(lambda row:folium.CircleMarker(location=[row["GPS_Latitude"], row["GPS_Longitude"]],
                                        radius=10,fill_color="#FF5733",popup=(row["GPS_Latitude"],row["GPS_Longitude"],row["locality"])).add_to(map_osm), axis=1)
map_osm

# ### Data per location
# Data have been collected in three different areas in Eastern DRC.

# In[3]:

import matplotlib.pyplot as plt
# this is needed if the surveys do not cover all states/offices
empty = []
for o in mfi.offices:
    select = mfi.HH['locality']==o

    if sum(select)==0:
        empty.append(o)

for o in empty:
    mfi.offices.remove(o)

mfi.plot_collection_barh()

# ## Dates of Collection
# The following figure shows the amount of surveys per day

# In[4]:

import numpy as np
S = odk.get_survey_duration(data)
dates = np.unique(np.array(mfi.HH['date']))
ind = np.arange(len(dates))
dates_plot = []
dates_labels = []

mean_e = []
mean_c = []
mean_tot = []

for d in dates:

    select = mfi.HH['date']== d
    dates_plot.append( sum(select) )
    dates_labels.append(d)

    # get surveys data on a diven date
    surveys = S[select]

    selectE = surveys['electricity']>0
    surveysE = surveys[selectE]
    mean_e.append(surveysE['electricity'].mean())

    selectC = surveys['cooking']>0
    surveysC = surveys[selectC]
    mean_c.append(surveysC['cooking'].mean())

    selectT = surveys['total']>0
    surveysT = surveys[selectT]
    mean_tot.append(surveys['total'].mean())
    import matplotlib.pyplot as plt

# change plot layout
plt.rcParams.update({'font.size': 20})
# survey per date
fig, ax = plt.subplots(figsize=(10,8))
plt.bar(ind, dates_plot, width=0.95,edgecolor='white')
plt.xticks(ind, dates, rotation=90)
ax.yaxis.grid(color='grey', linestyle='--', linewidth=0.5)
plt.show()

# ### Average Duration
# Average survey duration per day was on average between 5 and 27 minutes.
#
# **Note**: Some interviews only covered the household roster and are therefore much shorter.

# In[5]:

import matplotlib.pyplot as plt

# change plot layout
plt.rcParams.update({'font.size': 20})
# survey duration
fig, ax = plt.subplots(figsize=(10,8))
plt.bar(ind, mean_tot, width=0.95,edgecolor='white',color='blue',label='Total')
plt.xticks(ind, dates, rotation=90)
plt.legend(framealpha=1,frameon=False,bbox_to_anchor=(1.25,1.0),
                       loc='upper center').set_draggable(True)
ax.yaxis.grid(color='grey', linestyle='--', linewidth=0.85) # vertical lines
plt.show()

# ## Electricity Access Attributes
#

# In[6]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 20})
mfi.tier_barh(hedera.keys().attributes_electricity[0:8],
              hedera.names('en').e_attributes[0:8],legend=True)

# ## Primary Electricity Sources

# In[7]:

import matplotlib.pyplot as plt
mfi.electricity_sources_summary(lang='en',legend=True)

# ## Household Appliances

# In[8]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 14})
[appliances_per_x,u_id] = odk.compute_appliances_per_x(data,mfi.HH,mfi.offices,'locality')
odk.plot_appliances_per_x(len(mfi.HH),appliances_per_x,u_id,'locality',
                          mfi.offices,
                          figPath=None,c=mfi.office_color,lang=lang)

# ## MTF Electricity Index vs. Primary Source

# In[9]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 18})
mfi.stacked_tier_per_category('E_Index',hedera.keys().powerSources,
                              'primary_electricity_source',
                              hedera.names('en').powerSources,legend=True)

# ## Access to Modern Cooking Solutions Attributes
#

# In[10]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 20})
mfi.tier_barh(hedera.keys().attributes_cooking[0:4],hedera.names('en').c_attributes[0:4],legend=True)

# ### Primary Cooking Stoves

# In[11]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 18})
mfi.cooking_fuels_summary(lang='en',legend=True)

# ### MTF Index (Access to Cooking Solutions) vs. Primary Cooking Fuel

# In[12]:

import matplotlib.pyplot as plt
plt.rcParams.update({'font.size': 18})
mfi.stacked_tier_per_category('C_Index',hedera.keys().fuels,
                              'primary_cooking_fuel',
                              hedera.names('en').fuels)


import webapp2
from webapp2_extras.users import users
from webapp2_extras import jinja2
import models.user as user_model
import models.book as book_model

class BooksHandler(webapp2.RequestHandler):
    def get(self):

        usr = users.get_current_user()
        user = user_model.retrieve(usr)

        if usr and user:
            url_usr = users.create_logout_url("/")
            book_list = False
            books = book_model.all_books()
            listBooks = True
            template_values = {
                "books": books,
                "usr": usr,
                "user": user,
                "book_list": book_list,
                "listBooks": listBooks,
                "url_usr": url_usr
            }
            jinja = jinja2.get_jinja2(app=self.app)
            self.response.write(jinja.render_template("list_book.html", **template_values))
        else:
            return self.redirect("/")

app = webapp2.WSGIApplication([
    ('/books', BooksHandler)
], debug=True)


import json

import keras
from keras.engine.training import Model

from bert import optimization, modeling
import numpy as np
from util import Keras

import tensorflow as tf
from util import utility
from bert.modeling import get_model_config, BertEmbedding, Transformer
import time
import re
import random
from math import nan
from keras.utils.np_utils import to_categorical

# predicting and training instance containing the corpus data
class Instance:
    """
    [['input_ids', 'input_ids1'], 'label']
    """

    def __init__(self, left, right, label=nan, shuffle=False):
        self.x = left
        self.y = right
        self.label = label
        if shuffle :
            self.shuffle()

    def string2id(self, string2id):
        self.source = [self.x, self.y]
        self.input_ids = string2id(self.x)
        self.input_ids1 = string2id(self.y)

    def copy(self):
        return Instance(self.x, self.y, self.label, normalize=False)

    @property
    def reversed(self):
        if self.label == 'hyponym':
            label = 'hypernym'
        elif self.label == 'hypernym':
            label = 'hyponym'
        else:
            label = self.label

        inst = Instance(self.y, self.x, label, shuffle=False)
        if hasattr(self, 'source'):
            inst.source = [self.source[1], self.source[0]]
        if hasattr(self, 'input_ids'):
            inst.input_ids = self.input_ids1
            inst.input_ids1 = self.input_ids
        return inst

    def identity(self):
        if random.getrandbits(1):
            inst_x = Instance(self.x, self.x, 1, normalize=False)
            if hasattr(self, 'source'):
                x, y = re.compile(' */ *').split(self.source)
                inst_x.source = x + ' / ' + x
            return inst_x
        else:
            inst_y = Instance(self.y, self.y, 1, normalize=False)
            if hasattr(self, 'source'):
                x, y = re.compile(' */ *').split(self.source)
                inst_y.source = y + ' / ' + y
            return inst_y

    def normalize(self):
        if self.x > self.y:
            tmp = self.y
            self.y = self.x
            self.x = tmp

        return self

    def shuffle(self):
        if random.randint(0, 1):
            tmp = self.y
            self.y = self.x
            self.x = tmp

            if self.label == 'hypernym':
                self.label = 'hyponym'
            elif self.label == 'hyponym':
                self.label = 'hypernym'

        return self

    def __hash__(self):
        return hash(self.x.lower()) + hash(self.y.lower()) * 31

    def __eq__(self, other):
        return self.x.lower() == other.x.lower() and self.y.lower() == other.y.lower()

    def __lt__(self, other):
        if self.x.lower() < other.x.lower():
            return True
        if self.x.lower() > other.x.lower():
            return False
        return self.y.lower() < other.y.lower()

    def __str__(self):
        if hasattr(self, 'source'):
            return self.source

        return self.x + " / " + self.y

# assign a pair of phrases (x, y) a probability that y is a hyponym of x;
class LexiconClassifier(Keras.Model):

    def __init__(self):
        self.folder = utility.modelsDirectory + '%s/lexicon/' % self.lang
        self.modelFile = self.folder + 'model.h5'
        self.configFile = self.folder + 'config.json'

        self.init_config()
        self.label2id = {}
        self.labels = ('hypernym', 'unrelated', 'related', 'synonym', 'hyponym')
        for i, label in enumerate(self.labels):
            self.label2id[label] = i
        self.label2id['antonym'] = self.label2id['related']

        self.create_model(**self.config)

    def init_config(self):
        with open(self.configFile, 'r') as file:
            config = json.loads(file.read())
            self.config, self.checkpoint_file = get_model_config(**config)
            self.config.update(config)

    def predict(self, s1, s2):
#             print("first sentence:", s1)
#             print("second sentence:", s2)
        inst = Instance(s1, s2, None, False)
        inst.string2id(self.string2id)
#             print('input_ids:', sample.token)
        y_pred = self.model.predict([np.array([inst.input_ids]), np.array([inst.input_ids1])])[0]
        return self.labels[np.argmax(y_pred, -1)]

    interval = [(0, 0.01), (0.02, 0.2), (1, 2), (2, 3), (3.5, 4)]

    # assign the probability vector to a single score for hierarchical clustering purposes.
    def probability2score(self, probability):
        argmax = np.argmax(probability, -1);

        def probability2score_ab(probability, a, b):
            k = len(self.labels)
    #         (1 / k, 1) => (a, b)
    #         (1 / k)x + y = a
    #          x + y = b
            return (b - a) * k / (k - 1) * probability + (k * a - b) / (k - 1)

        return probability2score_ab(probability[argmax], *self.interval[argmax])

    def predicts(self, texts):
        n = len(texts)
        insts = []
        for i in range(n):
            for j in range(n):
                if i == j:
                    continue
                inst = Instance(texts[i], texts[j], None, False)
                inst.string2id(self.string2id)
                insts.append(inst)

        generator = Keras.Sequence(insts)

        res = self.model.predict_generator(generator)
        res = generator.reorder(res)
        scores = np.zeros((n, n))
        for k in range(len(res)):
            i = k // (n - 1)
            j = k % (n - 1)
            if j >= i:
                j += 1
            scores[i, j] = self.probability2score(res[k])
        return scores

    def create_model(self,
                     cross_layer_parameter_sharing,
                     num_attention_heads,
                     intermediate_size,
                     num_hidden_layers,
                     vocab_size,
                     max_position_embeddings,
                     hidden_size,
                     hidden_dropout_prob,
                     hidden_act,
                     embedding_size=None,
                     **_):
        embed_dim = embedding_size if cross_layer_parameter_sharing else hidden_size

        input_ids = keras.layers.Input(shape=(None,), name='Input-Token', dtype=tf.int32)
        input_ids1 = keras.layers.Input(shape=(None,), name='Input-Token1', dtype=tf.int32)

        layerBertEmbedding = BertEmbedding(num_attention_heads=num_attention_heads,
                                    vocab_size=vocab_size,
                                    embed_dim=embed_dim,
                                    hidden_size=hidden_size,
                                    max_position_embeddings=max_position_embeddings,
                                    dropout_rate=hidden_dropout_prob,
                                    inputSegment=False)

        embed_layer = layerBertEmbedding(input_ids)
        embed_layer1 = layerBertEmbedding(input_ids1)

        transformer = Transformer(num_hidden_layers,
                           num_attention_heads,
                           intermediate_size,
                           hidden_act=hidden_act,
                           dropout_rate=hidden_dropout_prob,
                           cross_layer_parameter_sharing=cross_layer_parameter_sharing)
        sent = transformer(embed_layer)
        sent1 = transformer(embed_layer1)

        probability = Keras.Bilinear(output_dim=len(self.labels),
                       activation='softmax',
                       constraint=[4, 1, 2, 3, 0],
                       name='Pairwise')([sent, sent1])

        self.model = Model([input_ids, input_ids1], probability)

        try:
            self.model.load_weights(self.modelFile)

        except Exception as e:
            print(e)
            self.load_trained_model_from_checkpoint()
#         self.model.summary(line_length=120)

    # load corpus data from mysql database
    def load_data(self, training=1, limit=None, csv=False, *__):
        if csv:
            csv = utility.corpusDirectory + '%s/tbl_lexicon_%s.csv' % (self.lang, self.lang)

            def generator():
                for line in utility.Text(csv):
                    *inst, _training = line.split('\t')
                    _training = int(_training)
                    if _training != training:
                        continue
                    yield inst

            generator = generator()
        else:
            from util import MySQL
            sql = 'select text, derivant, label from tbl_lexicon_%s where training = %s ' % (self.lang, training)
            if limit:
                sql += 'limit %s' % limit
            generator = MySQL.instance.select_from(sql)

        trainingSample = []
        for inst in generator:
            inst = Instance(*inst)
            inst.label = to_categorical(self.label2id[inst.label], len(self.labels))
            inst.string2id(self.string2id)
            trainingSample.append(inst)

        return trainingSample

    def load_trained_model_from_checkpoint(self):
        """Load trained official model from checkpoint.
        :param checkpoint_file: The path to the checkpoint files, should end with '.ckpt'.
        """
        modeling.load_trained_model_from_checkpoint(self.model, self.checkpoint_file)
        self.model.get_layer(name='Pairwise').set_weights([
            np.tile(tf.train.load_variable(self.checkpoint_file, 'bert/pooler/dense/kernel'), (5, 1, 1)),
            self.model.get_layer(name='Pairwise').get_weights()[1],
        ])

    def training(self,
                 epochs=4,
                 batch_size=32,
                 limit=None,
                 training=1,
                 csv=False,
                 incremental=True,
                 delimiter='<br>',
                 optimizer='adam',
                 **_):
        time_start = time.time()

        if not incremental:
            self.load_trained_model_from_checkpoint()

        generator = Keras.Sequence(self.load_data(training=training, limit=limit, csv=csv),
                                  batch_size=batch_size)

        validation_data = Keras.Sequence(self.load_data(training=1 - training, limit=limit, csv=csv),
                                  batch_size=batch_size)
        steps_per_epoch = len(generator)
        if optimizer == 'adam':
            optimizer = optimization.AdamOptimizer(steps_per_epoch * epochs)
        else:
            optimizer = optimization.LAMBOptimizer(steps_per_epoch * epochs)

        self.model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
#         self.load_pretrained_embedding(pretraining_weight)

        checkpoint = keras.callbacks.ModelCheckpoint(filepath=self.modelFile,
                                                     monitor='val_accuracy',
                                                     verbose=1,
                                                     save_best_only=True,
                                                     save_weights_only=True,
                                                     mode='max')

        _, checkpoint.best = self.model.evaluate_generator(validation_data)
        callbacks = [checkpoint]
        history = self.model.fit_generator(generator=generator,
#                                  verbose=2,
                                 steps_per_epoch=steps_per_epoch,
                                 validation_data=validation_data,
                                 epochs=epochs,
                                 callbacks=callbacks).history

        print('totally cost', (time.time() - time_start) / 60)
        self.print_history(history, delimiter)

#    check the sanctity of the bilinear layer, see following mathematical reference:
#    http://192.168.3.133:7000/sympy/axiom/neuron/bilinear/symmetry.php
    def test_bilinear(self):
        instances = self.load_data(limit=1000)

        y = Keras.Sequence(instances).predict(self.model)
        _y = Keras.Sequence([inst.reversed for inst in instances]).predict(self.model)

        tmp = np.array(y[:, 0])
        y[:, 0] = y[:, 4]
        y[:, 4] = tmp

        diff = y - _y
        if np.abs(diff).max() > 0.001:
            print(np.abs(diff).max())

# possible improvements yet to do:
# https://www.cnblogs.com/shiyublog/p/11185625.html
# https://github.com/tensorflow/tensor2tensor/blob/9e0a894034d8090892c238df1bd9bd3180c2b9a3/tensor2tensor/layers/common_attention.py#L1556-L1587
# https://blog.csdn.net/guotong1988/article/details/86505481
# Self-Attention with Relative Position Representations.pdf
if __name__ == '__main__':
    ...


import random

def create_random_list(n, k):
    L = []
    for i in range(n):
        L.append(random.randint(0, k - 1))
    return L

def linear_search(L, left, right, y):
    indexesFound = []
    i = left
    while i <= right:
        if y == L[i]:
            indexesFound.append(i)
        i += 1
    if len(indexesFound) != 0:
        return indexesFound
    else:
        return None

def main():
    myList = create_random_list(100, 10)
    print("Lista losowych numerów:", myList)

    find_number = myList[random.randint(0, len(myList) - 1)] #wybieram losowy number z listy
    print('Szukany numer:', find_number)

    print('Znalezione indeksy szukanego numeru w liście: ', linear_search(myList, 0, len(myList)-1, find_number))

if __name__ == "__main__":
    main()


import string
import sys
import unidecode

n = int(sys.argv[1])
message = sys.argv[2]
message = message.upper()

cipher = ""

for character in message:
    if character in string.ascii_uppercase:
        ascii_code = ord(character)
        alpha_index = ascii_code - ord("A")  # between 0 and 25
        alpha_index = (alpha_index + n) % 26  # between 0 and 25
        encrypted_ascii_code = ord("A") + alpha_index
        encrypted_character = chr(encrypted_ascii_code)
        cipher += encrypted_character

print(cipher)


def solution(a):
    MOD = 10000019

    def combine(row):
        nCr = [[0] * (row + 1) for _ in range(row + 1)]
        nCr[0][0] = 1
        for i in range(1, row + 1):
            for j in range(i + 1):
                if i == j:
                    nCr[i][j] = 1
                else:
                    nCr[i][j] = nCr[i-1][j-1] + nCr[i-1][j]
                nCr[i][j] %= MOD
        return nCr

    def get_one_cnt(row, col):
        one_cnt = [0] * (col + 1)
        for i in range(row):
            for j in range(col):
                one_cnt[j+1] += a[i][j]
        return one_cnt

    row = len(a)
    col = len(a[0])
    nCr = combine(row)
    one_cnt = get_one_cnt(row, col)
    DP = [[0] * (row + 1) for _ in range(col + 1)]
    DP[1][row - one_cnt[1]] = nCr[row][row - one_cnt[1]]

    for c in range(1, col):
        oc = one_cnt[c]
        for even_num in range(row + 1):
            if DP[c][even_num] == 0:
                continue
            for k in range(oc + 1):
                if even_num < k:
                    continue
                be_even_num = even_num + oc - (2 * k)
                if be_even_num > row:
                    continue
                result = (nCr[even_num][k] * nCr[row - even_num][oc - k]) % MOD
                DP[c + 1][be_even_num] = (DP[c + 1][be_even_num] + DP[c][even_num] * result) % MOD

    return DP[col][row]

data = [[0,1,0],[1,1,1],[1,1,0],[0,1,1]]
print(solution(data))

프로그래머스/짝수 행 세기.py


#定义一个节点
#分别有元素data， 指向下一个节点的指针next
class QueueNode:
    def __init__(self):
        self.data = None
        self.next = None

#定义一个链式队列
#提供链式队列的相关操作
class LinkQueue:
    #默认初始化队列的函数
    def __init__(self):
        tQueueNode = QueueNode()
        self.front = tQueueNode
        self.rear = tQueueNode

    #判断队列是否为空的函数
    def IsEmptyQueue(self):
        if self.front == self.rear:
            iQueue = True
        else:
            iQueue = False
        return iQueue

    #入队
    #主要操作是：创建一个新节点， 将其链接到队列的末尾， 并由rear指向它
    def EnQueue(self, data):
        tQueueNode = QueueNode() #入队前创建新节点
        tQueueNode.data = data #新节点添加元素
        self.rear.next = tQueueNode #将next指向新创建的节点
        self.rear = tQueueNode #将rear指针指向新节点
        print('当前入队元素为：',data)

    #出队
    #1,判断队列是否为空，队列为空无法出队


class proceso_ent:
    def __init__(self):
        self.__nombre=""
        self.__ruta=""
        self.__job=""
        self.__cantidad_filas=""
        self.__tipo=""
        self.__flg_log=""
        self.__cantidad_stm_sql=0
        self.__tipo_conexion=""
        self.__ult_exec_log=""
        self.__flg_estado=""