import pygame
from settings import *
from support import *
from pygame.math import Vector2 as vector
from sprites.super import Character
from sprites.animated import FxEffect, Fireball
from sprites.static import WarningMsg, Disappearing, DisappearFaded, DamageIndicator

class Enemy(Character):
    def __init__(self, pos, animations, groups, name, font, room):
        super().__init__(pos,animations,groups,room)
        self.name = name
        self.data = self.room.dungeon.map_script.ENEMY_DATA[name]
        self.drop_names, self.special_actions, self.max_health, self.behaviour, self.speed, self.attack_data = self.data
        self.special_actions = self.special_actions.split(",")
        self.health = self.max_health
        self.font = font
        self.attack_mode = 0
        self.cramming_rect = self.rect

        self.last_damage = 0
        self.hit_cooldown = 1000

    @external
    def damage(self, amount):
        if pygame.time.get_ticks() - self.last_damage >= self.hit_cooldown:
            self.health -= amount
            if self.health <= 0: self.die()
            self.last_damage = pygame.time.get_ticks()
            self.indicate_damage(amount)
            return True
        return False

    def indicate_damage(self, amount): DamageIndicator(self.rect.midtop, amount, [self.room.visible_top, self.room.updates],self.room,"green",self.font)

    def die(self):
        for name in self.drop_names:
            if ":" in name:
                split = name.split(":")
                chance = int(split[-1])
                name = split[0]
                if randint(0,100) > chance: break
            item = item_from_name(name)
            self.room.drop_item(item,self.rect.center)
        self.player.inventory.collect_souls(self.attack_data["souls"])
        self.player.indicate_soul(self.rect.midtop)
        self.room.defeated(self)
        self.kill()

    @runtime
    def draw_name(self, screen, offset): pass
    def draw_extra(self, screen,offset): pass

    @override
    def update(self, dt):
        self.animate(dt)
        self.debug.updates += 2

class EnemyAttacker(Enemy):
    def __init__(self,pos,animations,groups,name,font,room, vision_range=ENEMY_VISION_RANGE):
        super().__init__(pos,animations,groups,name,font,room)
        self.vision_range = vision_range
        self.collidable = self.room.collidable
        self.is_chasing = False
        self.orientation = "right"
        self.direction:vector = vector()
        self.hitbox = self.rect.inflate(-self.rect.w/4,0)
        self.hitbox.h = TILE_SIZE//4
        self.can_chase = self.behaviour=="attack"
        self.original_animations = self.animations
        self.flipped_animations = { key: [pygame.transform.flip(sprite,True,False) for sprite in value]
                                    for key, value in self.animations.items() }

    @runtime
    def chase(self,dt):
        if self.pos.distance_to(self.player.pos) <= self.vision_range and self.can_chase: self.is_chasing = True
        else: self.is_chasing = False
        if self.is_chasing:
            self.direction:vector = self.player.pos-self.pos
            if self.direction.x > 0: self.orientation = "right"
            else: self.orientation = "left"
            if self.direction.magnitude() != 0: self.direction.normalize_ip()

            self.pos.x += self.direction.x*self.speed*dt
            self.rect.centerx = round(self.pos.x)
            self.hitbox.midbottom = self.rect.midbottom
            self.collisions("horizontal")
            self.pos.y += self.direction.y*self.speed*dt
            self.rect.centery = round(self.pos.y)
            self.hitbox.midbottom = self.rect.midbottom
            self.collisions("vertical")

        elif self.direction.x != 0 or self.direction.y != 0: self.direction = vector()

    @runtime
    def collisions(self, direction):
        for sprite in self.collidable:
            if sprite.hitbox.colliderect(self.hitbox):
                if direction == "horizontal":
                    self.hitbox.right = sprite.hitbox.left if self.direction.x > 0 else self.hitbox.right
                    self.hitbox.left = sprite.hitbox.right if self.direction.x < 0 else self.hitbox.left
                    self.rect.centerx, self.pos.x = self.hitbox.centerx, self.hitbox.centerx
                    self.direction.x = 0
                else:
                    self.hitbox.top = sprite.hitbox.bottom if self.direction.y < 0 else self.hitbox.top
                    self.hitbox.bottom = sprite.hitbox.top if self.direction.y > 0 else self.hitbox.bottom
                    self.rect.bottom = self.hitbox.bottom
                    self.pos.y = self.rect.centery
                    self.direction.y = 0

    @runtime
    def get_status(self):
        status = "idle"
        if self.direction.x != 0 or self.direction.y != 0: status = "run"
        if self.orientation == "left": self.animations = self.flipped_animations
        else: self.animations = self.original_animations
        self.set_status(status, True)

    @override
    def update(self, dt):
        self.get_status()
        self.animate(dt)
        self.chase(dt)
        self.extra_update(dt)
        self.debug.updates += 3
    @runtime
    def extra_update(self, dt):pass

