import random
from typing import Dict, List, Tuple, Union

from transtool.checks.base.check import Check
from transtool.checks.starts_with_the_same_case import StartsWithTheSameCase
from transtool.decorators.overrides import overrides
from transtool.prop.file import PropFile
from transtool.prop.items import Translation
from transtool.utils import Utils
from tests.checks.checks_test_case import ChecksTestCase

class TestStartsWithTheSameCase(ChecksTestCase):

    @overrides(ChecksTestCase)
    def get_checker(self, config: Union[Dict, None] = None) -> Check:
        return StartsWithTheSameCase(config)

    # #################################################################################################

    def test_no_faults(self) -> None:
        cnt_min = 20
        cnt_max = 40
        keys = [self.get_random_string('key') for _ in range(random.randint(cnt_min, cnt_max))]

        ref_file = PropFile(self.config)
        trans_file = PropFile(self.config)
        for key in keys:
            value = self.get_random_string()
            ref_file.append(Translation(key, value))
            trans_file.append(Translation(key, value))

        self.check(trans_file, ref_file)

    def test_with_faults(self) -> None:
        cnt_min = 20
        cnt_max = 40
        keys = [self.get_random_string('key') for _ in range(random.randint(cnt_min, cnt_max))]

        expected_faults = 0

        ref_file = PropFile(self.config)
        trans_file = PropFile(self.config)
        for key in keys:
            ref_value = self.get_random_string()
            trans_value = ref_value

            # FIXME: there's slight chance that we will have 1s for whole run...
            if random.randint(0, 1) == 1:
                expected_faults += 1
                if ref_value[0].isupper():
                    trans_value = Utils.lower_first(trans_value)
                else:
                    trans_value = Utils.upper_first(trans_value)
            ref_file.append(Translation(key, ref_value))
            trans_file.append(Translation(key, trans_value))
        self.check(trans_file, ref_file, exp_warnings = expected_faults)

    def _do_scan_test(self, tests: List[Tuple[str, str]], exp_warnings = 0):
        for ref_value, trans_value in tests:
            ref_file = PropFile(self.config)
            trans_file = PropFile(self.config)
            key = self.get_random_string('key')
            ref_file.append(Translation(key, ref_value))
            trans_file.append(Translation(key, trans_value))
            self.check(trans_file, ref_file, exp_warnings = exp_warnings)

    def test_valid_special_cases(self) -> None:
        """
        Checks is checker will correctly compare sequences starting
        with alphabetic characters, no matter where they are located
        in the strings.
        """
        tests = [
            # These should be matched correctly.
            ('%s Statistics', 'Statystyki %s'),
            ('%s statistics', '123 statystyki %s'),
            ('%s 123 Statistics', 'Statystyki %s'),
        ]
        self.checker.config['accept_digits'] = False
        self._do_scan_test(tests, 0)

    def test_fault_special_cases(self) -> None:
        tests = [
            ('%s Statistics', 'statystyki %s'),
            ('%s statistics', '123 Statystyki %s'),
            ('%s 123 tatistics', 'Statystyki %s'),

            # Base has no real words, while translation has some.
            ('123 123 123', 'Some words here'),

            # Base has words, translation does not.
            ('Some words here', '123 123 123'),
        ]
        self.checker.config['accept_digits'] = False
        self._do_scan_test(tests, 1)

    def test_no_alpha_words(self) -> None:
        tests = [
            # These should be skipped silently.
            ('', ''),
            # No real words. This should be skipped silently.
            ('3434 3434 34', '123 123 123'),
        ]
        self.checker.config['accept_digits'] = False
        self._do_scan_test(tests)

    # #################################################################################################

    def test_opening_digits(self) -> None:
        tests = [
            ('Upper', '12345 lower'),
            ('12345 Upper', 'lower'),
            ('12345 Upper', '345345 lower'),
        ]
        self.checker.config['accept_digits'] = False
        self._do_scan_test(tests, exp_warnings = 1)

        self.checker.config['accept_digits'] = True
        self._do_scan_test(tests)

    # #################################################################################################

    def test_handling_of_unsupported_types(self) -> None:
        self.check_skipping_blank_and_comment()

    def test_handling_of_dangling_translation_keys(self) -> None:
        self.check_skipping_of_dangling_keys()

    def test_skipping_of_entry_items(self) -> None:
        """
        Checks if item is silently skipped if its value is empty string or value of reference
        string is empty.
        :return:
        """
        # generate some keys for translation file
        cnt_min = 20
        cnt_max = 40
        keys = [self.get_random_string('key') for _ in range(random.randint(cnt_min, cnt_max))]

        ref_file = self.build_propfile(keys, lower = True)
        trans_file = self.build_propfile(keys, lower = True)

        # Let's clear some values in both files
        upper_bound = 10
        for _ in range(random.randint(1, upper_bound)):
            ref_idx = random.randrange(len(ref_file.items))
            ref_file.items[ref_idx].value = ''

            trans_idx = random.randrange(len(trans_file.items))
            trans_file.items[trans_idx].value = ''

        # We expect no problems.
        self.check(trans_file, ref_file)


'''
It determines the sequence for the knight to reach all the squares in a n*n board without repetitions, starting from a corner.
'''
import sys
sys.setrecursionlimit(100_000)

MOVES = [(0, 0), (-1, -2), (1, -2), (2, -1), (2, 1), (-1, 2), (1, 2), (-2, -1), (-2, 1)]
#i = y * n + x

def solve(board, n, x, y, order):
    board[y * n + x] = order
    for dx, dy in MOVES:
        if(not is_solved(board, n)):
            board = reset_board(board, n, order)
            x1, y1 = x+dx, y+dy
            if 0 <= x1 < n and 0 <= y1 < n and board[y1 * n + x1] == 0:
                board = solve(board, n, x1, y1, order+1)

    return board

def reset_board(board, n, order): #setta a 0 le caselle col valore > dell'order
    for i in range(n*n):
        if board[i] > order:
            board[i] = 0
    return board

def is_solved(board, n):
    b = board[:]
    b.sort()
    for i in range(n*n):
        if b[i] != i+1:
            return False
    return True

def print_board(board, n):
    for y in range(n):
        for x in range(n):
            print(board[y * n + x], end="\t")
        print()

n=5
board = [0] * (n * n)

solved_board = solve(board, n, 0, 0, 1)

print_board(solved_board, n)


#!/usr/bin/env python3
#
# update-blt-screws-ztilt-cfg.py
#
# This script sets your [bltouch]
# [screws_tilt_adjust] settings
# with x,y offsets and screw positions set
# in the script or with the x,y offsets
# stated on the command line.  It writes
# new files as specified by the OUTFILES
# variable.
#
# Thanks to SourPickel for being a guinea pig
# As he said, YOLO.
#
# No lead screws were broken (yet) as a result
# of this script.
#
# Created July 25, 2021
# Modified September 3, 2022

from email import message
import sys
from datetime import datetime
from update_cfg_conf import *

def f_fmt(val, places=1):
    'Format value to fixed number of decimal places'
    float_fmt = '%%.0%sf' % places
    return float_fmt % val

offset = {
    'x': float(X_OFF),
    'y': float(Y_OFF),
    'cfg_x': f_fmt(X_OFF),
    'cfg_y': f_fmt(Y_OFF)
}

if len(sys.argv) > 3:
    print('Too many arguments.\nNeed BLT X offset and BLT Y offset')
elif len(sys.argv) == 1:
    print('Using default x and y offset values: (%s, %s)' % (offset['cfg_x'], offset['cfg_y']))

else:
    offset = {
        'x': float(sys.argv[1]),
        'y': float(sys.argv[2]),
        'cfg_x': f_fmt(sys.arg[1]),
        'cfg_y': f_fmt(sys.argv[2])
    }
    print('Using x and y offsets overrides (%s, %s)' % (offset['cfg_x'], offset['cfg_y']))

ZT_POS_X_MIN = f_fmt(ZT_BED_X_MIDPT - ZT_STEPPER_X_MIDPT - offset['x'])
ZT_POS_X_MAX = f_fmt(ZT_BED_X_MIDPT + ZT_STEPPER_X_MIDPT - offset['x'])
ZT_POS_Y = ZT_BED_X_MIDPT - offset['y']

ZT_POINT_Y = f_fmt(ZT_BED_Y_MIDPT - offset['y'])
ZT_POINT_MIN_X = f_fmt(ZT_X_MARGIN - offset['x'])
ZT_POINT_MIN_Y = ZT_POINT_Y
ZT_POINT_MID_X = f_fmt(ZT_BED_X_MIDPT - offset['x'])
ZT_POINT_MID_Y = ZT_POINT_Y
ZT_POINT_MAX_X = f_fmt(BED_X_MAX - ZT_X_MARGIN - offset['x'])
ZT_POINT_MAX_Y = ZT_POINT_Y

SCREW_ADJ_X_MIN = f_fmt(SCREW_X_MIN - offset['x'])
SCREW_ADJ_X_MAX = f_fmt(SCREW_X_MAX - offset['x'])
SCREW_ADJ_Y_MIN = f_fmt(SCREW_Y_MIN - offset['y'])
SCREW_ADJ_Y_MAX = f_fmt(SCREW_Y_MAX - offset['y'])

MESH_X_MIN = f_fmt(MESH_MARGIN)
MESH_X_MAX = f_fmt(BED_X_MAX - MESH_MARGIN + offset['x'])
MESH_Y_MIN = f_fmt(MESH_MARGIN)
MESH_Y_MAX = f_fmt(BED_Y_MAX - MESH_MARGIN + offset['y'])

SCREW_DATA = (
    {
        'name': 'front left screw',
        'xy': '%s, %s' % (SCREW_ADJ_X_MIN, SCREW_ADJ_Y_MIN)
    },
    {
        'name': 'front right screw',
        'xy': '%s, %s' % (SCREW_ADJ_X_MAX, SCREW_ADJ_Y_MIN)
    },
    {
        'name': 'rear right screw',
        'xy': '%s, %s' % (SCREW_ADJ_X_MAX, SCREW_ADJ_Y_MAX)
    },
    {
        'name': 'rear left screw',
        'xy': '%s, %s' % (SCREW_ADJ_X_MIN, SCREW_ADJ_Y_MAX)
    }
)

outfiles = OUTFILES_TEST if TESTING else OUTFILES_LIVE

def write_header(index):
    f.write('# %s\n' % outfiles[index])
    f.write('# Generated by update-blt-screws-ztilt-cfg.py %s\n#\n' %
        datetime.now().strftime("%Y-%m-%d %I:%M:%S %p"))
    f.write('# Using:\n# x_offset = %s\n# y_offset = %s\n' %
        (offset['x'], offset['y']))

# bltouch, safe_z_home, bed_mesh
with open(outfiles['BLT'], 'w') as f:
    write_header('BLT')

    f.write('\n[bltouch]\n')
    f.write('sensor_pin: %s\n' % BLT_SENSOR_PIN)
    f.write('control_pin: %s\n' % BLT_CONTROL_PIN)
    f.write('x_offset: %s\n' % offset['cfg_x'])
    f.write('y_offset: %s\n\n' % offset['cfg_y'])

    f.write('[safe_z_home]\n')
    f.write('home_xy_position: %s, %s\n'
        % (BLT_HOME_X_POS, BLT_HOME_Y_POS))
    f.write('z_hop: %s\n' % BLT_Z_HOP)
    f.write('z_hop_speed: %s\n\n' % BLT_Z_HOP_SPEED)

    f.write('[bed_mesh]\n')
    f.write('speed: %s\n' % MESH_SPEED)
    f.write('horizontal_move_z: %s\n' % MESH_HORIZ_MOVE_Z)
    f.write('mesh_min: %s, %s\n' %
        (
            MESH_X_MIN,
            MESH_Y_MIN
        )
    )
    f.write('mesh_max: %s, %s\n' %
        (
            MESH_X_MAX,
            MESH_Y_MAX
        )
    )
    f.write('probe_count: %s, %s\n' % (MESH_PROBE_CNT_X, MESH_PROBE_CNT_Y))
    f.write('algorithm: %s\n' % MESH_ALG)
    f.write('fade_start: %s\n' % MESH_FADE_START)
    f.write('fade_end: %s\n' % MESH_FADE_END)
    f.write('fade_target: %s\n' % MESH_FADE_TARGET)

