import json
import logging

from django.shortcuts import render
from django.utils import timezone
from dynaconf import settings as dynasettings
from ipware import get_client_ip
from rest_framework import mixins, viewsets, status, views
from rest_framework.response import Response

from common.auth.wechat.web_auth import WeChantWebAuthHandler
from common.model_manager.account_manager import AccountManager
from common.model_manager.marketer_manager import MarketerModelManager
from common.model_manager.transfer_record_manager import TransferRecordManager
from common.msg_service.sms_send import SendMessageApi, VerifySmsCode
from config import PAY_CHANNELS
from marketer.config import PHONE_CODE_STATUS, AREA_STATUS_CODE, \
    UNIONID_LIMIT, MAX_REQUEST_ONE_DAY, ALIPAY_VERIFY_TRANSFER_AMOUNT
from marketer.model_manager import AreaModelManager
from marketer.serializers.account import MarketerWithdrawSerializer
from marketer.serializers.marketer import CreateMarketerBaseSerializer, \
    UpdateMarketerSerializer
from marketer.serializers.nested_serializers import MarketerLoginSerializer
from marketer.utils.auth import MarketerRegisterAuthentication, \
    MarketerAuthentication
from marketer.utils.redis_utils import RedisUtil

ENV = dynasettings.ENV

dynasettings.configure()
dynasettings.namespace('PAYUNION')
app_id = dynasettings.SUBSCRIPTION_ACCOUNT_APP_ID_MARKETER if ENV != 'dev' else dynasettings.SUBSCRIPTION_ACCOUNT_APP_ID_USER
app_secret = dynasettings.SUBSCRIPTION_ACCOUNT_SECRET_MARKETER if ENV != 'dev' else dynasettings.SUBSCRIPTION_ACCOUNT_SECRET_USER
logger = logging.getLogger(__file__)

class MarketerLoginView(views.APIView):
    """
    登陆
    """

    def post(self, request):
        serializer = MarketerLoginSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return Response(
            status=status.HTTP_200_OK,
            data=dict(token=serializer.token)
        )

class MarketerRegisterViewSet(mixins.CreateModelMixin, viewsets.GenericViewSet):
    """
    create:
        Register marketer
    """
    serializer_class = CreateMarketerBaseSerializer
    authentication_classes = [MarketerRegisterAuthentication]

class MarketerWithdrawViewSet(viewsets.GenericViewSet):
    """ 邀请人/业务员 账户余额提现 """

    authentication_classes = [MarketerAuthentication]

    @staticmethod
    def withdraw(request):
        """ 提现 """
        marketer = request.user
        client_ip, _ = get_client_ip(request._request)

        logger.info(
            f'merchant({marketer.id, marketer.name, client_ip} '
            f'requested a withdraw: {request.data}')

        serializer = MarketerWithdrawSerializer(marketer.account,
                                                data=request.data,
                                                partial=True)
        serializer.is_valid(raise_exception=True)

        manager = AccountManager(marketer.account)

        if request.data['channel'] == PAY_CHANNELS.WECHAT:
            withdraw_error = manager.wechat_withdraw(
                serializer.validated_data['amount'],
                client_ip,
                dynasettings.SUBSCRIPTION_ACCOUNT_APP_ID_MARKETER
            )
        else:
            withdraw_error = manager.alipay_withdraw(
                serializer.validated_data['amount'])

        logger.info(
            f'marketer ({marketer.id, marketer.name, client_ip} '
            f'withdraw error is {withdraw_error}')

        return Response(status=status.HTTP_200_OK, data=withdraw_error or {})

class CheckAreaMarketerView(views.APIView):
    """验证区域是否存在业务员"""

    def get(self, request):
        adcode = self.request.query_params.get('adcode')
        manager = AreaModelManager()
        res = manager.has_marketer(adcode=adcode)
        if res:
            if res == 'DISABLE':
                return Response(status=status.HTTP_200_OK,
                                data=dict(code=AREA_STATUS_CODE['DISABLE'],
                                          message='未开放该区域'))
            else:
                return Response(status=status.HTTP_200_OK,
                                data=dict(code=AREA_STATUS_CODE['HAS_MARKETER'],
                                          message='该区域有业务员'))
        else:
            return Response(status=status.HTTP_200_OK,
                            data=dict(code=AREA_STATUS_CODE['NO_MARKETER'],
                                      message='该区域没业务员'))

class GetUserInfoView(views.APIView):
    """获取用户基本信息"""
    authentication_classes = [MarketerAuthentication]

    def get(self, request):
        user = self.request.user
        if user:
            manager = MarketerModelManager()
            user_info = manager.get_user_info(self.request.user.wechat_unionid)
            return Response(status=status.HTTP_200_OK, data=user_info)
        else:
            return Response(status=status.HTTP_200_OK, data=dict(
                user_name=None,
                user_phone=None,
                user_status='not_register',
                user_type=None,
                using_invited_merchants_num=0,
                reviewing_invited_merchants_num=0,
                total_bonus=0,
                user_withdrawable_balance=0,
                alipay_withdraw_balance=0,
                wechat_withdraw_balance=0
            ))

class MarketerSendMessageViewSet(viewsets.ViewSet):
    """ 邀请人、业务员 发短信 """
    authentication_classes = [MarketerRegisterAuthentication]

    def msg_send(self, request):
        # 发送短信验证码
        unionid = request.user.get('unionid')
        phone = request.data.get('phone')
        send_msg_api = SendMessageApi(phone=phone, wechat_unionid=unionid)
        result = send_msg_api.message_send()
        return Response(status=status.HTTP_200_OK, data=result)

class AuthenticatedMarketerSendMessageViewSet(viewsets.ViewSet):
    authentication_classes = [MarketerAuthentication]

    def msg_send(self, request):
        # 发送短信验证码
        user = request.user
        phone = request.data.get('phone')
        send_msg_api = SendMessageApi(phone=phone,
                                      wechat_unionid=user.wechat_unionid)
        result = send_msg_api.message_send()
        return Response(status=status.HTTP_200_OK, data=result)

class VerifySmsCodeViewSet(viewsets.ViewSet):
    """ 验证短信验证码 """
    authentication_classes = [MarketerAuthentication]

    def verfy_sms_code(self, request):
        phone = request.data.get('phone')
        verify_code = request.data.get('verify_code')
        verify_instace = VerifySmsCode(phone=phone, verify_code=verify_code)
        data = {'code': 0, 'message': "短信验证成功"}
        if not verify_instace.verify():
            data = {'code': -1, 'message': "验证码输入错误，请重新输入"}
        return Response(status=status.HTTP_200_OK, data=data)

class GetMarketerWechatInfo(viewsets.ViewSet):
    """
    微信授权回调 接收wechat code 根据code获取 access_token
    1、授权成功，先创建业务员／邀请人
    2、网页展示授权状态
    """

    def wechat_auth_redirect(self, request):
        code = request.query_params.get('code', '')

        wechat_auth_handler = WeChantWebAuthHandler(app_id=app_id,
                                                    app_secret=app_secret)
        access_token, openid = wechat_auth_handler.gen_access_token(code=code)
        user_info = wechat_auth_handler.gen_user_info(access_token, openid)
        if 'openid' not in user_info:
            user_info['openid'] = openid

        if not user_info.get('unionid'):
            return render(request, 'auth_web/auth_marketer_error.html',
                          {'title': "注册业务员", 'info': "授权异常"})
        if MarketerModelManager.check_marketer_exists(
                unionid=user_info['unionid']):
            logger.info(f"{user_info['nickname']} 该邀请人已经注册")
            return render(request, 'auth_web/auth_marketer_error.html',
                          {'title': "注册业务员", 'info': "该邀请人已经注册"})

        # marketer还没有注册 缓存openid, 昵称，缓存头像
        _user_info = json.dumps(user_info)
        RedisUtil.cache_data(user_info['unionid'], _user_info, data_type='wechat_info')

        return render(request, 'auth_web/auth_marketer.html',
                      {'title': "注册业务员", 'nickname': user_info['nickname']})

class UpdateMarketerInfoView(views.APIView):
    authentication_classes = [MarketerAuthentication]

    def put(self, requeest):
        serializer = UpdateMarketerSerializer(data=self.request.data)
        serializer.is_valid()
        serializer.update(instance=self.request.user,
                          validated_data=serializer.validated_data)
        return Response(status=status.HTTP_202_ACCEPTED,
                        data=serializer.validated_data)

class CheckPhoneExistView(views.APIView):
    def get(self, request):
        manager = MarketerModelManager()
        res = manager.check_phone_exist(self.request.query_params.get('phone'))
        if res:
            data = dict(code=PHONE_CODE_STATUS['EXIST'], message='手机已存在')
        else:
            data = dict(code=PHONE_CODE_STATUS['CAN_USE'], message='可以使用')
        return Response(status=status.HTTP_200_OK, data=data)

class CheckAlipayAccountView(viewsets.ViewSet):
    """ 验证支付宝账号名字是否正确 """
    authentication_classes = [MarketerRegisterAuthentication]

    API_CODE = {
        'SUCCESS_RECORD_NOT_EXIST': -5,
        'PARAMS_ERROR': -4,
        'REQUEST_FREQUENTLY': -3,
        'REQUEST_TOO_MANY': -2,
        'TRANSFER_FAILED': -1,
        'TRANSFER_FINISHED': 0,
        'SUCCESS_RECORD_EXIST': 1
    }

    def show_success_transfer_record(self, request):
        """ 根据unionid查询记录 """
        unionid = request.user.get('unionid')
        res = TransferRecordManager.check_transfer_success(unionid=unionid)
        data = dict(code=self.API_CODE['SUCCESS_RECORD_NOT_EXIST'],
                    message="没有与该unionid对应的成功记录",
                    alipay_data=res['record'])
        if res['exist']:
            data.update(
                code=self.API_CODE['SUCCESS_RECORD_EXIST'],
                message="存在转账成功记录",
                alipay_data=res['record'])
        return Response(status=status.HTTP_200_OK, data=data)

    def check_alipay_account(self, request):
        now = timezone.now()
        timestamp = now.timestamp()
        record_key = now.strftime('%Y_%m_%d')
        unionid = request.user.get('unionid')
        account_number = request.data.get('account_number')
        account_name = request.data.get('account_name')

        # 验证账号、名字不为空
        if not all([account_number, account_name]):
            return Response(status=status.HTTP_200_OK, data=dict(
                code=self.API_CODE['PARAMS_ERROR'],
                message="支付宝账号和姓名必填"
            ))

        # 验证当前接口请求次数
        if RedisUtil.record_request_one_day(record_key) > MAX_REQUEST_ONE_DAY:
            return Response(status=status.HTTP_200_OK, data=dict(
                code=self.API_CODE['REQUEST_TOO_MANY'],
                message="接口服务已达到单日请求上限"
            ))

        # 验证当前微信号请求转账频率
        list_len = RedisUtil.get_request_time_len(unionid=unionid)
        if list_len and list_len >= UNIONID_LIMIT['max_times']:
            oldest_time = RedisUtil.get_oldest_item(unionid=unionid)
            if timestamp < float(oldest_time) + UNIONID_LIMIT['limit_seconds']:
                data = dict(
                    code=self.API_CODE['REQUEST_FREQUENTLY'],
                    message=f"过去7天内已达到上限{UNIONID_LIMIT['max_times']}次"
                )
                return Response(status=status.HTTP_200_OK, data=data)

        # 验证该微信号、支付宝账号、姓名是否有成功转账记录
        check_data = TransferRecordManager.check_transfer_success(
            unionid=unionid,
            account_number=account_number,
            account_name=account_name)

        if check_data['exist']:
            data = dict(code=self.API_CODE['SUCCESS_RECORD_EXIST'],
                        message="存在转账成功记录",
                        alipay_data=check_data['record'])
            return Response(status=status.HTTP_200_OK, data=data)

        # 转账并记录
        errors = TransferRecordManager.transfer_to_account(
            unionid=unionid,
            account_number=account_number,
            account_name=account_name,
            amount=ALIPAY_VERIFY_TRANSFER_AMOUNT
        )

        data = dict(
            code=self.API_CODE['TRANSFER_FAILED'],
            message="支付宝账号或姓名错误",
            alipay_data={}
        )

        if not errors:
            RedisUtil.record_request_one_day(record_key, num_incr=True)
            if list_len + 1 > UNIONID_LIMIT['max_times']:
                RedisUtil.get_oldest_item(unionid=unionid, pop_item=True)
            RedisUtil.cache_request_time(unionid=unionid, time=timestamp)
            data.update(
                code=self.API_CODE['TRANSFER_FINISHED'],
                message="支付宝信息验证成功",
                alipay_data=dict(account_number=account_number,
                                 account_name=account_name)
            )

        return Response(status=status.HTTP_200_OK, data=data)