class SmallEnemy(EnemyAttacker):
    def __init__(self,pos,animations,groups,name,font,room):
        super().__init__(pos,animations,groups,name,font,room)
        self.other_enemies = room.enemies
        self.player = room.player
        self.size = (self.rect.w+self.rect.h)//2
        self.player_damage = self.attack_data["damage"]
        self.cramming_rect = self.rect.inflate(-TILE_SIZE//2,-TILE_SIZE//2)

    def draw_extra(self, screen, offset):
        if pygame.time.get_ticks() - self.last_damage <= self.hit_cooldown:
            mask = pygame.mask.from_surface(self.image)
            surf = mask.to_surface(setcolor="red")
            surf.set_colorkey("black")
            surf.set_alpha(150)
            offsetted_s = self.rect.copy()
            offsetted_s.center -= offset
            screen.blit(surf,offsetted_s)
            self.debug.blits += 1

    def other_collisions(self):
        for enemy in self.other_enemies:
            if self.cramming_rect.colliderect(enemy.cramming_rect):
                direction = enemy.pos-self.pos
                self.pos += -vector(direction.x/20,direction.y/20)

    def extra_update(self, dt):
        self.cramming_rect.center = self.rect.center
        self.other_collisions()
        if self.cramming_rect.colliderect(self.player.hitbox) and self.player.can_damage():
            self.player.stats.damage(self.player_damage)

class Boss(EnemyAttacker):
    def __init__(self, pos, animations, groups, name, font, room):
        super().__init__(pos,animations,groups,name,font,room,BOSS_VISION_RANGE)
        self.assets = self.room.dungeon.assets

    def warn(self): WarningMsg(self.rect.midtop+vector(0,0),self.assets["ui"]["emark"],[self.room.visible_top,self.room.updates],self.room)

class OgreBoss(Boss):
    def __init__(self, pos, animations, groups, name, font, room, weapon_surf):
        super().__init__(pos, animations, groups, name, font, room)
        self.weapon_ori_s = pygame.transform.scale_by(weapon_surf,0.75)
        self.weapon_offset_r,self.weapon_offset_l = vector(TILE_SIZE//2.5,TILE_SIZE//1.8),vector(-TILE_SIZE//2.5,TILE_SIZE//1.8)
        self.weapon_offset_ru,self.weapon_offset_lu = self.weapon_offset_r+vector(0,-SCALE_FACTOR),self.weapon_offset_l+vector(0,-SCALE_FACTOR)
        self.weapon_angle_r,self.weapon_angle_l = -45,45
        self.swing_start_angle,self.swing_end_angle_r,self.swing_end_angle_l = 0,-90-45,90+45
        self.swing_start_speed,self.swing_speed,self.swing_dir,self.swing_acceleration = 8,0,1,2
        self.next_angle,self.weapon_angle=0,0
        self.weapon_surf = self.weapon_ori_s; self.weapon_rect = self.weapon_surf.get_rect()

        self.last_attack,self.attack_cooldown = 0,2000
        self.player_damage,self.should_damage,self.wait_cooldown = 2,False,400
        self.crack1_damage,self.crack2_damage = 2,8
        self.attack_hitbox,self.notice_hitbox= self.rect.inflate(-TILE_SIZE//2,-TILE_SIZE),self.rect.inflate(TILE_SIZE,-TILE_SIZE*1.5)
        self.crack1_cooldown,self.crack2_cooldown = 3500,8000
        self.weapon_striked = False

    def draw_extra(self, screen, offset):
        if pygame.time.get_ticks() - self.last_damage <= self.hit_cooldown:
            mask = pygame.mask.from_surface(self.image)
            surf = mask.to_surface(setcolor="red"); surf.set_colorkey("black"); surf.set_alpha(150)
            offsetted_s = self.rect.copy(); offsetted_s.center -= offset
            screen.blit(surf,offsetted_s); self.debug.blits += 1
        offsetted = self.weapon_rect.copy(); offsetted.center -= offset
        screen.blit(self.weapon_surf,offsetted)

    def die(self):
        super().die()
        FxEffect(self.rect.center,self.assets["fx"]["MagicBarrier"],[self.room.visible_top,self.room.updates],self.room,1,1)

    def start_attack(self):
        self.weapon_striked = False
        self.can_chase,self.should_damage = False,True
        self.last_attack = pygame.time.get_ticks()
        self.weapon_angle,self.swing_speed = self.swing_start_angle,self.swing_start_speed
        self.next_angle = self.swing_end_angle_r if self.orientation == "right" else self.swing_end_angle_l
        self.swing_dir = 1 if self.orientation == "left" else -1
        self.warn()

    def attack(self):
        if self.attack_hitbox.colliderect(self.player.rect) and self.player.can_damage(): self.player.stats.damage(self.player_damage)
        self.should_damage = False

    def spawn_crack(self,pos,damage,cooldown,idx=0):
        if not self.weapon_striked:
            img = pygame.transform.rotate(self.assets["cracks"][idx],randint(0,360))
            Disappearing(pos,img,[self.room.visible_floor,self.room.updates,self.room.damages],self.room,cooldown,None,True,True,damage)
            self.weapon_striked = True

    def extra_update(self, dt):
        # weapon
        self.weapon_surf = pygame.transform.rotate(self.weapon_ori_s,self.weapon_angle)
        is_u = int(self.frame_index)%2 == 0
        offset = (self.weapon_offset_ru if is_u else self.weapon_offset_r) if self.orientation == "right" else (self.weapon_offset_lu if is_u else self.weapon_offset_l)
        pos = self.rect.center + offset

        if self.orientation == "right":
            key = "bottomleft" if self.weapon_angle > -90 else "midleft"
            self.weapon_rect = self.weapon_surf.get_rect(**{key:pos})
        else:
            key = "bottomright" if self.weapon_angle < 90 else "midright"
            self.weapon_rect = self.weapon_surf.get_rect(**{key:pos})

        # movement, attack
        self.notice_hitbox.center = self.rect.center
        if self.orientation == "right": self.attack_hitbox.midleft = self.rect.center
        else: self.attack_hitbox.midright = self.rect.center
        if self.notice_hitbox.colliderect(self.player.rect) and self.can_chase: self.start_attack()
        if not self.can_chase:
            if pygame.time.get_ticks() - self.last_attack >= self.attack_cooldown: self.can_chase = True
            else:
                self.swing_speed += self.swing_acceleration
                self.weapon_angle += self.swing_speed*self.swing_dir*dt
                if self.swing_dir == 1:
                    if self.weapon_angle > self.swing_end_angle_l:
                        self.weapon_angle = self.swing_end_angle_l
                        self.spawn_crack(self.weapon_rect.bottomleft,self.crack1_damage,self.crack1_cooldown)
                else:
                    if self.weapon_angle < self.swing_end_angle_r:
                        self.weapon_angle = self.swing_end_angle_r
                        self.spawn_crack(self.weapon_rect.bottomright,self.crack1_damage,self.crack1_cooldown)
            if self.should_damage:
                if pygame.time.get_ticks()-self.last_attack >= self.wait_cooldown: self.attack()
        else: self.weapon_angle = self.weapon_angle_r if self.orientation == "right" else self.weapon_angle_l

class HellblazeBoss(Boss):
    def __init__(self, pos, animations, groups, name, font, room):
        super().__init__(pos,animations,groups,name,font,room)

        self.mouth_hitbox = self.rect.inflate(-TILE_SIZE//2,-TILE_SIZE//2)
        self.mouth_damage, self.max_mouth_damage = 1,2
        self.poison_damage, self.damage_dealt = 4, 0

        self.change_mode_time = 0
        self.poison_wait_cooldown, self.poison_spawn_time, self.poison_effect = 500,0,None
        self.last_fireball, self.fireball_cooldown = 0, 400
        self.fireball_count, self.small_fireball_count = 0, 8

        self.lava_cooldown, self.lava_fade_speed = 3000, 200
        self.lava_amount_range, self.lava_damage = (8,15), 2

    def standard_attack(self):
        before = self.player.stats.health
        self.player.stats.damage(self.mouth_damage)
        if self.player.stats.health != before: self.damage_dealt += self.mouth_damage

    def spawn_lava(self):
        amount = randint(self.lava_amount_range[0],self.lava_amount_range[1])
        for _ in range(amount):
            pos = choice(self.room.visible_floor.sprites()).rect.topleft
            surf = choice(self.assets["lava"])
            lava = DisappearFaded(pos,surf,[self.room.visible_floor,self.room.updates,self.room.damages],self.room,self.lava_cooldown,None,self.lava_fade_speed,False,True,self.lava_damage)
            lava.name = "lava"

    def poison_attack(self):
        self.poison_effect = FxEffect(self.rect.center,self.assets["fx"]["PoisonClaw"],[self.room.visible_objects,self.room.updates],self.room,1,1.2)
        self.poison_spawn_time = pygame.time.get_ticks()

    def start_fireball_attack(self):
        self.last_fireball = pygame.time.get_ticks()
        self.fireball_count = 0
        self.spawn_lava()

    def change_from_standard(self):
        self.damage_dealt,self.can_chase,self.change_mode_time,self.attack_mode = 0,False,pygame.time.get_ticks(),choice([1,2])
        if self.attack_mode == 1: self.warn(); self.spawn_lava()
        if self.attack_mode == 2: self.warn(); self.start_fireball_attack()

    def spawn_fireball(self, size):
        sprites = self.assets["fx"]["FireBall"] if size == "small" else self.assets["fx"]["FireBall_2"]
        damage,speed_mul = (2,1) if size == "small" else (5,1.5)
        dir = self.player.pos-self.pos
        if dir.magnitude() != 0: dir.normalize_ip()
        Fireball(self.rect.center,sprites,
                 [self.room.visible_objects,self.room.updates,self.room.fireballs],self.room,
                 dir,damage,speed_mul)
        self.fireball_count += 1
        self.last_fireball = pygame.time.get_ticks()

    def die(self):
        super().die()
        FxEffect(self.rect.center,self.assets["fx"]["FireCast"],[self.room.visible_top,self.room.updates],self.room,1,1.5)
        FxEffect(self.rect.center,self.assets["fx"]["FireBurst"],[self.room.visible_top,self.room.updates],self.room,1,1.5)

    def extra_update(self, dt):
        self.mouth_hitbox.center = self.rect.center
        if self.mouth_hitbox.colliderect(self.player.hitbox) and self.player.can_damage(): self.standard_attack()
        if self.attack_mode == 0:
            self.can_chase = True
            if self.damage_dealt >= self.max_mouth_damage: self.change_from_standard()
        if not self.can_chase:
            diff = self.player.pos.x-self.pos.x
            if diff >= 0: self.orientation = "right"
            else: self.orientation = "left"
        if self.attack_mode == 1:
            if pygame.time.get_ticks()-self.change_mode_time >= self.poison_wait_cooldown and self.poison_spawn_time == 0: self.poison_attack()
            if self.poison_effect and not self.poison_effect.finished:
                if self.poison_effect.rect.colliderect(self.player.hitbox) and self.player.can_damage()\
                    and not self.player.inventory.effect_active("Poison Resistance"): self.player.stats.damage(self.poison_damage)
            else:
                if self.poison_spawn_time != 0: self.poison_spawn_time, self.attack_mode,self.poison_effect = 0,0,None
        elif self.attack_mode == 2:
            if pygame.time.get_ticks()-self.last_fireball >= self.fireball_cooldown:
                if self.fireball_count < self.small_fireball_count-1:
                    self.spawn_fireball("small")
                else:
                    self.spawn_fireball("big")
                    self.attack_mode = 0

    def draw_extra(self, screen, offset):
        if pygame.time.get_ticks() - self.last_damage <= self.hit_cooldown:
            mask = pygame.mask.from_surface(self.image)
            surf = mask.to_surface(setcolor="red"); surf.set_colorkey("black"); surf.set_alpha(150)
            offsetted_s = self.rect.copy(); offsetted_s.center -= offset
            screen.blit(surf,offsetted_s)
            self.debug.blits += 1


import math
import os.path
import random

import pygame

from Node.node import Node
import time
from Node.character import NPC, Character
from Node.portal import Portal
from Node.map_mask import MapMask
from Node.image_rect import ImageRect
from Node.animation import Animation8D
from Common.constants import *
from Common.common import *
from Node.camera import Camera
from Common.socket_id import *
from Database.effect_res import get_effect

from Game.res_manager import read_mapx, fill_res

class WorldMapJpg(ImageRect):
    def __init__(self):
        super(WorldMapJpg, self).__init__()

    # def update(self):
    #     super(WorldMapJpg, self).update()
    #     self.clear_children()
    #     if game.hero_path:
    #         for i, (x, y) in enumerate(game.hero_path):
    #             point = ImageRect()
    #             fill_res(point, 'wzife.rsp', 0x18E4B31B)
    #             point.x, point.y = x, y
    #             self.add_child(str(i), point)

class World(Node):
    def __init__(self):
        super(World, self).__init__()
        self.xy_timer = 0
        self.map_id = 0
        self.cur_npcs = []  # 当前地图的npc
        self.setup_ui()

    def setup_ui(self):
        self.add_child('map_jpg', WorldMapJpg())
        self.add_child('hero', Node())
        self.add_child('camera', Camera())

    def update_hero_xy(self):
        hero = game.hero
        if not hero:
            return
        send_data = {
            'x': hero.game_x,
            'y': hero.game_y,
            'mapid': self.map_id
        }
        self.director.client.send(C_更新坐标, send_data)

    def add_npc(self, data: dict):
        npc = NPC()
        npc.type = 'npc'
        npc.set_data(data)
        self.add_child('npc_' + str(npc.id), npc)
        # print('add npc:', data)
        npc.visible = not self.director.is_in_battle
        self.cur_npcs.append(npc)

    def add_player(self, data: dict):
        player = Character()
        player.type = 'player'
        player.set_data(data)
        self.add_child('player_' + str(player.id), player)
        # print('add player:', data)
        player.visible = not self.director.is_in_battle

    def remove_player(self, pid):
        for name, child in self.get_children().copy().items():
            if name == 'player_' + str(pid):
                if child.id == pid:
                    self.remove_child(name)

    def player_set_path(self, pid, path):
        for name, child in self.get_children().items():
            if name == 'player_' + str(pid):
                if child.id == pid:
                    child.set_path(path)

    def player_set_data(self, pid, data):
        if pid == game.hero.id:
            game.hero.set_data(data)
            return
        for name, child in self.get_children().items():
            if name == 'player_' + str(pid):
                if child.id == pid:
                    child.set_data(data)
                    return

    def player_add_speech_prompt(self, pid, text):
        for name, child in self.get_children().items():
            if name == 'player_' + str(pid):
                if child.id == pid:
                    child.child('speech_prompt').append(text)
        if game.hero.id == pid:
            print('hero sp:', text)
            game.hero.child('speech_prompt').append(text)

    def add_player_one_time_animation(self, pid, ani_name):
        """
        人物节点上添加一次性动画, 全部人可见
        """
        _hash, _rsp = get_effect(ani_name)
        for name, child in self.get_children().items():
            if name == 'player_' + str(pid):
                if child.id == pid:
                    add_onetime_animation(child, _rsp, _hash)
        if game.hero.id == pid:
            add_onetime_animation(game.hero, _rsp, _hash)

    def add_scene_one_time_animation(self, ani_name, x, y):
        """
        world节点上添加一次性动画, 全部人可见
        """
        _hash, _rsp = get_effect(ani_name)
        add_onetime_animation(self, _rsp, _hash)

    def change_map(self, map_id, x=None, y=None):
        print('change map:', map_id)
        self.map_id = map_id
        map_file = map_dir + str(map_id) + '.mapx'
        if not os.path.exists(map_file):
            print('map不存在:', map_id)
            return

        if x:
            game.hero.game_x = x
        if y:
            game.hero.game_y = y

        game.window_layer.child('小地图').enable = False  # 关闭小地图
        self.cur_npcs.clear()
        self.remove_all_npcs()
        self.remove_all_portals()
        self.remove_all_players()
        self.remove_all_masks()
        self.remove_map_jpg()
        self.director.mapx = read_mapx(map_id)
        # 镜头(先移动镜头, 避免先加载资源之后跳转地图瞬间快速闪动)
        hero = game.hero
        camera = game.camera
        camera.limit = [0, 0, self.director.mapx.width - self.director.window_w, self.director.mapx.height - self.director.window_h]
        camera.move_to(hero.map_x, hero.map_y)
        # 底图
        map_jpg = WorldMapJpg()
        self.director.astar.cell = self.director.mapx.navi
        map_jpg.image = self.director.mapx.jpg
        self.add_child('map_jpg', map_jpg)
        # NPC
        # --旧版NPC配置
        # for npc_id, npc_data in game.npcs.items():
        #     if int(npc_data['地图']) == self.director.mapx.map_id:
        #         npc_data['id'] = int(npc_id)
        #         self.add_npc(npc_data)
        # --BH NPC配置
        for npc_id, data in game.npcs.items():
            if data['地图'] and int(data['地图']) == self.director.mapx.map_id:
                npc_id = int(npc_id)
                data['id'] = npc_id
                self.add_npc(data)
        # TODO: test
        # if map_id == 1001:
        #     for _ in range(100):
        #         npx = {}
        #         npx['x'] = random.randint(210, 240)
        #         npx['y'] = random.randint(110, 130)
        #         npx['模型'] = random.sample(HERO_MODELS, 1)[0]
        #         pal = [(0, 0, 0), (1, 1, 0), (2, 2, 0), (3, 3, 0)]
        #         npx['染色'] = random.sample(pal, 1)[0]
        #         _id = random.randint(10000, 99999)
        #         npx['id'] = _id
        #         npx['名称'] = '名字{}'.format(_id)
        #         npx['方向'] = random.randint(0, 7)
        #         self.add_player(npx)

        # 传送阵
        for pid, portal in portals.items():
            mapid = portal['原地图']
            if int(mapid) == self.director.mapx.map_id:
                p = Portal()
                p.portal_id = pid
                p.game_x, p.game_y = int(float(portal['原地图x'])), int(float(portal['原地图y']))
                self.add_child('portal_' + str(pid), p)
        # 遮罩
        for mask in self.director.mapx.masks:
            self.add_child('mapmask_' + str(mask.id), mask)

        self.change_state(self.director.is_in_battle)
        self.director.is_hero_in_portal = False

    def remove_map_jpg(self):
        self.remove_child('map_jpg')

    def remove_all_npcs(self):
        for child_name, child in self.get_children().copy().items():
            if 'npc_' in child_name:
                self.remove_child(child_name)

    def remove_all_portals(self):
        for child_name, child in self.get_children().copy().items():
            if 'portal_' in child_name:
                self.remove_child(child_name)

    def remove_all_players(self):
        for child_name, child in self.get_children().copy().items():
            if 'player_' in child_name:
                self.remove_child(child_name)

    def remove_all_masks(self):
        for child_name, child in self.get_children().copy().items():
            if 'mapmask_' in child_name:
                self.remove_child(child_name)

    def change_state(self, state: bool):
        """
        切换状态
        :param state: True:战斗, False:非战斗
        :return:
        """
        print('world change state:', state)
        for name, child in self.get_children().copy().items():
            # 战斗时, portal/mapmask/npc隐藏, 反之显示
            if 'portal_' in name or 'mapmask_' in name or 'npc_' in name:
                self.child(name).visible = not state
        # 战斗时, hero隐藏, 反之显示
        self.child('hero').visible = not state
        # 战斗时, 关闭ysort
        self.ysort = not state

        # 若切换至非战斗, 删除战斗相关节点
        if not state:
            self.remove_child('grey_mask')
            self.remove_child('black_mask')
            self.remove_child('circle_mask')
            self.remove_child('units')

        if state:
            camera = game.camera
            # 纯色背景(战斗)
            node = ImageRect().from_color((15, 25, 60, 190))
            node.x, node.y = camera.x, camera.y
            self.add_child('grey_mask', node)
            # 黑色背景(战斗)
            node = ImageRect().from_color((0, 0, 0, 255))
            node.x, node.y = camera.x, camera.y
            node.visible = False
            self.add_child('black_mask', node)
            # 法阵圆圈(战斗)
            node = Animation8D()
            # fill_res(node, 'wzife.rsp', 0xD4BAB272)
            fill_res(node, 'addon.rsp', 0xE3B87E0F)
            # node.x, node.y = camera.x + 400, camera.y + 340
            node.x, node.y = 0, 200
            # node = set_node_attr(ImageRect(), {'rsp_file': 'wzife.rsp',
            #                                      'hash_id': 0xDE3F48B7,
            #                                      'top_left_x': 300,
            #                                      'top_left_y': 400})
            self.add_child('circle_mask', node)
            # 战斗场景(战斗)
            from Battle.battle_scene import BattleScene
            bs = BattleScene()
            bs.x, bs.y = camera.x, camera.y
            self.add_child('battle_scene', bs)
        # 切换音乐
        if state:
            play_battle_music('战斗BOSS1')
        else:
            play_scene_bgm(self.map_id)

    def check_event(self):
        super(World, self).check_event()
        if self.director.match_mouse_event(STOP, MOUSE_LEFT_DOWN):
            if self.director.grasped_item:
                send(C_丢弃物品, dict(page=self.director.grasped_item.bag_page, index=self.director.grasped_item.page_index))
                self.director.grasped_item.clear_grasp_state()
                return
            hero = game.hero
            camera = game.camera
            if hero.visible:
                mouse_x, mouse_y = int(pygame.mouse.get_pos()[0] + camera.x), int(pygame.mouse.get_pos()[1] + camera.y)
                hero_x, hero_y = int(hero.map_x), int(hero.map_y)
                # print('鼠标点击寻路:', (hero_x, hero_y), (mouse_x, mouse_y))
                path = self.director.astar.find_path((hero_x, hero_y), (mouse_x, mouse_y))
                # print('发送路径:', path)
                if path:
                    self.director.client.send(C_发送路径, dict(路径=path))

    def update(self):
        if self.director.is_in_battle:
            return
        # 更新主角坐标
        if time.time() - self.xy_timer > 1:
            self.update_hero_xy()
            self.xy_timer = time.time()
        # 距离主角一定范围内才显示
        hero = game.hero

        for child_name in self.get_children().copy().keys():
            child = self.child(child_name)
            if child != hero:
                if 'player_' in child_name or 'npc_' in child_name:
                    dis = math.dist((child.map_x, child.map_y), (hero.map_x, hero.map_y))
                    if dis < 600:
                        child.enable = True
                    if dis > 650:
                        child.enable = False
                if 'mask_' in child_name:
                    dis = math.dist((child.map_x + child.width//2, child.map_y + child.height//2), (hero.map_x, hero.map_y))
                    if dis < 600:
                        child.enable = True
                    if dis > 650:
                        child.enable = False


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

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy
import requests
import time
import logging
import configparser

# Config parser
cfg = configparser.ConfigParser()
cfg.read("general.cfg")

class ProxyfetcherItem(scrapy.Item):
    # Build of the item
    ip = scrapy.Field()
    port = scrapy.Field()
    country = scrapy.Field()
    con_type = scrapy.Field()
    response_time = scrapy.Field()
    full_address = scrapy.Field()

    def status_check(self, item):
        # Save timestamp for later calculation of elapsed time
        timestamp = time.time()
        # Call the judge for the proxy
        try:
            judge = requests.get(cfg.get('judge', "url", fallback="http://azenv.net/"),
                                 proxies = {"http" : "http://{}:{}".format(item["ip"], item["port"])},
                                 timeout = 5)
            # Only store the item if the judge makes a correct answer
            if (judge.status_code == 200) and ("HTTP_HOST" in judge.text):
                item["response_time"] = round(time.time() - timestamp, 3)
                return item
        # Exception handling
        except requests.exceptions.Timeout as e:
            logging.info("Timeout: "+str(e))
        except requests.exceptions.ProxyError as e:
            logging.info("Proxy error: "+str(e))
        except requests.exceptions.ConnectionError as e:
            logging.info("Connection Error: "+str(e))
        except requests.exceptions.ChunkedEncodingError as e:
            logging.info("Connection probably broken.")
        except Exception as e:
            logging.info("Uncaught exception: " +str(e))


from concurrent.futures import ThreadPoolExecutor
from instaloader import Instaloader, ProfileNotExistsException, Profile

L = Instaloader()

L.login("USER", "PASS")

def process_profile(L, PROFILE):
    try:
        posts = Profile.from_username(L.context, PROFILE).get_posts()
        try:
            most_recent_post = next(posts)

            post_url = f"https://www.instagram.com/p/{most_recent_post.shortcode}"

            with open('post_urls.txt', 'a') as output_file:
                print("Printing to file...")
                output_file.write(f"1172 | {post_url} | 2 | comment | comment \n")
                print("Done")
        except StopIteration:
            return
    except ProfileNotExistsException:
        return

with open('users.txt') as file:
    with ThreadPoolExecutor() as executor:
        for i in range(2000):#5 = 2 line of urls
            PROFILE = file.readline().strip()
            executor.submit(process_profile, L, PROFILE)


import zencad.assemble
import zencad.libs.screw
import numpy
import time

from abc import ABC, abstractmethod

from zencad.assemble import kinematic_unit

class kinematic_chain:
    """Объект-алгоритм управления участком кинематической чепи от точки
    выхода, до точки входа.

    Порядок следования обратный, потому что звено может иметь одного родителя,
    но много потомков. Цепочка собирается по родителю.

    finallink - конечное звено.
    startlink - начальное звено.
            Если не указано, алгоритм проходит до абсолютной СК"""

    def __init__(self, finallink, startlink=None):
        self.chain = self.collect_chain(finallink, startlink)
        self.simplified_chain = self.simplify_chain(self.chain)
        self.kinematic_pairs = self.collect_kinematic_pairs()

    def collect_kinematic_pairs(self):
        par = []
        for l in self.chain:
            if isinstance(l, kinematic_unit):
                par.append(l)
        return par

    # def collect_coords(self):
    #	arr = []
    #	for l in self.parametered_links:
    #		arr.append(l.coord)
    #	return arr

    def apply(self, speeds, delta):
        for i in range(len(speeds)):
            k = self.kinematic_pairs[len(self.kinematic_pairs) - i - 1]
            k.set_coord(k.coord + speeds[i] * delta)

    @staticmethod
    def collect_chain(finallink, startlink=None):
        chain = []
        link = finallink

        while link is not startlink:
            chain.append(link)
            link = link.parent

        if startlink is not None:
            chain.append(startlink)

        return chain

    @staticmethod
    def simplify_chain(chain):
        ret = []
        tmp = None

        for l in chain:
            if isinstance(l, kinematic_unit):
                if tmp is not None:
                    ret.append(tmp)
                    tmp = None
                ret.append(l)
            else:
                if tmp is None:
                    tmp = l.location
                else:
                    tmp = tmp * l.location

        if tmp is not None:
            ret.append(tmp)

        return ret

    def getchain(self):
        return self.chain

    def sensivity(self, basis=None):
        """Вернуть массив тензоров производных положения выходного
        звена по вектору координат в виде [(w_i, v_i) ...]"""

        trsf = _nulltrans()
        senses = []

        outtrans = self.chain[0].global_location

        """Два разных алгоритма получения масива тензоров чувствительности.
		Первый - проход по цепи с аккумулированием тензора трансформации.
		Второй - по глобальным объектам трансформации

		Возможно следует использовать второй и сразу же перегонять в btrsf вместо outtrans"""

        if False:
            for link in self.simplified_chain:
                if isinstance(link, Transformation):
                    trsf = link * trsf

                else:
                    lsenses = link.senses()
                    radius = trsf.translation()

                    for sens in reversed(lsenses):

                        wsens = sens[0]
                        vsens = wsens.cross(radius) + sens[1]

                        itrsf = trsf.inverse()

                        senses.append((
                            itrsf(wsens),
                            itrsf(vsens)
                        ))

                    trsf = link.location * trsf

        else:
            for link in self.kinematic_pairs:
                lsenses = link.senses()

                linktrans = link.output.global_location
                trsf = linktrans.inverse() * outtrans

                radius = trsf.translation()

                for sens in reversed(lsenses):

                    wsens = sens[0]
                    vsens = wsens.cross(radius) + sens[1]

                    itrsf = trsf.inverse()

                    senses.append((
                        itrsf(wsens),
                        itrsf(vsens)
                    ))

        """Для удобства интерпретации удобно перегнать выход в интуитивный базис."""
        if basis is not None:
            btrsf = basis.global_location
            #trsf =  btrsf * outtrans.inverse()
            # trsf =  outtrans * btrsf.inverse() #ok
            trsf = btrsf.inverse() * outtrans  # ok
            #trsf =  outtrans.inverse() * btrsf
            #trsf =  trsf.inverse()

            senses = [(trsf(w), trsf(v)) for w, v in senses]

        senses = [zencad.libs.screw.screw(ang=s[0], lin=s[1]) for s in senses]

        return list(reversed(senses))

    def decompose(self, vec, use_base_frame=False):
        sens = self.sensivity(self.chain[-1] if use_base_frame else None)
        #sens = self.sensivity(None)
        sens = [s.to_array() for s in sens]
        target = vec.to_array()
        return zencad.malgo.svd_backpack(target, sens)[0]

    def decompose_linear(self, vec, use_base_frame=False, maxsig=2, maxnorm=1,
                         priority=None):
        a = time.time()
        sens = self.sensivity(self.chain[-1] if use_base_frame else None)
        b = time.time()
        #sens = self.sensivity(None)
        sens = [s.lin for s in sens]
        target = vec

        if priority:
            for i in range(len(sens)):
                sens[i] = sens[i] * priority[i]

        # for i in range(len(sens)):
        #	print(abs(sens[i].dot(target)))
            # if abs(sens[i].dot(target)) > 10:
            #	sens[i] = (0,0,0)
        # print(sens)
        sigs = zencad.malgo.svd_backpack(target, sens)[0]
        c = time.time()

        if priority:
            for i in range(len(sens)):
                sigs[i] = sigs[i] * priority[i]
        # print(sigs)
        # print(sigs)

        #norm = numpy.linalg.norm(sigs)
        # if norm > maxnorm:
        #	sigs = sigs / norm * maxnorm
        # print(sigs)
        # if norm > maxnorm:
        #	sigs = sigs / norm * maxnorm

        #ssigs = list(sigs)
        # print(ssigs)
        # for i in range(len(sigs)):
        #	if abs(ssigs[i]) > maxsig:
        #		ssigs[i] = 0

        #print(b-a, c-b)

        return sigs

    def kunit(self, num):
        return self.kinematic_pairs[-num-1]


from datetime import datetime
from flask import render_template, flash, redirect, url_for, request, g, \
    jsonify, current_app
from flask_login import current_user, login_required
from flask_babel import _, get_locale
from app import db
from app.rack.forms import RackForm, SearchForm
from app.models import Rack, Equipment
from app.rack import bp

@bp.route('/rack', methods=['GET', 'POST'])
@login_required
def index():
    pagination = []
    search_form = SearchForm()
    page = request.args.get('page', 1, type=int)
    if search_form.validate_on_submit():
        name = search_form.name.data
        if name != '':
            pagination = Rack.query.filter_by(name=name) \
                .order_by(Rack.created_at.desc()).paginate(
                page, per_page=current_app.config['FLASK_PER_PAGE'],
                error_out=False)
        else:
            pagination = Rack.query \
                .order_by(Rack.created_at.desc()).paginate(
                page, per_page=current_app.config['FLASK_PER_PAGE'],
                error_out=False)
    else:
        pagination = Rack.query \
            .order_by(Rack.created_at.desc()).paginate(
            page, per_page=current_app.config['FLASK_PER_PAGE'],
            error_out=False)
    list = pagination.items
    return render_template('rack/list.html',
                           list=list, pagination=pagination,
                           title="equipment", search_form=search_form)

@bp.route('/rack/add', methods=['GET', 'POST'])
@login_required
def add():
    add = True
    form = RackForm()
    form.equipment.choices = [(c.id, c.name) for c in Equipment.query.all()]
    if form.validate_on_submit():
        rack = Rack(name=form.name.data,
                    equipment_id=form.equipment.data,
                    horizontal=form.horizontal.data,
                    vertical=form.vertical.data,
                    max_number=int(form.vertical.data) + int(form.horizontal.data),
                    status=0,
                    created_at=datetime.utcnow(),
                    created_by=current_user.id)
        db.session.add(rack)
        db.session.commit()
        flash(_('Data saved!'))
        return redirect(url_for('rack.index'))
    return render_template('rack/form.html', action="Add",
                           add=add, form=form,
                           title="Add rack")

@bp.route('/rack/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit(id):
    add = False
    rack = Rack.query.get_or_404(id)
    form = RackForm(obj=rack)
    form.equipment.choices = [(c.id, c.name) for c in Equipment.query.all()]
    if form.validate_on_submit():
        rack.equipment_id = form.equipment.data
        rack.max_number = form.max_number.data
        rack.name = form.name.data
        db.session.commit()
        flash('You have successfully edited the rack.')

        # redirect to the bps page
        return redirect(url_for('rack.index'))

    form.equipment.data = rack.equipment_id
    form.max_number.data = rack.max_number
    form.name.data = rack.name
    return render_template('rack/form.html', action="Edit",
                           add=add, form=form,
                           rack=rack, title="Edit rack")

@bp.route('/rack/<int:id>', methods=['GET', 'POST'])
@login_required
def detail(id):
    rack = Rack.query.get_or_404(id)
    return render_template('rack/detail.html', rack=rack)

@bp.route('/rack/delete/<int:id>', methods=['GET', 'POST'])
@login_required
def delete(id):
    rack = Rack.query.get_or_404(id)
    db.session.delete(rack)
    db.session.commit()
    flash('You have successfully deleted the rack.')

    # redirect to the bps page
    return redirect(url_for('rack.index'))


"""Executor async/await sequential (:mod:`fluidimage.executors.exec_async_sequential`)
======================================================================================

A executor using async for IO but launching CPU-bounded tasks sequentially.

.. autoclass:: ExecutorAsyncSequential
   :members:
   :private-members:

"""

import time

from fluidimage.util import cstring, log_memory_usage, logger

from .exec_async import ExecutorAsync

class ExecutorAsyncSequential(ExecutorAsync):
    """Async executor launching CPU-bounded tasks sequentially"""

    async def async_run_work_cpu(self, work):
        """Executes the work on an item (key, obj), and add the result on
        work.output_queue.

        Parameters
        ----------

        work :

          A work from the topology

        key : hashable

          The key of the dictionnary item to be process

        obj : object

          The value of the dictionnary item to be process

        """
        self.nb_working_workers_cpu += 1

        try:
            key, obj = work.input_queue.pop_first_item()
        except KeyError:
            self.nb_working_workers_cpu -= 1
            return

        if work.check_exception(key, obj):
            self.nb_working_workers_cpu -= 1
            return

        t_start = time.time()
        log_memory_usage(
            f"{time.time() - self.t_start:.2f} s. Launch work "
            + work.name_no_space
            + f" ({key}). mem usage"
        )
        # pylint: disable=W0703
        try:
            # here we do something very bad from the async point of view:
            # we launch a potentially long blocking function:
            ret = work.func_or_cls(obj)
        except Exception as error:
            self.log_exception(error, work.name_no_space, key)
            if self.stop_if_error:
                raise
            ret = error
        else:
            logger.info(
                f"work {work.name_no_space} ({key}) "
                f"done in {time.time() - t_start:.3f} s"
            )

        if work.output_queue is not None:
            work.output_queue[key] = ret
        self.nb_working_workers_cpu -= 1


"""
@author: Anne Hermann

Overview: Calculate the Vialov Profile from Greve (eq. 5.117 and 5.119).

Input:
    L = extent of ice sheet to the left and right from the peak at x = 0
    a = accumulation rate
    delta_x = grid size in x dir.
    n = 3 or 4, Glen's flow law
    A = flow rate factor
    rho = density of the ice
    g = gravity

"""

import numpy as np
def vialov(x,L,a,n,A,rho,g):
    A_0=2*A*(rho*g)**n/(n+2)
    h_0=2**(n/(2*n+2))*(a/A_0)**(1/(2*n+2))*L**(1/2)
    h = h_0*(1-(abs(x)/L)**((n+1)/n))**(n/(2*n+2))
    return h


import note_events as ne

import json

class OngoingNote:
    # onset and duration in number of samples
    def __init__(self, onset: int, duration: int) -> None:
        self.onset: int = onset
        self.duration: int = duration

def parse_noteevents(digistring_results: str) -> ne.NoteEvents:
    note_events = ne.NoteEvents()

    # Read and parse the JSON file
    json_events = None
    try:
        with open(digistring_results) as file:
            json_events = json.load(file)
    except json.JSONDecodeError:
        print(f"'{digistring_results}' is not a valid JSON file")

    # JSON -> NoteEvents
    sample_rate = json_events["Sample rate (Hz)"]
    ongoing_notes = {}
    for event in json_events["note events"]:
        # No notes in frame
        if event["midi_number"] == None:
            # Flush all ongoing notes
            for on_midi, on_on in ongoing_notes.items():
                note_events.add_event(on_midi, on_on.onset / sample_rate, (on_on.onset + on_on.duration) / sample_rate)
            ongoing_notes = {}

        # If note was in previous frame...
        elif event["midi_number"] in ongoing_notes:
            matching_ongoing = ongoing_notes[event["midi_number"]]
            # ...and offset perfectly aligns with onset
            if matching_ongoing.onset + matching_ongoing.duration == event["note_start (samples)"]:
                # Extent the note event
                matching_ongoing.duration += event["note_duration (samples)"]
            elif matching_ongoing.onset + matching_ongoing.duration > event["note_start (samples)"]:
                # If the new note starts before the old one ends, invalid note overlap
                print("Warning: Overlapping note events; merging them into one...")
                print(f"Merged note {event['midi_number']} at [{matching_ongoing.onset / sample_rate}, {(matching_ongoing.onset + matching_ongoing.duration) / sample_rate}]"
                        + f" and [{event['note_start (s)']}, {event['note_start (s)'] + event['note_duration (s)']}]", end="")
                matching_ongoing.duration += event["note_duration (samples)"] - ((matching_ongoing.onset + matching_ongoing.duration) - event["note_start (samples)"])
                print(f" merged to [{matching_ongoing.onset / sample_rate}, {matching_ongoing.duration / sample_rate}]")
            else:
                # Space between notes, so flush old and start new
                note_events.add_event(event["midi_number"], matching_ongoing.onset / sample_rate, (matching_ongoing.onset + matching_ongoing.duration) / sample_rate)
                ongoing_notes[event["midi_number"]] = OngoingNote(event["note_start (samples)"], event["note_duration (samples)"])

        # Note is not in ongoing_notes
        else:
            # So add it
            ongoing_notes[event["midi_number"]] = OngoingNote(event["note_start (samples)"], event["note_duration (samples)"])

    # Flush all notes that were still ongoing at the end
    for on_midi, on_on in ongoing_notes.items():
        note_events.add_event(on_midi, on_on.onset / sample_rate, (on_on.onset + on_on.duration) / sample_rate)

    return note_events


from Player import Player
'''
Created on Feb 1, 2018

@author: Yishan McNabb
'''
import prompt

def drop_player(players):
    while True:
        dropping = prompt.for_string("Enter the name of player who is dropping or (d)one", is_legal= lambda x : x in [y.name for y in players] or x == 'd', error_message='Invalid player name.')
        if dropping == 'd':
            break;
        for i in range(len(players)):
            if dropping == players[i]:
                del players[i]

a = Player('a')
b = Player('b')
c = Player('a')
d = Player('b')

a.wins.append(b)
a.wins.append(c)
b.losses.append(a)
b.losses.append(c)

drop_player([a,b,c,d])


import tensorflow as tf
import sklearn
import sklearn.base
import sklearn.ensemble
import sklearn.svm
import numpy as np

import logging

class NeuralNetwork(
    tf.keras.Model,
    sklearn.base.ClassifierMixin):

    def __init__(self, channel_list, validation = False):
        super(NeuralNetwork, self).__init__()
        self.channel_list = channel_list
        self.validation = validation

        tf.get_logger().setLevel(logging.WARNING)
        tf.random.set_seed(42)
        self._dense_layers = []
        for i in range(len(channel_list) - 1):
            self._dense_layers.append(tf.keras.layers.Dense(channel_list[i], activation = tf.nn.swish, \
                kernel_regularizer = tf.keras.regularizers.l2(1e-4), name = 'dense_' + str(i)))
        self._dense_layers.append(tf.keras.layers.Dense(channel_list[len(channel_list) - 1], activation = tf.nn.softmax, name = 'softmax'))

    def call(self, inputs):
        x = inputs
        for dense in self._dense_layers:
            x = dense(x)
        return x

    def fit(self, x, y, user = [], batch_size = 32, epochs = 200):
        self._label = np.unique(y)
        _dict = {}
        for i in range(len(self._label)):
            _dict[self._label[i]] = i
        _y = []
        for i in range(len(y)):
            _y.append(_dict[y[i]])
        _y = np.array(_y, dtype = np.uint8)
        lr = tf.keras.optimizers.schedules.ExponentialDecay(1e-3, 60 * len(x), 0.5, staircase = True)
        self.compile(optimizer = tf.keras.optimizers.SGD(learning_rate = lr, momentum = 0.9), \
            loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits = True), \
            metrics = ['accuracy'])
        self.build(input_shape = (None, np.shape(x)[1]))
        self.summary()

        callbacks = [
            tf.keras.callbacks.CSVLogger('nn_history.csv')
        ]
        if self.validation and len(user) == len(x):
            user_group = np.unique(user)
            np.random.shuffle(user_group)
            x_train = x[user != user_group[0]]
            _y_train = _y[user != user_group[0]]
            x_val = x[user == user_group[0]]
            _y_val = _y[user == user_group[0]]
            super(NeuralNetwork, self).fit(x_train, _y_train, validation_data = (x_val, _y_val), \
                    batch_size = batch_size, epochs = epochs, callbacks = callbacks)
        else:
            super(NeuralNetwork, self).fit(x, _y, \
                batch_size = batch_size, epochs = epochs, callbacks = callbacks)
        return self

    def predict(self, x, batch_size = 32):
        _y_pred_prob = super(NeuralNetwork, self).predict(x, batch_size = batch_size)
        _y_pred = np.argmax(_y_pred_prob, axis = 1)
        return self._label[_y_pred]


studentTotal, subjectTotal = map(int, input().split())
result =[]

for _ in range(subjectTotal):
    subject = list(map(float, input().split()))

    result += [subject]

zipped = zip(*result)

for scores in zipped:
    average = (sum(scores) / len(scores))
    print(average)


# Python 3.7.4
# OpenCV-Python 4.5.3.56

import cv2
import tkinter as tk
from utils import rescale_frame, make_1080p

cap = cv2.VideoCapture(0)
make_1080p(cap)

while True:
    ret, frame = cap.read()
    grayFrame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Upscale / Downscale method 1
    root = tk.Tk()
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    root.destroy()
    WIDTH = screen_width / 2
    HEIGHT = screen_height / 2
    frame = cv2.resize(frame, (int(WIDTH), int(HEIGHT)))

    # Upscale / Downscale method 2
    grayFrame = rescale_frame(grayFrame, 30)

    cv2.imshow("Normal Frame", frame)
    cv2.imshow('Grayscale Frame', grayFrame)

    # waitKey() basically determines how long cv waits for press key 'a', set to 1
    # ord('a') closes the browsers on 'a' keypress
    if cv2.waitKey(1) & 0xFF == ord('a'):
        break

cap.release()
cv2.destroyAllWindows()


# -*- coding: utf-8 -*-
# Created on Fri Dec 14 2018 14:15:15
# Author: WuLC
# EMail: liangchaowu5@gmail.com

# compare char by char, pay attention to the case when one word is the prefix of another word
class Solution(object):
    def isAlienSorted(self, words, order):
        """
        :type words: List[str]
        :type order: str
        :rtype: bool
        """
        order_num = {}
        for i, c in enumerate(order):
            order_num[c] = i
        for i in xrange(len(words) - 1):
            equal = True
            for j in xrange(min(len(words[i]), len(words[i+1]))):
                if order_num[words[i][j]] < order_num[words[i+1][j]]:
                    equal = False
                    break
                elif order_num[words[i][j]] > order_num[words[i+1][j]]:
                    return False
            if equal and len(words[i]) > len(words[i+1]):
                return False
        return True

Algorithm/Python/953. Verifying an Alien Dictionary.py


import numpy as np
from numpy.random import  randint
from threading import Thread
import requests
from time import sleep
import json
class PutData:
    def __init__(self,url) -> None:
        self.url=url
        self.format={'mass_flow':'12.2'}# example of how the data is store
    def sent(self,dato):
        res= requests.post(self.url,data=dato)
        return res.status_code==200
class GenerarDatos(Thread):
    url='http://127.0.0.1:5000/connection/put_flow/'
    running=True
    putData=PutData(url)
    def run(self):
        while self.running:
            data=randint(9,60)
            data={'mass_flow':data}
            print('sent',self.putData.sent(data))
            sleep(4)

if __name__=='__main__':
    generador=GenerarDatos()
    generador.start()
    while True:

        key=input('pres c to exit: ')

        if key=='c':
            generador.running=False
            sleep(1)
            break


#lol efficiency
def is_palindrome(number, base):
    digits = []
    while number > 0:
        digits += [number % base]
        number //= base
    stigid = digits.copy()
    stigid.reverse()
    return digits == stigid
tot = 0
for i in range(10 ** 6):
    if is_palindrome(i,10) & is_palindrome(i, 2):
        tot += i

print(tot)


from . import matching
import numpy as np
import scipy.linalg

import numpy as np
from collections import OrderedDict

"""
Table for the 0.95 quantile of the chi-square distribution with N degrees of
freedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv
function and used as Mahalanobis gating threshold.
"""
chi2inv95 = {
    1: 3.8415,
    2: 5.9915,
    3: 7.8147,
    4: 9.4877,
    5: 11.070,
    6: 12.592,
    7: 14.067,
    8: 15.507,
    9: 16.919}

class KalmanFilter(object):
    """
    A simple Kalman filter for tracking bounding boxes in image space.

    The 8-dimensional state space

        x, y, a, h, vx, vy, va, vh

    contains the bounding box center position (x, y), aspect ratio a, height h,
    and their respective velocities.

    Object motion follows a constant velocity model. The bounding box location
    (x, y, a, h) is taken as direct observation of the state space (linear
    observation model).

    """

    def __init__(self):
        ndim, dt = 4, 1.

        # Create Kalman filter model matrices.
        self._motion_mat = np.eye(2 * ndim, 2 * ndim)
        for i in range(ndim):
            self._motion_mat[i, ndim + i] = dt
        self._update_mat = np.eye(ndim, 2 * ndim)

        # Motion and observation uncertainty are chosen relative to the current
        # state estimate. These weights control the amount of uncertainty in
        # the model. This is a bit hacky.
        self._std_weight_position = 1. / 20
        self._std_weight_velocity = 1. / 160

    def initiate(self, measurement):
        """Create track from unassociated measurement.

        Parameters
        ----------
        measurement : ndarray
            Bounding box coordinates (x, y, a, h) with center position (x, y),
            aspect ratio a, and height h.

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector (8 dimensional) and covariance matrix (8x8
            dimensional) of the new track. Unobserved velocities are initialized
            to 0 mean.

        """
        mean_pos = measurement
        mean_vel = np.zeros_like(mean_pos)
        mean = np.r_[mean_pos, mean_vel]

        std = [
            2 * self._std_weight_position * measurement[3],
            2 * self._std_weight_position * measurement[3],
            1e-2,
            2 * self._std_weight_position * measurement[3],
            10 * self._std_weight_velocity * measurement[3],
            10 * self._std_weight_velocity * measurement[3],
            1e-5,
            10 * self._std_weight_velocity * measurement[3]]
        covariance = np.diag(np.square(std))
        return mean, covariance

    def predict(self, mean, covariance):
        """Run Kalman filter prediction step.

        Parameters
        ----------
        mean : ndarray
            The 8 dimensional mean vector of the object state at the previous
            time step.
        covariance : ndarray
            The 8x8 dimensional covariance matrix of the object state at the
            previous time step.

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector and covariance matrix of the predicted
            state. Unobserved velocities are initialized to 0 mean.

        """
        std_pos = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-2,
            self._std_weight_position * mean[3]]
        std_vel = [
            self._std_weight_velocity * mean[3],
            self._std_weight_velocity * mean[3],
            1e-5,
            self._std_weight_velocity * mean[3]]
        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))

        #mean = np.dot(self._motion_mat, mean)
        mean = np.dot(mean, self._motion_mat.T)
        covariance = np.linalg.multi_dot((
            self._motion_mat, covariance, self._motion_mat.T)) + motion_cov

        return mean, covariance

    def project(self, mean, covariance):
        """Project state distribution to measurement space.

        Parameters
        ----------
        mean : ndarray
            The state's mean vector (8 dimensional array).
        covariance : ndarray
            The state's covariance matrix (8x8 dimensional).

        Returns
        -------
        (ndarray, ndarray)
            Returns the projected mean and covariance matrix of the given state
            estimate.

        """
        std = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-1,
            self._std_weight_position * mean[3]]
        innovation_cov = np.diag(np.square(std))

        mean = np.dot(self._update_mat, mean)
        covariance = np.linalg.multi_dot((
            self._update_mat, covariance, self._update_mat.T))
        return mean, covariance + innovation_cov

    def multi_predict(self, mean, covariance):
        """Run Kalman filter prediction step (Vectorized version).
        Parameters
        ----------
        mean : ndarray
            The Nx8 dimensional mean matrix of the object states at the previous
            time step.
        covariance : ndarray
            The Nx8x8 dimensional covariance matrics of the object states at the
            previous time step.
        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector and covariance matrix of the predicted
            state. Unobserved velocities are initialized to 0 mean.
        """
        std_pos = [
            self._std_weight_position * mean[:, 3],
            self._std_weight_position * mean[:, 3],
            1e-2 * np.ones_like(mean[:, 3]),
            self._std_weight_position * mean[:, 3]]
        std_vel = [
            self._std_weight_velocity * mean[:, 3],
            self._std_weight_velocity * mean[:, 3],
            1e-5 * np.ones_like(mean[:, 3]),
            self._std_weight_velocity * mean[:, 3]]
        sqr = np.square(np.r_[std_pos, std_vel]).T

        motion_cov = []
        for i in range(len(mean)):
            motion_cov.append(np.diag(sqr[i]))
        motion_cov = np.asarray(motion_cov)

        mean = np.dot(mean, self._motion_mat.T)
        left = np.dot(self._motion_mat, covariance).transpose((1, 0, 2))
        covariance = np.dot(left, self._motion_mat.T) + motion_cov

        return mean, covariance

    def update(self, mean, covariance, measurement):
        """Run Kalman filter correction step.

        Parameters
        ----------
        mean : ndarray
            The predicted state's mean vector (8 dimensional).
        covariance : ndarray
            The state's covariance matrix (8x8 dimensional).
        measurement : ndarray
            The 4 dimensional measurement vector (x, y, a, h), where (x, y)
            is the center position, a the aspect ratio, and h the height of the
            bounding box.

        Returns
        -------
        (ndarray, ndarray)
            Returns the measurement-corrected state distribution.

        """
        projected_mean, projected_cov = self.project(mean, covariance)

        chol_factor, lower = scipy.linalg.cho_factor(
            projected_cov, lower=True, check_finite=False)
        kalman_gain = scipy.linalg.cho_solve(
            (chol_factor, lower), np.dot(covariance, self._update_mat.T).T,
            check_finite=False).T
        innovation = measurement - projected_mean

        new_mean = mean + np.dot(innovation, kalman_gain.T)
        new_covariance = covariance - np.linalg.multi_dot((
            kalman_gain, projected_cov, kalman_gain.T))
        return new_mean, new_covariance

    def gating_distance(self, mean, covariance, measurements,
                        only_position=False, metric='maha'):
        """Compute gating distance between state distribution and measurements.
        A suitable distance threshold can be obtained from `chi2inv95`. If
        `only_position` is False, the chi-square distribution has 4 degrees of
        freedom, otherwise 2.
        Parameters
        ----------
        mean : ndarray
            Mean vector over the state distribution (8 dimensional).
        covariance : ndarray
            Covariance of the state distribution (8x8 dimensional).
        measurements : ndarray
            An Nx4 dimensional matrix of N measurements, each in
            format (x, y, a, h) where (x, y) is the bounding box center
            position, a the aspect ratio, and h the height.
        only_position : Optional[bool]
            If True, distance computation is done with respect to the bounding
            box center position only.
        Returns
        -------
        ndarray
            Returns an array of length N, where the i-th element contains the
            squared Mahalanobis distance between (mean, covariance) and
            `measurements[i]`.
        """
        mean, covariance = self.project(mean, covariance)
        if only_position:
            mean, covariance = mean[:2], covariance[:2, :2]
            measurements = measurements[:, :2]

        d = measurements - mean
        if metric == 'gaussian':
            return np.sum(d * d, axis=1)
        elif metric == 'maha':
            cholesky_factor = np.linalg.cholesky(covariance)
            z = scipy.linalg.solve_triangular(
                cholesky_factor, d.T, lower=True, check_finite=False,
                overwrite_b=True)
            squared_maha = np.sum(z * z, axis=0)
            return squared_maha
        else:
            raise ValueError('invalid distance metric')

class TrackState(object):
    New = 0
    Tracked = 1
    Lost = 2
    Removed = 3

class BaseTrack(object):
    _count = 0

    track_id = 0
    is_activated = False
    state = TrackState.New

    history = OrderedDict()
    features = []
    curr_feature = None
    score = 0
    start_frame = 0
    frame_id = 0
    time_since_update = 0

    # multi-camera
    location = (np.inf, np.inf)

    @property
    def end_frame(self):
        return self.frame_id

    @staticmethod
    def next_id():
        BaseTrack._count += 1
        return BaseTrack._count

    def activate(self, *args):
        raise NotImplementedError

    def predict(self):
        raise NotImplementedError

    def update(self, *args, **kwargs):
        raise NotImplementedError

    def mark_lost(self):
        self.state = TrackState.Lost

    def mark_removed(self):
        self.state = TrackState.Removed

class STrack(BaseTrack):
    shared_kalman = KalmanFilter()

    def __init__(self, tlwh, score):

        # wait activate
        self._tlwh = np.asarray(tlwh, dtype=np.float)
        self.kalman_filter = None
        self.mean, self.covariance = None, None
        self.is_activated = False

        self.score = score
        self.tracklet_len = 0

    def predict(self):
        mean_state = self.mean.copy()
        if self.state != TrackState.Tracked:
            mean_state[7] = 0
        self.mean, self.covariance = self.kalman_filter.predict(
            mean_state, self.covariance
        )

    @staticmethod
    def multi_predict(stracks):
        if len(stracks) > 0:
            multi_mean = np.asarray([st.mean.copy() for st in stracks])
            multi_covariance = np.asarray([st.covariance for st in stracks])
            for i, st in enumerate(stracks):
                if st.state != TrackState.Tracked:
                    multi_mean[i][7] = 0
            multi_mean, multi_covariance = STrack.shared_kalman.multi_predict(
                multi_mean, multi_covariance
            )
            for i, (mean, cov) in enumerate(zip(multi_mean, multi_covariance)):
                stracks[i].mean = mean
                stracks[i].covariance = cov

    def activate(self, kalman_filter, frame_id):
        """Start a new tracklet"""
        self.kalman_filter = kalman_filter
        self.track_id = self.next_id()
        self.mean, self.covariance = self.kalman_filter.initiate(
            self.tlwh_to_xyah(self._tlwh)
        )

        self.tracklet_len = 0
        self.state = TrackState.Tracked
        if frame_id == 1:
            self.is_activated = True
        # self.is_activated = True
        self.frame_id = frame_id
        self.start_frame = frame_id

    def re_activate(self, new_track, frame_id, new_id=False):
        self.mean, self.covariance = self.kalman_filter.update(
            self.mean, self.covariance, self.tlwh_to_xyah(new_track.tlwh)
        )
        self.tracklet_len = 0
        self.state = TrackState.Tracked
        self.is_activated = True
        self.frame_id = frame_id
        if new_id:
            self.track_id = self.next_id()
        self.score = new_track.score

    def update(self, new_track, frame_id):
        """
        Update a matched track
        :type new_track: STrack
        :type frame_id: int
        :type update_feature: bool
        :return:
        """
        self.frame_id = frame_id
        self.tracklet_len += 1

        new_tlwh = new_track.tlwh
        self.mean, self.covariance = self.kalman_filter.update(
            self.mean, self.covariance, self.tlwh_to_xyah(new_tlwh)
        )
        self.state = TrackState.Tracked
        self.is_activated = True

        self.score = new_track.score

    @property
    # @jit(nopython=True)
    def tlwh(self):
        """Get current position in bounding box format `(top left x, top left y,
        width, height)`.
        """
        if self.mean is None:
            return self._tlwh.copy()
        ret = self.mean[:4].copy()
        ret[2] *= ret[3]
        ret[:2] -= ret[2:] / 2
        return ret

    @property
    # @jit(nopython=True)
    def tlbr(self):
        """Convert bounding box to format `(min x, min y, max x, max y)`, i.e.,
        `(top left, bottom right)`.
        """
        ret = self.tlwh.copy()
        ret[2:] += ret[:2]
        return ret

    @staticmethod
    # @jit(nopython=True)
    def tlwh_to_xyah(tlwh):
        """Convert bounding box to format `(center x, center y, aspect ratio,
        height)`, where the aspect ratio is `width / height`.
        """
        ret = np.asarray(tlwh).copy()
        ret[:2] += ret[2:] / 2
        ret[2] /= ret[3]
        return ret

    def to_xyah(self):
        return self.tlwh_to_xyah(self.tlwh)

    @staticmethod
    # @jit(nopython=True)
    def tlbr_to_tlwh(tlbr):
        ret = np.asarray(tlbr).copy()
        ret[2:] -= ret[:2]
        return ret

    @staticmethod
    # @jit(nopython=True)
    def tlwh_to_tlbr(tlwh):
        ret = np.asarray(tlwh).copy()
        ret[2:] += ret[:2]
        return ret

    def __repr__(self):
        return "OT_{}_({}-{})".format(self.track_id, self.start_frame, self.end_frame)

class BYTETracker(object):
    def __init__(
        self,
        track_thresh=0.5,
        track_buffer=30,
        match_thresh=0.8,
        min_box_area=10,
        mot20=False,
        frame_rate=30,
    ):
        self.tracked_stracks = []  # type: list[STrack]
        self.lost_stracks = []  # type: list[STrack]
        self.removed_stracks = []  # type: list[STrack]

        self.frame_id = 0
        self.track_thresh = track_thresh
        self.track_buffer = track_buffer
        self.match_thresh = match_thresh
        self.min_box_area = min_box_area
        self.mot20 = mot20
        self.frame_rate = frame_rate

        # self.det_thresh = args.track_thresh
        # print(self.track_thresh)
        self.det_thresh = self.track_thresh + 0.1
        self.buffer_size = int(self.frame_rate / 30.0 * self.track_buffer)
        self.max_time_lost = self.buffer_size
        self.kalman_filter = KalmanFilter()

    def update(self, bboxes, scores):
        self.frame_id += 1
        activated_starcks = []
        refind_stracks = []
        lost_stracks = []
        removed_stracks = []

        remain_inds = scores > self.track_thresh
        inds_low = scores > 0.1
        inds_high = scores < self.track_thresh

        inds_second = np.logical_and(inds_low, inds_high)
        dets_second = bboxes[inds_second]
        dets = bboxes[remain_inds]
        scores_keep = scores[remain_inds]
        scores_second = scores[inds_second]

        if len(dets) > 0:
            """Detections"""
            detections = [
                STrack(STrack.tlbr_to_tlwh(tlbr), s)
                for (tlbr, s) in zip(dets, scores_keep)
            ]
        else:
            detections = []

        """ Add newly detected tracklets to tracked_stracks"""
        unconfirmed = []
        tracked_stracks = []  # type: list[STrack]
        for track in self.tracked_stracks:
            if not track.is_activated:
                # `unconfiremed`是self.track_thresh < score < self.det_thresh的框
                unconfirmed.append(track)
            else:
                tracked_stracks.append(track)

        """ Step 2: First association, with high score detection boxes"""
        strack_pool = joint_stracks(tracked_stracks, self.lost_stracks)
        # Predict the current location with KF
        STrack.multi_predict(strack_pool)
        dists = matching.iou_distance(strack_pool, detections)
        if not self.mot20:
            # 由于mot20与mot17不一样，mot17是采用人的全身框作为标签(尽管有遮挡)
            # mot20的标签不包括遮挡的部分
            # 对于mot20的设置，有遮挡的框通常置信度更低且框变小了
            # mot17尽管也有低置信度框，但是框一般不会变小
            # fuse_score操作就是抑制这些置信度低但是iou匹配度高的框
            # 避免了一些边框变小了的较低分框去影响匹配
            dists = matching.fuse_score(dists, detections)
        matches, u_track, u_detection = matching.linear_assignment(
            dists, thresh=self.match_thresh
        )

        for itracked, idet in matches:
            track = strack_pool[itracked]
            det = detections[idet]
            if track.state == TrackState.Tracked:
                track.update(detections[idet], self.frame_id)
                activated_starcks.append(track)
            else:
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)

        """ Step 3: Second association, with low score detection boxes"""
        # association the untrack to the low score detections
        if len(dets_second) > 0:
            """Detections"""
            detections_second = [
                STrack(STrack.tlbr_to_tlwh(tlbr), s)
                for (tlbr, s) in zip(dets_second, scores_second)
            ]
        else:
            detections_second = []
        r_tracked_stracks = [
            strack_pool[i]
            for i in u_track
            if strack_pool[i].state == TrackState.Tracked
        ]
        dists = matching.iou_distance(r_tracked_stracks, detections_second)
        matches, u_track, u_detection_second = matching.linear_assignment(
            dists, thresh=0.5
        )
        for itracked, idet in matches:
            track = r_tracked_stracks[itracked]
            det = detections_second[idet]
            if track.state == TrackState.Tracked:
                track.update(det, self.frame_id)
                activated_starcks.append(track)
            else:
                track.re_activate(det, self.frame_id, new_id=False)
                refind_stracks.append(track)

        for it in u_track:
            track = r_tracked_stracks[it]
            if not track.state == TrackState.Lost:
                track.mark_lost()
                lost_stracks.append(track)

        """Deal with unconfirmed tracks, usually tracks with only one beginning frame"""
        # 第一步未匹配到已有tracks的高分边框，
        # 再与之前初始化的高分边框但置信度小于`self.det_thresh`的track(unconfirmed)匹配
        detections = [detections[i] for i in u_detection]
        dists = matching.iou_distance(unconfirmed, detections)
        if not self.mot20:
            dists = matching.fuse_score(dists, detections)
        matches, u_unconfirmed, u_detection = matching.linear_assignment(
            dists, thresh=0.7
        )
        for itracked, idet in matches:
            unconfirmed[itracked].update(detections[idet], self.frame_id)
            activated_starcks.append(unconfirmed[itracked])
        for it in u_unconfirmed:
            track = unconfirmed[it]
            track.mark_removed()
            removed_stracks.append(track)

        """ Step 4: Init new stracks"""
        for inew in u_detection:
            track = detections[inew]
            # 初始化新的tracks的时候，如果框的置信度低于`self.det_thresh`，
            # 则不激活，而是`unconfirmed`状态
            if track.score < self.det_thresh:
                continue
            track.activate(self.kalman_filter, self.frame_id)
            activated_starcks.append(track)
        """ Step 5: Update state"""
        for track in self.lost_stracks:
            if self.frame_id - track.end_frame > self.max_time_lost:
                track.mark_removed()
                removed_stracks.append(track)

        # print('Ramained match {} s'.format(t4-t3))

        self.tracked_stracks = [
            t for t in self.tracked_stracks if t.state == TrackState.Tracked
        ]
        self.tracked_stracks = joint_stracks(self.tracked_stracks, activated_starcks)
        self.tracked_stracks = joint_stracks(self.tracked_stracks, refind_stracks)
        self.lost_stracks = sub_stracks(self.lost_stracks, self.tracked_stracks)
        self.lost_stracks.extend(lost_stracks)
        self.lost_stracks = sub_stracks(self.lost_stracks, self.removed_stracks)
        self.removed_stracks.extend(removed_stracks)
        self.tracked_stracks, self.lost_stracks = remove_duplicate_stracks(
            self.tracked_stracks, self.lost_stracks
        )
        # get scores of lost tracks
        output_stracks = [track for track in self.tracked_stracks if track.is_activated]

        return output_stracks

def joint_stracks(tlista, tlistb):
    exists = {}
    res = []
    for t in tlista:
        exists[t.track_id] = 1
        res.append(t)
    for t in tlistb:
        tid = t.track_id
        if not exists.get(tid, 0):
            exists[tid] = 1
            res.append(t)
    return res

def sub_stracks(tlista, tlistb):
    stracks = {}
    for t in tlista:
        stracks[t.track_id] = t
    for t in tlistb:
        tid = t.track_id
        if stracks.get(tid, 0):
            del stracks[tid]
    return list(stracks.values())

def remove_duplicate_stracks(stracksa, stracksb):
    pdist = matching.iou_distance(stracksa, stracksb)
    pairs = np.where(pdist < 0.15)
    dupa, dupb = list(), list()
    for p, q in zip(*pairs):
        timep = stracksa[p].frame_id - stracksa[p].start_frame
        timeq = stracksb[q].frame_id - stracksb[q].start_frame
        if timep > timeq:
            dupb.append(q)
        else:
            dupa.append(p)
    resa = [t for i, t in enumerate(stracksa) if not i in dupa]
    resb = [t for i, t in enumerate(stracksb) if not i in dupb]
    return resa, resb


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

# Define here the models for your scraped items
#
# See documentation in:
# http://doc.scrapy.org/en/latest/topics/items.html

import scrapy
import datetime
import json

from k_util.time_op import get_time_str_unique, TZ_LOCAL, convert_time_obj_to_time_str, TIME_FORMAT_FOR_FILE

class MusicWebSpiderItem(scrapy.Item):
    page_type = scrapy.Field()
    category = scrapy.Field()
    update_time = scrapy.Field()
    update_time_str = scrapy.Field()
    page_url = scrapy.Field()
    title = scrapy.Field()
    cover_url = scrapy.Field()
    desc = scrapy.Field()
    author = scrapy.Field()
    label = scrapy.Field()
    label_list = scrapy.Field()

    def set_values(self, page_type, category, update_time=None, update_time_str=None, page_url=None, title=None,
                   cover_url=None, desc=None, author=None, label=None, label_list=None):
        if not update_time or not update_time_str:
            t = datetime.datetime.now(tz=TZ_LOCAL)
            update_time = t
            update_time_str = get_time_str_unique(convert_time_obj_to_time_str(t, TIME_FORMAT_FOR_FILE))
        self['page_type'] = page_type
        self['category'] = category
        self['update_time'] = update_time
        self['update_time_str'] = update_time_str
        self['page_url'] = page_url or ''
        self['title'] = title or ''
        self['cover_url'] = cover_url or ''
        self['desc'] = desc or ''
        self['author'] = author or ''
        self['label'] = label or ''
        self['label_list'] = label_list or ''

class MusicWebSpiderItemJEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return convert_time_obj_to_time_str(obj)
        # Let the base class default method raise the TypeError
        return json.JSONEncoder.default(self, obj)


from .keyboards import *
from RACK.parsers.number import *
from .Callback_to_user import *
import random
import time

sl_of_users = dict()  # Надо сделать бд
bot = telebot.TeleBot('1136386527:AAFRT-Oq7BzF0RjEfIxkyqF2JGWHwB0qfOg')

@bot.message_handler(commands=['start'])
def start_message(message):
    bot.send_message(message.chat.id, 'Этот бот определяет существует ли такой телефонный номер!', reply_markup=key1)

@bot.message_handler(commands=['error'])
def analytics_message(message):
    bot.send_message(message.chat.id, 'Что вы хотите отправить богу (админу)?')
    sl_of_users[message.chat.id] = True

@bot.message_handler(commands=['hack'])
def hack(message):
    bot.send_message(message.chat.id, 'Взлом пентагона начался! 😎')
    time.sleep(1)
    x = 0
    while x < 100:

        try:
            bot.edit_message_text(f'Процесс взлома завершен на {x}%...', message.chat.id, message.message_id + 1)
            time.sleep(0.3)
            x += random.randint(1, 4)
        except:
            pass
    bot.edit_message_text('Пентагон взломаааан! 😎', message.chat.id, message.message_id + 1)
    bot.send_message(message.chat.id)

@bot.message_handler(content_types=['text'])
def text_mes(message):
    n = is_num(message.text)
    if n[0]:
        bot.send_message(message.chat.id, f'Верно ли введен номер телефона? \n{n[1]}', reply_markup=key2)
    elif sl_of_users[message.chat.id]:
        send_analytic(message, 'CARAMBOJAbot')
        bot.send_message(message.chat.id, 'Успешно отправлено', reply_markup=key1)
        sl_of_users[message.chat.id] = False
    elif message.chat.id == 380907452:
        try:
            moy = message.text.split('\n')
            bot.send_message(int(moy[0]), moy[1])
        except IndexError:
            bot.send_message(message.chat.id, 'Мой царь, у меня что-то не получилось')

@bot.message_handler(content_types=['audio', 'photo', 'voice', 'video', 'document', 'location', 'contact', 'sticker'])
def except_message(message):
    bot.send_message(message.chat.id, 'Извините, я принимаю только текстовые сообщения')

@bot.callback_query_handler(func=lambda call: True)
def callbacks(call):
    if 'number' in call.data:
        numb = call.message.text.split('\n')[1]
        if call.data == 'number.all_inf':
            bot.send_message(call.message.chat.id, f'Оператор сети: {oper(numb)}\n'
                                                   f'Регион: {reg(numb)}')
        elif call.data == 'number.reg':
            bot.send_message(call.message.chat.id, f'Регион: {reg(numb)}')
        elif call.data == 'number.operator':
            bot.send_message(call.message.chat.id, f'Оператор сети: {oper(numb)}')
        bot.answer_callback_query(call.id)

def is_num(text):
    list_to_replace = ['(', ')', '-', '+']
    for i in list_to_replace:
        text = text.replace(i, '')
    if len(text) == 11:
        if text.isdigit():
            if text[0] == '7':
                return True, f'8{text[1::]}'
            elif text[0] == '8':
                return True, text
    return False, '0'


from typing import List

import setuptools

from carsimg.constants import VERSION

def _requires_from_file(filename: str) -> List[str]:
    return open(filename).read().splitlines()

setuptools.setup(
    name="carsimg",
    version=VERSION,
    install_requires=_requires_from_file('requirements.txt'),
    author="Hiroaki Takahashi",
    author_email="aphiloboe@gmail.com",
    url="https://github.com/MiLL4U/carsimg",
    description="GUI application for controll CARS imaging system",
    packages=setuptools.find_packages(),
    package_data={"carsimg": ["ui/image/*"]},
    classifiers=[
        "Programming Language :: Python :: 3",
        'Operating System :: Microsoft :: Windows',
    ],
    python_requires='>=3.10',
)


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

from pytest_xmlcomp.plugin import stringifylist
from lxml import etree
import pytest

def test_pytest_collect_good_files(good_dir):
    result = good_dir.runpytest("-vs")
    assert result.ret == 0

def test_pytest_collect_bad_files(bad_dir):
    result = bad_dir.runpytest("-vs")
    assert result.ret == 1

@pytest.mark.parametrize("test_input, expected", [
        ([etree.Comment('foobar')], ['<!--foobar-->']),
        ([etree.ProcessingInstruction("instruction")], ['<?instruction?>']),
        ([etree.Element('foobar')], ['<foobar>']),
        (['simplestring'], ['simplestring']),
        ([etree._ElementUnicodeResult("foo")], ['foo'])
    ])
def test_stringifylist(test_input, expected):
    res = stringifylist(test_input)
    assert res == expected

def test_repr_failure_good_data(good_dir):
    result = good_dir.runpytest()
    assert result.ret == 0

def test_repr_failure_bad_data(bad_dir):
    result = bad_dir.runpytest()
    result.stdout.fnmatch_lines([
        "XPath execution failed"
    ])
    assert result.ret == 1

def test_pytest_xmlcomp_transform_xml(good_dir):
    good_dir.makeconftest("""
    def pytest_xmlcomp_transform_xml(xmlfile):
        from lxml import etree
        tree = etree.parse(source = str(xmlfile))
        return tree
    """)
    result = good_dir.runpytest("-sv")
    assert result.ret == 0

def test_XMLSyntaxError(xml_synerror_dir):
    result = xml_synerror_dir.runpytest("-sv")
    result.stderr.fnmatch_lines([
        "XML Syntax Error in file*"
        ])
    assert result.ret == 2

def test_XMLSyntaxError_with_Namespaces(xml_synerror_nsp_dir):
    result = xml_synerror_nsp_dir.runpytest("-sv")
    result.stderr.fnmatch_lines([
        "XML Syntax Error in file*"
        ])
    assert result.ret == 2

def test_JSONSyntaxError(json_synerror_dir):
    result = json_synerror_dir.runpytest("-sv")
    result.stderr.fnmatch_lines([
        "JSON Syntax Error in file*"
        ])
    assert result.ret == 5

def test_JSONSyntaxError_with_Namespaces(json_synerror_namespaces_dir):
    result = json_synerror_namespaces_dir.runpytest("-sv")
    result.stderr.fnmatch_lines([
        "JSON Syntax Error in file*"
        ])
    assert result.ret == 5

def test_goodfiles_with_namespaces(good_namespaces_dir):
    result = good_namespaces_dir.runpytest("-sv")
    assert result.ret == 0

def test_badfiles_with_namespaces(bad_namespaces_dir):
    result = bad_namespaces_dir.runpytest("-sv")
    assert result.ret == 1


from collections import Counter
from pathlib import Path
from typing import List

DATA_PATH = Path(__file__).resolve().parents[1] / "data"

def read_input(path: Path) -> List[int]:
    return list(map(int, path.read_text().strip("\n").split("\n")))

def main(problem_number: int):
    data = read_input(DATA_PATH / f"input_{problem_number}.txt")

    # Part 1
    counter = Counter(list(a < b for a, b in zip(data[:-1], data[1:])))
    print(counter[True])

    # Part 2
    counter = Counter(list(a < b for a, b in zip(data[:-3], data[3:])))
    print(counter[True])


"""This module prepares ``bioagel.dta`` to extract events of unplanned
pregnancy and birth of children with disorders.

"""
from collections import OrderedDict

import numpy as np
import pandas as pd

from bld.project_paths import project_paths_join as ppj

NAN_IDENTIFIERS = [
    "[-1] keine Angabe",
    "[-2] trifft nicht zu",
    "[-3] nicht valide",
    "[-5] In Fragebogenversion nicht enthalten",
    "[-8] Frage in diesem Jahr nicht Teil des Frageprograms",
]

MONTH_DICT = OrderedDict(
    [
        ("[1] Januar", "January"),
        ("[2] Februar", "February"),
        ("[3] Maerz", "March"),
        ("[4] April", "April"),
        ("[5] Mai", "May"),
        ("[6] Juni", "June"),
        ("[7] Juli", "July"),
        ("[8] August", "August"),
        ("[9] September", "September"),
        ("[10] Oktober", "October"),
        ("[11] November", "November"),
        ("[12] Dezember", "December"),
    ]
)

VARIABLE_DICT_BIOAGEL = {
    # 'hhnr': 'ID_ORIGINAL_HH',  # original household id
    "hhnrakt": "ID_HH",  # current household ID
    "persnr": "ID_CHILD",
    "persnre": "ID_MOTHER",  # never changing personal ID of mother
    "syear": "YEAR",  # survey year
    # 'paround': 'INT_PARENTS_AROUND',
    "prebeg": "PREGNANCY_START",  # begin of pregnancy
    "preend": "PREGNANCY_END",  # end of pregnancy
    # 'fathinhh': 'FATHER_IN_HH',  # father lives in hh
    "pregplan": "PREGNANCY_UNPLANNED",  # pregnancy planned or unplanned
    "birthm": "CHILD_BIRTH_MONTH",  # month of birth of child
    "birthy": "CHILD_BIRTH_YEAR",  # year of birth of child
    "disord": "CHILD_DISORDER",  # does the child have disorders
    # 'disordu_fid': 'CHILD_DISORDER_CONFIRMED',  # first U exam confirming
    # disorder
    # 'disord1': 'DISORDERS_PERCEPTION',
    # 'disord2': 'DISORDERS_MOTOR',
    # 'disord3': 'DISORDERS_NEUROLOGIC',
    # 'disord4': 'DISORDERS_LANGUAGE',
    # 'disord5': 'DISORDERS_REGULATION',
    # 'disord6': 'DISORDERS_CHRONIC_ILLNESS',
    # 'disord7': 'DISORDERS_PHSYSICAL',
    # 'disord8': 'DISORDERS_MENTAL',
    # 'disord9': 'DISORDERS_OTHER',
    "pregy": "MOTHER_PREGNANT_AT_PQ_YEAR",  # mother was pregnant when taking
    # personal questionnaire
    # 'pregmo': 'MOTHER_PREGNANT_AT_PQ_MONTH_PREGNANCY',  # month of pregnancy
    # when taking pq
    # 'specned8_fid': 'CHILD_LL_DISEASE',  # long-lasting disease
}

RETAINED_COLUMNS_BIOAGEL = list(VARIABLE_DICT_BIOAGEL.keys())

def prepare_bioagel():
    # Read the data and rename columns
    df = pd.read_stata(ppj("IN_DATA", "bioagel.dta"), columns=RETAINED_COLUMNS_BIOAGEL)
    df = df.rename(columns=VARIABLE_DICT_BIOAGEL)
    # Keep only data from 2004 to 2015, we need 2004 for the full pregnancy
    # spell
    df = df.loc[df.YEAR.between(2004, 2015)]
    df.sort_values(["ID_CHILD", "YEAR"], axis="rows", inplace=True)
    df = df.groupby("ID_CHILD", as_index=False).first()

    # Extract year number to determine whether mother was pregnant at the time
    # of the interview
    df.MOTHER_PREGNANT_AT_PQ_YEAR = df.MOTHER_PREGNANT_AT_PQ_YEAR.str.extract(
        r"\[(\d+)\]", expand=False
    )
    df.MOTHER_PREGNANT_AT_PQ_YEAR = df.MOTHER_PREGNANT_AT_PQ_YEAR.astype(float)

    # Convert values of CHILD_BIRTH_MONTH to real months
    child_birth_month_values = list(df.CHILD_BIRTH_MONTH.unique())
    child_birth_month_dict = {
        k: MONTH_DICT[v]
        for v in MONTH_DICT
        for k in child_birth_month_values
        if k in v.casefold()
    }
    child_birth_month_dict.update(
        {"[-1] keine Angabe": np.nan, "[-2] trifft nicht zu": np.nan}
    )
    df.CHILD_BIRTH_MONTH.replace(child_birth_month_dict, inplace=True)
    df.CHILD_BIRTH_MONTH = df.CHILD_BIRTH_MONTH.astype("category")
    df.CHILD_BIRTH_MONTH.cat.set_categories(
        MONTH_DICT.values(), ordered=True, inplace=True
    )

    # Create PREGNANCY_START_YEAR and _MONTH
    pregstart = (
        df.PREGNANCY_START.str.split(" ", n=2, expand=True)
        .drop(0, axis=1)
        .fillna(value=np.nan)
    )
    pregstart = pregstart.rename(
        columns={1: "PREGNANCY_START_YEAR", 2: "PREGNANCY_START_MONTH"}
    )
    # Rename monthly values by comparing short values to the keys of MONTH_DICT
    # and then the values of MONTH_DICT to map them to MONTH_DICT values
    month_values = pregstart.PREGNANCY_START_MONTH.unique()
    month_values = month_values[pd.notnull(month_values)]
    correct_month_mapping = {
        k: MONTH_DICT[v]
        for v in MONTH_DICT
        for k in month_values
        if k.casefold() in v.casefold()
    }
    correct_month_mapping.update(
        {
            k: MONTH_DICT[v]
            for v in MONTH_DICT
            for k in month_values
            if k.casefold() in MONTH_DICT[v].casefold()
        }
    )
    pregstart.PREGNANCY_START_MONTH.replace(correct_month_mapping, inplace=True)

    # Create PREGNANCY_END_YEAR and _MONTH
    pregend = (
        df.PREGNANCY_END.str.split(" ", n=2, expand=True)
        .drop(0, axis=1)
        .fillna(value=np.nan)
    )
    pregend = pregend.rename(
        columns={1: "PREGNANCY_END_YEAR", 2: "PREGNANCY_END_MONTH"}
    )
    # Rename monthly values by comparing short values to the keys of MONTH_DICT
    # and then the values of MONTH_DICT to map them to MONTH_DICT values
    month_values = pregend.PREGNANCY_END_MONTH.unique()
    month_values = month_values[pd.notnull(month_values)]
    correct_month_mapping = {
        k: MONTH_DICT[v]
        for v in MONTH_DICT
        for k in month_values
        if (k.casefold() in v.casefold())
    }
    correct_month_mapping.update(
        {
            k: MONTH_DICT[v]
            for v in MONTH_DICT
            for k in month_values
            if k.casefold() in MONTH_DICT[v].casefold()
        }
    )
    pregend.PREGNANCY_END_MONTH.replace(correct_month_mapping, inplace=True)

    df = pd.concat([df, pregstart, pregend], axis="columns").drop(
        ["PREGNANCY_START", "PREGNANCY_END"], axis="columns"
    )
    # Cast new variables to the correct types and set ordered
    df.PREGNANCY_START_MONTH = df.PREGNANCY_START_MONTH.astype("category")
    df.PREGNANCY_START_MONTH.cat.set_categories(
        MONTH_DICT.values(), ordered=True, inplace=True
    )
    df.PREGNANCY_START_YEAR = pd.to_numeric(df.PREGNANCY_START_YEAR, errors="coerce")
    df.PREGNANCY_END_MONTH = df.PREGNANCY_END_MONTH.astype("category")
    df.PREGNANCY_END_MONTH.cat.set_categories(
        MONTH_DICT.values(), ordered=True, inplace=True
    )
    df.PREGNANCY_END_YEAR = pd.to_numeric(df.PREGNANCY_END_YEAR, errors="coerce")

    return df

def create_preg(df):
    # Identify an event of an unplanned pregnancy with the begin of the
    # pregnancy
    pregnancy_unplanned = {
        "[2] eher geplant": np.nan,
        "[1] eher ungeplant": True,
        "[3] erfolgte mit med. unterstuetzung": np.nan,
    }
    df.PREGNANCY_UNPLANNED.replace(pregnancy_unplanned, inplace=True)
    # Replace PREGNANCY_UNPLANNED with the month of the begin of the pregnancy
    df.loc[
        df.PREGNANCY_UNPLANNED.notnull(), "PREGNANCY_UNPLANNED_MONTH"
    ] = df.PREGNANCY_START_MONTH
    # Cast the variables to the appropriate types
    df.PREGNANCY_UNPLANNED_MONTH = df.PREGNANCY_UNPLANNED_MONTH.astype("category")
    df.PREGNANCY_UNPLANNED_MONTH.cat.set_categories(
        MONTH_DICT.values(), ordered=True, inplace=True
    )

    # Copy the necessary content
    preg = df[
        [
            "ID_HH",
            "ID_MOTHER",
            "PREGNANCY_UNPLANNED_MONTH",
            "PREGNANCY_START_YEAR",
            "MOTHER_PREGNANT_AT_PQ_YEAR",
        ]
    ].copy()
    # Restrict to events
    preg = preg.loc[preg.PREGNANCY_UNPLANNED_MONTH.notnull()]
    # Rename columns to match panel
    preg_columns = {"PREGNANCY_START_YEAR": "YEAR"}
    preg = preg.rename(columns=preg_columns)
    # Drop pregnancies which begin in 2004
    preg = preg.loc[preg.YEAR.between(2005, 2015)]
    # Drop pregnancies which were known at the time of the interview in 2005
    preg = preg.loc[~(preg.MOTHER_PREGNANT_AT_PQ_YEAR == 2005)]
    # We cannot drop pregnancies not known at the time of the pq in 2015 since
    # MOTHER_PREGNANT_AT_PQ_YEAR contains too much NaNs. The rest has to be
    # examined in comparison to INT_MONTH

    # There are 16 siblings with disabilities in our sample which leads to
    # the problem of two occurrences per ID and YEAR. Unfortunately, we cannot
    # handle this cases right now. Therefore, we drop the duplicates and save
    # them in another file to adjust the counts of events later.
    preg.loc[preg.duplicated(subset=["ID_MOTHER", "YEAR"])].to_pickle(
        ppj("OUT_DATA", "preg_siblings.pkl")
    )
    preg.drop_duplicates(subset=["ID_MOTHER", "YEAR"], inplace=True)

    # Save data
    preg.to_pickle(ppj("OUT_DATA", "preg.pkl"))

def create_dis(df):
    # Identify an event of an unplanned pregnancy with month of birth
    child_disorder = {
        "[1] ja, bei U(1-6) Untersuchung": True,
        "[2] ja, bei anderer Untersuchung": True,
        "[3] nein": np.nan,
    }
    df.CHILD_DISORDER.replace(child_disorder, inplace=True)
    # Replace CHILD_DISORDER with the month of birth
    df.loc[df.CHILD_DISORDER.notnull(), "CHILD_DISORDER_MONTH"] = df.CHILD_BIRTH_MONTH
    # Cast variable to the appropriate type
    df.CHILD_DISORDER_MONTH = df.CHILD_DISORDER_MONTH.astype("category")
    df.CHILD_DISORDER_MONTH.cat.set_categories(
        MONTH_DICT.values(), ordered=True, inplace=True
    )

    # Copy the necessary content
    dis = df[
        [
            "ID_HH",
            "ID_MOTHER",
            "CHILD_DISORDER_MONTH",
            "PREGNANCY_END_YEAR",
            "MOTHER_PREGNANT_AT_PQ_YEAR",
        ]
    ].copy()
    # Restrict to events
    dis = dis.loc[dis.CHILD_DISORDER_MONTH.notnull()]
    # Rename columns to match panel
    dis_columns = {"PREGNANCY_END_YEAR": "YEAR"}
    dis = dis.rename(columns=dis_columns)
    # Drop births in 2004
    dis = dis.loc[dis.YEAR.between(2005, 2015)]
    # There are 9 siblings with disabilities in our sample which leads to
    # the problem of two occurrences per ID and YEAR. Unfortunately, we cannot
    # handle this cases right now. Therefore, we drop the duplicates and save
    # them in another file to adjust the counts of events later.
    dis.loc[dis.duplicated(subset=["ID_MOTHER", "YEAR"])].to_pickle(
        ppj("OUT_DATA", "dis_siblings.pkl")
    )
    dis.drop_duplicates(subset=["ID_MOTHER", "YEAR"], inplace=True)

    dis.to_pickle(ppj("OUT_DATA", "dis.pkl"))

if __name__ == "__main__":
    # Prepare ``bioagel.dta``
    df = prepare_bioagel()
    # Create ``preg.pkl``
    create_preg(df)
    # Create ``dis.pkl``
    create_dis(df)


case = int(input())
lists = []
for i in range(case) :
    lists.append(input())

counting= 0

for i in lists :
    before = i[0]
    review = []
    breakout = False
    for j in i:
        if j != before and j in review :
            breakout = True
            break
        else :
            review.append(j)
            before = j
    if breakout == False:
        counting +=1

print(counting)