print('Wrote [bltouch], [safe_z_home], [bed_mesh] configurations to %s' % outfiles['BLT'])

# screws_tilt_adjust
with open(outfiles['SCREW'], 'w') as f:
    write_header('SCREW')

    f.write('%s\n' % SCREW_HEADER)

    f.write('[screws_tilt_adjust]\n')
    for i in range(4):
        f.write('screw%d: %s\n' % (i + 1, SCREW_DATA[i]['xy']))
        f.write('screw%d_name: %s\n' % (i + 1, SCREW_DATA[i]['name']))

    f.write('horizontal_move_z: %s\n' % SCREW_HORIZ_MOVE_Z)
    f.write('speed: %s\n' % SCREW_SPEED)
    f.write('screw_thread: %s\n' % SCREW_THREAD)

print('Wrote [screws_tilt_adjust] configuration to %s' % outfiles['SCREW'])

# z_tilt
with open(outfiles['ZT'], 'w') as f:
    write_header('ZT')

    # comments
    f.write('#\n# Stepper motors are %d mm apart: midpoint = %s\n' %
        (ZT_STEPPER_X_DIST, ZT_STEPPER_X_MIDPT))
    f.write('# Printer bed is %d x %d; x_midpoint = %s, y_midpoint = %s\n' %
        (BED_X_MAX, BED_Y_MAX, ZT_BED_X_MIDPT, ZT_BED_Y_MIDPT))
    f.write('# Subtract offsets from starting coordinates\n#\n')

    f.write('# ** z_positions **\n')
    f.write('# Start X1,X2 at %s +/- %s -> [%s, %s]; Y1 = Y2 = %s\n' %
        (
            ZT_BED_X_MIDPT,
            ZT_STEPPER_X_MIDPT,
            ZT_BED_X_MIDPT - ZT_STEPPER_X_MIDPT,
            ZT_BED_X_MIDPT + ZT_STEPPER_X_MIDPT,
            ZT_BED_Y_MIDPT
        )
    )
    f.write('# (X1,Y1) - (%s, %s) = (%s, %s)\n' %
        (offset['cfg_x'], offset['cfg_y'], ZT_POS_X_MIN, ZT_POS_Y))
    f.write('# (X2,Y2) - (%s, %s) = (%s, %s)\n#\n' %
        (offset['cfg_x'], offset['cfg_y'], ZT_POS_X_MAX, ZT_POS_Y))

    f.write('# X Margin: %s\n; x_offset: %s; y_offset: %s\n'
        % (ZT_X_MARGIN, offset['cfg_x'], offset['cfg_y']))
    f.write('# X values: [%s, %s, %s] - (%s) ==> [%s, %s, %s]\n'
        % ( ZT_X_MARGIN, ZT_BED_X_MIDPT, BED_X_MAX - ZT_X_MARGIN, offset['cfg_x'],
            ZT_POINT_MIN_X, ZT_POINT_MID_X, ZT_POINT_MAX_X))
    f.write('# Y value: %s - (%s) ==> %s\n\n'
        % (ZT_BED_Y_MIDPT, offset['cfg_y'], ZT_POINT_Y))

    # config
    f.write('[z_tilt]\n')
    f.write('z_positions: %s, %s\n' %
        (ZT_POS_X_MIN, ZT_POS_Y))
    f.write('    %s, %s\n' %
        (ZT_POS_X_MAX, ZT_POS_Y))
    f.write('points: %s, %s\n' %
        (ZT_POINT_MIN_X, ZT_POINT_Y))
    f.write('    %s, %s\n' %
        (ZT_POINT_MID_X, ZT_POINT_Y))
    f.write('    %s, %s\n' %
        (ZT_POINT_MAX_X, ZT_POINT_Y))

    f.write('speed: %d\n' %
        (ZT_SPEED))
    f.write('horizontal_move_z: %d\n' %
        (ZT_HORIZ_MOVE_Z))
    f.write('retries: %d\n' %
        (ZT_RETRIES))
    f.write('retry_tolerance: %s\n' %
        f_fmt(ZT_RETRY_TOLERANCE, places=2))

print('Wrote [z_tilt] configuration to %s' % outfiles['ZT'])


from typing import List

from fastapi import APIRouter, HTTPException
from fastapi import Depends
from sqlalchemy.orm import Session

import schemas
from routers import get_db
from services import users as user_service

router = APIRouter(
    prefix="/users",
    tags=["users"],
    dependencies=[],
    responses={404: {"description": "Not found"}},
)

@router.get("", response_model=List[schemas.User])
async def get_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
    users = user_service.get_users(db, skip=skip, limit=limit)
    return users

@router.get("/{user_id}/patients", response_model=List[schemas.Patient])
async def get_user_patients(user_id: int, db: Session = Depends(get_db)):
    user = user_service.get_user_by_id(db, user_id)
    if user is None:
        raise HTTPException(404)
    patients = user.patients
    return patients

@router.get("/{user_id}", response_model=schemas.User)
async def get_user(user_id: int, db: Session = Depends(get_db)):
    user = user_service.get_user_by_id(db, user_id)
    if user is None:
        raise HTTPException(404)
    return user

@router.post("")
async def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
    user_service.create_user(db, user)


import torch
from torch import Tensor
from torchaudio.transforms import MelSpectrogram, AmplitudeToDB
import numpy as np
from torch.nn import functional as F
import matplotlib.pyplot as plt
import librosa

__all__ = [
    'LogMelSpectrogram', 'DBScaleMelSpectrogram',
    'RandomlyCrop', 'RandomlyCropFraction',
    'RandomFlip', 'RandomCropCenter', 'CropCenter', 'Threshold', 'Smooth',
    'FrequencyMasking', 'TimeMasking', 'NormalizeAcrossTime',
    'DiscardFirstCoeff', 'TimePad', 'AugmentDelta',
    'Noise', 'SpeedNPitch'
]

class LogMelSpectrogram:
    """MelSpectrogram in Log Scale"""
    def __init__(self, **kwargs):
        self.mel_spec = MelSpectrogram(**kwargs)

    def __call__(self, input: Tensor) -> Tensor:
        return torch.log(self.mel_spec(input) + 1e-6)

class DBScaleMelSpectrogram:
    """MelSpectrogram in DB Scale"""
    def __init__(self, **kwargs):
        self.mel_spec = MelSpectrogram(**kwargs)
        self.db_scale = AmplitudeToDB()

    def __call__(self, input: Tensor) -> Tensor:
        return self.db_scale(self.mel_spec(input))

class RandomlyCrop:
    def __init__(self, length: int=48000):
        self.length = length

    def __call__(self, audio: Tensor):
        if audio.shape[-1] < self.length:
            return audio

        start = np.random.choice(audio.shape[-1] - self.length)
        return audio[:, start:start + self.length]

class RandomlyCropFraction:
    def __init__(self, ratio: float=0.75):
        self.ratio = ratio

    def __call__(self, audio: Tensor):
        length = int(self.ratio * audio.shape[-1])
        start = np.random.choice(audio.shape[-1] - length)
        return audio[:, start:start + length]

class FrequencyMasking:
    """
    Randomly masked some frequency channels of the log mel frequency spectrogram. Apply after normalization.

    References:

        Daniel S. Park, William Chan, Yu Zhang, Chung-Cheng Chiu, Barret Zoph, Ekin D. Cubuk, Quoc V. Le.
        "SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition."
        https://arxiv.org/abs/1904.08779v2
    """
    def __init__(self, max_length_mask: int):
        """
        :param max_length_mask: maximum length of mask
        """
        self.max_length_mask = max_length_mask

    def __call__(self, spectrogram: Tensor) -> Tensor:
        """
        :param spectrogram: data in mel spectrogram format. (C, F, L)
        :return: masked data.
        """
        mask_length = np.random.choice(self.max_length_mask)
        mask_start = np.random.choice(spectrogram.shape[1] - mask_length)
        mask = torch.ones(size=spectrogram.shape, dtype=spectrogram.dtype, device=spectrogram.device)
        mask[:, mask_start:mask_start + mask_length, :] = 0
        return spectrogram * mask

class TimeMasking:
    """
    Randomly masked an interval of time in the log mel frequency spectrogram. Apply after normalization.

    References:

        Daniel S. Park, William Chan, Yu Zhang, Chung-Cheng Chiu, Barret Zoph, Ekin D. Cubuk, Quoc V. Le.
        "SpecAugment: A Simple Data Augmentation Method for Automatic Speech Recognition."
        https://arxiv.org/abs/1904.08779v2
    """
    def __init__(self, max_length_mask: int, p: float=1.0):
        """
        :param max_length_mask: maximum length of mask
        :param p: fraction of length (in time) of spectrogram as an upper bound for the length of mask
        """
        self.max_length_mask = max_length_mask
        self.p = p

    def __call__(self, spectrogram: Tensor) -> Tensor:
        """
        :param spectrogram: data in mel spectrogram format. (C, F, L)
        :return: masked data.
        """
        mask_length = min(np.random.choice(self.max_length_mask), int(spectrogram.shape[2] * self.p))
        mask_start = np.random.choice(spectrogram.shape[2] - mask_length)
        mask = torch.ones(size=spectrogram.shape, dtype=spectrogram.dtype, device=spectrogram.device)
        mask[:, :, mask_start:mask_start + mask_length] = 0
        return spectrogram * mask

class NormalizeAcrossTime:
    """
    Normalization across time dimension for each frequency/MFCC coefficient.

    References:

        Haytham Fayek. "Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs)
        and What's In-Between." https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html

        https://musicinformationretrieval.com/mfcc.html

        https://www.kaggle.com/c/freesound-audio-tagging/discussion/54082
    """
    def __call__(self, input):
        """
        :param input: (C, freq, time)
        :return:
        """
        return (input - input.mean(-1, keepdims=True)) / (input.std(-1, keepdims=True) + 1e-6)

class DiscardFirstCoeff:
    """
    Discard the first MFCC coefficient.

    References:

        Haytham Fayek. "Speech Processing for Machine Learning: Filter banks, Mel-Frequency Cepstral Coefficients (MFCCs)
        and What's In-Between." https://haythamfayek.com/2016/04/21/speech-processing-for-machine-learning.html#fn:1

        https://musicinformationretrieval.com/mfcc.html
    """
    def __call__(self, mfcc: Tensor) -> Tensor:
        """
        :param mfcc: (C, freq, time)
        :return:
        """
        return mfcc[:, 1:, :]

class Noise:
    def __call__(self, data):
        """
        Adding White Noise.
        """
        # you can take any distribution from https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.random.html
        noise_amp = 0.1 * np.random.uniform() * torch.max(data)   # more noise reduce the value to 0.5
        data = data + noise_amp * torch.randn(size=data.shape)
        return data

def pitch(data, sample_rate):
    """
    Pitch Tuning.
    """
    bins_per_octave = 12
    pitch_pm = 2
    pitch_change =  pitch_pm * 2*(np.random.uniform())
    data = librosa.effects.pitch_shift(data.astype('float64'),
                                      sample_rate, n_steps=pitch_change,
                                      bins_per_octave=bins_per_octave)
    return data

def dyn_change(data):
    """
    Random Value Change.
    """
    dyn_change = np.random.uniform(low=-0.5 ,high=7)  # default low = 1.5, high = 3
    return (data * dyn_change)

class SpeedNPitch:
    def __call__(self, data):
        """
        Speed and Pitch Tuning.
        """
        # you can change low and high here
        length_change = np.random.uniform(low=0.8, high = 1)
        speed_fac = 1.2  / length_change
        tmp = np.interp(np.arange(0, data.shape[-1], speed_fac), np.arange(0, data.shape[-1]), data.view(-1))
        minlen = min(data.shape[-1], tmp.shape[-1])
        data *= 0
        data[:, 0:minlen] = torch.FloatTensor(tmp[0:minlen])
        return data

class RandomFlip:
    def __init__(self, prob: bool=0.5):
        self.prob = prob

    def __call__(self, spectrogram: Tensor) -> Tensor:
        if np.random.rand() < self.prob:
            spectrogram = torch.flip(spectrogram, dims=(-1, ))
        return spectrogram