marketer_withdraw = MarketerWithdrawViewSet.as_view({
    'put': 'withdraw',
})
marketer_msg_send = MarketerSendMessageViewSet.as_view({
    'post': 'msg_send',
})
authenticated_marketer_msg_send = AuthenticatedMarketerSendMessageViewSet.as_view({
    'post': 'msg_send',
})
marketer_msg_verify = VerifySmsCodeViewSet.as_view({
    'post': 'verfy_sms_code',
})
get_marketer_wechat_info = GetMarketerWechatInfo.as_view({
    'get': 'wechat_auth_redirect',
})
check_alipay_account = CheckAlipayAccountView.as_view({
    'get': 'show_success_transfer_record',
    'post': 'check_alipay_account',
})


from torchvision import transforms
from torch.utils.data import Dataset
from .dataset import MVB
import albumentations as A
from albumentations.pytorch import ToTensorV2

def get_augmentation(phase, input_size):
    if phase == "train":
        return  A.Compose([
                    A.LongestMaxSize(max_size = input_size ),
                    A.PadIfNeeded(min_height=input_size, min_width=input_size, p=1,value=0),
                    A.RandomResizedCrop(height= input_size, width=input_size,scale=(0.8,1.33)),
                    A.HorizontalFlip(p=0.5),
#                     A.RandomBrightnessContrast(p=0.5, brightness_limit=(-0.2, 0.2), contrast_limit=(-0.2, 0.2)),
#                     A.HueSaturationValue(p=0.5, hue_shift_limit=0.2, sat_shift_limit=0.2, val_shift_limit=0.2),
                    A.ShiftScaleRotate(p=0.5, shift_limit=0.0625, scale_limit=0.2, rotate_limit=20),
#                     A.CoarseDropout(p=0.5),
                    A.Normalize(),
                    ToTensorV2()
                ])
    elif phase in ['test','valid']:
        return A.Compose([
            A.LongestMaxSize(max_size = input_size),
            A.PadIfNeeded(min_height=input_size, min_width=input_size, p=1,value=0),
            A.Normalize(),
            ToTensorV2()
        ])
def make_dataset(traindf):
    dataloader =  MVB(traindf,transform = get_augmentation)
    return dataloader


import socket
import json
import time

SERVER = "192.168.68.114"
PORT = 1337
HEADER = 8
DISCONNECT_MSG = "!DISCONNECT"
GET_MSG = "!GET"

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((SERVER, PORT))

def send(msg):
    # Finds the size of the message to send in the header
    message = msg.encode('utf-8')
    message_length = len(message)

    send_length = str(message_length).encode('utf-8')
    # Pads the header to be 8 bytes
    send_length += b' ' * (HEADER - len(send_length))

    client.send(send_length)
    client.send(message)

send(GET_MSG)

msg_length = client.recv(HEADER).decode('utf-8')
if msg_length:
    msg_length = int(msg_length)

    raw_data = client.recv(msg_length)

send(DISCONNECT_MSG)

data = json.loads(raw_data)
print(round(float(data['temp']), 2))


string=input()
start=string[0]
end=string[-1]
alpha=[
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
]

a=start in alpha
# print(a)
# for i in range(len(alpha)):
#     if start==alpha[i]:
#         # print(alpha[i])
#         while end!=alpha[i-1]:
#             print(alpha[i])
#             i+=1
flag=False
for alphabet in alpha:
    if start == alphabet:
        flag = True

    if flag:
        print(alphabet)

    if end == alphabet:
        break


from src.crack_code.crack_code import crack_code

def test_if_letters_inside_bracket_are_not_in_alphabetical_returns_false():
    expected=False
    result=crack_code("aaa-vvv-dd-s(advs)")
    assert expected==result

    expected=False
    result=crack_code("a-b-c-d-e-f-g-h-i-577(acdb)")
    assert result==expected

def test_with_just_four_letters():
    expected=True
    result=crack_code("a-b-c-d(abcd)")
    assert result==expected

    expected=True
    result=crack_code("d-b-c-a(abcd)")
    assert result==expected

def test_most_common_letters():
    expected=True
    result=crack_code("ddd-aaa-z-y-x-123(adxy)")
    assert expected==result

    expected=False
    result=crack_code("fff-gg-xx-ss-y(fgsy)")
    assert expected==result

def test_equal_commonality_but_alphabetical():
    expected=True
    result=crack_code("a-b-c-d-e-f-g-h-i-577(abcd)")
    assert result==expected


import csdl
import numpy as np