class RandomCropCenter:
    def __init__(self, length: int=48000):
        self.length = length

    def __call__(self, audio: Tensor):
        if audio.shape[-1] < self.length:
            return audio

        start = np.random.randint(self.length // 2, audio.shape[-1] - self.length // 2 )
        audio = audio[:, start - self.length // 2 : start - self.length // 2 + self.length]

        return audio

class CropCenter:
    def __init__(self, length: int=48000):
        self.length = length

    def __call__(self, audio: Tensor):
        if audio.shape[-1] < self.length:
            return audio

        start = audio.shape[-1] // 2
        audio = audio[:, start - self.length // 2 : start - self.length // 2 + self.length]

        return audio

class Threshold:
    def __init__(self, lower: float, upper: float):
        self.lower = lower
        self.upper = upper

    def __call__(self, audio: Tensor):
        audio[torch.abs(audio) / torch.max(audio) < self.lower] = 0
        audio[torch.abs(audio) / torch.max(audio) > self.upper] = 0
        return audio

def gauss(n=26,sigma=10):
    r = range(-int(n/2),int(n/2)+1)
    return [1 / (sigma * np.sqrt(2*np.pi)) * np.exp(-float(x)**2/(2*sigma**2)) for x in r]

class Smooth:
    def __call__(self, audio: Tensor) -> Tensor:
        # plt.subplot(2, 1, 1)
        # plt.plot(range(audio.shape[-1]), audio.view(-1))

        kernel = torch.FloatTensor([[gauss()]])
        audio = F.conv1d(audio[None,:,:], kernel)[0]

        # plt.subplot(2, 1, 2)
        # plt.plot(range(audio.shape[-1]), audio.view(-1))
        # plt.show()

        return audio

class TimePad:
    def __init__(self, length, exact: bool=True, pad: str='center'):
        self.length = length
        self.exact = exact
        self.pad = pad

    def __call__(self, spectrogram: Tensor) -> Tensor:
        if self.exact:
            if spectrogram.shape[-1] >= self.length:
                start = spectrogram.shape[-1] // 2 - self.length // 2
                spectrogram = spectrogram[:, :, start : start + self.length]
        if spectrogram.shape[-1] < self.length:
            total_pad = self.length - spectrogram.shape[-1]
            if self.pad == 'center':
                left_pad = total_pad // 2
                right_pad = total_pad - left_pad
                spectrogram = torch.cat(
                    [
                        torch.zeros((spectrogram.shape[0], spectrogram.shape[1], left_pad)),
                        spectrogram,
                        torch.zeros((spectrogram.shape[0], spectrogram.shape[1], right_pad))
                    ],
                    dim=-1
                )
            elif self.pad == 'left':
                spectrogram = torch.cat(
                    [
                        torch.zeros((spectrogram.shape[0], spectrogram.shape[1], total_pad)),
                        spectrogram
                    ],
                    dim=-1
                )
            elif self.pad == 'right':
                spectrogram = torch.cat(
                    [
                        spectrogram,
                        torch.zeros((spectrogram.shape[0], spectrogram.shape[1], total_pad))
                    ],
                    dim=-1
                )

        # print(spectrogram.shape[-1])
        return spectrogram

class AugmentDelta:
    """
    Augment the spectrogram with 1st and 2nd order deltas
    """
    def __call__(self, spectrogram: Tensor) -> Tensor:
        delta = compute_deltas(spectrogram)
        delta2 = compute_deltas(delta)
        return torch.cat([spectrogram, delta, delta2], dim=0)

#### DIRECTLY FROM TORCHAUDIO MASTER BRANCH
def compute_deltas(specgram, win_length=5, mode="replicate"):
    # type: (Tensor, int, str) -> Tensor
    r"""Compute delta coefficients of a tensor, usually a spectrogram:
    .. math::
        d_t = \frac{\sum_{n=1}^{\text{N}} n (c_{t+n} - c_{t-n})}{2 \sum_{n=1}^{\text{N} n^2}
    where :math:`d_t` is the deltas at time :math:`t`,
    :math:`c_t` is the spectrogram coeffcients at time :math:`t`,
    :math:`N` is (`win_length`-1)//2.
    Args:
        specgram (torch.Tensor): Tensor of audio of dimension (..., freq, time)
        win_length (int): The window length used for computing delta
        mode (str): Mode parameter passed to padding
    Returns:
        deltas (torch.Tensor): Tensor of audio of dimension (..., freq, time)
    Example
        >>> specgram = torch.randn(1, 40, 1000)
        >>> delta = compute_deltas(specgram)
        >>> delta2 = compute_deltas(delta)
    """

    # pack batch
    shape = specgram.size()
    specgram = specgram.reshape(1, -1, shape[-1])

    assert win_length >= 3

    n = (win_length - 1) // 2

    # twice sum of integer squared
    denom = n * (n + 1) * (2 * n + 1) / 3

    specgram = torch.nn.functional.pad(specgram, (n, n), mode=mode)

    kernel = (
        torch
        .arange(-n, n + 1, 1, device=specgram.device, dtype=specgram.dtype)
        .repeat(specgram.shape[1], 1, 1)
    )

    output = torch.nn.functional.conv1d(specgram, kernel, groups=specgram.shape[1]) / denom

    # unpack batch
    output = output.reshape(shape)

    return output

class ComputeDeltas(torch.nn.Module):
    r"""Compute delta coefficients of a tensor, usually a spectrogram.
    See `torchaudio.functional.compute_deltas` for more details.
    Args:
        win_length (int): The window length used for computing delta.
    """
    __constants__ = ['win_length']

    def __init__(self, win_length=5, mode="replicate"):
        super(ComputeDeltas, self).__init__()
        self.win_length = win_length
        self.mode = mode

    def forward(self, specgram):
        r"""
        Args:
            specgram (torch.Tensor): Tensor of audio of dimension (channel, freq, time)
        Returns:
            deltas (torch.Tensor): Tensor of audio of dimension (channel, freq, time)
        """
        return compute_deltas(specgram, win_length=self.win_length, mode=self.mode)


# - *- coding: utf- 8 - *-
import telebot
import config
import requests
from bs4 import BeautifulSoup
# import time
import pyowm
from telebot import apihelper

apihelper.proxy = {'http':'http://10.10.1.10:3128'}
bot = telebot.TeleBot(config.TOKEN)
dollar_hr = 'https://www.google.com/search?ei=L4-LXuH5AcSsrgSzlZqgAw&q=%D0%BA%D1%83%D1%80%D1%81+%D0%B4%D0%BE%D0%BB%D0%BB%D0%B0%D1%80%D0%B0+%D0%BA+%D0%B3%D1%80%D0%B8%D0%B2%D0%BD%D0%B5&oq=%D0%BA%D1%83%D1%80%D1%81+%D0%B4%D0%BE%D0%BB%D0%BB%D0%B0%D1%80%D0%B0+&gs_lcp=CgZwc3ktYWIQAxgAMgIIADICCAAyAggAMgIIADICCAAyAggAMgIIADICCAAyAggAMgIIADoECAAQRzoFCAAQxAI6BggAEBYQHkoNCBcSCTEwLTU2ZzEwNUoKCBgSBjEwLTRnMlDSXFidb2D4fmgDcAJ4AIABYIgB8gKSAQE0mAEAoAEBqgEHZ3dzLXdpeg&sclient=psy-ab'
euro_hr = 'https://www.google.com/search?ei=QI-LXufkGcOEwPAPgYi-EA&q=%D0%BA%D1%83%D1%80%D1%81+%D0%B5%D0%B2%D1%80%D0%BE+%D0%BA+%D0%B3%D1%80%D0%B8%D0%B2%D0%BD%D0%B5&oq=%D0%BA%D1%83%D1%80%D1%81+%D0%B5%D0%B2%D1%80%D0%BE+%D0%BA+%D0%B3%D1%80%D0%B8%D0%B2%D0%BD%D0%B5&gs_lcp=CgZwc3ktYWIQARgAMgUIABDEAjIGCAAQBxAeMgYIABAHEB4yAggAMgIIADICCAAyAggAMgIIADICCAAyAggAOgQIABBHOggIABAIEAcQHjoICAAQBxAeEBNKEAgXEgwxMC0xMDVnMTAxZzdKDAgYEggxMC0zZzdnM1Dh5TdYiIw4YLaVOGgDcAN4AIABZIgBqAeSAQM5LjGYAQCgAQGqAQdnd3Mtd2l6&sclient=psy-ab'
covid_w = 'https://www.google.com/search?q=covid-19+statistic+ukraine'
covid_ua = 'https://www.google.com/search?q=covid-19+statistic+ukraine'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'}

@bot.message_handler(commands=['start'])
def welcome(message):
    bot.send_message(message.chat.id, 'Ну здарова!')

@bot.message_handler(commands=['weather'])
def get_weather_kh(message):
    owm = pyowm.OWM('71a225bf9495530081f8c057c514003e')

    obs = owm.weather_at_place('Kharkiv')
    w = obs.get_weather()
    temperature = w.get_temperature(unit = 'celsius')
    status = w.get_detailed_status()
    # icon = w.get_weather_icon_name()
    weather_message = 'Weather in Kharkov: ' + str(temperature['temp']) + '°C\n' + status
    bot.send_message(message.chat.id, weather_message)

@bot.message_handler(commands=['rate'])
def get_course(message):
    full_page_1 = requests.get(dollar_hr, headers=headers, proxies=apihelper.proxy)
    soup_dollar = BeautifulSoup(full_page_1.content, 'html.parser')
    convert_1 = soup_dollar.select("div.dDoNo.vk_bk.gsrt span")

    full_page_2 = requests.get(euro_hr, headers=headers)
    soup_euro = BeautifulSoup(full_page_2.content, 'html.parser')
    convert_2 = soup_euro.select("div.dDoNo.vk_bk.gsrt span")

    rate_message = 'Dollar exchange rate = ' + str(convert_1[0].text) + '\nEuro exchange rate = ' + str(convert_2[0].text)

    bot.send_message(message.chat.id, rate_message)
    # time.sleep(60)
    # check_carrency()

@bot.message_handler(commands=['covid_world'])
def get_statistic_w(message):
    full_page_3 = requests.get(covid_w, headers=headers)
    soup_corona_w = BeautifulSoup(full_page_3.content, 'html.parser')
    print(soup_corona_w)

    selector_w = soup_corona_w.select("tr:contains('Worldwide') td div")
    print(selector_w)

    covid_w_message = 'World COVID-19 statistic' + '\nTotal infected: ' + selector_w[0].text + '\nRecovered: ' + selector_w[1].text + '\nDied: ' + selector_w[2].text
    bot.send_message(message.chat.id, covid_w_message)

@bot.message_handler(commands=['covid_ukr'])
def get_statistic_ua(message):
    full_page_4 = requests.get(covid_ua, headers=headers)
    soup_corona_ua = BeautifulSoup(full_page_4.content, 'html.parser')

    selector_ua = soup_corona_ua.select("tr:contains('Ukraine') td div")
    print(selector_ua)

    covid_ua_message = 'Ukrainian COVID-19 statistic' + '\nTotal infected: ' + selector_ua[0].text + '\nRecovered: ' + selector_ua[1].text + '\nDied: ' + selector_ua[2].text
    bot.send_message(message.chat.id, covid_ua_message)

bot.polling(none_stop=True)


import os
import random
from typing import Tuple
import numpy as np
import pandas as pd
import math
import logging

def seed_it_all(seed=7):
    """ Attempt to be Reproducible """
    os.environ['PYTHONHASHSEED'] = str(seed)
    random.seed(seed)
    np.random.seed(seed)

def angular_dist_score(az_true, zen_true, az_pred, zen_pred) -> float:
    '''
    calculate the MAE of the angular distance between two directions.
    The two vectors are first converted to cartesian unit vectors,
    and then their scalar product is computed, which is equal to
    the cosine of the angle between the two vectors. The inverse
    cosine (arccos) thereof is then the angle between the two input vectors

    The lower the angle, the more similar the two vectors are meaning the score is better.

    Parameters:
    -----------

    az_true : float (or array thereof)
        true azimuth value(s) in radian
    zen_true : float (or array thereof)
        true zenith value(s) in radian
    az_pred : float (or array thereof)
        predicted azimuth value(s) in radian
    zen_pred : float (or array thereof)
        predicted zenith value(s) in radian

    Returns:
    --------

    dist : float
        mean over the angular distance(s) in radian
    '''

    if not (np.all(np.isfinite(az_true)) and
            np.all(np.isfinite(zen_true)) and
            np.all(np.isfinite(az_pred)) and
            np.all(np.isfinite(zen_pred))):
        raise ValueError("All arguments must be finite")

    # pre-compute all sine and cosine values
    sa1 = np.sin(az_true)
    ca1 = np.cos(az_true)
    sz1 = np.sin(zen_true)
    cz1 = np.cos(zen_true)

    sa2 = np.sin(az_pred)
    ca2 = np.cos(az_pred)
    sz2 = np.sin(zen_pred)
    cz2 = np.cos(zen_pred)

    # scalar product of the two Cartesian vectors (x = sz*ca, y = sz*sa, z = cz)
    scalar_prod = sz1*sz2*(ca1*ca2 + sa1*sa2) + (cz1*cz2)

    # scalar product of two unit vectors is always between -1 and 1, this is against numerical instability
    # that might otherwise occur from the finite precision of the sine and cosine functions
    scalar_prod =  np.clip(scalar_prod, -1, 1)

    # convert back to an angle (in radian)
    return np.average(np.abs(np.arccos(scalar_prod)))

def cartesian_to_sphere(x: float, y: float, z: float) -> Tuple[float, float]:
    """Maps vector cartesian coordinates (x, y, z) from the origin to spherical angles azimuth and zenith.

    See: https://en.wikipedia.org/wiki/Spherical_coordinate_system

    Args:
        x (float): The x-coordinate of the point.
        y (float): The y-coordinate of the point.
        z (float): The z-coordinate of the point.

    Returns:
        tuple[float, float]: The azimuth and zenith angles in radians.
    """
    x2y2 = x**2 + y**2
    r = math.sqrt(x2y2 + z**2)
    azimuth = math.acos(x / math.sqrt(x2y2)) * np.sign(y)
    zenith = math.acos(z / r)
    return azimuth, zenith

def sphere_to_cartesian(azimuth: float, zenith: float) -> Tuple[float, float, float]:
    """Map spherical coordinates to cartesian coordinates.
    see: https://stackoverflow.com/a/10868220/4521646

    Args:
        azimuth (float): The azimuth angle in radians.
        zenith (float): The zenith angle in radians.

    Returns:
        tuple: The x, y, z vector cartesian coordinates of the point from the origin.
    """
    x = math.sin(zenith) * math.cos(azimuth)
    y = math.sin(zenith) * math.sin(azimuth)
    z = math.cos(zenith)
    return x, y, z

def adjust_sphere(azimuth:float, zenith:float) -> Tuple[float, float]:
    """Adjust azimuth and zenith to be within [-pi, pi]

    Args:
        azimuth (float): The azimuth to adjust
        zenith (float): The zenith to adjust

    Returns:
        float: The adjusted azimuth and zenith
    """
    if zenith < 0:
        zenith += math.pi
        azimuth += math.pi
    if azimuth < 0:
        azimuth += math.pi * 2
    azimuth = azimuth % (2 * math.pi)
    return azimuth, zenith

def compose_event_df(
    batch_df: pd.DataFrame,
    event_id: str,
    sensor_geometry: pd.DataFrame,
) -> pd.DataFrame:
    """Composes the event dataframe from the batch dataframe and the sensor geometry dataframe.

    Args:
        batch_df (pd.DataFrame): _description_
        event_id (str): The event id to extract from the data frame
        sensor_geometry (pd.DataFrame): The dataframe containing the sensor geometry.

    Returns:
        pd.DataFrame: a dataframe containing the data for one event.
    """

    # filter the batch dataframe for the event_id
    event_df = batch_df[batch_df['event_id'] == event_id]
    # merge the event dataframe with the sensor geometry dataframe
    event_df = pd.merge(
        left = event_df,
        right = sensor_geometry,
        how='inner',
        on='sensor_id'
    )
    # sort the dataframe by sensor_id
    event_df.sort_values(by=['time'], inplace=True)
    return event_df

def reduce_mem_usage(df, verbose=True):
    numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
    start_mem = df.memory_usage().sum() / 1024**2
    for col in df.columns:
        logging.info(f'Optimizing col {col}')
        col_type = df[col].dtypes
        if col_type in numerics:
            c_min = df[col].min()
            c_max = df[col].max()
            if str(col_type)[:3] == 'int':
                if c_min > np.iinfo(np.int8).min and c_max < np.iinfo(np.int8).max:
                    df[col] = df[col].astype(np.int8)
                elif c_min > np.iinfo(np.int16).min and c_max < np.iinfo(np.int16).max:
                    df[col] = df[col].astype(np.int16)
                elif c_min > np.iinfo(np.int32).min and c_max < np.iinfo(np.int32).max:
                    df[col] = df[col].astype(np.int32)
                elif c_min > np.iinfo(np.int64).min and c_max < np.iinfo(np.int64).max:
                    df[col] = df[col].astype(np.int64)
            else:
                if c_min > np.finfo(np.float16).min and c_max < np.finfo(np.float16).max:
                    df[col] = df[col].astype(np.float16)
                elif c_min > np.finfo(np.float32).min and c_max < np.finfo(np.float32).max:
                    df[col] = df[col].astype(np.float32)
                else:
                    df[col] = df[col].astype(np.float64)

    end_mem = df.memory_usage().sum() / 1024**2
    logging.info('Memory usage after optimization is: {:.2f} MB'.format(end_mem))
    logging.info('Decreased by {:.1f}%'.format(100 * (start_mem - end_mem) / start_mem))
    return df

def convert_bytes_to_gmbkb(bytes) -> str:
    """Converts bytes to a human readable format."""
    if bytes >= 1099511627776:  # 1 TB = 1024 GB * 1024 MB * 1024 KB bytes
        return f"{bytes / 1099511627776:.2f} TB"
    elif bytes >= 1073741824:  # 1 GB = 1024 MB * 1024 KB bytes
        return f"{bytes / 1073741824:.2f} GB"
    elif bytes >= 1048576:  # 1 MB = 1024 KB bytes
        return f"{bytes / 1048576:.2f} MB"
    elif bytes >= 1024:  # 1 KB = 1024 bytes
        return f"{bytes / 1024:.2f} KB"
    else:
        return f"{bytes} bytes"


import os
import subprocess

# Directory containing the .ass files
input_directory = "/mnt/backup/Video/Angel Beats/Season 01"

# Output directory for the .srt files
output_directory = "/mnt/backup/Video/Angel Beats/Season 11"

# Make sure the output directory exists, create it if not
if not os.path.exists(output_directory):
    os.makedirs(output_directory)

# Iterate through all .ass files in the input directory
for filename in os.listdir(input_directory):
    if filename.endswith(".ass"):
        input_file = os.path.join(input_directory, filename)
        output_file = os.path.join(output_directory, os.path.splitext(filename)[0] + ".srt")

        # Run the ffmpeg command
        cmd = ["ffmpeg", "-i", input_file, "-c:s", "srt", output_file]

        try:
            subprocess.run(cmd, check=True)
            print(f"Converted {input_file} to {output_file}")
        except subprocess.CalledProcessError as e:
            print(f"Error converting {input_file}: {e}")


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

import networkx as nx
# import graphviz
import matplotlib.pyplot as plt
from networkx.readwrite import json_graph
import json
import numpy as np

"""
Funcion para eliminar duplicados en una lista
Function to eliminate duplicates in a list
"""

def eliminar_duplicados(lista):

    lista_final = []

    for indice, item in enumerate(lista):

        # Verificamos si el item no está entre los valores previos de la lista
        # We check if the item is not among the previous values of the list
        if item not in lista[:indice]:
            # Si no es así añadimos el item
            # If item not in list we add the item
            lista_final.append(item)

    return lista_final

"""
Funcion que determina el número de relaciones transitivas en un arreglo de relaciones R

Entradas:
R: Lista de vertices (Edges) en el formato (Node1, Node2)
verbose = Ture para mostrar detalles de la función

Salidas:
Lista con todas las relaciones transitivas en el grafo

----- ENG:
Function that determines the number of transitive relations in an array of rrelations R

Inputs:
R: List of vertices (Edges) in the format (Node1, Node2)
verbose = Ture to display function details

Outputs:
List with all transitive relations in the graph
"""
def es_transitiva(R, verbose=None):
    transitiva = []
    for relacion_1 in R:
        for relacion_2 in R:
            # No queremos analizar relaciones iguales
            # We don't want to analyze self-loops
            if relacion_1 == relacion_2:
                continue
            # Igualamos el segundo y la primer elemento de las relaciones
            # First and second element in a relation should be the same
            if relacion_1[1] == relacion_2[0]:
                # Si se cumple que: relacion_1 = (a, b) & relacion_2 = (b, c)
                # Creamos la relacion_3 = (a, c)
                relacion_3 = (relacion_1[0], relacion_2[1])
                # Validamos si la relación_3 (a, c) se encuentra en R:
                if relacion_3 in R:
                    if verbose:
                        print(f'Relación {relacion_3} está en R, por lo tanto {relacion_1, relacion_2} es transitiva')
                    transitiva.append([relacion_1, relacion_2, relacion_3])
                else:
                    if verbose:
                        print(f'La relación {relacion_3} no está en R, por lo tanto es no Transitiva')

    # Nos quedamos con las relaciones transitivas y eliminamos duplicados:
    transitiva = eliminar_duplicados(transitiva)

    if verbose:
        print(f'El número de relaciones transitivas (transitive relations): {len(transitiva)}')

    return transitiva

"""
Mostrar grafo
Plot Graph
"""

def plot_graph(G, k=0.5, labels=True, color='skyblue', figsize=(12,12)):
    plt.figure(figsize=figsize)
    # k regulates the distance between nodes
    pos = nx.spring_layout(G, k=k)
    nx.draw(G, with_labels=labels, node_color=color, node_size=1500, edge_cmap=plt.cm.Blues, pos = pos)
    plt.show()

"""
Generar Grafo
Generate Graph
"""
#!pip install networkx
#!pip install graphviz
#%conda install pygraphviz

def generar_grafo(nodos, aristas, info=True, plot=True):
    G = nx.Graph()

    #Añadir nodos
    G.add_nodes_from(nodos)

    #Añadir aristas
    G.add_edges_from(aristas)

    if info:
        print("====== Nodos (Nodes): =====")
        print(f'El número de nodos es (# of nodes): {len(G.nodes)}')
        print(f'Nodos (Nodes):')
        print(G.nodes)

        print("====== Aristas (Edges): =====")
        print(f'El número de aristas es (# of edges): {len(G.edges)}')
        print(f'Aristas (edges):')
        print(G.edges)

    if plot:
        plot_graph(G)

    return G

def relacion_bidireccional(edges):
    edges = list(edges)
    bidirectional = []
    for edge in edges:
        if ((edge[1], edge[0]) in edges) and (edge[1] != edge[0]):
            bidirectional.append(edge)
    return bidirectional

def auto_vertice(edges):
    edges = list(edges)
    auto = []
    for edge in edges:
        if edge[1] == edge[0]:
            auto.append(edge)
    return auto

def informacion_de_vertices(edges):
    print(f'El número de vertices (edges): {len(edges)}')

    bidirectional = relacion_bidireccional(edges)
    print(f'El número de vertices bidireccionales (bidirectional edges) {len(bidirectional)}')

    auto = auto_vertice(edges)
    print(f'El número de relaciones de nodos con ellos mismos es (self-loops) {len(auto)}')

    print(f""" De los {len(edges)} vertices, {len(bidirectional) + len(auto)} son realciones bidireccionales o con ellos mismos""")

    return bidirectional, auto

# Para leer los datos de las proteinas
class Dataset():
    """A toy Protein-Protein Interaction network dataset.

    Adapted from https://github.com/williamleif/GraphSAGE/tree/master/example_data.

    The dataset contains 24 graphs. The average number of nodes per graph
    is 2372. Each node has 50 features and 121 labels.

    We use 20 graphs for training, 2 for validation and 2 for testing.
    """
    def __init__(self, mode, PATH):
        """Initialize the dataset.

        Paramters
        ---------
        mode : str
            ('train', 'valid', 'test').
        """
        self.mode = mode

        with open(f'{PATH}/raw/{self.mode}_graph.json') as jsonfile:
            self.g_data = json.load(jsonfile)

        self.labels = np.load(f'{PATH}/raw/{self.mode}_labels.npy')
        self.features = np.load(f'{PATH}/raw/{self.mode}_feats.npy')
        self.graph_id = np.load(f'{PATH}/raw/{self.mode}_graph_id.npy')

        self.graph = nx.DiGraph(json_graph.node_link_graph(self.g_data))

    def subgrafo(self, size=0):
        if size == 0:
            index = np.unique(self.graph_id)[0]
            subset = np.sum(self.graph_id == index)
            subset = range(0, subset)
        elif size == 1:
            index = np.unique(self.graph_id)[1]
            subset = np.sum(self.graph_id == index)
            subset = range(subset, self.graph_id.shape[0])
        elif size < 0 or size > self.graph_id.shape[0]:
            print('Error, el tamaño del subgrafo debe ser mayor a 0 y menor a el grafo total')
            return 0
        else:
            subset = range(0, size)

        subgraph = self.graph.subgraph(subset)
        return subgraph

"""
Distribución de probabilidad
Probability Distrobution
1. Probability Density Function (PDF)
2. Complementary Cumulative Distribution Function (CCDF)
"""
def distribucion_probabilidades(valores_grado):
    pdf = []
    ccdf = []
    grado_indice = []
    acumulado = 0

    max_d = valores_grado.max()

    # Cacular la probabilidad para cada grado posible (Calculate the probability for each degree)
    for grado in range(0, max_d+1):

        grado_indice.append(grado)

        # PDF:
        # Cacular los nodos con grado igual a "grado"
        # Calculate the nodes with degree "grado"
        valor_grado = (valores_grado == grado).sum()
        probabilidad = valor_grado/len(valores_grado)
        pdf.append(probabilidad)

        # CCDF
        acumulado += valor_grado
        probabilidad_acumulada = acumulado/len(valores_grado)
        ccdf.append(probabilidad_acumulada)

    return pdf, ccdf, grado_indice

"""
Graficar PDF
Plot PDF
"""
def plot_pdf(pdf, grado_indice, x=None, y=None):
    grid = sns.lineplot(x=grado_indice, y=pdf)
    grid.set(xlim=0)

    if x=='log' and y=='log':
        grid.set(xscale="log", yscale="log")
        plt.xlabel('Grado [log]')
        plt.ylabel('Probabilidad [log]')
        plt.title('PDF log - log')

    elif x=='log':
        grid.set(xscale="log")
        plt.xlabel('Grado [log]')
        plt.ylabel('Probabilidad')
        plt.title('PDF linear - log')
    elif y=='log':
        grid.set(yscale="log")
        plt.xlabel('Grado')
        plt.ylabel('Probabilidad [log]')
        plt.title('PDF log - linear')
    else:
        plt.xlabel('Grado')
        plt.ylabel('Probabilidad')
        plt.title('PDF')
    grid.set(xlim=0)
    plt.show()

"""
Graficar ECDF
Plot ECDF
"""
def plot_ecdf(ecdf, grado_indice, x=None, y=None):
    grid = sns.lineplot(x=grado_indice, y=ecdf)
    grid.set(xlim=0)

    if x=='log' and y=='log':
        grid.set(xscale="log", yscale="log")
        plt.xlabel('Grado [log]')
        plt.ylabel('Probabilidad [log]')
        plt.title('ECDF log - log')

    elif x=='log':
        grid.set(xscale="log")
        plt.xlabel('Grado [log]')
        plt.ylabel('Probabilidad')
        plt.title('ECDF linear - log')
    elif y=='log':
        grid.set(yscale="log")
        plt.xlabel('Grado')
        plt.ylabel('Probabilidad [log]')
        plt.title('ECDF log - linear')
    else:
        plt.xlabel('Grado')
        plt.ylabel('Probabilidad')
        plt.title('ECDF')
    grid.set(xlim=0)
    plt.show()


import os
import httpx
import aioredis
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_utils.tasks import repeat_every
from fastapi.middleware.cors import CORSMiddleware
from fastapi import FastAPI
from dotenv import load_dotenv

from api.shot import router as ShotRouter
from api.user import router as UserRouter
from api.auth import router as AuthRouter
from api.search import router as SearchRouter
from api.tag import router as TagRouter
from api.files import router as FilesRouter
from api.calendar import router as CalendarRouter
from api.plus import router as PlusRouter

# app = FastAPI(docs_url=None, redoc_url=None)
app = FastAPI()

origins = [
    'https://blck.darkmaterial.space',
    'https://bum.darkmaterial.space',
    'https://dev-bum.darkmaterial.space',
    'https://darkmaterial.space',
    'https://www.blck.darkmaterial.space',
    'https://www.dev-bum.darkmaterial.space',
    'https://www.bum.darkmaterial.space',
    'https://www.darkmaterial.space',
    'http://localhost:3000'
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# app.include_router(PaymentRouter)
app.include_router(ShotRouter)
app.include_router(UserRouter)
app.include_router(AuthRouter)
app.include_router(SearchRouter)
app.include_router(TagRouter)
app.include_router(FilesRouter)
app.include_router(CalendarRouter)
app.include_router(PlusRouter)

@app.on_event('startup')
@repeat_every(seconds=60 * 10)
async def wakeUpServer():
    response = httpx.get('https://api.darkmaterial.space/')
    if response.is_success:
        print('i woke up myself')
    else:
        print(f"Couldn't wake up {response.status_code}")

@app.on_event('startup')
async def startup_event():
    load_dotenv()
    redis = aioredis.from_url(f"redis://{os.getenv('REDIS_HOST')}:{os.getenv('REDIS_PORT')}", encoding='utf-8', decode_responses=True)
    FastAPICache.init(RedisBackend(redis=redis), prefix='fastapi-cache')

@app.get('/')
def HI_API():
    return 'DM API'


import requests
import urllib.request
import time
from bs4 import BeautifulSoup

# https://www.ebay-kleinanzeigen.de/s-tamron-sp-24-70-2.8-vc-nikon/k0

base_url = 'https://www.ebay-kleinanzeigen.de'
search_term = 'tamron sp 24 70 2.8 vc nikon'

search_term_url = search_term.replace(' ', '-')

url = base_url+'/s-'+search_term_url+'/k0'

html = requests.get(url).text

bs = BeautifulSoup(html, 'html.parser')

articles = bs.findAll('article')

id = articles[0]['data-adid']
href = articles[0].find('a')['href']
article_html = requests.get(base_url+href).text


from ursina import *
from panda3d.core import Camera as PandaCamera

app = Ursina()
window.fps_counter.enabled = True

camera.perspective = True
camera.fov = 35

cube = Entity(model='cube', color=color.white, scale=(2,6,2), texture="water.jpg")

for cube in cube:
    cube.rotation_y += time.dt * 5

app.run()

Randoms/FanFic Bot/Random/Solar System Sim.py


from matplotlib import pyplot as plt
from matplotlib import font_manager
import pandas as pd

file_path = "E:/Datasets/directory.csv"
plt.figure(figsize=(20,8),dpi=80)
pd.set_option("display.max_columns",None)
my_font = font_manager.FontProperties(fname="C:/Windows/Fonts/SIMHEI.TTF")

#中国每个城市店铺数量
df = pd.read_csv(file_path)

china = df[df['Country']=='CN']

province_data = china.groupby(by="City")['Brand'].count()[:25]

plt.bar(range(len(province_data.index)),province_data.values)

plt.xticks(range(len(province_data.index)),province_data.index,rotation=90,fontproperties=my_font)

plt.show()


#Abraham David Hartanto / 71200632
#Set
'''
Membuat program untuk petugas bandara yang akan digunakan untuk mendata jumlah pendatang yang bebas maupun terjangkit virus corona
Pendatang dibedakan menjadi imigran dan turis
Pendatang dapat merupakan keduanya (dalam artian imigran sementara (misal satu tahun))
Mungkin terdapat pendatang ilegal
'''

print("======= Selamat Datang di Program Pendataan Pendatang =======")
data = set()
data_turis = set()
data_imigran = set()
data_terjangkit = set()
#input
jumlah = int(input("Masukkan jumlah pendatang : "))
for i in range(0,jumlah) :
    nama = str(input("Masukkan nama pendatang : "))
    data.add(nama)
jumlah_turis = int(input("Masukkan jumlah turis :"))
for i in range(0,jumlah_turis) :
    nama_turis = str(input("Masukkan nama turis : "))
    data_turis.add(nama_turis)
jumlah_imigran = int(input("Masukkan jumlah imigran :"))
for i in range(0,jumlah_imigran) :
    nama_imigran = str(input("Masukkan nama imigran : "))
    data_imigran.add(nama_imigran)
jumlah_terjangkit = int(input("Masukkan jumlah pendatang yang terjangkit virus :"))
for i in range(0,jumlah_terjangkit) :
    nama_terjangkit = str(input("Masukkan nama pendatang yang terjangkit : "))
    data_terjangkit.add(nama_terjangkit)
hitung = len(data_turis) + len(data_imigran)
#Proses + Output
while True :
    print("Pilihan :")
    print("1. Jumlah pendatang,turis dan imigran " + "\n" + "2. Pendatang yang termasuk imigran dan turis" + "\n" + "3. Imigran dan turis yang bebas dari virus" + "\n" + "4. Pendatang Ilegal" + "\n" + "5. Keluar")
    pilih = int(input("Masukkan nomor pilihan :"))
    if pilih == 1 :
        print(" Jumlah pendatang = " + str(len(data)) + "\n Jumlah turis = " + str(len(data_turis)) + "\n Jumlah Imigran = " + str(len(data_imigran)))
        if len(data) != hitung :
            print("Kemungkinan terdapat pendatang ilegal")
    elif pilih == 2 :
        print("Pendatang yang termasuk imigran dan turis adalah : ",data_imigran.intersection(data_turis))
    elif pilih == 3 :
        print("Imigran yang bebas dari virus adalah : ",data_imigran - data_terjangkit)
        print("Turis yang bebas dari virus adalah : ",data_turis - data_terjangkit)
    elif pilih == 4 :
        gabungan = data_turis.union(data_imigran)
        ilegal = data - gabungan
        if len(ilegal) == 0 :
            print("Tidak ada pendatang ilegal")
        else :
            print(ilegal)
    elif pilih == 5 :
        print("Terimakasih telah menggunakan program ini")
        break
    else :
        print("Pilihan tidak ada ! ")
        break


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

from typing import List

from chaoslib.discovery.discover import (
    discover_actions,
    discover_probes,
    initialize_discovery_result,
)
from chaoslib.exceptions import InterruptExecution
from chaoslib.types import Configuration, DiscoveredActivities, Discovery, Secrets
from logzero import logger

from chaosopenstack.client import OpenstackClientWrapper

__version__ = "0.2.0"

__all__ = ["discover", "__version__"]

def openstack_client(configuration: Configuration = None, secrets: Secrets = None):
    """
    Create and return an openstack connection.

    Only Config Files are supported, because the same config can be used across tools and languages.
    cf. https://docs.openstack.org/openstacksdk/latest/user/guides/connect_from_config.html
    """  # noqa 508

    cloud = configuration.get("openstack_cloud")
    regions = configuration.get("openstack_regions")

    if not regions:
        raise InterruptExecution("Openstack requires at least one region to be set!")

    return OpenstackClientWrapper(cloud, regions)

def discover(discover_system: bool = True) -> Discovery:
    """
    Discover Openstack capabilities offered by this extension.
    """
    logger.info("Discovering capabilities from chaostoolkit-openstack")

    discovery = initialize_discovery_result(
        "chaostoolkit-openstack", __version__, "openstack"
    )
    discovery["activities"].extend(load_exported_activities())

    return discovery

###############################################################################
# Private functions
###############################################################################
def load_exported_activities() -> List[DiscoveredActivities]:
    """
    Extract metadata from actions and probes exposed by this extension.
    """
    activities = []
    activities.extend(discover_actions("chaosopenstack.compute.actions"))
    activities.extend(discover_probes("chaosopenstack.compute.probes"))

    return activities


#Data directories
DAT = '/data/data/'
ALL = DAT + 'all/'
TRN = DAT + 'train/'
VAL = DAT + 'val/'
TST = DAT + 'test/'

#Capstone directories
CAP = '/home/ubuntu/capstone/'
APP = CAP + 'app/'
AUX = CAP + 'aux_files/'
MOD = CAP + 'model/'
SRC = CAP + 'src/'

#Src subdirectories
IMG = SRC + 'image_utils/'
NET = SRC + 'pymodels/'


class 수학:
    def 삼각형넓이(self,가로,세로):
        넓이=가로*세로/2
        return 넓이
구냥=수학()

for i in range(5):
    rnsid=input("밑변의 길이를 입력하시오:")
    rnsids=input("높이의 길이를 입력하시오:")
    print(f"밑변이 {rnsid}이고 높이가{rnsids}일때 삼각형의 넓이는{구냥.삼각형넓이(int(rnsid), int(rnsids))}")


import json
import os
from typing import Any, Callable, List

class JsonDB(object):
    key_string_error = TypeError('Key/name must be a string!')

    def __init__(self, location: str, auto_dump=True):
        '''Creates a database object and loads the data from the location path.
        If the file does not exist it will be created on the first update.
        '''
        self.load(location, auto_dump)

    def load(self, location: str, auto_dump: bool) -> True:
        '''Loads, reloads or changes the path to the db file'''
        location = os.path.expanduser(location)
        self.loco = location
        self.auto_dump = auto_dump
        if os.path.exists(location):
            self._loaddb()
        else:
            self.db = {}
        return True

    def dump(self) -> True:
        '''Force dump memory db to file'''
        with open(self.loco, 'wt') as file:
            json.dump(self.db, file)
        return True

    def _loaddb(self) -> None:
        '''Load or reload the json info from the file'''
        try:
            with open(self.loco, 'rt') as file:
                self.db = json.load(file)
        except ValueError:
            # Error raised because file is empty
            if os.stat(self.loco).st_size == 0:
                self.db = {}
            else:
                raise  # File is not empty, avoid overwriting it

    def _autodumpdb(self) -> None:
        '''Write/save the json dump into the file if auto_dump is enabled'''
        if self.auto_dump:
            self.dump()

    def set(self, key: str, value: Any) -> True:
        '''Set the str value of a key'''
        if isinstance(key, str):
            self.db[key] = value
            self._autodumpdb()
            return True
        else:
            raise self.key_string_error

    def get(self, key) -> Any:
        '''Get the value of a key'''
        try:
            return self.db[key]
        except KeyError:
            return None

    def insert_document(self, collection: str, document: Any) -> int:
        ''' Insert Document into collection an returns an id'''
        document = document.__dict__
        if collection not in self.db:
            self.db[collection] = {}
            self.db[collection + '_id'] = 1
        self.db[collection + '_id'] += 1
        document['id'] = self.db[collection + '_id']
        self.db[collection][document['id']] = document
        if self.auto_dump:
            self._autodumpdb()
        return document['id']

    def documents(self, collection: str) -> List[Any]:
        if collection in self.db:
            return list(self.db[collection].values())
        return []

    def find_document_by_id(self, collection: str, id: str) -> Any:
        return self.db[collection][id]

    def find_document_by(
            self, collection: str, func: Callable[[Any], Any]) -> List[Any]:
        return list(filter(func, self.db[collection].values()))

    def update_document_by(self, collection, id, document) -> Any:
        self.db[collection][id].update(document)
        if self.auto_dump:
            self._autodumpdb()
        return self.db[collection][id]

    def delete_document_by(self, collection, id) -> None:
        del self.db[collection][id]
        if self.auto_dump:
            self._autodumpdb()


"""
    http_handler.py: handle the lifecycle http protocol
"""

import socket
from typing import Optional
from collections import deque
import threading
import logging

from .connection import TcpConnection
from .http_parser import HttpParser
from .constants import CONNECTION_ESTABLISHED_MESSAGE
from .flag import flags
from .cert import CertificateHelper

logger = logging.getLogger(__name__)

class HttpProxyHandler:

    def __init__(self, client: TcpConnection, work_queue: deque,
                 lock: threading.Lock):
        self.client = client
        self.work_queue = work_queue
        self.lock = lock
        self.upstream: Optional[TcpConnection] = None
        self.request = HttpParser()
        self.id = self.client.get_id()
        self.client.set_handler_id(self.id)
        self.wrap_client_after_flush = False

    def connect_upstream(self):
        assert self.request.host and self.request.port
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((self.request.host, self.request.port))
        sock.setblocking(False)
        logger.info('Connect to upstream %s:%d, fd %d',
                    self.request.host, self.request.port, sock.fileno())
        self.upstream = TcpConnection(sock, self.request.host, 'upstream')
        self.upstream.set_handler_id(self.id)
        if self.request.has_buffer():
            self.pipe_data_to_upstream(self.request.get_buffer())
        self.pipe_data_to_client(CONNECTION_ESTABLISHED_MESSAGE)
        with self.lock:
            self.work_queue.append(self.upstream)
        if flags.args.man_in_the_middle and self.request.port == 443:
            if self.client.has_buffer():
                self.wrap_client_after_flush = True
            else:
                self.client.wrap_socket(self.request.host)
            self.upstream.wrap_socket(self.request.host)

    def read_from_fd(self, fd):
        if fd == self.client.fileno():
            return self.recv_from_client()
        elif self.upstream and fd == self.upstream.fileno():
            return self.recv_from_upstream()

    def write_to_fd(self, fd):
        if fd == self.client.fileno():
            return self.send_to_client()
        elif self.upstream and fd == self.upstream.fileno():
            return self.send_to_upstream()

    def recv_from_client(self):
        data = self.client.recv()
        if data is None:
            self.close_client()
            # also close the upstream
            self.close_upstream()
            return True
        if self.request.is_completed():
            assert self.upstream
            self.pipe_data_to_upstream(data)
        else:
            self.request.parse(data)
            if not self.upstream and self.request.has_host():
                self.connect_upstream()
        return False

    def recv_from_upstream(self):
        assert self.upstream
        data = self.upstream.recv()
        if data is None:
            self.close_upstream()
            # also close the client
            self.close_client()
            return True
        self.pipe_data_to_client(data)
        return False

    def send_to_client(self):
        n = self.client.flush()
        if self.wrap_client_after_flush:
            if not self.client.has_buffer():
                self.client.wrap_socket(self.request.host)
                self.wrap_client_after_flush = False
        return n

    def send_to_upstream(self):
        assert self.upstream
        return self.upstream.flush()

    def pipe_data_to_client(self, data):
        self.client.push_buffer(data)

    def pipe_data_to_upstream(self, data):
        assert self.upstream
        self.upstream.push_buffer(data)

    def close_client(self):
        self.client.flush_close()

    def close_upstream(self):
        if self.upstream:
            self.upstream.flush_close()


# RECURSION 1 MY WAY
def possb(s :str, l: int):
    if(l==len(s)-1):
        return 1
    if(l==len(s)):
        return 1
    if int(s[l]) == 0:
        return 0

    res = possb(s,l+1)

    if(int(s[l:l+2])<=26):
        res+= possb(s,l+2)
    return res

# RECURSION 2
def recurse(s, l):
    if(l==0):
        return 1
    if(l==1):
        return 1
    res=0
    if(s[l-1]!='0'):
        res = recurse(s,l-2)
    res2 =0
    if(int(s[l-2:l])<=26):
        res2 = recurse(s,l-3)
    return res+res2

# Dynamic programming

def dynamic(s):
    if(s[0]=='0'):
        return 0
    dp = [0]*(len(s)+1)
    dp[0]=1
    dp[1]=1

    for i in range(2,len(s)+1):
        if(s[i-1]>'0'):
            dp[i] = dp[i-2]
        if(int(s[i-2:i])<=26):
            dp[i]+=dp[i-3]
    return dp[len(s)]

s="10"
print(possb(s,0))

# print(recurse(s,len(s)))
print(dynamic(s))


from typing import List, Optional, Dict, Union
from copy import deepcopy
import numpy as np
from tdw.add_ons.robot_base import RobotBase
from tdw.output_data import Version
from tdw.tdw_utils import TDWUtils
from tdw.release.pypi import PyPi
from magnebot.util import get_data, check_version
from magnebot.arm import Arm
from magnebot.ik.orientation_mode import OrientationMode
from magnebot.ik.target_orientation import TargetOrientation
from magnebot.magnebot_static import MagnebotStatic
from magnebot.magnebot_dynamic import MagnebotDynamic
from magnebot.arm_joint import ArmJoint
from magnebot.actions.action import Action
from magnebot.action_status import ActionStatus
from magnebot.image_frequency import ImageFrequency
from magnebot.collision_detection import CollisionDetection
from magnebot.actions.turn_by import TurnBy
from magnebot.actions.turn_to import TurnTo
from magnebot.actions.move_by import MoveBy
from magnebot.actions.move_to import MoveTo
from magnebot.actions.reach_for import ReachFor
from magnebot.actions.grasp import Grasp
from magnebot.actions.drop import Drop
from magnebot.actions.reset_arm import ResetArm
from magnebot.actions.reset_position import ResetPosition
from magnebot.actions.rotate_camera import RotateCamera
from magnebot.actions.look_at import LookAt
from magnebot.actions.move_camera import MoveCamera
from magnebot.actions.reset_camera import ResetCamera
from magnebot.actions.slide_torso import SlideTorso
from magnebot.actions.stop import Stop
from magnebot.actions.wait import Wait
from magnebot.constants import TDW_VERSION, DEFAULT_CAMERA_POSITION_TORSO, DEFAULT_CAMERA_POSITION_COLUMN
from magnebot.wheel import Wheel

class Magnebot(RobotBase):
    """
    The Magnebot agent is a high-level robotics-like API for [TDW](https://github.com/threedworld-mit/tdw) This high-level API supports:

    - Creating a complex interior environment
    - Directional movement
    - Turning
    - Arm articulation via inverse kinematics (IK)
    - Grasping and dropping objects
    - Image rendering
    - Scene state metadata

    The Magnebot has various [actions](actions/action.md). Each action has a start and end, and has a [status](action_status.md) that indicates if it is ongoing, if it succeeded, or if it failed (and if so, why).

    ***

    ## Basic usage

    You can add a Magnebot to a regular TDW controller:

    ```python
    from tdw.controller import Controller
    from tdw.tdw_utils import TDWUtils
    from magnebot import Magnebot
    from magnebot.action_status import ActionStatus

    m = Magnebot(robot_id=0, position={"x": 0.5, "y": 0, "z": -1})
    c = Controller()
    c.add_ons.append(m)
    c.communicate(TDWUtils.create_empty_room(12, 12))
    m.move_by(1)
    while m.action.status == ActionStatus.ongoing:
        c.communicate([])
    c.communicate({"$type": "terminate"})
    ```

    It is possible to create a multi-agent Magnebot simulation simply by adding more Magnebot agents:

    ```python
    from tdw.controller import Controller
    from tdw.tdw_utils import TDWUtils
    from magnebot import Magnebot
    from magnebot.action_status import ActionStatus

    m0 = Magnebot(robot_id=0, position={"x": 0.5, "y": 0, "z": -1})
    m1 = Magnebot(robot_id=1, position={"x": -0.5, "y": 0, "z": 1})
    c = Controller()
    c.add_ons.extend([m0, m1])
    c.communicate(TDWUtils.create_empty_room(12, 12))
    m0.move_by(1)
    m1.move_by(-2)
    while m0.action.status == ActionStatus.ongoing:
        c.communicate([])
    c.communicate({"$type": "terminate"})
    ```

    For a simplified single-agent API, see [`MagnebotController`](magnebot_controller.md):

    ```python
    from magnebot import MagnebotController

    m = MagnebotController()
    m.init_scene()
    m.move_by(2)
    m.end()
    ```

    ***

    ## Skipped frames

    The `Magnebot` and `MagnebotController` were originally the same code--the controller was a hard-coded single-agent simulation.

    The Magnebot has been designed so that a certain number of physics frames will be skipped per frame that actually returns data back to the controller. The `MagnebotController` does this automatically but you can easily add this to your simulation with a [`StepPhysics`](https://github.com/threedworld-mit/tdw/blob/master/Documentation/python/add_ons/step_physics.md) object:

    ```python
    from tdw.controller import Controller
    from tdw.tdw_utils import TDWUtils
    from tdw.add_ons.step_physics import StepPhysics
    from magnebot.magnebot import Magnebot

    m = Magnebot()
    s = StepPhysics(10)
    c = Controller()
    c.add_ons.extend([m, s])
    c.communicate(TDWUtils.create_empty_room(12, 12))
    print(m.dynamic.transform.position)
    c.communicate({"$type": "terminate"})
    ```

    ***

    ## Parameter types

    The types `Dict`, `Union`, and `List` are in the [`typing` module](https://docs.python.org/3/library/typing.html).

    #### Dict[str, float]

    Parameters of type `Dict[str, float]` are Vector3 dictionaries formatted like this:

    ```json
    {"x": -0.2, "y": 0.21, "z": 0.385}
    ```

    `y` is the up direction.

    To convert from or to a numpy array:

    ```python
    from tdw.tdw_utils import TDWUtils

    target = {"x": 1, "y": 0, "z": 0}
    target = TDWUtils.vector3_to_array(target)
    print(target) # [1 0 0]
    target = TDWUtils.array_to_vector3(target)
    print(target) # {'x': 1.0, 'y': 0.0, 'z': 0.0}
    ```

    #### Union[int, Dict[str, float], np.ndarray]

    Parameters of type `Union[int, Dict[str, float], np.ndarray]` can be either a Vector3, an [x, y, z] numpy array, or an integer (an object ID).

    #### Arm

    All parameters of type `Arm` require you to import the [Arm enum class](arm.md):

    ```python
    from magnebot import Arm

    print(Arm.left)
    ```

    ***
    """

    # If True, we've already checked the version.
    _CHECKED_VERSION: bool = False

    def __init__(self, robot_id: int = 0, position: Dict[str, float] = None, rotation: Dict[str, float] = None,
                 image_frequency: ImageFrequency = ImageFrequency.once, parent_camera_to_torso: bool = True,
                 visual_camera_mesh: bool = False, visual_camera_scale: Dict[str, float] = None,
                 check_version: bool = True):
        """
        :param robot_id: The ID of the robot.
        :param position: The position of the robot. If None, defaults to `{"x": 0, "y": 0, "z": 0}`.
        :param rotation: The rotation of the robot in Euler angles (degrees). If None, defaults to `{"x": 0, "y": 0, "z": 0}`.
        :param image_frequency: [The frequency of image capture.](image_frequency.md)
        :param parent_camera_to_torso: If True, the camera will be parented to the Magnebot's torso. If False, the camera will be parented to the Magnebot's column.
        :param visual_camera_mesh: If True, the camera will receive a visual mesh. The mesh won't have colliders and won't respond to physics. If False, the camera won't have a visual mesh.
        :param visual_camera_scale: The scale of the visual camera mesh as an x, y, z dictionary. If None, defaults to `{"x": 1, "y": 1, "z": 1}`. Ignored if `visual_camera_mesh == False`.
        :param check_version: If True, check whether an update to the Magnebot API or TDW API is available.
        """

        super().__init__(robot_id=robot_id, position=position, rotation=rotation)
        """:field
        [Cached static data for the Magnebot](magnebot_static.md) such as the IDs and segmentation colors of each joint:

        ```python
        from tdw.controller import Controller
        from tdw.tdw_utils import TDWUtils
        from magnebot.magnebot import Magnebot

        m = Magnebot()
        c = Controller()
        c.add_ons.append(m)
        c.communicate(TDWUtils.create_empty_room(12, 12))
        for arm_joint in m.static.arm_joints:
            joint_id = m.static.arm_joints[arm_joint]
            segmentation_color = m.static.joints[joint_id].segmentation_color
            print(arm_joint, joint_id, segmentation_color)
        c.communicate({"$type": "terminate"})
        ```
        """
        self.static: Optional[MagnebotStatic] = None
        """:field
        [Per-frame dynamic data for the Magnebot](magnebot_dynamic.md) such as its position and images:

        ```python
        from tdw.controller import Controller
        from tdw.tdw_utils import TDWUtils
        from magnebot.magnebot import Magnebot

        m = Magnebot()
        c = Controller()
        c.add_ons.append(m)
        c.communicate(TDWUtils.create_empty_room(12, 12))
        print(m.dynamic.transform.position)
        c.communicate({"$type": "terminate"})
        ```
        """
        self.dynamic: Optional[MagnebotDynamic] = None
        """:field
        The Magnebot's current [action](actions/action.md). Can be None (no ongoing action).
        """
        self.action: Optional[Action] = None
        """:field
        This sets [how often images are captured](image_frequency.md).
        """
        self.image_frequency: ImageFrequency = image_frequency
        """:field
        [The collision detection rules.](collision_detection.md) This determines whether the Magnebot will immediately stop moving or turning when it collides with something.
        """
        self.collision_detection: CollisionDetection = CollisionDetection()
        """:field
        The current (roll, pitch, yaw) angles of the Magnebot's camera in degrees as a numpy array. This is handled outside of `self.state` because it isn't calculated using output data from the build. See: `magnebot.actions.RotateCamera.CAMERA_RPY_CONSTRAINTS` and `self.rotate_camera()`
        """
        self.camera_rpy: np.array = np.array([0, 0, 0])
        self._previous_resp: List[bytes] = list()
        self._previous_action: Optional[Action] = None
        self._check_version: bool = check_version
        self._parent_camera_to_torso: bool = parent_camera_to_torso
        self._visual_camera_mesh: bool = visual_camera_mesh
        if visual_camera_scale is None:
            self._visual_camera_scale: Dict[str, float] = {"x": 1, "y": 1, "z": 1}
        else:
            self._visual_camera_scale = visual_camera_scale

    def get_initialization_commands(self) -> List[dict]:
        """
        This function gets called exactly once per add-on by the controller; don't call this function yourself!

        :return: A list of commands that will initialize this add-on.
        """

        MagnebotDynamic.FRAME_COUNT = 0
        commands = super().get_initialization_commands()
        commands.extend([{"$type": "send_magnebots",
                         "frequency": "always"},
                         {"$type": "send_transforms",
                          "frequency": "always"},
                         {"$type": "send_collisions",
                          "enter": True,
                          "stay": False,
                          "exit": True,
                          "collision_types": ["obj", "env"]}])
        if not Magnebot._CHECKED_VERSION:
            commands.append({"$type": "send_version"})
        return commands

    def on_send(self, resp: List[bytes]) -> None:
        """
        This is called after commands are sent to the build and a response is received.

        This function is called automatically by the controller; you don't need to call it yourself.

        :param resp: The response from the build.
        """

        super().on_send(resp=resp)
        self._previous_resp = resp
        if self.action is None or self.action.done:
            return
        else:
            if not self.action.initialized:
                # Some actions can fail immediately.
                if self.action.status == ActionStatus.ongoing:
                    self.action.initialized = True
                    initialization_commands = self.action.get_initialization_commands(resp=resp, static=self.static,
                                                                                dynamic=self.dynamic, image_frequency=self.image_frequency)
                    # This is an ongoing action.
                    if self.action.status == ActionStatus.ongoing:
                        self.commands.extend(initialization_commands)
                        # Set the status after initialization.
                        # This is required from one-frame actions such as RotateCamera.
                        self.action.set_status_after_initialization()
                        # This action is done. Append end commands.
                        if self.action.status != ActionStatus.ongoing:
                            self.commands.extend(self.action.get_end_commands(resp=resp,
                                                                              static=self.static,
                                                                              dynamic=self.dynamic,
                                                                              image_frequency=self.image_frequency))
            else:
                action_commands = self.action.get_ongoing_commands(resp=resp, static=self.static, dynamic=self.dynamic)
                # This is an ongoing action. Append ongoing commands.
                if self.action.status == ActionStatus.ongoing:
                    self.commands.extend(action_commands)
                # This action is done. Append end commands.
                else:
                    self.commands.extend(self.action.get_end_commands(resp=resp,
                                                                      static=self.static,
                                                                      dynamic=self.dynamic,
                                                                      image_frequency=self.image_frequency))
            # This action ended. Remember it as the previous action.
            if self.action.status != ActionStatus.ongoing:
                # Mark the action as done.
                self.action.done = True
                # Remember the previous action.
                self._previous_action = deepcopy(self.action)

    def turn_by(self, angle: float, aligned_at: float = 1, set_torso: bool = True) -> None:
        """
        Turn the Magnebot by an angle.

        While turning, the left wheels will turn one way and the right wheels in the opposite way, allowing the Magnebot to turn in place.

        :param angle: The target angle in degrees. Positive value = clockwise turn.
        :param aligned_at: If the difference between the current angle and the target angle is less than this value, then the action is successful.
        :param set_torso: If True, slide the torso to its default position when the wheel motion begins.
        """

        self.action = TurnBy(angle=angle, aligned_at=aligned_at, collision_detection=self.collision_detection,
                             previous=self._previous_action, dynamic=self.dynamic, set_torso=set_torso)

    def turn_to(self, target: Union[int, Dict[str, float], np.ndarray], aligned_at: float = 1,
                set_torso: bool = True) -> None:
        """
        Turn the Magnebot to face a target object or position.

        While turning, the left wheels will turn one way and the right wheels in the opposite way, allowing the Magnebot to turn in place.

        :param target: The target. If int: An object ID. If dict: A position as an x, y, z dictionary. If numpy array: A position as an [x, y, z] numpy array.
        :param aligned_at: If the difference between the current angle and the target angle is less than this value, then the action is successful.
        :param set_torso: If True, slide the torso to its default position when the wheel motion begins.
        """

        self.action = TurnTo(target=target, resp=self._previous_resp, aligned_at=aligned_at,
                             collision_detection=self.collision_detection, previous=self._previous_action,
                             dynamic=self.dynamic, set_torso=set_torso)

    def move_by(self, distance: float, arrived_at: float = 0.1, set_torso: bool = True) -> None:
        """
        Move the Magnebot forward or backward by a given distance.

        :param distance: The target distance. If less than zero, the Magnebot will move backwards.
        :param arrived_at: If at any point during the action the difference between the target distance and distance traversed is less than this, then the action is successful.
        :param set_torso: If True, slide the torso to its default position when the wheel motion begins.
        """

        self.action = MoveBy(distance=distance, arrived_at=arrived_at, collision_detection=self.collision_detection,
                             previous=self._previous_action, dynamic=self.dynamic, set_torso=set_torso)

    def move_to(self, target: Union[int, Dict[str, float], np.ndarray], arrived_at: float = 0.1, aligned_at: float = 1,
                arrived_offset: float = 0, set_torso: bool = True) -> None:
        """
        Move to a target object or position. This combines turn_to() followed by move_by().

        :param target: The target. If int: An object ID. If dict: A position as an x, y, z dictionary. If numpy array: A position as an [x, y, z] numpy array.
        :param arrived_at: If at any point during the action the difference between the target distance and distance traversed is less than this, then the action is successful.
        :param aligned_at: If the difference between the current angle and the target angle is less than this value, then the action is successful.
        :param arrived_offset: Offset the arrival position by this value. This can be useful if the Magnebot needs to move to an object but shouldn't try to move to the object's centroid. This is distinct from `arrived_at` because it won't affect the Magnebot's braking solution.
        :param set_torso: If True, slide the torso to its default position when the wheel motion begins.
        """

        self.action = MoveTo(target=target, resp=self._previous_resp, dynamic=self.dynamic,
                             collision_detection=self.collision_detection, arrived_at=arrived_at, aligned_at=aligned_at,
                             arrived_offset=arrived_offset, previous=self._previous_action, set_torso=set_torso)

    def stop(self) -> None:
        """
        Stop the Magnebot's wheels at their current positions.
        """

        self.action = Stop()

    def reach_for(self, target: Union[Dict[str, float], np.ndarray], arm: Arm, absolute: bool = True,
                  orientation_mode: OrientationMode = OrientationMode.auto,
                  target_orientation: TargetOrientation = TargetOrientation.auto, arrived_at: float = 0.125,
                  set_torso: bool = True) -> None:
        """
        Reach for a target position. The action ends when the magnet is at or near the target position, or if it fails to reach the target.
        The Magnebot may try to reach for the target multiple times, trying different IK orientations each time, or no times, if it knows the action will fail.

        :param target: The target position. If dict: A position as an x, y, z dictionary. If numpy array: A position as an [x, y, z] numpy array.
        :param arm: [The arm that will reach for the target.](arm.md)
        :param absolute: If True, `target` is in absolute world coordinates. If `False`, `target` is relative to the position and rotation of the Magnebot.
        :param arrived_at: If the magnet is this distance or less from `target`, then the action is successful.
        :param orientation_mode: [The orientation mode.](ik/orientation_mode.md)
        :param target_orientation: [The target orientation.](ik/target_orientation.md)
        :param set_torso: If True, stop sliding the torso when the arms stop moving at the end of the action.
        """

        if isinstance(target, dict):
            target = TDWUtils.vector3_to_array(target)

        self.action = ReachFor(target=target, arm=arm, absolute=absolute, orientation_mode=orientation_mode,
                               target_orientation=target_orientation, arrived_at=arrived_at, dynamic=self.dynamic,
                               set_torso=set_torso)

    def grasp(self, target: int, arm: Arm, orientation_mode: OrientationMode = OrientationMode.auto,
              target_orientation: TargetOrientation = TargetOrientation.auto, set_torso: bool = True) -> None:
        """
        Try to grasp a target object.
        The action ends when either the Magnebot grasps the object, can't grasp it, or fails arm articulation.

        :param target: The ID of the target object.
        :param arm: [The arm that will reach for and grasp the target.](arm.md)
        :param orientation_mode: [The orientation mode.](ik/orientation_mode.md)
        :param target_orientation: [The target orientation.](ik/target_orientation.md)
        :param set_torso: If True, stop sliding the torso when the arms stop moving at the end of the action.
        """

        self.action = Grasp(target=target, arm=arm, orientation_mode=orientation_mode,
                            target_orientation=target_orientation, dynamic=self.dynamic,
                            set_torso=set_torso)

    def drop(self, target: int, arm: Arm, wait_for_object: bool = True, set_torso: bool = True) -> None:
        """
        Drop an object held by a magnet.

        :param target: The ID of the object currently held by the magnet.
        :param arm: [The arm of the magnet holding the object.](arm.md)
        :param wait_for_object: If True, the action will continue until the object has finished falling. If False, the action advances the simulation by exactly 1 frame.
        :param set_torso: If True, stop sliding the torso when the arms stop moving at the end of the action.
        """

        self.action = Drop(arm=arm, target=target, wait_for_object=wait_for_object, dynamic=self.dynamic,
                           set_torso=set_torso)

    def reset_arm(self, arm: Arm, set_torso: bool = True) -> None:
        """
        Reset an arm to its neutral position.

        :param arm: [The arm to reset.](arm.md)
        :param set_torso: If True, stop sliding the torso when the arms stop moving at the end of the action.
        """

        self.action = ResetArm(arm=arm, set_torso=set_torso)

    def reset_position(self) -> None:
        """
        Reset the Magnebot so that it isn't tipping over.
        This will rotate the Magnebot to the default rotation (so that it isn't tipped over) and move the Magnebot to the nearest empty space on the floor.
        It will also drop any held objects.

        This will be interpreted by the physics engine as a _very_ sudden and fast movement.
        This action should only be called if the Magnebot is a position that will prevent the simulation from continuing (for example, if the Magnebot fell over).
        """

        self.action = ResetPosition()

    def rotate_camera(self, roll: float = 0, pitch: float = 0, yaw: float = 0) -> None:
        """
        Rotate the Magnebot's camera by the (roll, pitch, yaw) axes.

        Each axis of rotation is constrained by the following limits:

        | Axis | Minimum | Maximum |
        | --- | --- | --- |
        | roll | -55 | 55 |
        | pitch | -70 | 70 |
        | yaw | -85 | 85 |

        :param roll: The roll angle in degrees.
        :param pitch: The pitch angle in degrees.
        :param yaw: The yaw angle in degrees.
        """

        self.action = RotateCamera(roll=roll, pitch=pitch, yaw=yaw, camera_rpy=self.camera_rpy)
        # Update the camera RPY angles.
        self.camera_rpy = np.array(self.action.camera_rpy[:])

    def look_at(self, target: Union[int, Dict[str, float], np.ndarray]) -> None:
        """
        Rotate the Magnebot's camera to look at a target object or position.

        This action is not compatible with `rotate_camera()` because it will ignore (roll, pitch, yaw) constraints; if you use this action, `rotate_camera()` won't work as intended until you call `reset_camera()`.

        :param target: The target. If int: An object ID. If dict: A position as an x, y, z dictionary. If numpy array: A position as an [x, y, z] numpy array.
        """

        self.action = LookAt(target=target)

    def move_camera(self, position: Union[Dict[str, float], np.ndarray]) -> None:
        """
        Move the Magnebot's camera by an offset position.

        By default, the camera is parented to the torso and will continue to move when the torso moves. You can prevent this by setting `parent_camera_to_torso=False` in the Magnebot constructor.

        :param position: The positional offset that the camera will move by.
        """

        self.action = MoveCamera(position=position)

    def reset_camera(self, position: bool = True, rotation: bool = True) -> None:
        """
        Reset the rotation of the Magnebot's camera to its default angles and/or its default position relative to its parent (by default, its parent is the torso).

        :param position: If True, reset the camera's position.
        :param rotation: If True, reset the camera' rotation.
        """

        self.action = ResetCamera(position=position, rotation=rotation, parented_to_torso=self._parent_camera_to_torso)
        # Reset the camera RPY angles.
        if rotation:
            self.camera_rpy = np.array([0, 0, 0])

    def reset(self, position: Dict[str, float] = None, rotation: Dict[str, float] = None) -> None:
        super().reset(position=position, rotation=rotation)
        self.action = None
        self._previous_action = None
        self.camera_rpy: np.array = np.array([0, 0, 0])
        self.collision_detection = CollisionDetection()
        self._previous_resp.clear()

    def slide_torso(self, height: float) -> None:
        """
        Slide the Magnebot's torso up or down.

        :param height: The height of the torso. Must be between `magnebot.constants.TORSO_MIN_Y` and `magnebot.constants.TORSO_MAX_Y`.
        """

        self.action = SlideTorso(height=height)

    def _cache_static_data(self, resp: List[bytes]) -> None:
        """
        Cache static output data.

        :param resp: The response from the build.
        """

        if self._check_version and not Magnebot._CHECKED_VERSION:
            Magnebot._CHECKED_VERSION = True
            check_version()
            version_data = get_data(resp=resp, d_type=Version)
            build_version = version_data.get_tdw_version()
            PyPi.required_tdw_version_is_installed(required_version=TDW_VERSION, build_version=build_version,
                                                   comparison=">=")
        self.static = MagnebotStatic(robot_id=self.robot_id, resp=resp)
        # Wait for the joints to finish moving.
        self.action = Wait()
        # Add an avatar and set up its camera.
        self.commands.extend([{"$type": "create_avatar",
                               "type": "A_Img_Caps_Kinematic",
                               "id": self.static.avatar_id},
                              {"$type": "set_pass_masks",
                               "pass_masks": ["_img", "_id", "_depth"],
                               "avatar_id": self.static.avatar_id},
                              self._get_parent_avatar_command(),
                              {"$type": "enable_image_sensor",
                               "enable": False,
                               "avatar_id": self.static.avatar_id},
                              {"$type": "set_img_pass_encoding",
                               "value": False}])
        # Visualize the camera.
        if self._visual_camera_mesh:
            self.commands.append({"$type": "add_visual_camera_mesh",
                                  "avatar_id": self.static.avatar_id,
                                  "scale": self._visual_camera_scale})

    def _set_dynamic_data(self, resp: List[bytes]) -> None:
        """
        Set dynamic data.

        :param resp: The response from the build.
        """

        if self.dynamic is None:
            frame_count = 0
        else:
            self.dynamic: MagnebotDynamic
            frame_count = self.dynamic.frame_count
        dynamic = MagnebotDynamic(static=self.static, resp=resp, frame_count=frame_count)
        wheels_moving: Dict[Wheel, bool] = dict()
        if self.dynamic is not None:
            # Set whether the wheels are moving.
            for wheel in self.static.wheels:
                wheel_id = self.static.wheels[wheel]
                wheels_moving[wheel] = np.linalg.norm(self.dynamic.joints[wheel_id].angles[0] -
                                                      dynamic.joints[wheel_id].angles[0]) > 0.1
        self.dynamic = self._set_joints_moving(dynamic)
        # Set whether the wheels are moving.
        for wheel in wheels_moving:
            self.dynamic.joints[self.static.wheels[wheel]].moving = wheels_moving[wheel]

    def _get_add_robot_command(self) -> dict:
        """
        :return: The command to add the Magnebot.
        """

        return {"$type": "add_magnebot",
                "position": self.initial_position,
                "rotation": self.initial_rotation,
                "id": self.robot_id}

    def _get_parent_avatar_command(self) -> dict:
        """
        :return: A command to parent the avatar to the Magenbot. The parent body part is determined by `self._parent_camera_to_torso` and the `parent_camera_to_torso` constructor parameter.
        """

        return {"$type": "parent_avatar_to_robot",
                "position": DEFAULT_CAMERA_POSITION_TORSO if self._parent_camera_to_torso else DEFAULT_CAMERA_POSITION_COLUMN,
                "body_part_id": self.static.arm_joints[ArmJoint.torso if self._parent_camera_to_torso else ArmJoint.column],
                "avatar_id": self.static.avatar_id,
                "id": self.static.robot_id}


from django.urls import path

from .views import (CreateMeetupView, UpcomingMeetupsView,
                    SpecificMeetupView, AskQuestionView,
                    GetMeetupQuestionsView, VoteView,
                    SpecificQuestionView, AnswerQuestionView,
                    GetQuestionAnswersView)

urlpatterns = [
	path('', CreateMeetupView.as_view(), name='create'),
	path('upcoming/', UpcomingMeetupsView.as_view(), name='upcoming'),
	path('<pk>', SpecificMeetupView.as_view(), name='specific'),
	path('<pk>/questions/ask/', AskQuestionView.as_view(),
	     name='ask-questions'),
	path('<for_meetup_id>/questions/get/', GetMeetupQuestionsView.as_view(),
	     name='get-questions'),
	path('questions/<pk>/', SpecificQuestionView.as_view(), name='question'),
	path('questions/<pk>/vote/', VoteView.as_view(), name='vote'),
	path('questions/<pk>/answer/', AnswerQuestionView.as_view(), name='answer'),
	path('questions/<for_question_id>/answers/', GetQuestionAnswersView.as_view(), name='answers'),
	]


#!/usr/bin/env python
###############################################################################
# This software and supporting documentation are distributed by CEA/NeuroSpin,
# Batiment 145, 91191 Gif-sur-Yvette cedex, France. This software is governed
# by the CeCILL license version 2 under French law and abiding by the rules of
# distribution of free software. You can  use, modify and/or redistribute the
# software under the terms of the CeCILL license version 2 as circulated by
# CEA, CNRS and INRIA at the following URL "http://www.cecill.info".
###############################################################################

"""
This script does the following:
* create the connectivity profile overlap the mask
* normalize of the profile by its max of connections
* write the mean profile on the disk

Main dependencies: PyAims library

Author: Sandrine Lefranc, 2015
"""

#----------------------------Imports-------------------------------------------

# python system module
from __future__ import absolute_import
import sys
import numpy
import argparse
import textwrap

# aims module
from soma import aims

#----------------------------Functions-----------------------------------------

def parse_args(argv):
    """Parses the given list of arguments."""

    # creating a parser
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent("""\
            -------------------------------------------------------------------
            Create the connectivity profile overlap the mask and normalize the
            profile by its max of connections
            -------------------------------------------------------------------
            """))

    # adding arguments
    parser.add_argument("mask", type=str, help="binary profile")
    parser.add_argument("meanprofile", type=str,
                        help="mean profile is generated from the mask")
    parser.add_argument("normprofile", type=str,
                        help="normed mean profile")

    # parsing arguments
    return parser, parser.parse_args(argv)

def main():
    # load the arguments of parser (delete script name: sys.arg[0])
    arguments = (sys.argv[1:])
    parser, args = parse_args(arguments)

    # read the files with aims
    aims_mask = aims.read(args.mask)
    aims_profile = aims.read(args.meanprofile)

    # transform the aims files to numpy array
    np_profile = aims_profile[0].arraydata()
    np_mask = aims_mask[0].arraydata()

    # create the connectivity profile overlap the mask
    np_profile[numpy.where(np_mask == 0)] = 0

    # normalize of the profile by its max of connections
    if np_profile.max() > 0:
        np_profile *= 1. / np_profile.max()

    # create a time texture object by assigning the mean profile
    aimstex = aims.TimeTexture_FLOAT()
    aimstex[0].assign(np_profile)

    # write the file on the disk
    aims.write(aimstex, args.normprofile)

#----------------------------Main program--------------------------------------

if __name__ == "__main__":
    main()