class LoadIntegrationModel(csdl.Model):
    def initialize(self):
        self.parameters.declare('num_radial', default=10) # RADIAL NODES IN BLADE
        self.parameters.declare('num_azim', default=20) # AZIMUTHAL STEPS IN ROTATION OF BLADES
        self.parameters.declare('num_blades', default=2) # NUMBER OF BLADES
        self.parameters.declare('num_nodes', default=1)
        self.parameters.declare('load_harmonics', default=np.arange(0,11,1))

    def define(self):
        num_radial = self.parameters['num_radial']
        num_azim = self.parameters['num_azim']
        num_blades = self.parameters['num_blades']
        num_nodes = self.parameters['num_nodes']
        load_harmonics = self.parameters['load_harmonics']

        sectional_D = csdl.expand(
            self.declare_variable('_dD', shape=(num_nodes, num_radial, num_azim)), # num_azim should provide the number of timesteps
            shape=(num_nodes, num_blades, num_radial, num_azim),
            indices='ijk->iajk'
        )

        sectional_T = csdl.expand(
            self.declare_variable('_dT', shape=(num_nodes, num_radial, num_azim)), # num_azim should provide the number of timesteps
            shape=(num_nodes, num_blades, num_radial, num_azim),
            indices='ijk->iajk'
        )

        radial_sum_D = csdl.sum(sectional_D, axes=(2,)) # total blade drag as a function of theta
        radial_sum_T = csdl.sum(sectional_T, axes=(2,)) # total blade thrust as a function of theta

        theta = np.linspace(0., 2*np.pi, num_azim) # we assume num_azim is the number of azimuthal divisions in ONE ROTATION

        n_theta_prod = self.create_input('n_theta_prod', np.outer(load_harmonics, theta)) # (num_harmonics, num_azim)
        cos_vec = csdl.expand(csdl.cos(n_theta_prod), (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ij->abicj') # CHECK
        sin_vec = csdl.expand(csdl.sin(n_theta_prod), (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ij->abicj') # CHECK

        # aT_integrand = self.register_output(
        #     'aT_integrand',
        #     csdl.expand(radial_sum_T, (num_nodes, num_blades, len(load_harmonics), num_azim), 'ijk->ijak') * cos_vec
        # )
        # aD_integrand = self.register_output(
        #     'aD_integrand',
        #     csdl.expand(radial_sum_D, (num_nodes, num_blades, len(load_harmonics), num_azim), 'ijk->ijak') * cos_vec
        # )
        # bT_integrand = self.register_output(
        #     'bT_integrand',
        #     csdl.expand(radial_sum_T, (num_nodes, num_blades, len(load_harmonics), num_azim), 'ijk->ijak') * sin_vec * -1.
        # )
        # bD_integrand = self.register_output(
        #     'bD_integrand',
        #     csdl.expand(radial_sum_D, (num_nodes, num_blades, len(load_harmonics), num_azim), 'ijk->ijak') * sin_vec * -1.
        # )

        aT_integrand = self.register_output(
            'aT_integrand',
            csdl.expand(sectional_T, (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ijkl->ijakl') * cos_vec
        )
        aD_integrand = self.register_output(
            'aD_integrand',
            csdl.expand(sectional_D, (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ijkl->ijakl') * cos_vec
        )
        bT_integrand = self.register_output(
            'bT_integrand',
            csdl.expand(sectional_T, (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ijkl->ijakl') * sin_vec * -1.
        )
        bD_integrand = self.register_output(
            'bD_integrand',
            csdl.expand(sectional_D, (num_nodes, num_blades, len(load_harmonics), num_radial, num_azim), 'ijkl->ijakl') * sin_vec * -1.
        )

        input_shape = aT_integrand.shape
        dim = 4
        input_names = ['aT_integrand', 'aD_integrand', 'bT_integrand', 'bD_integrand']
        # output_names = ['aT', 'aD', 'bT', 'bD']
        output_names = ['aT_unsteady', 'aD_unsteady', 'bT_unsteady', 'bD_unsteady']

        for i in range(4):
            self.add(
                TrapezoidMethod(
                    input_name=input_names[i],
                    input_shape=input_shape,
                    dim=dim,
                    output_name=output_names[i],
                    num_azim=num_azim
                ),
                f'{output_names[i]}_load_integration_model'
            )

        '''
        OUTPUT SHAPE OF aT, ... is (num_nodes, num_blades, num_harmonics)
        '''

class TrapezoidMethod(csdl.Model):
    def initialize(self):
        self.parameters.declare('input_name')
        self.parameters.declare('input_shape', types=tuple)
        self.parameters.declare('dim', types=int) # dimension in which sum is taken for numerical integration
        self.parameters.declare('output_name')
        self.parameters.declare('num_azim')

    def define(self):
        input_name = self.parameters['input_name']
        input_shape = self.parameters['input_shape']
        output_name = self.parameters['output_name']
        dim = self.parameters['dim']
        num_azim = self.parameters['num_azim']

        h = self.create_input(f'{input_name}_dtheta', val=2.*np.pi/num_azim) # FIX TO USE THE AZIMUTHAL SEPARATIONS
        f = self.declare_variable(input_name, shape=input_shape)
        # out_pre_integration = 1/(2*np.pi)*(f[:,:,:,0:-1] + f[:,:,:,1:]) *  csdl.expand(h, shape=f[:,:,:,1:].shape)/ 2.
        # out = self.register_output(output_name, csdl.sum(out_pre_integration, axes=(dim,)))
        out_pre_integration = 1/(2*np.pi)*(csdl.sum(f, axes=(4,))) * csdl.expand(h, input_shape[:4])
        self.register_output(output_name, out_pre_integration)
        print(out_pre_integration.shape)

'''
NOTE:
- start with a general trapezoid rule (make a CSDL model for this)
- then, add a higher-order method (like midpoint or Simpson)
'''

if __name__ == '__main__':
    from python_csdl_backend import Simulator

    # m = TrapezoidMethod(
    #     input_name='a',
    #     input_size=5,
    #     output_name='b'
    # )

    # sim = Simulator(m)
    # sim['step_size'] = 0.5
    # sim.run()

    m = LoadIntegrationModel()
    sim = Simulator(m)
    sim.run()


def solution(n, money):
    dp = [[0 for _ in range(n+1)] for _ in range(len(money))]
    dp[0][0] =1
    for i in range(money[0], n+1, money[0]): # 동전의 최소값으로 만들 수 있는 값들
        dp[0][i] = 1

    for y in range(1, len(money)):
        for x in range(n+1):
            if x>=money[y]:
                dp[y][x] = dp[y-1][x] + dp[y][x - money[y]]
            else:
                dp[y][x] = dp[y-1][x]
    return dp[-1][-1] % 1000000007

print(solution(4, [1,2,5]))

def solution(n, money):
    dp = [1] + [0] * n
    for i in money:
        for j in range(i, n+1):
            dp[j] += dp[j-i]
    return dp[n] % 1000000007

print(solution(4, [1,2,5]))


'''
Created on 15.04.2013

@author: capone
'''
import unittest
import os

from mock import MagicMock
from mock import patch
import mock
from crashtec.utils.exceptions import  CtGeneralError

from crashtec.utils.exceptions import CtBaseException
from crashtec.db.provider.routines import Record
from crashtec.infrastructure.public import definitions as infradefs
from crashtec.db.schema.fields import PRIMARY_KEY_FIELD

from crashtec.cdbprocessor import dbmodel
from crashtec.cdbprocessor import processor
from crashtec.cdbprocessor import resultparsers

import testconfig

TEST_DATA_FOLDER = 'test_data'
DUMP_FILE_NAME = os.path.join(os.path.dirname(__file__),
                                        TEST_DATA_FOLDER,
                                        "dump.dmp")

class Test01_CommandsHolder(unittest.TestCase):
    def test_positive_get_debugger_commands_for_task(self):
        task = Record()
        task[dbmodel.TASKS_PROBLEM_ID] =  infradefs.PROBLEMID_HANG
        commands_holder = processor.CdbCommandsHolder(testconfig)
        self.assertEqual(testconfig.HANG_COMMANDS_LIST,
                    commands_holder.get_debugger_commands_for_task(task),
                    "Wrong result for passed problem id"
                    )

    def test_negative_get_debugger_commands_for_task(self):
        task = Record()
        task[dbmodel.TASKS_PROBLEM_ID] = 'unknown_problem'
        commands_holder = processor.CdbCommandsHolder(testconfig)
        with self.assertRaises(CtBaseException):
                    commands_holder.get_debugger_commands_for_task(task)

class Test02_Debugger(unittest.TestCase):
    def test_positive_execute(self):
        debugger = processor.CdbDebugger(self.mock_config)
        task = Record()
        task[dbmodel.TASKS_PLATFORM_FIELD] = infradefs.PLATFORM_WIN32
        task[dbmodel.TASKS_DUMP_FILE_FIELD] = DUMP_FILE_NAME
        task[dbmodel.TASKS_SYMBOLS_PATH] = 'c:\\mock_path'
        result = debugger.execute(task, testconfig.HANG_COMMANDS_LIST)
        self.assertTrue(result, "Should not be empty")

    def test_negative_execute(self):
        debugger = processor.CdbDebugger(self.mock_config)
        task = Record()
        task[dbmodel.TASKS_PLATFORM_FIELD] = infradefs.PLATFORM_WIN32
        task[dbmodel.TASKS_DUMP_FILE_FIELD] = "z:\\unknown_dump.dmp"
        task[dbmodel.TASKS_SYMBOLS_PATH] = 'c:\\mock_path'
        with self.assertRaises(CtBaseException):
            debugger.execute(task, testconfig.HANG_COMMANDS_LIST)

    def setUp(self):
        self.mock_config = mock.MagicMock()
        self.mock_config.STANDARD_SYMBOLS_PATH = str()

_sample_task = {'id':1}
_sample_debugger_commnds = ['coommand1', 'command2']
_sample_debugger_output = 'sample output'
_sample_parsed_results = 'parsed_results'

class MockProcessorBuilder(object):
    def build_commands_holder(self):
        self.commands_holder = mock.create_autospec(
                            processor.CdbCommandsHolder(), spec_set = True)
        self.commands_holder.get_debugger_commands_for_task = MagicMock(
            return_value = _sample_debugger_commnds)
        return self

    def build_debugger(self):
        self.debugger =  mock.create_autospec(
                            processor.CdbDebugger(), spec_set = True)
        self.debugger.execute = MagicMock(
            return_value = _sample_debugger_output)
        return self

    def build_parser(self):
        self.parser =  mock.create_autospec(
                            resultparsers.create_parser(), spec_set = True)
        self.parser.parse_output = MagicMock(
                            return_value = _sample_parsed_results)
        return self

    def build_publisher(self):
        self.publisher =  mock.create_autospec(
                            processor.DbPublisher(), spec_set = True)
        self.publisher.publish_results = MagicMock()
        return self

    def create(self):
        impl = processor.Implementation(self.commands_holder,
                                        self.debugger,
                                        self.parser,
                                        self.publisher)
        return processor.Processor('class_type', 'instance_name',
                                   'group_id', impl)

class MockProcessorOneStepThrowsBuilder(MockProcessorBuilder):
    def build_publisher(self):
        self.publisher =  mock.create_autospec(
                            processor.DbPublisher(), spec_set = True)
        self.publisher.publish_results = MagicMock(
                        side_effect = CtGeneralError('Mock intended error'))
        return self

@patch('crashtec.infrastructure.public.agentbase.RegistrationHolder')
class Test03_Processor(unittest.TestCase):
    # Here we should not have any errors. It is just regular success path.
    def test_task_success(self, mock_class):
        # Setup mock's
        processor_instance = self.create_mock_processor(MockProcessorBuilder())

        processor_instance.task_failed = MagicMock(side_effect =
                                        RuntimeError("Should not be called"))

        # Call
        processor_instance.process_task(_sample_task)

        # Validate call's
        impl = processor_instance.impl
        impl.commands_holder.get_debugger_commands_for_task.\
                        assert_called_once_with(_sample_task)
        impl.debugger.execute.\
                        assert_called_once_with(_sample_task,
                                                _sample_debugger_commnds)
        impl.parser.parse_output.\
                        assert_called_once_with(_sample_debugger_output)
        impl.publisher.publish_results.\
                        assert_called_once_with(_sample_task,
                                                _sample_parsed_results)
        processor_instance.task_finished.assert_called_once_with(_sample_task)

    def test_task_failed(self, mock_class):
        # Setup mock's
        processor_instance = self.create_mock_processor(
                                        MockProcessorOneStepThrowsBuilder())

        processor_instance.task_finished = MagicMock(side_effect =
                                        RuntimeError("Should not be called"))

        # Call
        processor_instance.process_task(_sample_task)

        # Validate call's
        processor_instance.task_failed.assert_called_once_with(_sample_task)

    def create_mock_processor(self, builder):
        instance = builder.build_commands_holder().\
                    build_debugger().\
                    build_parser().\
                    build_publisher().\
                    create()
        instance.task_failed = MagicMock()
        instance.task_finished = MagicMock()
        return instance

def _get_sample_signature():
    return resultparsers.CrashSignature('problem_class',
                                        'image_name',
                                        'symbol_name',
                                        'failure_bucket_id')

@patch('crashtec.db.provider.routines.create_new_record')
class Test04_DbPublisher(unittest.TestCase):
    def test_publish_results(self, mock_create_new_record):
        # Prepare samnple data
        task = Record()
        d = dbmodel
        task[PRIMARY_KEY_FIELD] = 212
        SAMPLE_DBG_OUTPUT = 'sample_output'

        # Call publisher
        publisher = processor.DbPublisher()
        r = resultparsers
        publisher.publish_results(task, [
                        r.CrashSignatureParserResults(_get_sample_signature()),
                        r.RawOutputParserResults(SAMPLE_DBG_OUTPUT)])

        # Validate publisher behavior
        s = _get_sample_signature()
        self.assertEqual(task[d.TASKS_PROBLEM_CLASS], s.problem_class)
        self.assertEqual(task[d.TASKS_SYMBOL_NAME], s.symbol_name)
        self.assertEqual(task[d.TASKS_FAIL_IMAGE], s.image_name)
        self.assertEqual(task[d.TASKS_FAILURE_BUCKET_ID], s.failure_bucket_id)

        new_record = Record()
        new_record[d.RAWRESULTS_TASK_ID] = 212
        new_record[d.RAWRESULTS_DBG_OUTPUT] = SAMPLE_DBG_OUTPUT
        mock_create_new_record.assert_called_once_with(d.RAWRESULTS_TABLE,
                                                       new_record)

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']e
    unittest.main()


'''Exercício Python 075: Desenvolva um programa que leia quatro valores pelo teclado e guarde-os em uma tupla. No final, mostre:

A) Quantas vezes apareceu o valor 9.

B) Em que posição foi digitado o primeiro valor 3.

C) Quais foram os números pares.'''
i = c = nove = 0
pares = ()
tupla = (int(input('Digite um número: ')), int(input('Digite outro número: ')), int(input('Mais um: ')), int(input('O último agora: ')))
print(f'O valor 9 apareceu {tupla.count(9)} vezes.')
if 3 in tupla:
    print(f'O valor 3 foi digitado primeiramente na {tupla.index(3) + 1}ª solicitação')
else:
    print('O valor 3 não foi digitado em nenhuma posição')
print(f'Os números pares digitados foram:', end = (' '))
for c in tupla:
    if c % 2 == 0:
        print(c, end = (' '))
        i += 1
if i == 0:
    print('(Não foram digitados números pares)')


print ("How many kitties do you have!?")

kittycount = input()

def kCounter(userInput):
	global kittycount
	try:
		if int(kittycount) >= 4:
			print("WOWSERS, that is A LOT of kitties")
		elif int(kittycount) == 0:
				print("You should get a kitty!")
		elif int(kittycount) < 0:
			print("Come on! you cant have negative kitties!")
			print("Please enter a POSITIVE number :)")
			kittycount = input()
			kCounter(kittycount)
		else:
			print("Step up the kitty game bruh")
	except (ValueError):
		print("Please enter a numeral")
		kittycount = input()
		kCounter(kittycount)

kCounter(kittycount)


from abc import ABC, abstractmethod
from typing import List

class Move:
    def __init__(self, moveStr: str):
        self.direction, step = moveStr.split(" ")
        self.step = int(step)

class Validator(ABC):

    @abstractmethod
    def GetPosition(self, moves: List[Move]) ->  int:
        pass

class AimCalculator(Validator):

    def GetPosition(self, moves: List[Move]) -> int:
        position, debt, aim = 0, 0, 0

        for move in moves:
            if move.direction == "forward":
                position += move.step
                debt += aim * move.step
            if move.direction == "down":
                aim += move.step
            if move.direction == "up":
                aim -= move.step

        return position * debt

class RouteCalculator(Validator):

    def GetPosition(self, moves: List[Move]):
        position, debt = 0, 0

        for move in moves:
            if move.direction == "forward":
                position += move.step
            if move.direction == "down":
                debt += move.step
            if move.direction == "up":
                debt -= move.step

        return position * debt


import sys
import pymongo
from log import Log
from config import Config
import bson
from bson import json_util
from bson import objectid

Config.load()

class ItemsDatabase:
    ''' Items database class '''

    collectionName = ''

    def __init__(self):
        Log.dbg("ItemsDatabase.__init__()")

        self.client = None

        self.db = None

        self.started = False

    def __del__(self):
        Log.dbg("ItemsDatabase.__del__()")

        self.stop()

    def start(self):
        Log.info("ItemsDatabase.start()")

        if (self.started):
            return

        try:
            Log.info("Configuration data:")
            Log.info(Config.data())

            self.client = pymongo.MongoClient(Config.data()['db']['host'], Config.data()['db']['port'])

            self.db = self.client[Config.data()['db']['dbname']]

            self.started = True

        except Exception as e:
            Log.exception('Exception ocurred in database connection.')
            Log.exception('Exception: ' + e)
            Log.exception('Traceback: ' + e.with_traceback)

            sys.exit(1)

    def getItems(self):
        Log.info("ItemsDatabase.getItems()")

        try:
            items = self.db['items'].find()

            result = []

            for item in items:
                result.append({
                    '_id': str(item['_id']),
                    'name': item['name'],
                    'price': item['price']
                })

            return result

        except Exception as e:
            Log.error(e)

            return []

    def getItem(self, _id):
        Log.info("ItemsDatabase.getItem()")
        Log.info("Item ID: " + _id)

        try:
            items = self.db['items'].find({'_id': objectid.ObjectId(_id)})

            if (items is None or items.count() < 1):
                return json_util.dumps({})

            item = items[0]

            result = {
                'name': item['name'],
                'price': item['price']
            }

            Log.info("y")

            Log.info("result:")
            Log.info(result)

            return result

        except bson.errors.InvalidId as e:
            Log.error(e)

            return {}

        except Exception as e:
            Log.error(e)

            return {}

    def saveItem(self, item):
        Log.info("ItemsDatabase.saveItem()")
        Log.info("item:")
        Log.info(item)

        if 'name' not in item:
            Log.info("Invalid item name")
            return

        if 'price' not in item:
            Log.info("Invalid item price")
            return

        itemId = objectid.ObjectId()

        dbResult = self.db['items'].insert({'_id': itemId, 'name': item['name'], 'price': item['price']})

        return str(itemId)

    def deleteItem(self, data):
        Log.info("ItemsDatabase.deleteItem()")
        Log.info("item id:" + data['_id'])

        dbResult = self.db['items'].delete_one({'_id': objectid.ObjectId(data['_id'])})

        if dbResult is None:
            return {
                "result": -1,
                "deleted": 0
            }

        return {
            "result": 0,
            "deleted": dbResult.deleted_count
        }

    def stop(self):
        Log.info("ItemsDatabase.stop()")

        if self.client is not None:
            self.client.close()

            self.started = False


import tensorflow as tf
import tensorflow.keras.backend as K
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.layers import Lambda, Input, Dense, BatchNormalization
from tensorflow.keras.models import Model,Sequential

inputs3d =  keras.layers.Input(shape=[80,80,80,1], name='cnn3d_inputs')

##### LVAE funcs #####
class sampler(keras.layers.Layer):
    def call(self, inputs):
        mu, sigma = inputs
        return K.random_normal(tf.shape(mu), seed=5) * sigma + mu

class vae_sampler(keras.layers.Layer):
    def __init__(self,size, activation=None, **kwargs):
        super().__init__(**kwargs)
        self.Dense_1 = Dense(size, kernel_initializer='zeros')  # mu
        self.Dense_2  = Dense(size, activation=activation, kernel_initializer='zeros')  # 2log_var
        self.sampler = sampler()

    def call(self, inputs):
        h = inputs
        mu = self.Dense_1(h)
        logsigma = self.Dense_2(h)
        logsigma = tf.clip_by_value(logsigma, 1e-7, 50)
        sigma = K.exp(logsigma)
        return self.sampler([mu, sigma]), mu, logsigma
    # 保存设置
    def get_config(self):
        base_config = super().get_config()
        return {**base_config}

class precision_weighted_sampler(keras.layers.Layer):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.sampler = sampler()
    def call(self, inputs):
        mu1, sigma1, mu2, sigma2 = inputs
        sigma1__2 = 1 / K.square(sigma1)
        sigma2__2 = 1 / K.square(sigma2)
        mu = ( mu1*sigma1__2 + mu2*sigma2__2 )/(sigma1__2 + sigma2__2)
        sigma = 1 / (sigma1__2 + sigma2__2)
        logsigma = K.log(sigma + 1e-7)
        z = self.sampler([mu, sigma])
        return z, mu, logsigma
    def get_config(self):
        base_config = super().get_config()
        return {**base_config}

class get_loss_kl(keras.layers.Layer):
    def call(self, inputs):
        d_mu, d_logsigma, p_mu, p_logsigma = inputs
        d_sigma = K.exp(d_logsigma)
        p_sigma = K.exp(p_logsigma)
        d_sigma2, p_sigma2 = K.square(d_sigma), K.square(p_sigma)
        _lambda = 10.
        Lzs = 0.5 * K.sum((K.square(d_mu) + d_sigma2) - 2 * d_logsigma - 0.5, 1)
        Lzs = tf.math.maximum(_lambda, Lzs)

        Lzs2 = 0.5 * K.sum( (K.square(d_mu - p_mu) + d_sigma2) / p_sigma2 - 2 * K.log((d_sigma / p_sigma) + 1e-7) - 0.5, 1)
        return K.mean(Lzs), K.mean(Lzs2)


class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        numsort=sorted(nums)
        left=0
        right=len(nums)-1
        while left < right:
            if numsort[left]+numsort[right]==target:
                leftindex=nums.index(numsort[left])
                nums[leftindex]='a'
                rightindex=nums.index(numsort[right])
                return [leftindex,rightindex]
            elif numsort[left]+numsort[right]<target:
                left+=1
            else:
                right-=1


l=[]
from os import system

def menu():
    ch=0
    while(ch<1 or ch>4):
        print("\n"*30)
        print("\n\n\n\n\n")
        print("\t\t\t1: Insert")
        print("\t\t\t2: Delete")
        print("\t\t\t3: Display")
        print("\t\t\t4: EXIT")
        ch=int(input("\n\t\t\tEnter your choice(1-4) : "))
    return ch

def insert():
    pos=int(input("\t\t\tEnter the Position:"))
    pos=pos-1
    if(pos>=0 and pos<=len(l)):
            item=int(input("\t\t\tEnter an item to insert"))
            l.insert(pos,item)
            print("\t\t\tItem ",item," inserted in the list")
    else:
            print("\t\t\tInvalid Position")

def Delete():
    if(l==[]):
        print("\t\t\tNO Item to Delete")
    else:
        pos=int(input("\t\t\tEnter the position"))
        pos=pos-1
        if(pos>=0 and pos< len(l)):
                item=l.pop(pos)
                print("\t\t\tItem ",item," Deleted from List")
        else:
                print("\t\t\tInvalid position")

def display():
    if(l==[]):
        print("\t\t\tEmpty List")
    else:
        print("\n\t\t\t",end="")
        for i in l:
            print(i," ",end="")

import sys
ch=0

while(ch!=4):
    ch=menu()
    if(ch==1):
        insert()
    elif(ch==2):
        Delete()
    elif(ch==3):
        display()
    elif(ch==4):
        print("\t\t\tAborting Program...........")
        sys.exit()
    av=input("\n\t\t\tPress any key to continue.....\n")


''' message function '''
from datetime import datetime as dt, timedelta, timezone
from server.help_server import getData, getUserFromToken, save, find_channel, find_message, inChannel
from server.help_server import AccessError, Value_Error

def add_message(channel_id, message_id, u_id, message, time_sent):
    ''' add a new message to data '''
    data = getData()
    data['messages'].append({'channel_id': channel_id, 'message_id': message_id,
                             'u_id': u_id, 'message': message,
                             'time_created': time_sent, 'reacts': [{'react_id': 1, 'u_ids': [], 'is_this_user_reacted': None}], 'is_pinned': False})
    return data

def get_new_message_id():
    ''' return a new message id '''
    data = getData()
    if len(data['messages']) == 0:
        return 0
    return (int(data['messages'][len(data['messages']) - 1]['message_id']) + 1)

def sendlater(token, channel_id, message, time_sent):
    ''' Send a message from authorised_user to the channel specified
    by channel_id automatically at a specified time in the future '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    right_channel_index = find_channel(channel_id)

    if type(time_sent) != dt:
        time_sent = dt.utcfromtimestamp(int(time_sent))

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    message_id = get_new_message_id()

    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if not inChannel(token, channel_id):
        raise AccessError("the authorised user has not joined the channel they are trying to post to")

    now = dt.utcnow()
    if now > time_sent:
        raise Value_Error("Time sent is a time in the past")

    data = add_message(channel_id, message_id, user['u_id'],  message, time_sent)

    save(data)
    return {'message_id': message_id}

def send(token, channel_id, message):
    ''' Send a message from authorised_user to the
    channel specified by channel_id '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    message_id = get_new_message_id()
    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if not inChannel(token, channel_id):
        raise AccessError("the authorised user has not joined the channel they are trying to post to")

    data = add_message(channel_id, message_id, user['u_id'], message, dt.utcnow())

    save(data)
    return {'message_id': message_id}

def remove(token, message_id):
    ''' Given a message_id for a message, this
    message is removed from the channel '''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    message_index = find_message(message_id)

    if message_index is None:
        raise Value_Error(f"Message (based on ID) no longer exists")
    message = data['messages'][message_index]

    if user['u_id'] != message['u_id'] and int(user['permission']) not in range(1, 3):
        raise Value_Error("Message with message_id was not sent by the authorised user making this request and The authorised user is not an admin or owner of this channel or the slackr")

    data['messages'].remove(message)
    save(data)
    return {}

def edit(token, message_id, message):
    ''' Given a message, update it's text with new text '''
    data = getData()
    user_dict = data['users'][getUserFromToken(token)]
    msg_dict = data['messages'][find_message(message_id)]

    if msg_dict['u_id'] != user_dict['u_id'] and user_dict['permission'] != 1 and user_dict['permission'] != 2:
        raise AccessError("Unauthorised user making edit request")

    msg_dict['message'] = message
    save(data)
    return {}

def react(token, message_id, react_id):
    ''' Given a message within a channel the authorised user is
    part of, add a "react" to that particular message '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_dict = data['messages'][find_message(message_id)]
    channel_id = msg_dict['channel_id']

    '''Check if the user is in this particular channel_id of the message'''
    user_channel_list = user_dict['user_channel']
    error_flag = 1
    for i in user_channel_list:
        if i['channel_id'] == channel_id:
            error_flag = 0

    if error_flag == 1:
        raise Value_Error("Not a valid message within a channel that the authorised user has joined")

    if react_id != 1:
        raise Value_Error("Not a valid react_id")

    reacts_list = msg_dict['reacts']

    if user_id in reacts_list[int(react_id) - 1]['u_ids']:
        raise Value_Error("Message already contains active react with the same react_id")

    reacts_list[int(react_id) - 1]['u_ids'].append(user_id)

    save(data)
    return {}

def unreact(token, message_id, react_id):
    ''' Given a message within a channel the authorised user is
    part of, remove a "react" to that particular message '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_dict = data['messages'][find_message(message_id)]
    reacts_list = msg_dict['reacts']
    channel_id = msg_dict['channel_id']

    '''Check if the user is in this particular channel_id of the message '''
    user_channel_list = user_dict['user_channel']
    error_flag = 1
    for i in user_channel_list:
        if i['channel_id'] == channel_id:
            error_flag = 0

    if error_flag == 1:
        raise Value_Error("Not a valid message within a channel that the authorised user has joined")

    if react_id != 1:
        raise Value_Error("Not a valid react_id")

    reacts_list = msg_dict['reacts']

    if user_id not in reacts_list[int(react_id) - 1]['u_ids']:
        raise Value_Error("Message with ID message_id does not contain an active React with ID react_id")

    reacts_list[int(react_id) - 1]['u_ids'].remove(user_id)
    save(data)
    return {}

def pin(token, message_id):
    ''' Given a message within a channel, mark it as "pinned" to
    be given special display treatment by the frontend '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_id = find_message(message_id)

    if msg_id is None:
        raise Value_Error("Message_Id is not a valid message")

    msg_dict = data['messages'][msg_id]

    if user_dict['permission'] == 3:
        raise Value_Error("The authorised user is not an admin")

    if not inChannel(token, msg_dict['channel_id']):
        raise AccessError("The authorised user is not a member of the channel that the message is within")

    if msg_dict['is_pinned'] is True:
        raise Value_Error(f"Message with ID message_id: {message_id} already pinned")

    msg_dict['is_pinned'] = True
    save(data)
    return {}

def unpin(token, message_id):
    ''' Given a message within a channel, remove it's mark as unpinned '''
    data = getData()
    user_id = getUserFromToken(token)
    user_dict = data['users'][user_id]
    msg_id = find_message(message_id)

    if msg_id is None:
        raise Value_Error("Message_Id is not a valid message")

    msg_dict = data['messages'][msg_id]

    if user_dict['permission'] is 3:
        raise Value_Error("Message with message_id was not sent by the authorised user making this request and The authorised user is not an admin or owner of this channel or the slackr")

    if not inChannel(token, msg_dict['channel_id']):
        raise AccessError("you need to be in the channel to pin the message")

    if msg_dict['is_pinned'] is False:
        raise Value_Error(f"Message with ID message_id: {message_id} already unpinned")

    msg_dict['is_pinned'] = False
    save(data)
    return {}

def standup_start(token, channel_id, length):
    '''For a given channel, start the standup period whereby for the
    next 15 minutes if someone calls "standup_send" with a message,
    it is buffered during the 15 minute window then at the end of the
    15 minute window a message will be added to the message queue in
    the channel from the user who started the standup.'''
    data = getData()
    right_channel_index = find_channel(channel_id)
    now_time = dt.utcnow()

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]

    if not inChannel(token, channel_id):
        raise AccessError('The authorised user is not a member of the channel that the message is within')

    if standup_active(token, channel_id)['is_active'] is False:
        time_finish = now_time + timedelta(seconds=int(length))
        message = sendlater(token, channel_id, '', time_finish)

        # update data
        data = getData()
        right_channel_index = find_channel(channel_id)
        right_channel = data['channels_list'][right_channel_index]
        right_channel['standup']['finish_time'] = time_finish
        right_channel['standup']['message_id'] = message['message_id']
    else:
        raise Value_Error('An active standup is currently running in this channel')

    save(data)
    return {'time_finish': time_finish.replace(tzinfo=timezone.utc).timestamp()}

def standup_active(token, channel_id):
    ''' For a given channel, return whether a standup is active in it,
    and what time the standup finishes. If no standup is active,
    then time_finish returns None '''
    data = getData()
    right_channel_index = find_channel(channel_id)

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]
    finish_time = right_channel['standup']['finish_time']
    is_active = True
    if right_channel['standup']['finish_time'] < dt.utcnow():
        is_active = False

    return {'is_active': is_active, 'time_finish': finish_time.replace(tzinfo=timezone.utc).timestamp()}

def standup_send(token, channel_id, message):
    '''Sending a message to get buffered in the standup queue,
    assuming a standup is currently active'''
    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]
    right_channel_index = find_channel(channel_id)

    if right_channel_index is None:
        raise Value_Error(f"Channel ID: {channel_id} is not a valid channel")

    right_channel = data['channels_list'][right_channel_index]

    if len(message) > 1000:
        raise Value_Error("Message is more than 1000 characters")

    if right_channel['standup']['finish_time'] < dt.utcnow():
        raise Value_Error('An active standup is not currently running in this channel')

    if not inChannel(token, channel_id):
        raise AccessError('The authorised user is not a member of the channel that the message is within')

    message_id = right_channel['standup']['message_id']
    msg_id = find_message(message_id)
    old_message = data['messages'][msg_id]['message']
    old_message += str(user['handle']) + ': ' + message + ' '
    edit(token, message_id, old_message)

    # update data after edit
    data = getData()
    save(data)
    return {}

def search(token, query_str):
    '''Given a query string, return a collection of
    message_list that match the query'''
    if query_str == '':
        return {'messages': []}

    data = getData()
    user_id = getUserFromToken(token)
    user = data['users'][user_id]

    search_list = []
    for user_channel in user['user_channel']:
        for message_info in data['messages']:
            if int(message_info['channel_id']) == int(user_channel['channel_id']) and int(message_info['u_id']) == user_id:
                if str(query_str) in str(message_info['message']):
                    message_info['time_created'] = message_info['time_created'].replace(tzinfo=timezone.utc).timestamp()
                    for reaction in message_info['reacts']:
                        reaction['is_this_user_reacted'] = (user_id in reaction['u_ids'])
                    search_list.append(message_info)
    return {'messages': search_list}


import numpy as np
from scipy import signal

from guidedfilter_MLRI import guidedfilter_MLRI

def interpolation(green, mosaic_color, mask_color, eps):
    # parameters for guided upsampling
    h, v = 5, 5
    # Laplacian
    F = np.array(
        [
            [0, 0, -1, 0, 0],
            [0, 0, 0, 0, 0],
            [-1, 0, 4, 0, -1],
            [0, 0, 0, 0, 0],
            [0, 0, -1, 0, 0],
        ]
    )

    # R interpolation
    tentative = guidedfilter_MLRI(
        green, mosaic_color, mask_color,
        signal.convolve2d(green * mosaic_color, F, mode="same"),
        signal.convolve2d(mosaic_color, F, mode="same"),
        mask_color, h, v, eps,
    )
    residual = mask_color * (mosaic_color - tentative)
    # Bilinear interpoaltion
    H = np.array([[1 / 4, 1 / 2, 1 / 4], [1 / 2, 1, 1 / 2], [1 / 4, 1 / 2, 1 / 4]])
    residual = signal.convolve2d(residual, H, mode="same")
    return residual + tentative


"""Read cf-json spectra files."""
import json

import dateutil
import xarray as xr

from wavespectra.core.attributes import attrs, set_spec_attributes
from wavespectra.specdataset import SpecDataset

def read_cf_json(filename):
    """Read Spectra from cf-json format from MSL spectra API.

    Args:
        - filename (str): name of cf-json file to read.

    Returns:
        - dset (SpecDataset): spectra dataset object read from json file.

    """
    with open(filename, "r") as stream:
        spec_dict = json.load(stream)

    data = {}
    for varname, vardata in spec_dict["variables"].items():
        dims = vardata.get("shape", [])
        if varname == "time":
            attrs = {}
            vals = to_datetime(vardata["data"])
        else:
            attrs = vardata["attributes"]
            vals = vardata["data"]
        data.update({varname: (dims, vals, attrs)})
    return xr.Dataset(data)

def to_datetime(times):
    return [dateutil.parser.parse(t) for t in times]


n = int(input())

li = [0] * 301 # 계단을 입력받을 배열
result = [0] * 301 # 계단의 합의 최대값을 구할 배열

for i in range(n):
    li[i]=int(input())

result[0] = li[0]  # 첫 번째 계단은 항상 최대값
result[1] = li[0] + li [1] # 두 번쨰 계단도 항상 첫번째와 두번째 계단을 더한 값이 최대값
result[2] = max(li[1]+li[2], li[0]+li[2]) # 3번째 계단은 두번째계단 + 세 번째 계단 또는 첫번째 계단 + 세번째 계단

for i in range(3,n): # 4번째부터는 조건에 맞게 배열에 저장한다.
    result[i] = max(result[i-3]+li[i-1]+li[i],result[i-2] + li[i])
print(result[n-1])


def findMaximumBefore(arr, n):

    # Loop to iterate over every
    # element of the array
    for i in range(n):

        currAns = -1

        # Loop to find the maximum smallest
        # number before the element arr[i]
        for j in range(i-1,-1,-1):
            if (arr[j] > currAns and
                arr[j] < arr[i]):
                currAns = arr[j]

        print(currAns,end=" ")

# Driver Code
if __name__ == '__main__':

    arr=[4, 7, 6, 8, 5 ]

    n = len(arr)

    # Function Call
    findMaximumBefore(arr, n)


import json
import argparse
import os
import numpy as np
from parse import parse
from glob import glob
from typing import List, Dict
from progressbar import ProgressBar
import pandas as pd
import json
import re
import math
import matplotlib.pyplot as plt
import time

"""Sets the sender pseudonym as sender ID for sybil attack scenarios and protocol level attacks"""

INITIAL_TRUST = 0.5
AGING_FACTOR=0.5

def vehicleParser(json_file, path_to_json,attacker_dict_ground_truth):
    log_name_tokens = os.path.splitext(json_file)[0].split("-")
    vehicle_id = log_name_tokens[1]  # [0]:= 'JSONlog' [1]:=vehicle instance count [2]:=vehicle id [1]:=vehicle attack type
    vehicle_OMNET_ID = log_name_tokens[2]  # [0]:= 'JSONlog' [1]:=vehicle instance count [2]:=vehicle id [1]:=vehicle attack type

    attack_type = log_name_tokens[3]
    if attack_type == 'A0':
        is_vehicle_attacker = 0
    else:
        is_vehicle_attacker = 1

    # start parsing the file
    BSMList = [] # received BSM messages
    GPSList=[] # own gps messages

    file_path = os.path.join(path_to_json, json_file)
    with open(file_path, "r") as f:
        log_rows = f.readlines()

    for row in log_rows:
        json_row = json.loads(row)
        json_row['vehicle_ID'] = vehicle_id  # set here, change later
        # json_row['vehicle_OMNET_ID'] = vehicle_OMNET_ID
        json_row['is_attacker'] = is_vehicle_attacker
        if json_row['type'] == 2: # discard the self GPS messages
            # gps_row = json_row

            # extract position
            json_row['pos_x'] = json_row['pos'][0]
            json_row['pos_y'] = json_row['pos'][1]
            #json_row['pos_z'] = json_row['pos'][2]
            del json_row['pos']

            # extract speed
            json_row['spd_x'] = json_row['spd'][0]
            json_row['spd_y'] = json_row['spd'][1]
            #json_row['spd_z'] = json_row['spd'][2]
            del json_row['spd']

            # extract position noise
            json_row['pos_x_noise'] = json_row['pos_noise'][0]
            json_row['pos_y_noise'] = json_row['pos_noise'][1]
            #json_row['pos_z_noise'] = json_row['pos_noise'][2]
            del json_row['pos_noise']

            # extract spd noise
            json_row['spd_x_noise'] = json_row['spd_noise'][0]
            json_row['spd_y_noise'] = json_row['spd_noise'][1]
            #json_row['spd_z_noise'] = json_row['spd_noise'][2]
            del json_row['spd_noise']

            # Acceleration
            json_row['accel_x'] = json_row['acl'][0]
            json_row['accel_y'] = json_row['acl'][1]
            #json_row['accel_z'] = json_row['acl'][2]
            del json_row['acl']

            # Heading
            json_row['heading_x'] = json_row['hed'][0]
            json_row['heading_y'] = json_row['hed'][1]
            #json_row['heading_z'] = json_row['hed'][2]
            del json_row['hed']

            # heading noise
            json_row['heading_x_noise'] = json_row['hed_noise'][0]
            json_row['heading_y_noise'] = json_row['hed_noise'][1]
            # json_row['heading_z'] = json_row['hed'][2]
            del json_row['hed_noise']

            # remove unnecessary columns
            del json_row['acl_noise']
            del json_row['type']
            #del json_row['hed_noise']

            # add new dict to list
            GPSList.append(json_row)

        else:

            # extract position
            json_row['pos_x'] = json_row['pos'][0]
            json_row['pos_y'] = json_row['pos'][1]
            #json_row['pos_z'] = json_row['pos'][2]
            del json_row['pos']

            # extract speed
            json_row['spd_x'] = json_row['spd'][0]
            json_row['spd_y'] = json_row['spd'][1]
            #json_row['spd_z'] = json_row['spd'][2]
            del json_row['spd']

            # extract position noise
            json_row['pos_x_noise'] = json_row['pos_noise'][0]
            json_row['pos_y_noise'] = json_row['pos_noise'][1]
            #json_row['pos_z_noise'] = json_row['pos_noise'][2]
            del json_row['pos_noise']

            # extract spd noise
            json_row['spd_x_noise'] = json_row['spd_noise'][0]
            json_row['spd_y_noise'] = json_row['spd_noise'][1]
            #json_row['spd_z_noise'] = json_row['spd_noise'][2]
            del json_row['spd_noise']

            # Acceleration
            json_row['accel_x'] = json_row['acl'][0]
            json_row['accel_y'] = json_row['acl'][1]
            #json_row['accel_z'] = json_row['acl'][2]
            del json_row['acl']

            # Heading
            json_row['heading_x'] = json_row['hed'][0]
            json_row['heading_y'] = json_row['hed'][1]
            #json_row['heading_z'] = json_row['hed'][2]
            del json_row['hed']

            # heading noise
            json_row['heading_x_noise'] = json_row['hed_noise'][0]
            json_row['heading_y_noise'] = json_row['hed_noise'][1]
            # json_row['heading_z'] = json_row['hed'][2]
            del json_row['hed_noise']

            # remove unnecessary columns
            del json_row['acl_noise']
            del json_row['sendTime']
            del json_row['type']
            # del json_row['senderPseudo']
            del json_row['messageID']
            #del json_row['hed_noise']

            # add new dict to list
            BSMList.append(json_row)

    # creat gps df
    GPS_df = pd.DataFrame(GPSList)
    if not GPS_df.empty:
        GPS_df = GPS_df.sort_values(["rcvTime"])

    # create bsm df
    BSM_df = pd.DataFrame(BSMList)
    if not BSM_df.empty:
        BSM_df = BSM_df.sort_values(["senderPseudo", "rcvTime"])

    # trust_dict= assignTrust(BSM_df=BSM_df,GPS_df=GPS_df)

    return GPS_df,BSM_df

def plausibilityParser(vehicle_ID,vehicle_plausibility_record):

    file_path =vehicle_plausibility_record
    f = open(file_path, )

    data = json.load(f)

    data_list = []
    for row in data:
        json_row = {}

        json_row['vehicle_ID'] = vehicle_ID  # set here, change later

        json_row['sender'] = row['BsmPrint']['BSMs'][0]['RealId']

        json_row['rcvTime'] = row['BsmPrint']['BSMs'][0]['ArrivalTime']

        json_row['proximityPlausibility'] = row['BsmPrint']['BsmCheck']['rpP']

        json_row['rangePlausibility'] = row['BsmPrint']['BsmCheck']['rP']

        json_row['PositionPlausibility'] = row['BsmPrint']['BsmCheck']['pP']

        json_row['SpeedPlausibility'] = row['BsmPrint']['BsmCheck']['sP']

        json_row['PositionConsistancy'] = row['BsmPrint']['BsmCheck']['pC']

        json_row['SpeedConsistancy'] = row['BsmPrint']['BsmCheck']['sC']

        json_row['PositionSpeedConsistancy'] = row['BsmPrint']['BsmCheck']['psC']

        json_row['PositionSpeedMaxConsistancy'] = row['BsmPrint']['BsmCheck']['psmC']

        json_row['PositionHeadingConsistancy'] = row['BsmPrint']['BsmCheck']['phC']

        json_row['SuddenAppearence'] = row['BsmPrint']['BsmCheck']['sA']

        json_row['BeaconFrequency'] = row['BsmPrint']['BsmCheck']['bF']

        data_list.append(json_row)

    # create bsm df
    BSM_df = pd.DataFrame(data_list)
    if not BSM_df.empty:
        BSM_df = BSM_df.sort_values(["sender", "rcvTime"])

    return BSM_df

def vehicleIDfromPlausibility(filename):

    name_components = re.split('_', os.path.splitext(filename)[0])

    vehicle_ID = name_components[2]

    # remove first "10" and last "1" to get the real ID of vehicles
    vehicle_ID =vehicle_ID[2:]
    vehicle_ID=vehicle_ID[:-1]

    return vehicle_ID

def parsePlausibilityRecords(plausibility_path):

    vehicle_records= os.listdir(plausibility_path)
    big_df = pd.DataFrame()

    for vehicle_plausibility_record in vehicle_records:

        vehicle_ID = vehicleIDfromPlausibility(vehicle_plausibility_record)

        cur_file = os.path.join(plausibility_path,vehicle_plausibility_record)
        parsed_df = plausibilityParser(vehicle_ID,cur_file)
        big_df = pd.concat([big_df, parsed_df], axis=0, ignore_index=True)

    return big_df

def mergePlausibility(plausibility_records,BSM_records):

    # from the beginning of time step
    plausibility_records['rcvTime'] = plausibility_records['rcvTime'].apply(np.floor)
    BSM_records['rcvTime'] = BSM_records['rcvTime'].apply(np.floor)

    trust_records = createTrustRecords(plausibility_records)

    all_data = pd.merge(BSM_records, trust_records, how='left', left_on=['vehicle_ID', 'senderPseudo', 'rcvTime'], right_on=['vehicle_ID', 'senderPseudo', 'rcvTime'])

    return all_data

    pass

def calculateTrust(sender,receiver,messages):

    considered_modules= ["rangePlausibility","positionConsistency","speedConsistency","positionSpeedConsistancy","positionHeadingConsistancy"]

    num_modules = len(considered_modules)
    module_weights = [1/num_modules]*num_modules # equal weights for all for now
    initial_trust= INITIAL_TRUST
    aging_factor = AGING_FACTOR

    # sort by message receiving time for time-based records
    trust_records = {}

    for index,row in messages.iterrows():
        cur_time = row['rcvTime']

        # find the prev trust
        if trust_records.keys() and (min(trust_records.keys())) < cur_time:

            # previous record exists, find the latest record
            max_time = max(trust_records.keys())
            prev_trust = trust_records[max_time]
        else:

            # no records exist
            prev_trust= initial_trust

        ## calculate the current step trust contribution
        current_step_score = 0
        for i,module in enumerate(considered_modules):
            current_step_score += module_weights[i] * row[module]

        # age the trust
        eventual_trust = aging_factor*prev_trust + (1-aging_factor) * current_step_score
        trust_records[cur_time] = eventual_trust

    # convert to data frame and merge
    trust_df = pd.DataFrame.from_dict(trust_records, orient='index',
                           columns=['Trust'])
    trust_df['rcvTime'] =trust_df.index
    trust_df.sort_values(['rcvTime'])

    new_messages = pd.merge(messages, trust_df, how='left', left_on=['rcvTime'], right_on=['rcvTime'])
    return new_messages

def trustEvolutionForReceiver(receiver_ID,records):

    sender_list = records['senderPseudo'].unique()
    g = records.groupby(["senderPseudo"])

    big_df = pd.DataFrame()

    for sender in sender_list:
        sender_records = g.get_group(sender)

        trust_records = calculateTrust(sender=sender,receiver=receiver_ID,messages=sender_records)
        pass

        big_df = pd.concat([big_df, trust_records], axis=0, ignore_index=True)

    return big_df

def createTrustRecords(plausibility_records):

    receiver_vehicles = plausibility_records['vehicle_ID'].unique()
    g = plausibility_records.groupby(['vehicle_ID'])

    big_df = pd.DataFrame()

    for receiver_vehicle in receiver_vehicles:
        current_records = g.get_group(receiver_vehicle)
        receiver_trust = trustEvolutionForReceiver(receiver_vehicle,current_records)

        big_df = pd.concat([big_df, receiver_trust], axis=0, ignore_index=True)

    return big_df

def parseSim(data_folder,output_path):
    print("Current data folder: "+data_folder)

    folder_list = os.listdir(data_folder)
    plausibility_path = None

    for folder in folder_list:
        if "MDBsmsList" in folder:
            plausibility_path = os.path.join(data_folder,folder)
        if "VeReMi" in folder:
            path_to_json = os.path.join(data_folder,folder)

    if plausibility_path:
        plausibility_records = parsePlausibilityRecords(plausibility_path=plausibility_path)

    else:
        # extract some plausibilties here
        pass

    """Find the json files"""

    json_files = [pos_json for pos_json in os.listdir(path_to_json) if
                  (pos_json.endswith('.json') and pos_json.startswith('traceJSON'))]

    ground_truth_file_path = [pos_json for pos_json in os.listdir(path_to_json) if
                              (pos_json.endswith('.json') and pos_json.startswith('traceGroundTruth'))]

    # json_files=json_files[:10] # remove later
    # start parsing

    big_df = pd.DataFrame()
    plausibility_records=pd.DataFrame()
    for json_file in json_files:
        GPS_df,BSM_df = vehicleParser(json_file, path_to_json,
                                  {})  # .sort_values(["sender","rcvTime"])

        if len(BSM_df)<1:
            continue # do not append anything from here

        plausibilities= createPlausibilities(GPS_df=GPS_df,BSM_df=BSM_df)

        big_df = pd.concat([big_df, BSM_df], axis=0, ignore_index=True)
        plausibility_records=pd.concat([plausibility_records,plausibilities], axis=0, ignore_index=True)

    # rename if wrong name
    if 'vehicle_ID_bsm' in plausibility_records.columns:
        plausibility_records.rename(columns={"vehicle_ID_bsm": "vehicle_ID"}, inplace=True)

    big_df = mergePlausibility(plausibility_records=plausibility_records,BSM_records=big_df)

    # drop noise columns before saving
    big_df.drop(list(big_df.filter(regex="noise")),axis=1,inplace=True)
    if 'sender_x' in big_df.columns:
        big_df.rename(columns={"sender_x": "sender"}, inplace=True)
        big_df.drop(['sender_y'],axis=1,inplace=True)

    # make the export file name
    dir_lst = data_folder.split(sep="/")
    exportfilename=os.path.join(output_path,dir_lst[1] + "_" + "parsed.csv")
    big_df.to_csv(index=False, path_or_buf=exportfilename)

    return big_df

def createPlausibilities(GPS_df,BSM_df):
    """
    Extract the palusibilities and append to BSM_df for additional features
    Args:
        GPS_df:
        BSM_df:

    Returns:

    """

    TOTAL_TIME=0
    NUM_MESSAGES=0

    MAX_PLAUSIBLE_RANGE = 420

    # get all unique senders in session
    all_senders = BSM_df['senderPseudo'].unique()

    BSM_df['rcvTime'] = BSM_df['rcvTime'].apply(np.floor)

    big_df_merged = pd.DataFrame()

    non_records = 0
    for sender in all_senders:

        sender_records = BSM_df[BSM_df['senderPseudo'] == sender]

        # align time vectors
        sliced_GPS_df= GPS_df[GPS_df.rcvTime.isin(sender_records.rcvTime)]
        merged= sender_records.merge(sliced_GPS_df,left_on='rcvTime',right_on='rcvTime',suffixes=('_bsm','_gps'))

        for index,row in merged.iterrows():

            try:
                # range plausibility
                merged.loc[index,'rangePlausibility']=rangePlausibility(sender_records.iloc[index],sliced_GPS_df.iloc[index])
            except:
                # range plausibility
                merged.loc[index, 'rangePlausibility'] = INITIAL_TRUST
                print("SYBIL,NON EXISTENT RECORD,initial trust value\n")
                non_records+=1

            if index==0:
                merged.loc[index, 'positionConsistency'] = INITIAL_TRUST #positionConsistencyCheck(row, oldRow)

                merged.loc[index, 'speedConsistency'] = INITIAL_TRUST # speedConsistencyCheck(row, oldRow)

                # position speed check
                merged.loc[index, 'positionSpeedConsistancy'] =INITIAL_TRUST # positionSpeedConsistancyCheck(row, oldRow)

                # position heading check
                merged.loc[index, 'positionHeadingConsistancy'] = INITIAL_TRUST # PositionHeadingConsistancyCheck(row, oldRow)

            else:

                oldRow =merged.loc[index-1]
                # speed and position consistency

                start = time.time()

                merged.loc[index, 'positionConsistency'] = positionConsistencyCheck(row,oldRow)

                merged.loc[index, 'speedConsistency'] = speedConsistencyCheck(row,oldRow)

                #position speed check
                merged.loc[index, 'positionSpeedConsistancy'] = positionSpeedConsistancyCheck(row, oldRow)

                # position heading check
                merged.loc[index, 'positionHeadingConsistancy'] = PositionHeadingConsistancyCheck(row, oldRow)

                end = time.time()
                current_elapsed_time = end - start
                TOTAL_TIME += current_elapsed_time
                NUM_MESSAGES+=1
                #print("Calculating trust: " + " took" + str(current_elapsed_time) + " seconds")

        #print("Average Time:" + str(TOTAL_TIME / NUM_MESSAGES))

        big_df_merged = pd.concat([big_df_merged,merged], axis=0, ignore_index=True)

    plausibilities= big_df_merged[["rcvTime","sender","senderPseudo","vehicle_ID_bsm","positionHeadingConsistancy","positionSpeedConsistancy","speedConsistency","positionConsistency","rangePlausibility"]]
    #BSM_df.reset_index(inplace=True,drop=True)
    #BSM_df=BSM_df.join(plausibilities)
    # print(non_records)
    return plausibilities #BSM_df

PI=math.pi

def PositionHeadingConsistancyCheck(row,oldRow):

    """
    (veins::Coord* curHeading,
    veins::Coord* curHeadingConfidence, veins::Coord* oldPosition,
    veins::Coord* oldPositionConfidence, veins::Coord* curPosition,
    veins::Coord* curPositionConfidence, double deltaTime, double curSpeed,
    double curSpeedConfidence):
    """

    POS_HEADING_TIME = 1.1
    MAX_HEADING_CHANGE = 90

    curHeading =calculateHeadingAngle(row)
    curHeadingConfidence=0
    oldPositionConfidence=calculatePositionConf(oldRow)
    curPositionConfidence=calculatePositionConf(row)
    deltaTime= np.abs(row.rcvTime - oldRow.rcvTime)
    curSpeed=calculateSpeedPtr(row)
    curSpeedConfidence=calculateSpeedConf(row)

    if (deltaTime < POS_HEADING_TIME):
        distance = calculateDistancePtr(row,oldRow);
        if (distance < 1):
            return 1;

        if (curSpeed - curSpeedConfidence < 1):
            return 1;

        curHeadingAngle = curHeading#calculateHeadingAnglePtr(curHeading);

        #relativePos = (curPosition->x - oldPosition->xcurPosition->y - oldPosition->y,curPosition->z - oldPosition->z);
        positionAngle = calculateHeadingAnglePtr(row.pos_x_bsm-oldRow.pos_x_bsm,row.pos_y_bsm-oldRow.pos_y_bsm);
        angleDelta = np.abs(curHeadingAngle - positionAngle);

        if (angleDelta > 180):
            angleDelta = 360 - angleDelta;

        angleLow = angleDelta - row.heading_x_noise_bsm;
        if (angleLow < 0):
            angleLow = 0;

        angleHigh = angleDelta + row.heading_x_noise_bsm;
        if (angleHigh > 180):
            angleHigh = 180;

        xLow = distance * np.cos(angleLow * PI / 180);

        curFactorLow = 1;
        if (row.heading_x_noise_bsm == 0):
            if (angleLow <= MAX_HEADING_CHANGE):
                curFactorLow = 1;

            else:
                curFactorLow = 0;

        else:
            curFactorLow =calculateCircleSegment(row.pos_x_noise_bsm,
                                                 row.pos_x_noise_bsm + xLow) /(PI * row.pos_x_noise_bsm * row.pos_x_noise_bsm);

        oldFactorLow = 1;
        if (oldRow.pos_x_noise_bsm == 0):
            if (angleLow <= MAX_HEADING_CHANGE):
                oldFactorLow = 1;

            else:
                oldFactorLow = 0;

        else:
            oldFactorLow = 1 - calculateCircleSegment(oldRow.pos_x_noise_bsm,oldRow.pos_x_noise_bsm - xLow) / (PI * oldRow.pos_x_noise_bsm * oldRow.pos_x_noise_bsm);

        xHigh = distance * np.cos(angleHigh * PI / 180);
        curFactorHigh = 1;
        if (row.pos_x_noise_bsm == 0):
            if (angleHigh <= MAX_HEADING_CHANGE):
                curFactorHigh = 1;

            else:
                curFactorHigh = 0;

        else:
            curFactorHigh =calculateCircleSegment(row.pos_x_noise_bsm,
                    row.pos_x_noise_bsm + xHigh) / (PI * row.pos_x_noise_bsm * row.pos_x_noise_bsm);

        oldFactorHigh = 1;
        if (oldRow.pos_x_noise_bsm == 0):
            if (angleHigh <= MAX_HEADING_CHANGE):
                oldFactorHigh = 1;

            else:
                oldFactorHigh = 0;

        else:
            oldFactorHigh = 1 - calculateCircleSegment(oldRow.pos_x_noise_bsm, oldRow.pos_x_noise_bsm - xHigh) / (PI * oldRow.pos_x_noise_bsm * oldRow.pos_x_noise_bsm);

        factor = (curFactorLow + oldFactorLow + curFactorHigh + oldFactorHigh) / 4;

        return factor;

    else:
        return 1; # 1

def calculateHeadingAnglePtr(heading_x_bsm,heading_y_bsm):
    x2 = 1;
    y2 = 0;

    dot = heading_x_bsm * x2 + heading_y_bsm * y2; # dot product between [x1, y1] and [x2, y2]
    det =heading_x_bsm  * y2 - heading_y_bsm * x2;      # determinant
    angle = np.arctan2(det, dot) * 180 / PI; # atan2(y, x) or atan2(sin, cos);

    if (heading_x_bsm  >= 0 and heading_y_bsm  > 0):
        angle = 360 + angle;
    elif (heading_x_bsm < 0 and heading_y_bsm  >= 0):
        angle = 360 + angle;

    return angle;

def calculateHeadingAngle(row):
    x2 = 1;
    y2 = 0;

    dot = row.heading_x_bsm * x2 + row.heading_y_bsm * y2; # dot product between [x1, y1] and [x2, y2]
    det =row.heading_x_bsm  * y2 - row.heading_y_bsm * x2;      # determinant
    angle = np.arctan2(det, dot) * 180 / PI; # atan2(y, x) or atan2(sin, cos);

    if (row.heading_x_bsm  >= 0 and row.heading_y_bsm  > 0):
        angle = 360 + angle;
    elif (row.heading_x_bsm < 0 and row.heading_y_bsm  >= 0):
        angle = 360 + angle;

    return angle;

def positionSpeedConsistancyCheck(row,oldRow):
    MAX_TIME_DELTA = 3.1

    MAX_MGT_RNG_DOWN = 6.2
    MAX_MGT_RNG_UP = 2.1

    MAX_PLAUSIBLE_ACCEL=2.6
    MAX_PLAUSIBLE_DECEL = 4.5

    MAX_PLAUSIBLE_SPEED=15
    MAX_PLAUSIBLE_RANGE=420

    speedDelta = calculateSpeedPtr(row) - calculateSpeedPtr(oldRow)

    curSpeed = calculateSpeedPtr(row)
    oldspeed = calculateSpeedPtr(oldRow)

    time= np.abs(row.rcvTime - oldRow.rcvTime)
    curSpeedConfidence=calculateSpeedConf(row)
    oldSpeedConfidence=calculateSpeedConf(oldRow)

    if (time < MAX_TIME_DELTA):
        distance = calculateDistancePtr(row, oldRow);

        curTest_1 = calculateSpeedPtr(row) + curSpeedConfidence;
        oldTest_1 = calculateSpeedPtr(oldRow) - oldSpeedConfidence;

        curTest_2 = calculateSpeedPtr(row) - curSpeedConfidence;
        oldTest_2 = calculateSpeedPtr(oldRow) + oldSpeedConfidence;

        if (curTest_2 < oldTest_2):
            curTest_2 = (curSpeed + oldspeed) / 2;
            oldTest_2 = (curSpeed + oldspeed) / 2;

        minSpeed = min(curSpeed, oldspeed);

        addon_mgt_range = MAX_MGT_RNG_DOWN + 0.3571 * minSpeed - 0.01694 * minSpeed * minSpeed;
        if (addon_mgt_range < 0):
            addon_mgt_range = 0;

        retDistance_1= [0]*2;
        calculateMaxMinDist(curTest_1, oldTest_1, time,MAX_PLAUSIBLE_ACCEL, MAX_PLAUSIBLE_DECEL, MAX_PLAUSIBLE_SPEED,
            retDistance_1);

        factorMin_1 = 1 - CircleCircleFactor(distance, row.pos_x_noise_bsm, oldRow.pos_x_noise_bsm, retDistance_1[0]);
        factorMax_1 = OneSidedCircleSegmentFactor(distance,row.pos_x_noise_bsm,oldRow.pos_x_noise_bsm,
            retDistance_1[1] + MAX_MGT_RNG_UP)

        retDistance_2 = [0] *2
        calculateMaxMinDist(curTest_2, oldTest_2, time,
            MAX_PLAUSIBLE_ACCEL, MAX_PLAUSIBLE_DECEL, MAX_PLAUSIBLE_SPEED,
            retDistance_2);
        factorMin_2 = 1 - OneSidedCircleSegmentFactor(distance, row.pos_x_noise_bsm,oldRow.pos_x_noise_bsm, retDistance_2[0] - addon_mgt_range);
        factorMax_2 = OneSidedCircleSegmentFactor(distance,
            row.pos_x_noise_bsm,oldRow.pos_x_noise_bsm,
            retDistance_2[1] + MAX_MGT_RNG_UP);

        retDistance_0= [0]*2
        calculateMaxMinDist(curSpeed, oldspeed, time,
            MAX_PLAUSIBLE_ACCEL, MAX_PLAUSIBLE_DECEL, MAX_PLAUSIBLE_SPEED,
            retDistance_0);
        factorMin_0 = 1 - OneSidedCircleSegmentFactor(distance, row.pos_x_noise_bsm, oldRow.pos_x_noise_bsm, retDistance_0[0] - addon_mgt_range);
        factorMax_0 = OneSidedCircleSegmentFactor(distance,
            row.pos_x_noise_bsm,oldRow.pos_x_noise_bsm,
            retDistance_0[1] + MAX_MGT_RNG_UP);

        factorMin = (factorMin_1 + factorMin_0 + factorMin_2) / 3.0;
        factorMax = (factorMax_1 + factorMax_0 + factorMax_2) / 3.0;

        return min(factorMin, factorMax);

    else:
        return INITIAL_TRUST # 1

PI =math.pi

def OneSidedCircleSegmentFactor(d, r1, r2,range):

    if (d < 0):
        return 1;

    if (range > d + r1 + r2):
        return 1;
    else:
        if (range < d - r1 - r2):
            return 0;
        else:
            d1 = 0;
            d2 = 0;
            if (d > 0):
                d1 = (r1 * r1 + d * d - r2 * r2) / (2 * d);
                d2 = (r2 * r2 + d * d - r1 * r1) / (2 * d);
                if ((d1 + r1) < range / 2 and (d2 + r2) > range / 2):
                    d2 = d2 - (range / 2 - (d1 + r1));
                    d1 = d1 + (range / 2 - (d1 + r1));

                if ((d2 + r2) < range / 2 and (d1 + r1) > range / 2):
                    d1 = d1 - (range / 2 - (d2 + r2));
                    d2 = d2 + (range / 2 - (d2 + r2));

            if (r1 <= 0 and r2 <= 0):
                if (range >= d):
                    return 1;
                else:
                    return 0;

            elif (r1 <= 0):
                if (range / 2 >= d1):
                    intD2 = (range / 2) - (d2 - r2);
                    area2 = calculateCircleSegment(r2, intD2);

                    factor = (area2) / (PI * r2 * r2);
                    return factor;
                else:
                    return 0;

            elif (r2 <= 0):
                if (range / 2 >= d2):
                    intD1 = (range / 2) - (d1 - r1);
                    area1 = calculateCircleSegment(r1, intD1);

                    factor = (area1) / (PI * r1 * r1);

                    return factor;
                else:
                    return 0;

            else:

                intD1 = (range / 2) - (d1 - r1);
                intD2 = (range / 2) - (d2 - r2);

                area1 = calculateCircleSegment(r1, intD1);
                area2 = calculateCircleSegment(r2, intD2);

                factor = (area1 + area2) / (PI * r1 * r1 + PI * r2 * r2);

                return factor;

def calculateCircleSegment(radius, intDistance):
    area = 0;

    if (radius <= 0):
        return 0;

    if (intDistance <= 0):
        return 0;

    if (intDistance > 2 * radius):
        return PI * radius * radius;

    if (radius > intDistance):
        area = radius * radius * SafeAcos((radius - intDistance) / radius)- (radius - intDistance)* math.sqrt(
                                2 * radius * intDistance
                                        - intDistance * intDistance);
    else:
        intDistanceTemp = 2 * radius - intDistance;
        area = radius * radius * SafeAcos((radius - intDistanceTemp) / radius)- (radius - intDistanceTemp)* math.sqrt(
                                2 * radius * intDistanceTemp
                                        - intDistanceTemp * intDistanceTemp);
        area = PI * radius * radius - area;

    return area;

def SafeAcos(x):
    if (x < -1.0):
        x = -1.0;
    elif (x > 1.0):
        x = 1.0;
    return np.arccos(x);

def CircleCircleFactor(d, r1, r2,range):

    d1 = 0;
    d2 = 0;
    if (d > 0):
        d1 = (r1 * r1 + d * d - r2 * r2) / (2 * d);
        d2 = (r2 * r2 + d * d - r1 * r1) / (2 * d);

        if ((d1 + r1) < range / 2 and (d2 + r2) > range / 2):
            d2 = d2 - (range / 2 - (d1 + r1));
            d1 = d1 + (range / 2 - (d1 + r1));

        if ((d2 + r2) < range / 2 and (d1 + r1) > range / 2):
            d1 = d1 - (range / 2 - (d2 + r2));
            d2 = d2 + (range / 2 - (d2 + r2));

    if (r1 <= 0 and r2 <= 0):
        if (range >= d):
            return 1;
        else:
            return 0;

    elif (r1 <= 0):
        if (range / 2 >= d1):
            area2 = calculateCircleCircleIntersection(r2, range / 2, d2);
            factor = (area2) / (math.pi * r2 * r2);
            return factor;
        else:
            return 0;

    elif (r2 <= 0) :
        if (range / 2 >= d2):
            area1 = calculateCircleCircleIntersection(r1, range / 2, d1);
            factor = (area1) / (math.pi * r1 * r1);
            return factor;
        else:
            return 0;

    else:
        area1 = calculateCircleCircleIntersection(r1, range / 2, d1);
        area2 = calculateCircleCircleIntersection(r2, range / 2, d2);
        factor = (area1 + area2) / (math.pi * r1 * r1 + math.pi * r2 * r2);
        return factor;

def calculateCircleCircleIntersection(r0,r1,d):

    if (r0 <= 0 or r1 <= 0):
        return 0;

    rr0 = r0 * r0;
    rr1 = r1 * r1;

    # Circles do not overlap
    if (d > r1 + r0):
        return 0;

    # Circle1 is completely inside circle0
    elif (d <= np.abs(r0 - r1) and r0 >= r1):
        # Return area of circle1
        return math.pi * rr1;

# Circle0 is completely inside circle1
    elif (d <= np.abs(r0 - r1) and r0 < r1):
        #Return area of circle0
        return math.pi * rr0;

    else:
        phi = (SafeAcos((rr0 + (d * d) - rr1) / (2 * r0 * d))) * 2;
        theta = (SafeAcos((rr1 + (d * d) - rr0) / (2 * r1 * d))) * 2;
        area1 = 0.5 * theta * rr1 - 0.5 * rr1 * np.sin(theta);
        area2 = 0.5 * phi * rr0 - 0.5 * rr0 * np.sin(phi);

# Return area of intersection
        return area1 + area2;

def calculateMaxMinDist(curSpeed, oldspeed, time,MAX_PLAUSIBLE_ACCEL,MAX_PLAUSIBLE_DECEL,MAX_PLAUSIBLE_SPEED,returnDistance):

    if(curSpeed<0):
        curSpeed = 0;

    if(oldspeed<0):
        oldspeed = 0;

    deltaV = curSpeed - oldspeed;

    T_1 = (deltaV + time * MAX_PLAUSIBLE_DECEL) / (MAX_PLAUSIBLE_ACCEL + MAX_PLAUSIBLE_DECEL);
    T_2 = time - T_1;

    maxSpeed = MAX_PLAUSIBLE_ACCEL * T_1 + oldspeed;
    maxDistance = 0;
    if (maxSpeed > MAX_PLAUSIBLE_SPEED):
        newT_1 = (MAX_PLAUSIBLE_SPEED - oldspeed) / MAX_PLAUSIBLE_ACCEL;
        newT_2 = (MAX_PLAUSIBLE_SPEED - curSpeed)/ MAX_PLAUSIBLE_DECEL;

        maxDistance = oldspeed * newT_1+ 0.5 * MAX_PLAUSIBLE_ACCEL * newT_1 * newT_1+ maxSpeed * newT_2- \
                      0.5 * MAX_PLAUSIBLE_DECEL * newT_2 * newT_2+ MAX_PLAUSIBLE_SPEED * (time - newT_1 - newT_2);
    else:
        maxDistance = oldspeed * T_1 + 0.5 * MAX_PLAUSIBLE_ACCEL * T_1 * T_1 + maxSpeed * T_2 - 0.5 * MAX_PLAUSIBLE_DECEL * T_2 * T_2;

    minSpeed = -MAX_PLAUSIBLE_DECEL * T_2 + oldspeed;
    minDistance = 0;
    if (minSpeed < 0):
        newT_1 = curSpeed / MAX_PLAUSIBLE_ACCEL;
        newT_2 = oldspeed / MAX_PLAUSIBLE_DECEL;

        minDistance = oldspeed * newT_2- 0.5 * MAX_PLAUSIBLE_DECEL * newT_2 * newT_2 + 0.5 * MAX_PLAUSIBLE_ACCEL * newT_1 * newT_1;
    else:
        minDistance = oldspeed * T_2 - 0.5 * MAX_PLAUSIBLE_DECEL * T_2 * T_2 + minSpeed * T_1 + 0.5 * MAX_PLAUSIBLE_ACCEL * T_1 * T_1;

    returnDistance[0] = minDistance;
    returnDistance[1] = maxDistance;

def rangePlausibility(row1,row2):

    MAX_PLAUSIBLE_RANGE=420

    def helper(row1, row2):
        x_2 = (row1.pos_x - row2.pos_x) ** 2
        y_2 = (row1.pos_y - row2.pos_y) ** 2
        return math.sqrt(x_2 + y_2)

    distance = helper(row1,row2)

    factor = CircleCircleFactor(distance,row1.pos_x_noise, row2.pos_x_noise,MAX_PLAUSIBLE_RANGE);

    return factor;

def positionConsistencyCheck(row,oldRow):

    MAX_PLAUSIBLE_SPEED=15

    distance = calculateDistancePtr(row,oldRow)
    timediff= np.abs(row.rcvTime - oldRow.rcvTime)

    if distance<MAX_PLAUSIBLE_SPEED*timediff:
        return 1
    else:
        return 0

def speedConsistencyCheck(row,oldRow):

    MAX_PLAUSIBLE_ACCEL=2.6
    MAX_PLAUSIBLE_DECEL = 4.5

    speedDelta = calculateSpeedPtr(row) - calculateSpeedPtr(oldRow)

    timediff= np.abs(row.rcvTime - oldRow.rcvTime)
    curSpeedConfidence=calculateSpeedConf(row)
    oldSpeedConfidence=calculateSpeedConf(oldRow)

    factor = 1;
    if (speedDelta > 0):
        factor = SegmentSegmentFactor(speedDelta, curSpeedConfidence,
            oldSpeedConfidence, MAX_PLAUSIBLE_ACCEL * timediff)

    else:
        factor = SegmentSegmentFactor(np.abs(speedDelta),
            curSpeedConfidence, oldSpeedConfidence,
            MAX_PLAUSIBLE_DECEL * timediff);

    return factor;

def SegmentSegmentFactor(d, r1,r2,range):

    d1 = 0
    d2 = 0
    if (d > 0) :
        d1 = (r1 * r1 + d * d - r2 * r2) / (2 * d)
        d2 = (r2 * r2 + d * d - r1 * r1) / (2 * d)

        if ((d1 + r1) < range / 2 and (d2 + r2) > range / 2) :
            d2 = d2 - (range / 2 - (d1 + r1))
            d1 = d1 + (range / 2 - (d1 + r1))

        if ((d2 + r2) < range / 2 and (d1 + r1) > range / 2):
            d1 = d1 - (range / 2 - (d2 + r2))
            d2 = d2 + (range / 2 - (d2 + r2))

    overlap1 = 0;
    overlap2 = 0;

    addon = 0;

    if ((d1 - range / 2) < r1):
        if ((d1 - range / 2) > -r1):
            addon = -(d1 - r1)
            overlap1 = range / 2 + addon

        else:
            overlap1 = 2 * r1

    if ((d2 - range / 2) < r2):
        if ((d2 - range / 2) > -r2):
            addon = -(d2 - r2)
            overlap2 = range / 2 + addon

        else:
            overlap2 = 2 * r2

    if (r1 == float(0) and r2 == float(0)):
        if (d > range):
            return 0
        else:
            return 1

    factor = (overlap1 + overlap2 ) / (2 * r1 + 2 * r2)

    return factor

def calculateSpeedPtr(row):

    return math.sqrt(row.spd_x_bsm**2 + row.spd_y_bsm**2)

def calculateSpeedConf(row):
    return math.sqrt(row.spd_x_noise_bsm**2 + row.spd_y_noise_bsm**2)

def calculatePositionConf(row):
    return math.sqrt(row.pos_x_noise_bsm**2 + row.pos_y_noise_bsm**2)

def calculateDistancePtr(row1,row2):
    x_2 = (row1.pos_x_bsm-row2.pos_x_bsm)**2
    y_2 =(row1.pos_y_bsm-row2.pos_y_bsm)**2
    return math.sqrt(x_2+y_2)

def findAndParseAllData(sim_path,num_cases,output_path):
    from functools import partial
    from multiprocessing import Pool

    test_folders = os.listdir(sim_path)

    for i,folder in enumerate(test_folders):
        test_folders[i]=os.path.join(sim_path,folder)

    # Create the pool and start parsing
    func = partial(parseSim, output_path=output_path)
    pool = Pool()
    pool.map(func, test_folders)
    pool.close()
    pool.join()

if __name__ == '__main__':

    sim_path = "raw_logs-veremiExtension/" # raw data path
    num_cases = 2
    output_path ="parsed_logs-veremiExtension/"
    findAndParseAllData(sim_path,num_cases,output_path)


import socket
s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

serverip=input("Enter Server IP : ")
print()
#serverip="192.168.0.109"
serverport=1234

port=4444;
ip="192.168.0.108";
s.bind((ip,port));

while True:
    data=input("Enter msg : ")
    s.sendto(data.encode(),(serverip,serverport))

    if "bye" in data:
        break

    print("Messge form server")
    y=s.recvfrom(1024);   # Receive all info
    client_ip=y[1][0]
    data=y[0].decode();
    print(client_ip + " : "+ data)
    print()


import bpy

class BAKE_TRANS(bpy.types.Operator):

    bl_label = "BakeTrans"
    bl_idname = "object.baketrans"

    def execute(self, context):
        obj = bpy.context.active_object

        # Check if the active object is a mesh
        if obj.type == 'MESH':
            # Store the material name
            material_name = obj.active_material.name

            # Unlink the material from the object
            obj.active_material_index = 0
            bpy.ops.object.material_slot_remove()

            # Bake your desired settings (adjust as needed)
            bpy.ops.object.bake(type='SHADOW')

            # Re-link the material to the object
            new_material = bpy.data.materials.get(material_name)
            if new_material:
                obj.data.materials.append(new_material)
                obj.active_material = new_material

                print("Baking complete.")

            else:
                print("Active object is not a mesh.")

        return{"FINISHED"}


'''
https://www.practicepython.org/exercise/2015/11/16/26-check-tic-tac-toe.html
26 - Check Tic Tac Toe
As you may have guessed, we are trying to build up to a full tic-tac-toe board.
However, this is significantly more than half an hour of coding, so we’re doing it in pieces.
Today, we will simply focus on checking whether someone has WON a game of Tic Tac Toe, not worrying about how the moves were made.

If a game of Tic Tac Toe is represented as a list of lists, like so:
game = [[1, 2, 0],
	    [2, 1, 0],
	    [2, 1, 1]]
where a 0 means an empty square, a 1 means that player 1 put their token in that space, and a 2 means that player 2 put their token in that space.

Your task this week: given a 3 by 3 list of lists that represents a Tic Tac Toe game board, tell me whether anyone has won, and tell me which player won, if any.
A Tic Tac Toe win is 3 in a row - either in a row, a column, or a diagonal. Don’t worry about the case where TWO people have won - assume that in every board there will only be one winner.
'''

def check_winner(game):
    # for rows
    for i in range(3):
        row = set([game[i][0], game[i][1], game[i][2]])
        if len(row) == 1 and game[i][0] != 0:
            return game[i][0]
    # for columns
    for i in range(3):
        column = set([game[0][i], game[1][i], game[2][i]])
        if len(column) == 1 and game[0][i] != 0:
            return game[0][i]
    # for diagonals
    diag1 = set([game[0][0], game[1][1], game[2][2]])
    diag2 = set([game[0][2], game[1][1], game[2][0]])
    if len(diag1) == 1 or len(diag2) == 1 and game[1][1] != 0:
        return game[1][1]


#Board must be connected to a router
#This code used for testing the Ethernet and communicate with the DNS server

import network
import socket
nic = network.Ethernet()
nic.active(True)
nic.ifconfig('dhcp')
print(nic.ifconfig())
socket.getaddrinfo('micropython.org', 80)