import argparse
from dataclasses import dataclass
from functools import partial
import json
import multiprocessing
import multiprocessing.dummy
from pathlib import Path
import sys
from typing import List

import soundfile as sf
from soundfile import LibsndfileError, SoundFileError
from tqdm import tqdm

from ldc_bpcsad import __version__ as VERSION
from ldc_bpcsad.decode import decode
from ldc_bpcsad.io import (write_audacity_label_file, write_htk_label_file,
                           write_rttm_file, write_textgrid_file)
from ldc_bpcsad.logging import getLogger, setup_logger, DEBUG, WARNING
from ldc_bpcsad.utils import get_nframes_wav, which

logger = getLogger()

class ChannelNotFoundError(Exception):
    """Raised when a channel doesn't exist."""
    pass

class FileEmptyError(Exception):
    """Raised when a file contains no data."""
    pass

@dataclass
class Channel:
    """Channel of recording.

    Parameters
    ----------
    id : str
        Unique identifier of channel. Used to name output file containing SAD
        output.

    audio_path : Path
        Path to audio file channel is on.

    channel : int
        Channel number on audio file (1-indexed).

    Attributes
    ----------
    format : str
        Audio format (derived from extension).
    """
    id: str
    audio_path: Path
    channel: int

    def __post_init__(self):
        self.audio_path = Path(self.audio_path)
        self.channel = int(self.channel)
        self.format = self.audio_path.suffix.lstrip('.').upper()

    def validate(self):
        """Check that channel is valid.

        If all checks pass, return the channel. Otherwise, raises an exception.
        """
        # Check that file exists.
        if not self.audio_path.exists():
            raise FileNotFoundError(
                f'Audio file does not exist: {self.audio_path}')

        # Check that file is not empty.
        n_bytes = self.audio_path.lstat().st_size
        if n_bytes == 0:
            raise FileEmptyError('File contains no data.')

        # Check in a known audio format.
        if self.format not in sf._formats:
            raise SoundFileError(f'Unknown format "{self.format}"')

        # Check that soundfile can, in actuality, read it  --  the header is a
        # lie, etc.
        info = sf.info(self.audio_path, verbose=True)
        logger.debug(f'Source audio file: {info}')
        logger.debug('')
        logger.debug(f'Source channel: {self.channel}.')
        logger.debug('')

        # Check that file does not consists of JUST a header.
        if info.frames == 0 or info.frames == 9223372036854775807:
            # soundfile.info seems to encounter an underflow errors for some
            # formats when file is empty.
            raise FileEmptyError('File contains no data.')

        # Check that # frames indicated in header agrees with actual # frames.
        # Currently only implemented for WAV.
        if self.format == 'WAV':
            try:
                n_frames_header = get_nframes_wav(self.audio_path)
                n_frames_actual = info.frames
                if n_frames_header != n_frames_actual:
                    logger.warning(
                        f'Header frame count wrong for file '
                        f'"{self.audio_path}": '
                        f'{n_frames_header} != {n_frames_actual}')
            except Exception as e:
                # Bare except, yes, yes. yada, yada, yada/
                pass

        # Check that channel EXISTS on file.
        if not 1 <= self.channel <= info.channels:
            raise ChannelNotFoundError(
                f'Invalid source channel: {self.channel}. Source '
                f'channel be positive integer <= {info.channels}.')

        return self

def load_htk_script_file(fpath, channel=1):
    """Read channels to process from HTK script file.

    An HTK script file specifies a set of file paths, each path separated by a
    newline; e.g.:

        /data/flac/rec01.flac
        /data/flac/rec02.flac
        /data/flac/rec03.flac

    Parameters
    ----------
    fpath : Path
        Path to script file.

    channel : int, optional
        Channel number (1-indexed) to perform SAD on for each file.
        (Default: 1)

    Returns
    -------
    list of Channel
        Channels to perform SAD on.
    """
    channels = []
    with open(fpath, 'r', encoding='utf-8') as f:
        for line in f:
            audio_path = Path(line.strip())
            channel_id = audio_path.stem
            chan = Channel(channel_id, audio_path, channel)
            channels.append(chan)
    return channels

def load_json_script_file(fpath):
    """Read channels to process from JSON file.

    The JSON file should consist of a sequence of JSON objects, each containing
    the following three key-value pairs:

    - ``channel_id``  --  Unique identifier of channel. Used to name output
      file containing SAD output.
    - ``audio_path``  --  Path to audio file that the channel is on.
    - ``channel``  --  Channel number of audio file to process (1-indexed).

    For instance:

        ```json
        [{
            "channel_id": "rec1_c1",
            "audio_path": "/path/to/rec1.flac",
            "channel": 1
        }, {
            "channel_id": "rec1_c2",
            "audio_path": "/path/to/rec1.flac",
            "channel": 2
        }, {
            "channel_id": "rec2_c1",
            "audio_path": "/path/to/rec2.flac",
            "channel": 1
        }]
        ```

    Parameters
    ----------
    fpath : Path
        Path to script file.

    Returns
    -------
    list of Channel
        Channels to perform SAD on.
    """
    with open(fpath, 'r', encoding='utf-8') as f:
        records = json.load(f)
    channels = []
    for record in records:
        try:
            channel = Channel(
                record['channel_id'], Path(record['audio_path']),
                int(record['channel']))
        except Exception as e:
            channel = None
        if not channel:
            logger.warning(
                f'Malformed record in JSON script file. Skipping. '
                f'SCRIPT FILE: {fpath}, RECORD: {record}')
            continue
        channels.append(channel)
    return channels

# Mapping from output formats to corresponding extensions.
OUTPUT_EXTS = {'htk': '.lab',
               'audacity': '.txt',
               'rttm': '.rttm',
               'textgrid': '.TextGrid'}

@dataclass
class CompletedProcess:
    """Return value from `parallel_wrapper`, representing a process that has
    completed.

    Parameters
    ----------
    channel : Channel
        Channel SAD was attempted on.

    success : bool
        Did processing succeed for the channel.
    """
    channel: Channel
    success: bool

def _process_one_file(channel, args):
    """Process one file."""
    success = False
    try:
        logger.debug('#' * 72)
        logger.debug('Attempting SAD.')
        logger.debug('#' * 72)

        # Basic validation of channel.
        channel.validate()

        # Perform SAD.
        with open(channel.audio_path, 'rb') as f:
            x, sr = sf.read(f)
        if x.ndim > 1:
            x = x[:, channel.channel - 1]
        segs = decode(
            x, sr, min_speech_dur=args.min_speech_dur,
            min_nonspeech_dur=args.min_nonspeech_dur,
            speech_scale_factor=args.speech_scale_factor,
            silent=False)

        # Write to output file.
        rec_dur = len(x) / sr
        kwargs = {'is_sorted': True, 'precision': 2}
        ext = OUTPUT_EXTS[args.output_fmt]
        output_path = Path(args.output_dir, channel.id + ext)
        logger.debug(f'Saving SAD to "{output_path}".')
        logger.debug(f'Output file format: {args.output_fmt}')
        if args.output_fmt == 'htk':
            write_htk_label_file(
                output_path, segs, rec_dur=rec_dur, **kwargs)
        elif args.output_fmt == 'audacity':
            write_audacity_label_file(
                output_path, segs, rec_dur=rec_dur, **kwargs)
        elif args.output_fmt == 'rttm':
            write_rttm_file(
                output_path, segs, file_id=channel.audio_path.stem,
                channel=channel.channel, **kwargs)
        elif args.output_fmt == 'textgrid':
            write_textgrid_file(
                output_path, segs, tier='sad', rec_dur=rec_dur, **kwargs)

        success = True
    except LibsndfileError as e:
        logger.debug(e, exc_info=True)
        msg = str(e)
        if (msg.endswith('unknown format.') or
            msg.endswith('unimplemented format.') or
            msg.endswith('Format not recognised.')):
            # If unknown/unsupported file format, remind users what formats
            # are supported.
            logger.debug('To see supported formats, run:')
            logger.debug('')
            logger.debug('    ldc-bpcsad --help')
    except Exception as e:
        logger.debug(e, exc_info=True)

    return CompletedProcess(channel, success)

def process_one_file(channel, args):
    """Process one file."""
    p = _process_one_file(channel, args)
    if not p.success:
        logger.warning(
            f'SAD failed for channel {p.channel.channel} of '
            f'"{p.channel.audio_path}". Skipping. For more details rerun with '
            f'the --debug flag.')

def get_parser():
    """Return `argparse.ArgumentParser`."""
    audio_formats = ', '.join(sorted(sf.available_formats().values()))
    parser = argparse.ArgumentParser(
        description='Perform speech activity detection on audio files.',
        epilog=f'audio file formats: {audio_formats}',
        add_help=True)
    parser.add_argument(
        'audio_path', metavar='audio-path', type=Path, nargs='*',
        help='audio files to be processed')
    parser.add_argument(
        '--channel', default=1, type=int, metavar='CHAN',
        dest='channel',
        help='channel (1-indexed) to process on each audio file '
             '(Default: %(default)s)')
    parser.add_argument(
        '--scp', metavar='SCP', type=Path,
        dest='scp_path',
        help='path to script file (Default: %(default)s)')
    parser.add_argument(
        '--scp-fmt', metavar='SCP-FMT', dest='scp_fmt', default='htk',
        choices=['htk', 'json'],
        help='script file format (Default: %(default)s)')
    parser.add_argument(
        '--output-dir', metavar='OUTPUT-DIR', type=Path, dest='output_dir',
        default=Path.cwd(),
        help="output segmentations to OUTPUT-DIR (Default: current directory)")
    parser.add_argument(
        '--output-fmt', metavar='OUTPUT-FMT', default='htk',
        choices=sorted(OUTPUT_EXTS.keys()),
        help='output file format (Default: %(default)s)')
    parser.add_argument(
        '--speech', metavar='SPEECH-DUR', default=0.500, type=float,
        dest='min_speech_dur',
        help='filter speech segments shorter than SPEECH-DUR seconds '
             '(Default: %(default)s)')
    parser.add_argument(
        '--nonspeech', metavar='NONSPEECH-DUR', default=0.300, type=float,
        dest='min_nonspeech_dur',
        help='merge speech segments separated by less than NONSPEECH-DUR '
             'seconds (Default: %(default)s)')
    parser.add_argument(
        '--speech-scale-factor', metavar='SPEECH-SCALE', default=1.,
        type=float,
        help='post-multiply speech model acoustic likelihoods by '
             'SPEECH-SCALE (Default: %(default)s)')
    parser.add_argument(
        '--disable-progress', default=False, action='store_true',
        help='disable progress bar')
    parser.add_argument(
        '--debug', default=False, action='store_true',
        help='enable DEBUG mode')
    parser.add_argument(
        '--n-jobs', '-j', nargs=None, default=1, type=int, metavar='INT',
        dest='n_jobs', help='set num threads to use (Default: %(default)s)')
    parser.add_argument(
        '--version', action='version', version='%(prog)s ' + VERSION)
    if len(sys.argv) == 1:
        parser.print_help()
        parser.exit()
    return parser

def main():
    parser = get_parser()
    args = parser.parse_args()

    # Set up logger.
    log_level = DEBUG if args.debug else WARNING
    setup_logger(logger, level=log_level)

    # Ensure HTK is installed.
    if not which('HVite'):
        # TODO: Update link when docs are online.
        logger.error(
            'HVite is not installed. Please install HTK and try again: '
            '[INSERT LINK TO INSTRUCTIONS HERE]')
        sys.exit(1)

    # Load channels.
    if args.scp_path:
        if args.scp_fmt == 'htk':
            channels = load_htk_script_file(
                args.scp_path, channel=args.channel)
        elif args.scp_fmt == 'json':
            channels = load_json_script_file(args.scp_path)
        else:
            assert False
    else:
        channels = []
        for audio_path in args.audio_path:
            channels.append(Channel(audio_path.stem, audio_path, args.channel))
    # TODO: Check for dupes.
    if not channels:
        return

    # Perform SAD on files in parallel.
    args.output_dir.mkdir(parents=True, exist_ok=True)
    args.n_jobs = min(args.n_jobs, len(channels))
    logger.debug(f'COMMAND LINE CALL: {" ".join(sys.argv)}')
    if args.debug:
        logger.debug(
            'Flag "--n-jobs" is ignored for debug mode. Using single-threaded '
            'implementation.')
        args.n_jobs = 1
        logger.debug('Progress bar is disabled for debug mode.')
        logger.debug('')
        args.disable_progress = True
    Pool = multiprocessing.Pool
    if args.n_jobs == 1:
        Pool = multiprocessing.dummy.Pool
    with Pool(args.n_jobs) as pool:
        f = partial(process_one_file, args=args)
        with tqdm(total=len(channels), disable=args.disable_progress) as pbar:
            for res in pool.imap(f, channels):
                pbar.update(1)

if __name__ == '__main__':
    main()


import seaborn as sns
import matplotlib.pyplot as plt

def entropy_plot(dataframe):
    df_tmp = dataframe.copy()
    df_tmp['classification'] = df_tmp['gt_label'] == df_tmp['pred_lbl']
    fig, ax = plt.subplots(figsize=(8, 6))
    # ax = sns.boxplot(ax=ax, data=df_tmp, x="classification", y="entropy", hue="quality_category")
    # ax = sns.swarmplot(ax=ax, data=df_tmp, x="classification", y="entropy", hue="quality_category")
    ax = sns.swarmplot(ax=ax, data=df_tmp, x="classification", y="entropy")
    ax.set(ylabel="Entropy")
    ax.set(xlabel="Classification")

def entropy_vs_myb(dataframe):
    df_tmp = dataframe.copy()
    df_tmp['classification'] = df_tmp['gt_label'] == df_tmp['pred_lbl']
    fig, ax = plt.subplots(figsize=(8, 6))

    df_true = df_tmp.loc[df_tmp['classification']]
    ax.scatter(df_true.myb_annotated, df_true.entropy, label='True prediction')
    df_false = df_tmp.loc[~df_tmp['classification']]
    ax.scatter(
        df_false.myb_annotated,
        df_false.entropy,
        label='False prediction')
    ax.set(ylabel="Entropy")
    ax.set(xlabel="Myeloblast percentage")
    ax.legend(title='Percent of myeloblasts in differential blood count',
              bbox_to_anchor=(1, 0., 0.5, 1), loc=10)


import pygame as pg
from Settings import *
from Player import Player
from Render import Render
from Map import *

class Main:
    def __init__(self):
        pg.init()
        self.screen = pg.display.set_mode((0, 0), pg.FULLSCREEN)
        # self.screen = pg.display.set_mode((1200, 1000))
        self.clock = pg.time.Clock()
        self.player = Player(pg.display.get_surface().get_size())
        self.render = Render(self.screen)
        self.run = True

    def events(self):
        for event in pg.event.get():
            if event.type == pg.KEYUP:
                if event.key == pg.K_ESCAPE:
                    self.run = False

        keys = pg.key.get_pressed()
        if keys[pg.K_a]:
            self.player.speed_directions[LEFT] = self.player.speed
        if keys[pg.K_d]:
            self.player.speed_directions[RIGHT] = self.player.speed
        if keys[pg.K_w]:
            if self.player.can_jump:
                self.player.speed_directions[UP] = self.player.jump_speed

    def main_loop(self):
        while self.run:
            self.clock.tick(FPS)
            pg.display.set_caption(str(self.clock.get_fps()))
            self.events()
            self.player.move()

            self.rendering()

    def rendering(self):
        self.screen.fill(BLACK)
        self.render.map(self.player.camera_pos)
        self.render.player(self.player.camera_pos, self.player)
        pg.display.update()

main = Main()
main.main_loop()
pg.quit()


from django.shortcuts import render
from django.http import JsonResponse
from rest_framework.response import Response
from .models import (
  PointTransaction,
  Point,
)
from rest_framework.views import APIView
from django.views.generic.base import View

class PointCheckoutAjaxView(APIView):

  def post(self, request, *args, **kwargs):
    if not request.user.is_authenticated:
      return JsonResponse({}, status=401)

    user = request.user
    print(user)
    amount = request.POST.get('amount')
    print(amount)
    type = request.POST.get('type')
    print(type)
    try:
      trans = PointTransaction.objects.create_new(
        user=user,
        amount=amount,
        type=type
      )
    except:
      trans = None
    print(trans)
    if trans is not None:
      data = {
        "works": True,
        "merchant_id": trans
      }
      return JsonResponse(data)
    else:
      return JsonResponse({}, status=401)

class PointImpAjaxView(APIView):
  def post(self, request, *args, **kwargs):
    if not request.user.is_authenticated:
      return JsonResponse({}, status=401)

    user = request.user
    merchant_id = request.POST.get('merchant_id')
    imp_id = request.POST.get('imp_id')
    amount = request.POST.get('amount')

    try:
      trans = PointTransaction.objects.get(
        user=user,
        order_id=merchant_id,
        amount=amount
      )
    except:
      trans = None

    if trans is not None:
      trans.transaction_id = imp_id
      trans.success = True
      trans.save()

      data = {
        "works": True
      }

      return JsonResponse(data)
    else:
      return JsonResponse({}, status=401)

def charge_point(request):
  template = 'charge.html'

  return render(request, template)


from rest_framework import serializers
from agendamentos.models import Agendamentos
from historicos.api.serializers import HistoricosSerializer,HistoricosDetalhesSerializer

class AgendamentosSerializer(serializers.ModelSerializer):
    class Meta:
        model = Agendamentos
        fields = '__all__'
class AgendamentosDetalhesSerializer(serializers.ModelSerializer):
    historicos = HistoricosDetalhesSerializer(many=True, read_only=True)
    nome_paciente = serializers.ReadOnlyField(source='id_paciente.nome')
    nome_medico = serializers.ReadOnlyField(source='id_medico.nome')
    class Meta:
        model = Agendamentos
        fields = [
            'id_agendamento',
            'data_hora' ,
            'data_criacao' ,
            'cancelado',
            'obs' ,
            'tipo',
            'nome_medico',
            'nome_paciente',
            'historicos'
        ]


"""
mainwindow.py has the MainWindow class and defines the startMainMenu and startStallMenu functions.

Criteria Fulfilled:
- Program Organization
- Programming Style
- Program Correctness
"""

from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtGui import QImage, QPalette, QBrush
from PyQt5.QtCore import QSize
from functools import partial
import sys
import mainmenu as main_menu
import stall_menu
import app_data as info

class MainWindow(QMainWindow):
    # By Kyaw and Nisha
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # Background Image
        self.setGeometry(50, 50, 400, 450)
        self.setFixedSize(592, 808)
        oImage = QImage("icons/background.jpg")
        sImage = oImage.scaled(QSize(592,808))
        palette = QPalette()
        palette.setBrush(10, QBrush(sImage))
        self.setPalette(palette)

        # Start the Main Menu
        self.startMainMenu()

    # startStallMenu is called when a stall's button is clicked on the GUI.
    # This function will then get the necessary information and open up the Stall Menu GUI.
    def startStallMenu(self,name):
        # By Kyaw
        self.name = name
        self.StallMenu = stall_menu.StallMenu(self.Window,name)

        self.setWindowTitle(info.stalls[name]+" Menu")
        self.setCentralWidget(self.StallMenu)
        self.StallMenu.backButton.clicked.connect(self.startMainMenu)
        self.show()

    # startMainMenu is called when the application first starts up
    #and whenever the back button on the Stall Menu is clicked
    def startMainMenu(self):
        # By Nisha
        self.Window = main_menu.MainMenu(self)
        self.setWindowTitle("North Spine Food Explorer")
        self.setCentralWidget(self.Window)
        for x in range(25):
            self.Window.btn[x].clicked.connect(partial(self.startStallMenu, info.stalls_list[x]))
        # If time has been set by user, then don't run live timer, just show the user-set time.
        # But if it's not, it will throw an error, which we want to avoid, so just do nothing for the error
        try:
            if "Set Time: " in self.StallMenu.time_label.text():
                self.Window.timer.stop()
                self.Window.time_label.setText(self.StallMenu.time_label.text())
        except:
            pass
        self.show()


import ClassesBraucon
import RPi.GPIO as GPIO
import time as tm
import numpy as np
import threading as trd
from scipy.ndimage.interpolation import shift
#import matplotlib.pyplot as plt
import os

GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#RC-Pins & LED Setup
ON_CH  = 21
OFF_CH = 26
LED    = 2
GPIO.setup(ON_CH,GPIO.OUT)
GPIO.setup(OFF_CH,GPIO.OUT)
GPIO.setup(LED,GPIO.OUT)
GPIO.output(ON_CH,GPIO.LOW)
GPIO.output(OFF_CH,GPIO.LOW)
GPIO.output(LED,GPIO.LOW)
# SPI Setup
csPin   = 8
misoPin = 9
mosiPin = 10
clkPin  = 11
# Max31865 Initialization
max31865 = ClassesBraucon.max31865(csPin,misoPin,mosiPin,clkPin)
# Variables
CurrSocketState = False # False--> Socket OFF
TempValBuffer = np.arange(10,dtype=float)
#CycCounter = 0
rootdir = os.path.dirname(os.path.realpath(__file__))+'/'#'/home/pi/braucon/'

# Functions
def Socket (NewSocketState):#, CurrSocketState):

    global CurrSocketState

    if (CurrSocketState == False and NewSocketState == True):
        GPIO.output(ON_CH,GPIO.HIGH)
        tm.sleep(0.3)
        GPIO.output(ON_CH,GPIO.LOW)
        CurrSocketState = True
    elif (CurrSocketState == True and NewSocketState == False):
        GPIO.output(OFF_CH,GPIO.HIGH)
        tm.sleep(0.3)
        GPIO.output(OFF_CH,GPIO.LOW)
        CurrSocketState = False

    return CurrSocketState

def ApplyDuty(ratio,T):
    Socket(True)
    tm.sleep(ratio*T)
    Socket(False)
    tm.sleep((1-ratio)*T)

def ReadPhasesCal():
    data = np.loadtxt(rootdir + 'MaischPhasen.dat', delimiter='\t',dtype='str')
    data = [x[2:-1] for x in data]
    phases = np.array([x.split(',') for x in data])
    gain,offset = np.loadtxt(rootdir + 'Calibration.data', dtype=float)
    del data

    return phases,gain,offset

def Pt100_Filter_C():

    global TempValBuffer

    FilterBuffer = np.zeros(50, dtype=float)

    while True:
        for i in range (48):
            T = max31865.readTemp()
            FilterBuffer = shift(FilterBuffer,1,cval= T)
            tm.sleep(0.02)

        FilterBuffer = np.sort(FilterBuffer, axis=0)
        IQR_Mean = np.mean(FilterBuffer[12:36])
        IQR_MeanCal = np.round(gain * IQR_Mean + offset,2) ##calibrated
        TempValBuffer = shift(TempValBuffer,1,cval=IQR_MeanCal)

def CalcDeltaT (PhaseNum):

    global CycCounter

    T_soll = float(phases[PhaseNum][1])
    T_curr = TempValBuffer[0] #--- T_curr = Pt100_Mean_C(2,0.5)
    DeltaT = T_curr-T_soll
    print('T='+str(T_curr) +'GrC\t' +'Delta= ' + str(DeltaT) + 'GrC')

    return DeltaT

def HeatToTemp(PhaseNum):

    while ( CalcDeltaT(PhaseNum) < -0.4):

        Delta = abs(CalcDeltaT(PhaseNum))
        print(str(TempValBuffer[0]) + 'GrC')
        if (Delta > 5):
            Socket(True)
            tm.sleep(5)
        elif(Delta < 5 and Delta > 2.5):
            print('75%')
            ApplyDuty(0.75,50)
##            tm.sleep(5)
        elif(Delta < 2.5  and Delta > 1.0):
            print('50%')
            ApplyDuty(0.5,40)
##            tm.sleep(10)
        elif(Delta < 1.0  and Delta > 0.3):
            print('15%')
            ApplyDuty(0.15,30)
            tm.sleep(20)
        else:
            print('0%')
            Socket(False)
            tm.sleep(5)
    print('Heating done!')

def Rast(PhaseNum):
    RastTime = int(phases[PhaseNum][2])

    for i in range(RastTime):
        print(phases[PhaseNum][2])
        print(str(RastTime-i) + ' minutes remaining')
        tm.sleep(40)
        if ( CalcDeltaT(PhaseNum) < -0.2):
            Delta = abs(CalcDeltaT(PhaseNum))
            print(str(TempValBuffer[0]) + 'GrC')

            if(Delta < 2  and Delta > 0.8):
                print('15%')
                ApplyDuty(0.15,20)
            elif(Delta < 0.8  and Delta > 0.1):
                print('5%')
                ApplyDuty(0.05,20)
        else:
            print('0%')
            Socket(False)
            tm.sleep(20)

def ExecPhase(PhaseNum):
    print('Executing:  ' + phases[PhaseNum][0])
    T_soll = float(phases[PhaseNum][1])
    print('T_soll:  ' + str(T_soll) )#+ '°C')

    HeatToTemp(PhaseNum)
    print('Rast started:')
    Rast(PhaseNum)

def Background():
    Pt100_Filter_C()

def Main():

   # fig = plt.figure()

    for i in range(1,len(phases)):
        print('starting phase ' + str(i))
        ExecPhase(i)

    GPIO.cleanup()

##Read Calibration and phases
#global phases,gain,offset
phases,gain,offset = ReadPhasesCal()
print(phases)
print('Gain: ' + str(gain) + ' Offset: ' + str(offset))

## Initialize Temperature measurement
TempThread = trd.Thread(target=Background) #new values with 2Hz
MainThread = trd.Thread(target=Main)
##TempThread.daemon = True
TempThread.start()
tm.sleep(2) #TempValBuffer has to be filled
MainThread.start()


"""

This too is an incomplete version of feebackloop where Louis tried his own idea of solving the problem.
Please ignore this one as well.

@author: Louis
"""
import cv2
import numpy as np
import imutils
import requests
import copy
from RE__Needle_robotics.Steedle_software_package.img2 import segmentImg2
from Motor_controller import motor_controller
from Calculate_insertion import calculateInsertion

controller = motor_controller()

cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)
url = "http://145.94.151.26:8080/shot.jpg"  # live phone streaming link

frame_conversion = 150 / 1280  # pixel to mm # TODO: Should be converted properly with cropped frame

def needleTip(image):
    # blur the image
    image2 = cv2.GaussianBlur(image, (5, 5), 0)

    hsvPlate = cv2.cvtColor(image2, cv2.COLOR_BGR2HSV)
    grayPlate = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

    # TODO: These colors will need to be min maxed
    colorMin = np.array([50, 100, 100])
    colorMax = np.array([120, 255, 255])

    holdImg = copy.deepcopy(image)
    mask = cv2.inRange(hsvPlate, colorMin, colorMax)
    segPlate = cv2.bitwise_and(holdImg, holdImg, mask=mask)

    element = cv2.getStructuringElement(cv2.MORPH_RECT, (6, 6))
    elementCircle = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
    elementEclipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13))
    segPlate = cv2.erode(segPlate, elementCircle)
    segPlate = cv2.dilate(segPlate, elementCircle)

    return segPlate

def god():
    # img_resp = requests.get(url)
    # img_arr = np.array(bytearray(img_resp.content), dtype=np.uint8)
    # frame = cv2.imdecode(img_arr, -1)

    # Get the first frame to use an input for next step
    ret, frame = cap.read()

    # Flip the frame horizontally (Not required)
    frame = cv2.flip(frame, 1)

    # Intended filename to save results in
    fileName = 'output'

    # Get the intended insertion point and goal, then save to a file
    calculateInsertion(fileName, frame)

    # Having calculated the parabola, extract the intended points
    data = np.load('{}.npy'.format(fileName))
    arrX = data[0]
    arrZ = data[1]

    def fixArrZ(arrZ):
        arr = copy.deepcopy(arrZ)
        placeholder = arr[-1]
        for i in range(1, len(arr)):
            arr[i] = arrZ[i - 1]
        arr[0] = placeholder
        return arr

    arrZ = fixArrZ(arrZ)
    # print(arrX)

    for step in range(0, len(arrZ)):
        controller.Home()

        arrZ = arrZ * frame_conversion  # Conversion from pixel value to metric [mm]
        arrX = arrX * frame_conversion  # 720 and 1280 are image sizes

        X_coord, Y_coord = controller.Move_tip(arrX[step], 0)  # Todo: Movement code
        Current_X, Current_Y, X_coord, Y_coord = controller.Insert(arrZ[step])

        # having the movement done we know that the needle is where it 'should' be,
        # so we can take an image capture here and use that as the actual needle posiiton
        img_resp = requests.get(url)
        img_arr = np.array(bytearray(img_resp.content), dtype=np.uint8)
        image = cv2.imdecode(img_arr, -1)
        # Now having the image taken, we can do a mask to find the needle tip since its a unique color we chose
        # img = needleTip(img)
        # For now we use this for debugging purposes
        img = segmentImg2(image)

        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        ret, thresh = cv2.threshold(img_gray, 150, 255, cv2.THRESH_BINARY)
        # detect the contours on the binary image using cv2.CHAIN_APPROX_NONE
        contours, hierarchy = cv2.findContours(image=thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)
        cnts = cv2.findContours(image=thresh, mode=cv2.RETR_TREE, method=cv2.CHAIN_APPROX_NONE)
        # draw contours on the original image
        image_copy = image.copy()
        res = cv2.drawContours(image=image_copy, contours=contours, contourIdx=-1, color=(0, 0, 255), thickness=5)

        cnts = imutils.grab_contours(cnts)
        cX = 0
        cZ = 0
        count = 0
        for c in cnts:
            # compute the center of the contour
            M = cv2.moments(c)
            cX = int(M["m10"] / M["m00"]) + cX
            cZ = int(M["m01"] / M["m00"]) + cZ
            count = count + 1

        # Actual coordinates of tip of needle
        cX = int(cX / count)
        cZ = int(cZ / count)

        # TODO: compute error
        eX = np.abs(cX - arrX[step])  # distance error between actual and theoretical tip position
        eZ = np.abs(cZ - arrZ[step])

        e_tot = np.sqrt(eX ** 2 + eZ ** 2)
        e_lim = 10  # maximum error in [mm]
        # if e_tot <= e_lim / frame_conversion:
            # TODO: Insert error correction function

god()


import cv2
import os
import numpy as np
import torch
import math
import random

from detectron2.structures.boxes import Boxes
from detectron2.structures.instances import Instances
from detectron2.engine import DefaultPredictor
import detectron2.data.transforms as T
from detectron2.structures import ImageList

def get_images_from_dir(path):

    extensions = ['jpg', 'png', 'bmp']
    contents = os.listdir(path)
    contents.sort()
    image_contents = [imgpath for imgpath in contents if imgpath.split('.')[-1] in extensions and 'Annotated' not in imgpath]

    return image_contents

def draw_bboxes(img, cars_indices, BBOX_WIDTH):

    for r, c in zip(cars_indices[0], cars_indices[1]):
        start_point = (c - BBOX_WIDTH, r - BBOX_WIDTH)
        end_point = (c + BBOX_WIDTH, r + BBOX_WIDTH)
        img = cv2.rectangle(img, start_point, end_point, (0, 0, 255), 1)

def calculate_image_slices(img, patch_size):

    height = img.shape[0]
    width = img.shape[1]
    h_grid = int(np.floor(height/patch_size))
    w_grid = int(np.floor(width/patch_size))
    patch_coords = [0]*h_grid*w_grid

    i = 0
    for row in range(h_grid):
        for col in range(w_grid):
            patch_coords[i] = (row*patch_size, col*patch_size)
            i += 1

    return patch_coords

def get_instances(cars_img, neg_img, bbox_width, patch_coords, patch_size):

        h_start = patch_coords[0]
        w_start = patch_coords[1]
        cars_patch = cars_img[h_start : h_start+patch_size, w_start : w_start+patch_size]
        # cv2.imshow('cars', cars_patch)
        neg_patch = neg_img[h_start : h_start+patch_size, w_start : w_start+patch_size]
        cars_indices = np.where(cars_patch[:, :, 2] == 255)
        neg_indices = np.where(neg_patch[:, :, 0] == 255)
        pos_bboxes = [[c - bbox_width, r - bbox_width, c + bbox_width, r + bbox_width] for r, c in zip(cars_indices[0], cars_indices[1])]
        neg_bboxes = [[c - bbox_width, r - bbox_width, c + bbox_width, r + bbox_width] for r, c in zip(neg_indices[0], neg_indices[1])]
        pos_classes = [1]*len(pos_bboxes)
        neg_classes = [0]*len(neg_bboxes)

        #crop bboxes to patch
        for b in range(len(pos_bboxes)):
            for c in range(len(pos_bboxes[b])):
                if pos_bboxes[b][c] < 0:
                    pos_bboxes[b][c] = 0
                if pos_bboxes[b][c] >= patch_size:
                    pos_bboxes[b][c] = patch_size

        for b in range(len(neg_bboxes)):
            for c in range(len(neg_bboxes[b])):
                if neg_bboxes[b][c] < 0:
                    neg_bboxes[b][c] = 0
                if neg_bboxes[b][c] >= patch_size:
                    neg_bboxes[b][c] = patch_size

        boxes = Boxes(torch.tensor(pos_bboxes + neg_bboxes).to(torch.device('cuda:0')) )
        gt_classes = torch.tensor(pos_classes + neg_classes).to(torch.device('cuda:0') )

        return boxes, gt_classes

class CowcDataloaderOld():

    def __init__(self, config, DATASET_DIR):

        self.IMG_PATCH_SIZE = config.INPUT.MIN_SIZE_TEST
        self.BATCH_SIZE = 100
        self.BBOX_WIDTH = 18
        self.DATASET_DIR = DATASET_DIR
        self.config = config
        self.predictor = DefaultPredictor(config)
        self.backbone = self.predictor.model.backbone
        self.box_pooler = self.predictor.model.roi_heads.box_pooler
        self.box_head = self.predictor.model.roi_heads.box_head

        self.batches_per_img = []
        print("Loading dataset...")
        imgnames = get_images_from_dir(self.DATASET_DIR)
        for imgname in imgnames:
            print(imgname)
            self.batches_per_img.append(self.get_batches_from_img(imgname))
        print('Dataset loaded.')

    def preprocess_image(self, original_image):

        device = torch.device(self.config.MODEL.DEVICE)
        transform_gen = T.ResizeShortestEdge(
            [self.config.INPUT.MIN_SIZE_TEST, self.config.INPUT.MIN_SIZE_TEST], self.config.INPUT.MAX_SIZE_TEST
        )
        pixel_mean = torch.Tensor(self.config.MODEL.PIXEL_MEAN).to(device).view(-1, 1, 1)
        pixel_std = torch.Tensor(self.config.MODEL.PIXEL_STD).to(device).view(-1, 1, 1)
        height, width = original_image.shape[:2]
        image = transform_gen.get_transform(original_image).apply_image(original_image)
        image = torch.as_tensor(image.astype("float32").transpose(2, 0, 1))
        inputs = {"image": image, "height": height, "width": width}
        batched_inputs = [inputs]

        images = [x["image"].to(device) for x in batched_inputs]
        images = [(x - pixel_mean) / pixel_std for x in images]
        images = ImageList.from_tensors(images, self.backbone.size_divisibility)
        return images

    def get_instances(self, cars_img, neg_img, bbox_width, patch_coords, patch_size):

        h_start = patch_coords[0]
        w_start = patch_coords[1]
        cars_patch = cars_img[h_start : h_start+patch_size, w_start : w_start+patch_size]
        # cv2.imshow('cars', cars_patch)
        neg_patch = neg_img[h_start : h_start+patch_size, w_start : w_start+patch_size]
        cars_indices = np.where(cars_patch[:, :, 2] == 255)
        neg_indices = np.where(neg_patch[:, :, 0] == 255)
        pos_bboxes = [[c - bbox_width, r - bbox_width, c + bbox_width, r + bbox_width] for r, c in zip(cars_indices[0], cars_indices[1])]
        neg_bboxes = [[c - bbox_width, r - bbox_width, c + bbox_width, r + bbox_width] for r, c in zip(neg_indices[0], neg_indices[1])]
        pos_classes = [1]*len(pos_bboxes)
        neg_classes = [0]*len(neg_bboxes)

        #crop bboxes to patch
        for b in range(len(pos_bboxes)):
            for c in range(len(pos_bboxes[b])):
                if pos_bboxes[b][c] < 0:
                    pos_bboxes[b][c] = 0
                if pos_bboxes[b][c] >= patch_size:
                    pos_bboxes[b][c] = patch_size - 1

        for b in range(len(neg_bboxes)):
            for c in range(len(neg_bboxes[b])):
                if neg_bboxes[b][c] < 0:
                    neg_bboxes[b][c] = 0
                if neg_bboxes[b][c] >= patch_size:
                    neg_bboxes[b][c] = patch_size - 1

        boxes = Boxes(torch.tensor(pos_bboxes + neg_bboxes).to(torch.device('cuda:0')) )
        gt_classes = torch.tensor(pos_classes + neg_classes).to(torch.device('cuda:0') )

        return boxes, gt_classes

    def get_batches_from_img(self, imgname):

        cars_imgname = imgname.split('.')[0] + '_Annotated_Cars.png'
        neg_imgname = imgname.split('.')[0] + '_Annotated_Negatives.png'
        cars_img = cv2.imread(os.path.join(self.DATASET_DIR, cars_imgname))
        neg_img = cv2.imread(os.path.join(self.DATASET_DIR, neg_imgname))
        bigimg = cv2.imread(os.path.join(self.DATASET_DIR, imgname))
        patches_startpoints = calculate_image_slices(bigimg, self.IMG_PATCH_SIZE)
        train_features = None
        train_classes = None

        for patch_coords in patches_startpoints:
            h_start = patch_coords[0]
            w_start = patch_coords[1]
            img_patch = bigimg[h_start : h_start+self.IMG_PATCH_SIZE, w_start : w_start+self.IMG_PATCH_SIZE]
            boxes, gt_classes = get_instances(cars_img, neg_img, self.BBOX_WIDTH, patch_coords, self.IMG_PATCH_SIZE)
            if len(gt_classes) > 0:
                with torch.no_grad():
                    batched_input = self.preprocess_image(img_patch)
                    features = self.backbone(batched_input.tensor)
                    features = [features[f] for f in self.config.MODEL.ROI_HEADS.IN_FEATURES]
                    roi_features = self.box_pooler(features, [boxes])
                    conv_roi_features = self.box_head(roi_features)
                if train_features is None:
                    train_features = conv_roi_features.cpu()
                    train_classes = gt_classes.cpu()
                else:
                    train_features = torch.cat([train_features, conv_roi_features.cpu()], 0)
                    train_classes = torch.cat([train_classes, gt_classes.cpu()], 0)

        pos_indices = torch.where(train_classes == 1)[0]
        neg_indices = torch.where(train_classes == 0)[0]
        num_pos = len(pos_indices)
        num_neg = len(neg_indices)
        paired_num = min(num_pos, num_neg)
        num_samples = int(self.BATCH_SIZE/2)
        num_batches = math.floor(paired_num / num_samples)

        batches_list = []
        for batch_idx in range(num_batches):

            batch_pos_indices = pos_indices[batch_idx*num_samples : (batch_idx+1)*num_samples]
            batch_neg_indices = neg_indices[batch_idx*num_samples : (batch_idx+1)*num_samples]
            pos_features = train_features[batch_pos_indices]
            neg_features = train_features[batch_neg_indices]
            batch_train_features = torch.cat([pos_features, neg_features], 0)
            batch_train_labels = torch.tensor([1]*num_samples + [0]*num_samples)
            batches_list.append( (batch_train_features, batch_train_labels) )

        return batches_list

class CowcDataloader():

    def __init__(self, config, DATASET_DIR):

        self.IMG_PATCH_SIZE = config.INPUT.MIN_SIZE_TEST
        self.BATCH_SIZE = 100
        self.BBOX_WIDTH = 18
        self.IMAGES_PER_BATCH = 2
        self.DATASET_DIR = DATASET_DIR
        self.config = config
        self.imgnames = get_images_from_dir(self.DATASET_DIR)
        self.current_img = None
        self.current_cars_img = None
        self.current_patches_startpoints = None
        self.current_instances_per_patch = None

    def preprocess_image(self, original_image):

        device = torch.device(self.config.MODEL.DEVICE)
        transform_gen = T.ResizeShortestEdge(
            [self.config.INPUT.MIN_SIZE_TEST, self.config.INPUT.MIN_SIZE_TEST], self.config.INPUT.MAX_SIZE_TEST
        )
        pixel_mean = torch.Tensor(self.config.MODEL.PIXEL_MEAN).to(device).view(-1, 1, 1)
        pixel_std = torch.Tensor(self.config.MODEL.PIXEL_STD).to(device).view(-1, 1, 1)
        height, width = original_image.shape[:2]
        image = transform_gen.get_transform(original_image).apply_image(original_image)
        image = torch.as_tensor(image.astype("float32").transpose(2, 0, 1))
        inputs = {"image": image, "height": height, "width": width}
        batched_inputs = [inputs]

        images = [x["image"].to(device) for x in batched_inputs]
        images = [(x - pixel_mean) / pixel_std for x in images]
        images = ImageList.from_tensors(images, self.backbone.size_divisibility)
        return images

    def load_img(self, imgname):

        cars_imgname = imgname.split('.')[0] + '_Annotated_Cars.png'
        self.current_img = cv2.imread(os.path.join(self.DATASET_DIR, imgname) )
        self.current_cars_img = cv2.imread(os.path.join(self.DATASET_DIR, cars_imgname) )
        self.current_patches_startpoints = calculate_image_slices(self.current_img, self.IMG_PATCH_SIZE)
        self.current_instances_per_patch = {}
        for patch_coords in self.current_patches_startpoints:
            h_start = patch_coords[0]
            w_start = patch_coords[1]
            img_patch = self.current_img[h_start : h_start+self.IMG_PATCH_SIZE, w_start : w_start+self.IMG_PATCH_SIZE]
            cars_patch = self.current_cars_img[h_start : h_start+self.IMG_PATCH_SIZE, w_start : w_start+self.IMG_PATCH_SIZE]
            cars_indices = np.where(cars_patch[:, :, 2] == 255) # tuple of two arrays
            if len(cars_indices[0]) > 0:
                patch_instances = Instances( (self.IMG_PATCH_SIZE, self.IMG_PATCH_SIZE) )
                pos_bboxes = [[c - self.BBOX_WIDTH, r - self.BBOX_WIDTH, c + self.BBOX_WIDTH, r + self.BBOX_WIDTH] for r, c in zip(cars_indices[0], cars_indices[1])]
                classes = [0]*len(pos_bboxes)
                for b in range(len(pos_bboxes)):
                    for c in range(len(pos_bboxes[b])):
                        if pos_bboxes[b][c] < 0:
                            pos_bboxes[b][c] = 0
                        if pos_bboxes[b][c] >= self.IMG_PATCH_SIZE:
                            pos_bboxes[b][c] = self.IMG_PATCH_SIZE - 1
                gt_boxes = Boxes(torch.tensor(pos_bboxes).to(torch.device('cuda:0')) )
                gt_classes = torch.tensor(classes).to(torch.device('cuda:0') )
                patch_instances._fields['gt_boxes'] = gt_boxes
                patch_instances._fields['gt_classes'] = gt_classes
                self.current_instances_per_patch[patch_coords] = patch_instances

    def get_batch(self):

        batch = []
        for i in range(self.IMAGES_PER_BATCH):
            print(patches_startpoints)

    # def get_imgdict(self, patch_coords):


import logging
import sys

def setup():
    logging.basicConfig(
        level=logging.INFO,
        handlers=[ColorStdErr()]
    )

class ColorStdErr(logging.StreamHandler):
    def __init__(self):
        class AddColor(logging.Formatter):
            def format(self, record):
                msg = super().format(record)
                color = '\033[1;' + ('32m', '36m', '33m', '31m', '41m')[
                    min(4, int(4*record.levelno / logging.FATAL))]
                return color + record.levelname + '\033[1;0m: ' + msg
        super().__init__(sys.stderr)
        self.setFormatter(AddColor())


from flask import Blueprint, jsonify, request
from flask_login import login_required, current_user
from sqlalchemy.orm import relationship, sessionmaker, joinedload, load_only
from app.models import db,  User, Like, Post

like_routes = Blueprint('like', __name__)
@like_routes.route('/posts/<int:postId>/likes', methods=['get'])
def get_like_by_post_id(postId):
    if not Post.query.filter(Post.id == postId).one_or_none():
        return {"errors": ["Post couldn't be found"]}, 404

    likes = Like.query.filter(Like.post_id == postId).filter(Like.like_status == True).options(joinedload(Like.user).options(load_only('id','first_name', 'last_name', 'username', 'preview_image'))).all()
    # return {'likes': [like.to_dict() for like in likes]}

    return {
        "Like" : [
            {
                "id": like.id,
                "user_Id": like.user_id,
                "post_id": like.post_id,
                "like_status": like.like_status,
                "created_at": like.created_at,
                "updated_at": like.updated_at,
                "Owner": {
                    "id": like.user.id,
                    "username": like.user.username,
                    "first_name": like.user.first_name,
                    "last_name": like.user.last_name,
                    "previewImage": like.user.preview_image
                }
            } for like in likes
        ]
    }

@login_required
@like_routes.route('/posts/<int:postId>/likes', methods=['POST'])
def like_a_post(postId):
    if not Post.query.filter(Post.id == postId).one_or_none():
        return {"errors": ["Post couldn't be found"]}, 404

    user_id = current_user.get_id()

    #check whether the user has liked the post or not
    the_like_relation = Like.query.filter(Like.user_id == user_id).filter(Like.post_id == postId).one_or_none()
    if the_like_relation:
        if the_like_relation.like_status == True:
            return {"errors": ["Current user liked this post already"]}, 401
        else:
            the_like_relation.like_status = True
            db.session.commit()
            return the_like_relation.to_dict()

    like = Like(
        user_id = user_id,
        post_id = postId,
        like_status = True
    )
    db.session.add(like)
    db.session.commit()

    return like.to_dict()

@login_required
@like_routes.route('/likes/<int:likeId>', methods=['PUT'])
def unlike_a_post(likeId):
    user_id = current_user.get_id()

    the_like_relation = Like.query.filter(Like.id == likeId).one_or_none()
    if not the_like_relation:
        return {"errors": ["Like couldn't be found"]}, 404
    if not int(user_id) == int(the_like_relation.user_id):
        return {'errors': ['Unauthorized']}
    # db.session.delete(the_like_relation)
    the_like_relation.like_status = False
    db.session.commit()
    return the_like_relation.to_dict()


import sys
sys.path.append('..')
import os
import random
import math
import json
from Gladiator.Equipments.GladiatorEquipments import GladiatorEquipments
from MongoDB.Connector import Connector
import pathlib

path = pathlib.Path(__file__).parent.absolute()

MongoDatabase = Connector()

def save_profile(func):
    def wrapper(self, *args, **kwargs):
        out = func(self, *args, **kwargs)
        filename = path / "UserProfileData" / f"{self.profile_stats['_id']}.json"
        json.dump(self.profile_stats, open(
            filename, "w"), indent=4, sort_keys=True)
        MongoDatabase.save_profile(self.profile_stats)
        return out
    return wrapper

class Profile():
    def __init__(self, member, **kwargs):
        self.member = member
        profile_path = path / "UserProfileData" / f"{self.member.id}.json"

        profile_settings = json.load(open(path / "Settings" / "GladiatorGameSettings.json", "r"))["profile_settings"]
        self.XP_TO_LEVEL_MULTIPLIER = profile_settings["XP_TO_LEVEL_MULTIPLIER"]
        self.XP_TO_LEVEL_WHEN_LOST_MULTIPLIER = profile_settings["XP_TO_LEVEL_WHEN_LOST_MULTIPLIER"]
        self.XP_GAIN_MULTIPLIER = profile_settings["XP_GAIN_MULTIPLIER"]
        self.LEVEL_UP_DIFFICULTY_CONSTANT = profile_settings["LEVEL_UP_DIFFICULTY_CONSTANT"]
        self.LEVEL_UP_START_POINT = profile_settings["LEVEL_UP_START_POINT"]
        if os.path.exists(profile_path):
            self.profile_stats = json.load(open(profile_path, "r"))
        else:
            self.create_default_profile(**kwargs)

    @save_profile
    def create_default_profile(self, **kwargs):
        self.profile_stats = json.load(open(path / "UserProfileData" / "default_profile.json", "r"))
        self.profile_stats["_id"] = str(self.member.id)
        self.profile_stats.update(kwargs)

    def get_level(self):
        return self.profile_stats["Level"]

    @save_profile
    def event_bonus(self, profile_stat_key: str, amount: int) -> str:
        self.profile_stats[profile_stat_key] += amount
        return f"Added **{amount} {profile_stat_key}** to your profile!"

    def calculate_xp_for_next_level(self):
        return round(self.XP_TO_LEVEL_MULTIPLIER*(self.get_level()**2)*self.LEVEL_UP_DIFFICULTY_CONSTANT - (self.XP_TO_LEVEL_MULTIPLIER * self.get_level()) + self.LEVEL_UP_START_POINT) + 1

    @save_profile
    def update_stats(self):
        default_stats = json.load(open(path / "UserProfileData" / "default_profile.json", "r"))["Stats"]

        lvl = self.get_level()
        for stat in default_stats.keys():
            curr_stat = self.profile_stats["Stats"][stat]
            curr_stat = round(curr_stat + (lvl/15)**1.1, 2)
            self.profile_stats["Stats"][stat] = curr_stat

class GladiatorProfile(Profile):
    def __init__(self, member, **kwargs):
        super().__init__(member=member)
        self.equipment_info = GladiatorEquipments()

    @save_profile
    def buy_equipment(self, equipment_name: str) -> str:
        equipment = self.equipment_info.find_equipment(equipment_name)

        if not equipment:
            return "Couldn't find the equipment for given id"

        for eq in self.profile_stats["Inventory"]:
            if eq["name"] == equipment["name"]:
                return f"You are already using {eq['name']}!"

        if self.profile_stats["HutCoins"] - equipment["price"] < 0:
            return "You cannot afford this item!"

        self.profile_stats["HutCoins"] -= equipment["price"]

        slot = self.equipment_info.find_slot(
            equipment["type"])
        # if there is a slot already occupied in the profile, remove that slot and that equipment
        for index, eq in enumerate(self.profile_stats["Inventory"]):
            if eq["type"] == slot["Slot Name"]:
                del self.profile_stats["Inventory"][index]
                break
        # add the equipment to the profile inventory
        self.profile_stats["Inventory"].append({"name" : equipment["name"], "type" : equipment["type"]})
        return f"Successfully bought **{equipment['name']}**. You have **{self.profile_stats['HutCoins']} HutCoins** left."

    def update_games(self, other_profile_level: int, won: bool, **kwargs) -> str:
        self.profile_stats["Games Played"] += 1
        if won:
            self.profile_stats["Games Won"] += 1
            return self.gain_xp(other_profile_level, kwargs.get("XP", 0)) + self.reward_player(kwargs.get("HutCoins", 0))

        self.profile_stats["Games Lost"] += 1
        return self.gain_xp(other_profile_level/self.XP_TO_LEVEL_WHEN_LOST_MULTIPLIER)

    @save_profile
    def reward_player(self, bonus_coins: int = 0) -> str:
        coin = random.randint(20, 75) + bonus_coins
        self.profile_stats["HutCoins"] += coin
        return f"**You earned {coin} HutCoins!**"

    @save_profile
    def gain_xp(self, other_profile_level: int, bonus_xp: int = 0) -> str:
        xp_gained = math.ceil(other_profile_level /
                              self.get_level()) * self.XP_GAIN_MULTIPLIER + random.randint(self.get_level(), self.get_level()*5) + bonus_xp

        self.profile_stats["XP"] += xp_gained
        msg = f"Gained {xp_gained} XP\n"
        self.profile_stats["XP To Next Level"] = self.calculate_xp_for_next_level()
        while self.profile_stats["XP"] >= self.profile_stats["XP To Next Level"]:
            self.profile_stats["Level"] += 1
            self.profile_stats["XP To Next Level"] = self.calculate_xp_for_next_level()
            msg += f"You have levelled up!\n"
            self.update_stats()

        return msg

    def get_stats(self):
        return self.profile_stats["Stats"]

    def __repr__(self):
        msg = ""
        for key in self.profile_stats.keys():
            if not key in ("_id", "Stats"):
                if key == "Inventory":
                    for item in self.profile_stats[key]:
                        msg += f"{item['type']} : **{item['name']}\n**"
                    continue
                msg += f"{key} : **{self.profile_stats[key]}**\n"
        return msg


# This file is an example file for how predictions should be made

print('Importing libraries...')
import numpy as np
import pandas as pd
import tensorflow as tf
import keras
import gzip
import glob

def compress():
    '''Compress data in all .h5 files'''
    for i in glob.glob('./*.h5'):
        l = gzip.compress(open(i, 'rb').read(),compresslevel=9)
        open(i, 'wb').write(l)

def decompress():
    '''Decompress data in all .h5 files'''
    for i in glob.glob('./*.h5'):
        l = gzip.decompress(open(i, 'rb').read())
        open(i, 'wb').write(l)

print('Decompressing weights files...')
decompress() # remove this line if .h5 files are already decompressed

print('Loading data...')
words = [word.strip() for word in open('./wordle.txt').readlines()]
word_dict = {v:i for i,v in enumerate(words)}
idx_dict = {i:v for i,v in enumerate(words)}

data = pd.read_csv('./wordle.csv')
labels = np.array([int(i) for i in data.pop('labels').to_numpy(dtype=np.int16)])
data.head()

data = data.to_numpy().flatten()

t = sorted(set(''.join(data)))
char2idx = {v:i for i,v in enumerate(t)}
idx2char = {i:v for i,v in enumerate(t)}
del t

def encode(array: np.ndarray):
    l = []
    for i in array:
        l.append([char2idx[v] for v in i])
    d = np.array(l, dtype=np.int8)
    return d

print('Encoding data...')
data = encode(data)

def build_model(mode: int=0):
    '''Returns a keras.Sequential model with the loaded weights.'''
    mode+=1
    model = keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(5,)),
    tf.keras.layers.Dense(128*mode, activation='relu'),
    tf.keras.layers.Dense(256*mode, activation='relu'),
    tf.keras.layers.Dense(512*mode, activation='relu'),
    tf.keras.layers.Dense(len(set(labels)), activation='softmax')
    ])
    model.compile(optimizer='nadam', loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), metrics=['accuracy'], jit_compile=True)
    model.summary()
    model.load_weights('./smaller_model.h5' if mode==1 else './larger_model.h5')
    return model

model = build_model(0)

def predict(arr: np.ndarray):
    out = tuple(model.predict(encode(arr.flatten())).flatten())
    out = ((words[i],v) for i,v in enumerate(out))
    return sorted(out, key=lambda x: x[1], reverse=True)

# test lines to showcase accuracy
print(*predict(np.array(['fle_s']))[:5]) # outputs tuple[tuple[str, float]]
# the [:5] takes the 5 most likely options


import os
import shutil
import argparse

DS_PROJ_DIR = 'dataset-projects'
DATASET_SUBDIR = 'dataset'
TEMPLATE_DIR = 'template'
CONFIG_NAME = 'config.yaml'
PYTHON_BLENDER_SCRIPT = 'blender_script.py'

description = "Generate folder structure for a new dataset generated with Blender"

parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('dataset_project_name', help="Folder name of the dataset project generation folder")
parser.add_argument('subfolders', nargs="*", help="Subfolder dataset names")

args = parser.parse_args()
dataset_project_name = args.dataset_project_name
subfolders = args.subfolders

# Unique names for subfolders, can not be same
assert(len(subfolders) == len(set(subfolders)))

dataset_project_path = os.path.join(DS_PROJ_DIR, dataset_project_name)

shutil.copytree(TEMPLATE_DIR, dataset_project_path)
dataset_subdir_path = os.path.join(dataset_project_path, DATASET_SUBDIR)
for subfolder in subfolders:
    subfolder_path = os.path.join(dataset_subdir_path, subfolder)
    os.mkdir(subfolder_path)

config_yaml_path = os.path.join(dataset_project_path, CONFIG_NAME)

with open(config_yaml_path, 'a') as f:
    f.write(f'blender_script: {PYTHON_BLENDER_SCRIPT}\n')
    for subfolder in subfolders:
        relative_subfolder_path = os.path.join(DATASET_SUBDIR, subfolder)
        f.write(f'{subfolder}_path: {relative_subfolder_path}\n')

print(f"Created dataset project {dataset_project_name}")
if subfolders:
    print(f'with subfolders {subfolders}')


# A Crypto Notifier Application

# Import modules

import pandas as pd
import os
from pathlib import Path
import numpy as np
from pycoingecko import CoinGeckoAPI
import questionary
from twilio.rest import Client
from twilio.base.exceptions import TwilioRestException
from dotenv import load_dotenv

load_dotenv()

# Set Variable for coingecko API
cg = CoinGeckoAPI()

#Data for app to pull
#Dataframe for swing thresholds
crypto_swing_thresholds = {'Coin':['bitcoin','ethereum','ripple','cardano','solana'],'pct_change_Threshold':[0.029452,0.038992,0.044968,0.045519,0.057073]}
swing_thresholds_df = pd.DataFrame(crypto_swing_thresholds).set_index('Coin')
#Simulation data - two weeks DataFrame
simdata_path = Path('./Resources/simdata.csv')
# Read in data and index by dates
two_week_daily_pct_change_df = pd.read_csv(simdata_path, index_col='date')

# Define code for ticker
def get_symbols():
    symbols = []
    symbols = questionary.checkbox(
        "Select CryptoCurrencies",
        choices=["bitcoin","ethereum","ripple","cardano", "solana"
        ]).ask()
    return symbols

# what is ave % increase threshold by comparing x time in the past generate average daily return swing
# put user two weeks back and compare each day
# if day has a big swing send message
# if after two weeks send message no big swings
#
def get_symbols():
    symbols = []
    symbols = questionary.checkbox(
        "Select CryptoCurrencies",
        choices=["bitcoin","ethereum","ripple","cardano", "solana"]
    ).ask()
    return symbols

def get_user_number():
    phone_number = []
    phone_number = questionary.text("What is your 10 digit phone number?:").ask()
    return phone_number

# Define code for Twilio message
# Set up twilio client
# Create twilio id and tolken for use in sdk
twilio_account_id = os.environ["TWILIO_ACCOUNT_ID"]
twilio_token = os.environ["TWILIO_AUTH_TOKEN"]
twilio_phone_number = os.environ["TWILIO_PHONE_NUMBER"]

# Create twilio rest client
client = Client(twilio_account_id, twilio_token)

# Define generate twilio message
def generate_twilio_message(phone_number, twilio_phone_number, information):
    try:
        client.messages.create(to=f"+1{phone_number}", from_=f"+1{twilio_phone_number}",
                                    body=information)
    # Implement your fallback code
    except TwilioRestException as e:
        print(e)

if __name__ == "__main__":
    # User input phone number to variable
    user_phone_number = get_user_number()

    # User input tickers to variable
    user_symbols = get_symbols()

    # Create conditional to pass information into message
    # Create empty message list to house information
    message_list = []

    for row in two_week_daily_pct_change_df:
        for symbol in user_symbols:
            if float(row[symbol]) >= float(swing_thresholds_df[symbol]):
                information_to_send = f"There was a big price swing for {symbol} today compared to the last three years worth of daily changes \n"
                message_list.append(information_to_send)
            else:
                no_big_swing = f'There was no significant price swing for {symbol} from yesterday compared to the last three years worth of daily changes'
                message_list.append(no_big_swing)

    message_list = ". ".join(message_list)
    generate_twilio_message(user_phone_number, twilio_phone_number, message_list)

    print(f"A message has been sent to your phone {user_phone_number} with a two week summary report for {user_symbols}")


from selenium import webdriver
from pprint import pprint
import time
from collections import Counter

driver = webdriver.Chrome('chromedriver')
driver.get('http://zzzscore.com/color/')
driver.implicitly_wait(100)  # time.sleep과 같은 역할

btns = driver.find_elements_by_xpath('//*[@id="grid"]/div')
                                      # 형식이 통일되어있지 않기에 [*]를 못 씀
                                    # bs의 findAll처럼 리스트로 반환해줌
                                    # 셀레늄의 장점 : 셀레늄으로 가져온 요소는
                                    # 실시간으로 값이 바뀌는 것을 감지
                                    # 크롬 드라이버와 연결되어 계속 최신화

def analysis():  # 색 비교로 유일한 색(다른 색)을 찾아 버튼 클릭하는 함수
    # 색정보 css property
    btns_rgba = [btn.value_of_css_property('background-color') for btn in btns]
    pprint(btns_rgba)

    result = Counter(btns_rgba)   # 딕셔너리 형태로 반환
    pprint(result) #여기서 value가 1인게 정답

    #value가 1인 것 탐색
    for key, value in result.items():
        if value == 1:
            answer = key
            break
    else:
        answer = None
        print("정답을 찾을 수 없습니다.")

    # 정답 클릭
    # 1. btns_rgba에서 인덱스 값을 구하고
    # 2. 그 인덱스 값으로 btns 인덱스에 접근. 클릭
    if answer:
        index = btns_rgba.index(answer)
        btns[index].click()
'''
start = time.time()
while time.time()-start <= 60:
    analysis()
'''
# 색 비교가 아닌 소스코드에서 정답 찾기
start = time.time()
while time.time() - start <= 60:
    try:
        btn = driver.find_element_by_class_name("main")
        btn.click()
    except:
        pass


import torch
from torch import nn
from torch.nn.utils.rnn import *
import numpy as np
from torch.utils.data import DataLoader, Dataset, TensorDataset
import torch.nn.functional as F
import random
import time
import torch.optim as optim
import numpy as np
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torch.nn.utils as utils
import pickle as pk
from torch.utils.data import DataLoader, Dataset
import time
import Levenshtein

letter_list = ['0','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',\
             'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '-', "'", '.', '_', '+', ' ','<sos>','<eos>']

############ Transformer Functions #####################
def transform_letter_to_index(transcript, letter_list):
    train_Y=[]
    for sen in transcript:
        res=[letter_list.index('<sos>')]
        for word in sen:
            for letter in word.decode('utf-8'):
                res.append(letter_list.index(letter))
            res.append(letter_list.index(' '))
        res.pop()
        res.append(letter_list.index('<eos>'))
        train_Y.append(res)
    return train_Y

def transform_index_to_letter(pred_indx):#input (N,L)
    res=[]
    for row in pred_indx:
        string=''
        for i in row:
            if letter_list[i]=='<eos>':
                string += letter_list[i]
                break
            else:
                string+=letter_list[i]
        res.append(string)
    return res

def transform_index_to_letter_test(pred_indx):#input (N,L)
    res=[]
    for row in pred_indx:
        string=''
        for i in row:
            if letter_list[i]=='<eos>' or letter_list[i]=='0':
                break
            else:
                string+=letter_list[i]
        res.append(string)
    return res

def transform_index_to_letter_Train(pred_indx):#input (N,L)
    res=[]
    for row in pred_indx:
        string=''.join(letter_list[i] for i in row)
        res.append(string)
    return res

############# DataLoader ##############################
class MyDataset(Dataset):
    def __init__(self, x, y):
        super().__init__()
        assert len(x) == len(y)
        self._x = x
        self._y = y

    def __len__(self):
        return len(self._x)

    def __getitem__(self, index):
        x = self._x[index]
        y = self._y[index]
        return x, y

class MyDataset_test(Dataset):
    def __init__(self, x):
        super().__init__()
        self._x = x

    def __len__(self):
        return len(self._x)

    def __getitem__(self, index):
        x = self._x[index]
        return x

def my_collate(batch):
    X = [torch.tensor(x) for x,_ in batch]
    Y = [torch.LongTensor(y) for _,y in batch]
    return [X, Y]

def my_collate_test(batch):
    X = [torch.tensor(x) for x in batch]
    return X


from aiogram import types
from config import dp,bot
from .messages import *
from aiogram.dispatcher import FSMContext
from Include.core.states import AddGroups, MessageToGroup,ChatRemove
from Include.core.helpers.requestsApi import *
from Include.core.helpers import telegram as tg_helper
import openpyxl

@dp.callback_query_handler(text='create_newsletter',state="*")
async def process_callback_authbtn(callback_query: types.CallbackQuery):
    await bot.edit_message_text(chat_id=callback_query.from_user.id,message_id=callback_query.message.message_id,
    text=select_group,reply_markup=get_groups_btn())

@dp.callback_query_handler(lambda c: str(c.data).split("_")[0].__eq__("createnewslettergroup"),state="*")
async def create_newsletter_group(callback_query: types.CallbackQuery, state: FSMContext):
    groupid = str(callback_query.data).split("_")[1]
    async with state.proxy() as data:
        data['groupid']=groupid
        await MessageToGroup.WriteAndSendMSG.set()
        await bot.send_message(callback_query.from_user.id,write_msg)

@dp.message_handler(lambda message: message.text, state=MessageToGroup.WriteAndSendMSG, content_types=types.ContentTypes.TEXT)
async def WriteAndSendMSG(message: types.Message, state: FSMContext):
    if message.text == "/cancel":
        await stop_state(state, message)
        return
    async with state.proxy() as data:
            send_msg(data['groupid'],message.text)
            await bot.send_message(message.from_user.id,msg_sended)

@dp.message_handler(lambda message: message.text, state=ChatRemove.ChatId)
async def ChatRemove_func(message: types.Message, state: FSMContext):
    if message.text == "/cancel":
        await stop_state(state,message)
        return
    async with state.proxy() as data:
        try:
            id = int(message.text)
            if delete_chat(id):
                await bot.send_message(message.from_user.id, text=chat_deleted)
                await state.finish()
                return
            else:
                await bot.send_message(message.from_user.id, text=chat_del_err)
        except:
            await bot.send_message(message.from_user.id, text=chat_del_err)
            pass

@dp.callback_query_handler(text='remove_chat',state="*")
async def process_callback_authbtn(callback_query: types.CallbackQuery):
    await ChatRemove.ChatId.set()
    await bot.send_message(callback_query.from_user.id,text=chat_del_msg)

@dp.callback_query_handler(lambda c: str(c.data).split("_")[0].__eq__("group"),state="*")
async def manage_group(callback_query: types.CallbackQuery):
    groupid = str(callback_query.data).split("_")[1]
    chats = get_chats_in_group(groupid)
    btns = {
        ("Удалить группу", "removegroup_"+str(groupid)),
        ("Удалить чат", "remove_chat"),
        ("Назад", "create_newsletter"),
        ("Рассылка в группу", "createnewslettergroup_"+str(groupid))
    }
    group_manager = tg_helper.create_inline_markup(*btns)
    text = 'Чаты в этой группе:\n'
    i=0
    for chat in chats:
        i+=1
        text = text+str(i)+" ("+str(chat['id'])+"). "+str(chat['name'])+"\n"
    await bot.edit_message_text(chat_id=callback_query.from_user.id,message_id=callback_query.message.message_id,
                          text=text,reply_markup=group_manager)

@dp.callback_query_handler(lambda c: str(c.data).split("_")[0].__eq__("removegroup"),state="*")
async def remove_group(callback_query: types.CallbackQuery):
    groupid = str(callback_query.data).split("_")[1]
    delete_group(groupid)
    await bot.edit_message_text(chat_id=callback_query.from_user.id, message_id=callback_query.message.message_id,
                                text=group_deleted + "\n" + select_group, reply_markup=get_groups_btn())

def get_groups_btn():
    groups = get_groups()
    data_list = []
    for group in groups:
        tulist = (str(group['name']), "group_"+ str(group['id']))
        data_list.append(tulist)
    btns = tg_helper.create_inline_markup(*data_list, row_width=2)
    return btns

@dp.message_handler(state=AddGroups.GetFile, content_types=['document'])
async def get_names(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        file = await bot.get_file(message.document.file_id)
        file_path = file.file_path
        await bot.download_file(file_path, message.document.file_name)
        try:
            wb = openpyxl.load_workbook(message.document.file_name)
            sheetes = wb.get_sheet_names()
            sheet = wb.get_sheet_by_name(sheetes[0])
            rows = sheet.max_row
            groups = []
            groups.append(data['name'])
            for i in range(1, rows + 1):
                cell = sheet.cell(row=i, column=1).value
                groups.append(cell)
        except:
            await bot.send_message(message.from_user.id, text=file_error)
        add_groups(groups)
        await bot.send_message(message.from_user.id,text=good_loaded,reply_markup=START_INLINE_BTN)

@dp.message_handler(lambda message: message.text, state=AddGroups.NewGroupName, content_types=types.ContentTypes.TEXT)
async def get_name(message: types.Message, state: FSMContext):
    if message.text == "/cancel":
        await stop_state(state,message)
        return
    async with state.proxy() as data:
        data['name'] = message.text
        await AddGroups.next()
        await bot.send_message(message.from_user.id,send_me_file)

@dp.callback_query_handler(text='create_group',state="*")
async def process_callback_authbtn(callback_query: types.CallbackQuery):
    await bot.send_message(callback_query.from_user.id,text=new_gropu_name)
    await AddGroups.NewGroupName.set()

async def stop_state(state,message):
    current_state = await state.get_state()
    if current_state is None:
        return
    await state.finish()
    await message.reply('Действие отменено', reply_markup=types.ReplyKeyboardRemove())


from django.urls import path

from . import views

app_name='peak_numbers'
urlpatterns=[

    path('num',views.num,name="peaknum"),
    path('leaders',views.leaders,name="leaders"),
    path('common',views.common_num,name="common")
]


#coding=utf-8
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.request import CommonRequest
import sqlite3
import threading
import os.path
aukey=''
ausecret=''
areaname="cn-hangzhou"
areadomain="edas.cn-hangzhou.aliyuncs.com"
termnum="2testcms"                    #2test
appflag=1    #0关闭，1开启
def startapp(appid):
    #print(appid)
    client = AcsClient(aukey, ausecret, areaname)
    request = CommonRequest()
    request.set_accept_format('json')
    request.set_method('POST')
    request.set_protocol_type('https')
    request.set_domain("edas.cn-hangzhou.aliyuncs.com")
    #request.set_domain(areadomain)报错
    request.set_version('2017-08-01')
    request.add_query_param("RegionId", areaname)
    request.add_query_param('AppId', appid)
    request.set_uri_pattern('/pop/v5/changeorder/co_start')
    response = client.do_action(request)
    print(str(response, encoding='utf-8'))

def stopapp(appid):
    #print(appid)
    client = AcsClient(aukey, ausecret, areaname)
    request = CommonRequest()
    request.set_accept_format('json')
    request.set_method('POST')
    request.set_protocol_type('https')
    request.set_domain("edas.cn-hangzhou.aliyuncs.com")
    #request.set_domain(areadomain)报错
    request.set_version('2017-08-01')
    request.add_query_param("RegionId", areaname)
    request.add_query_param('AppId', appid)
    request.set_uri_pattern('/pop/v5/changeorder/co_stop')
    response = client.do_action(request)
    print(str(response, encoding='utf-8'))
if __name__=="__main__":
    BASE_DIR = os.path.dirname(os.path.abspath(__file__))
    ADD_LIST = os.path.join(BASE_DIR, 'edas.db')
    conn = sqlite3.connect(ADD_LIST)
    cursor = conn.cursor()
    cursor.execute('select appid,appname from apps where env=?',(termnum,))
    values = cursor.fetchall()
    cursor.close()
    conn.close()
    print(values)
    progroup={}
    if appflag == 0:
        operfunc=stopapp
    else:
        operfunc=startapp

    for appinfo in values:
        threadname=appinfo[1]
        progroup[threadname] = threading.Thread(name='th'+appinfo[1],target=operfunc,args=(appinfo[0],))
        print("%s ok" % appinfo[1])
        progroup[threadname].start()


#! /usr/bin/env python3
# SPDX-License-Identifier: GPL-3.0+

import argparse
import sys

from assayist.processor.container_analyzer import ContainerAnalyzer
from assayist.processor.container_go_analyzer import ContainerGoAnalyzer
from assayist.processor.container_rpm_analyzer import ContainerRPMAnalyzer
from assayist.processor.loose_artifact_analyzer import LooseArtifactAnalyzer
from assayist.processor.main_analyzer import MainAnalyzer
from assayist.processor.post_analyzer import PostAnalyzer
from assayist.processor.error import AnalysisFailure

parser = argparse.ArgumentParser(description='Run the Assayist analyzers on a Koji build')
parser.add_argument('--input-dir', type=str,
                    help='The directory containing the "metadata" directory')
args = parser.parse_args()

input_dir = args.input_dir or '.'

analyzers = [MainAnalyzer, ContainerAnalyzer, ContainerRPMAnalyzer, ContainerGoAnalyzer,
             LooseArtifactAnalyzer, PostAnalyzer]
analyzer_failures = []

for analyzer in analyzers:
    print(f'Running {analyzer.__name__}...')
    try:
        analyzer(input_dir).main()
    except AnalysisFailure as error:
        # Don't continue if the main analyzer failed since other analyzers rely on it
        if analyzer == MainAnalyzer:
            print('MainAnalyzer failed with the following:\n{}'.format(error),
                  file=sys.stderr)
            sys.exit(3)

        analyzer_failures.append(str(error))

if analyzer_failures:
    print('The following were error(s) encountered during the analysis:\n{}'.format(
        '\n'.join(analyzer_failures)), file=sys.stderr)
    sys.exit(3)


import numpy as np
import taichi as ti
import numpy as np

from tolvera.vera._particle import Particles

@ti.data_oriented
class Physarum(Particles):
    def __init__(self,
                 x=1024,
                 y=1024,
                 n=1024,
                 sense_angle=0.20 * np.pi,
                 sense_dist=4.0,
                 evaporation=0.97,
                 move_angle=0.1 * np.pi,
                 move_step=2.0,
                 substep=8):
        super().__init__(x, y, n)
        self._ang = ti.field(dtype=ti.f32, shape=(self._n))
        self._i = 0
        self.world = ti.field(dtype=ti.f32, shape=(1, self._x, self._y))
        self.sense_angle = ti.field(ti.f32, ())
        self.sense_dist  = ti.field(ti.f32, ())
        self.evaporation = ti.field(ti.f32, ())
        self.move_angle  = ti.field(ti.f32, ())
        self.move_step   = ti.field(ti.f32, ())
        self.substep     = ti.field(ti.i32, ())
        self.sense_angle[None] = sense_angle
        self.sense_dist[None]  = sense_dist
        self.evaporation[None] = evaporation
        self.move_angle[None]  = move_angle
        self.move_step[None]   = move_step
        self.substep[None]     = substep
        self.init()

    @ti.kernel
    def init(self):
        self.randomise()

    @ti.func
    def randomise(self):
        for i in self._pos:
            self._pos[i] = ti.Vector([ti.random()*self._x, ti.random()*self._y])
            self._ang[i] = ti.random() * np.pi * 2.0

    @ti.func
    def sense(self, pos, ang):
        p = pos + ti.Vector([ti.cos(ang), ti.sin(ang)]) * self.sense_dist[None]
        px = ti.cast(p[0], ti.i32) % self._x
        py = ti.cast(p[1], ti.i32) % self._y
        return self.world[0, px, py]

    @ti.kernel
    def move(self):
        for i in self._pos:
            pos, ang = self._pos[i], self._ang[i]
            l = self.sense(pos, ang - self.sense_angle[None])
            c = self.sense(pos, ang)
            r = self.sense(pos, ang + self.sense_angle[None])
            if l < c < r:
                ang += self.move_angle[None]
            elif l > c > r:
                ang -= self.move_angle[None]
            elif c < l and c < r:
                ang += self.move_angle[None] * (2 * (ti.random() < 0.5) - 1)
            pos += ti.Vector([ti.cos(ang), ti.sin(ang)]) * self.move_step[None]
            self._pos[i], self._ang[i] = pos, ang

    # @ti.kernel
    # def deposit(self):
    #     for i in self._pos:
    #         iposx = ti.cast(self._pos[i][0], ti.i32) % self._x
    #         iposy = ti.cast(self._pos[i][1], ti.i32) % self._y
    #         self.world[0, iposx, iposy] += 1.0

    @ti.kernel
    def deposit(self, _pos: ti.template()):
        # TODO: deposit clashes with substep
        for i in _pos:
            iposx = ti.cast(_pos[i][0], ti.i32) % self._x
            iposy = ti.cast(_pos[i][1], ti.i32) % self._y
            self.world[0, iposx, iposy] += 1.0

    @ti.kernel
    def diffuse(self):
        for i, j in ti.ndrange(self._x, self._y):
            a = 0.0
            for di in ti.static(range(-1, 2)):
                for dj in ti.static(range(-1, 2)):
                    dx = (i + di) % self._x
                    dy = (j + dj) % self._y
                    a += self.world[0, dx, dy]
            a *= self.evaporation[None] / 9.0
            self.world[0, i, j] = a

    def step(self):
        self.move()
        self.deposit(self._pos)
        self.diffuse()

    def get_image(self):
        return self.world.to_numpy()[0]

    def process(self):
        if self.pause == False:
            for _ in range(int(self.substep[None])):
                self.step()
                self._i += 1
        return self.get_image()

# `jurigged -v tulvera/tulvera/vera/_physarum.py`
def update(p):
    pass
    # p.sense_angle[None] = 0.2 * np.pi

def main():
    ti.init(arch=ti.vulkan)
    x = 1920
    y = 1080
    n = 2048
    physarum = Physarum(x, y, n)
    physarum.pause = False
    window = ti.ui.Window("Physarum", (x, y))
    canvas = window.get_canvas()
    while window.running:
        # update(physarum) # jurigged
        canvas.set_image(physarum.process())
        window.show()

if __name__ == '__main__':
    main()


"""KenDB3 API model decorator

The goal of this subsystem is to automate generation of REST-like endpoints.
Ideally, each field or every object should only be defined once - in its Django
model.

This subsystem currently only handles (de-)serialization to basic Python obj-
ects - acceptable for DjangoJSONEncoder. It will probably be expanded later.

TypeScript class declarations are automatically generated for all API models,
accessible via `import { MyModel } from 'dataman';` in frontend code.

# Usage

From the system's viewpoint, model instances are collections of fields that can
be read or assigned using getattr and setattr, respectively. However, Django
models and API objects don't necessarily coincide: sometimes it makes sense to
only serialize part of the model. Field groups solve this problem: every field
is assigned to one or more field groups (default being '*'); they are specified
when registering fields. Serialization and deserialization routines can then be
told to use fields from a particular group.

## Boilerplate

 1. Add a `_api` attribute, and initialize it to a APIEngine instance.
 2. Add a @api_model decorator.

Resulting model class template looks like this:

    from api_lib.api_fields import api_model, APIEngine

    @api_model
    class MyModel(models.Model):
        _api = APIEngine()
        # the rest of the model

## Specifying fields

Three syntactical options are available. The example for every option registers
two fields: `my_field` in the default '*' group, and `fav_pizza` in groups
'food_prefs' and 'moral_worth'.

 1. Annotation syntax, usually appropriate for Django Fields. Yes, this is
    incompatible with type hints. We don' use 'em here. Believe or not, annota-
    tions were designed for different uses.

        my_field: _api() = models.CharField(...)
        fav_pizza: _api('food_prefs', 'moral_worth') = models.CharField(...)

 2. Decorator syntax, usually appropriate for @property's. Note that @property
    itself is missing, replaced entirely by @_api().property.

        @_api().property
        def my_field(self): ...
        @my_field.setter
        def my_field(self, value): ...

        @_api('food_prefs', 'moral_worth').property
        def fav_pizza(self): ...
        @my_field.setter
        def fav_pizza(self, value): ...

 3. Manually, for all those pesky special cases.

        # some weird stuff that defines a 'my_field' attribute
        _api.add_field('my_field')

        # more weird weirdness that adds a 'fav_pizza' attribute
        _api.add_field('fav_pizza', groups=['food_prefs', 'moral_worth'])

## Complete model example

    from api_lib.api_fields import api_model, APIEngine

    @api_model
    class Car(models.Model):
        _api = APIEngine()

        make: _api() = models.CharField(max_length=64)
        color = models.CharField(max_length=16)
        design_desc: api('looks') = models.TextField()

        @_api('*', 'looks').property
        def color_rgb(self):
            return to_rgb(self.color)

        @color_rgb.setter
        def color_rgb(self, value):
            return self.color = from_rgb(value)

## Serialization and deserialization

    >>> myCar.api_serialize()
    {'id': 123, 'make': 'Batmobile', 'color_rgb': [0, 0, 0]}
    >>> myCar.api_serialize('looks')
    {'id': 123, 'design_desc': 'Looks cool.', 'color_rgb': [0, 0, 0]}
    >>> t34 = Car.api_deserialize({'id': 456, 'make': 'Soviet tank T-34'})
    >>> t34
    <Car: Car object (456)>
    >>> t34.make
    'Soviet tank T-34'
    >>> t34.color
    ''

## Handling of relational fields

Relational fields are serialized to relevant primary keys. This is currently
implemented by using fields with `_id` suffix if they exist.

Note that fields are set in the order of their registration.
"""

import builtins
from collections import namedtuple
import re

from django.db import models

from taggit.managers import _TaggableManager

from . import api_autogenerator
from . import api_server

def api_model(cls):
    """Create API methods and classmethods in cls and schedule autogeneration.

    This decorator expects to find an APIEngine instance in cls._api, which
    should have been used to mark API fields. See module docstring for details.
    """

    cls._api._assemble_groups(cls)

    api_server.all_models[cls._api.api_name] = cls

    cls.api_serialize = _api_serialize_impl
    cls.api_deserialize = _api_deserialize_impl

    api_autogenerator.include_model(cls)

    return cls

class _Registrar:
    """An object used to mark fields."""

    def __init__(self, api_engine, groups):
        self.groups = groups
        self.api_engine = api_engine
        api_engine._request(self, groups=groups)

    def __repr__(self):
        return '@_api(' + ', '.join(repr(g) for g in self.groups) + ')'

    def __str__(self):
        return repr(self)

    def property(self, getter):
        """Return a property attribute that is marked as an API field."""
        if isinstance(getter, builtins.property):
            raise TypeError(
                "Don't use @property together with @_api().property")

        registrar = self

        class _APIProperty(builtins.property):
            """Helps keep track of property mutations.

            Each use of property.getter, property.setter or property.deleter
            creates a new instance of property, which makes attributes defined
            with @property hard to track. This class updates references automa-
            tically.
            """

            def getter(self, getter_fn):
                return self._update(builtins.property.getter(self, getter_fn))
            def setter(self, setter_fn):
                return self._update(builtins.property.setter(self, setter_fn))
            def deleter(self, deleter_fn):
                return self._update(builtins.property.deleter(self, deleter_fn))

            def _update(self, new_instance):
                request.find_by = new_instance
                return new_instance

            def __repr__(self):
                spr = builtins.property.__repr__(self)
                return f"{registrar}.property({spr})"
            def __str__(self):
                spr = builtins.property.__str__(self)
                return f"{registrar}.property({spr})"

        first_wrapper = _APIProperty(getter)
        request = self.api_engine._request(first_wrapper, groups=self.groups)
        return first_wrapper

class APIEngine:
    """Orchestrator of API field registrations.

    See module docstring for details.
    """

    class _Request:
        """A request to register a field.

        See APIEngine._request() for details.
        """
        def __init__(self, find_by, groups, getter=None, setter=None):
            if isinstance(groups, str):
                raise TypeError('groups must be a non-str iterable')
            bad_groups = [g for g in groups if not isinstance(g, str)]
            if bad_groups:
                raise TypeError(f"groups must be strs, not {bad_groups}")

            self.find_by = find_by
            self.groups = groups
            self.accessors = (getter, setter) if getter or setter else None

    def __init__(self):
        self._requests = []
        self.field_groups = None
        self.api_name = None
        pass

    def __call__(self, *groups):
        return _Registrar(self, groups or ['*'])

    def _request(self, find_by, **kwargs):
        """Request that a field identified by find_by be registered as a field.

        find_by can take these values:
          - Attribute name (str)
          - Attribute object that will be looked up in cls.__dict__
          - _Registrar object that will be looked up in cls.__annotations__

        If an attribute object isn't found, of if multiple attributes match, an
        error will be raised by @api_method.

        The _Request object is returned and can be modified afterwards.
        """
        if self._requests is None:
            raise ValueError('API is already assembled, '
                             f"cannot request registration of {find_by!r}")

        request = APIEngine._Request(find_by, **kwargs)
        self._requests.append(request)
        return request

    def add_field(self, name, groups='*', getter=None, setter=None):
        """Manually register an API field in given groups.

        Prefer using annotations or decorators to this manual method.

        groups can be a single str or an iterable of strs. If omitted, defaults
        to '*'.

        getter and setter, if specified, will be used to serialize and deseri-
        alize the field. Their call signatures should match getattr and setattr
        builtins.
        """
        if isinstance(groups, str):
            groups = [groups]
        self._request(name, groups=groups, getter=getter, setter=setter)

    def add_related(self, name, groups='*'):
        """Register a related manager as an API field in given groups.

        groups can be a single str or an iterable of strs. If omitted, defaults
        to '*'.
        """
        self.add_field(name + '_ids', groups,
                       getter=_related_manager_get,
                       setter=_related_manager_set)

    def _assemble_groups(self, cls):
        field_groups = {}
        requests = self._requests
        self._requests = None

        for request in requests:
            if isinstance(request.find_by, str):
                name = request.find_by
            elif isinstance(request.find_by, _Registrar):
                if not hasattr(cls, '__annotations__'):
                    continue
                name = _find_exactly_one(
                    (name for name, annotation in cls.__annotations__.items()
                     if annotation is request.find_by),
                    message_if_zero=None,
                    message_if_many=('@_api() annotation reused on fields {{}}'
                                     f" in {cls}")
                )
                if name is None:
                    continue
            else:
                name = _find_exactly_one(
                    (name for name, value in cls.__dict__.items()
                     if value is request.find_by),
                    message_if_zero=(f"Attribute object {request.find_by}, "
                                     f"marked as API, not found in {cls}"),
                    message_if_many=(f"Attribute object {request.find_by}, "
                                     'marked as API, found in several fields '
                                     f"in {cls}: {{}}")
                )

            if request.accessors:
                field = FieldMeta(name, *request.accessors)
            else:
                field = _determine_field_meta(cls, name)

            for group in request.groups:
                if group not in field_groups:
                    field_groups[group] = []
                field_groups[group].append(field)

        self.field_groups = field_groups
        self.api_name = re.sub(r'(?<!^)(?=[A-Z])', '_', cls.__name__).lower();
        self.all_fields = { meta.name for group in self.field_groups.values()
                                      for meta in group }

    def _get_fields(self, group):
        result = self.field_groups.get(group, None)
        if result is not None:
            return result
        raise ValueError(f"No fields registered in group {group!r}")

    def __repr__(self):
        return '_api: APIEngine'

    def __str__(self):
        return 'APIEngine'

def _find_exactly_one(candidates, message_if_zero, message_if_many):
    """Extract the only item from candidates, or optionally raise errors."""

    non_existant = object()
    candidate_iterable = iter(candidates)

    # Candidate 1 should exist
    candidate1 = next(candidate_iterable, non_existant)
    if candidate1 is non_existant:
        if message_if_zero:
            raise ValueError(message_if_zero)
        else:
            return None

    # Candidate 2 should not exist
    candidate2 = next(candidate_iterable, non_existant)
    if candidate2 is not non_existant:
        if message_if_many:
            raise ValueError(message_if_many.format(
                [candidate1, candidate2] + list(candidate_iterable)
            ))
        else:
            return None

    return candidate1

FieldMeta = namedtuple('FieldMeta',
                       'name, getter, setter',
                       defaults=(getattr, setattr))

def _determine_field_meta(cls, name):
    """Create FieldMeta for field registered as name in model cls."""

    if not hasattr(cls, name):
        # Probably a dynamic attribute
        return FieldMeta(name)

    attribute = getattr(cls, name)

    # Check for foreign keys and use object IDs instead
    if hasattr(attribute, 'field'):
        django_field = attribute.field
        if isinstance(django_field, models.ForeignKey):
            return FieldMeta(django_field.attname)
        elif isinstance(django_field, models.OneToOneField):
            return FieldMeta(django_field.attname)

    # Check for TaggableManager
    if isinstance(attribute, _TaggableManager):
        return FieldMeta(name, _taggable_manager_get, _taggable_manager_set)

    # Check for RelatedManager
    if hasattr(attribute, 'related_manager_cls'):
        return FieldMeta(name + '_ids',
                         _related_manager_get,
                         _related_manager_set)

    return FieldMeta(name)

def _related_manager_get(obj, name):
    manager = getattr(obj, name.removesuffix('_ids'))
    return [pk for (pk,) in manager.values_list('pk')]

def _related_manager_set(obj, name, value):
    manager = getattr(obj, name.removesuffix('_ids'))
    objects = manager.model.objects.filter(pk__in=value)
    manager.set(objects)

def _taggable_manager_get(obj, name):
    return list(getattr(obj, name).names())

def _taggable_manager_set(obj, name, value):
    return getattr(obj, name).set(value)

def _api_serialize_impl(self, group='*'):
    """Serializes this object into a Python dict.

    The dict will include the values of all API fields in the requested group,
    and `'id': self.pk`.
    """

    fields = type(self)._api._get_fields(group)
    result = {name: getter(self, name) for name, getter, _ in fields}
    result['id'] = self.pk
    return result

@classmethod
def _api_deserialize_impl(cls, data, group='*'):
    """Creates an object from a Python dict.

    The object is created roughly so:

        obj = type(self)()
        if 'id' in data: obj.pk = data['id']
        if 'field_1' in data: obj.field_1 = data['field_1']
        ...
        if 'field_N' in data: obj.field_N = data['field_N']

    All API fields from the requested group will be looked up in data. Missing
    fields, and dict entries not corresponding to a field are silently ignored.

    Returned object is not saved automatically.
    """
    fields = cls._api._get_fields(group)

    obj = cls()
    if 'id' in data:
        obj.pk = data['id']

    for field, _, setter in fields:
        if field in data:
            setter(self, field, data[field])
    return obj


'''
Navigation Screen
=================
Display a Navigation drawer

-------- ----------------------------------
        | =    PyCon India 2017            |
        |__________________________________
        |                                  |
        |                                  |
        |                                  |
But1    |                                  |
        |     Logo Here                    |
But2    |                                  |
        |                                  |
But3    |       ----------------------     |
        |     [ Workshop + Dev Sprints ]   |
But4    |       ----------------------     |
        |                                  |
But5    |       ----------------------     |
        |     [ Conference Days        ]   |
But6    |       ----------------------     |
        |                                  |
        |                                  |
'''

# from kivy.factory import Factory
# Factory.register('NavigationDrawer', module='uix.navigationdrawer')
from uix.navigationdrawer import NavigationDrawer
from kivy.uix.screenmanager import Screen
from kivy.properties import (ObjectProperty, NumericProperty, OptionProperty,
                             BooleanProperty, StringProperty)
from kivy.factory import Factory
from kivy.lang import Builder
from kivy.app import App

from uix.buttons import ImageButton

import json

class NavButton(Factory.ButtonBehavior, Factory.BoxLayout):
    menu_item_text = StringProperty('')
    icon_source = StringProperty('')
    navigate_to = StringProperty('')

class LeftPanel(Factory.BoxLayout):
    Builder.load_string('''
<LeftPanel>
    orientation: 'vertical'
    canvas:
        Color:
            rgba: 1, 1, 1, 1
        Rectangle:
            size: self.size
            pos: self.pos
    Image
        id: img_back
        source: "data/images/background.png"
        allow_stretch: True
        keep_ratio: False
        size_hint: 1, None
        height: self.width/2
        Image
            source: 'data/images/logo.png'
            size: img_back.width, img_back.height/3.
            center: img_back.center

    RelativeLayout
        size_hint: 1, 1
        BoxLayout
            id: menu_buttons_container
            size_hint: 1, .8
            pos_hint: {'center_y': .55}
            orientation: 'vertical'

    ''')

class TopBar(Factory.BoxLayout):

    #this part of code loads data from event.json for event title
    with open('eventsapp/data/jsonfiles/event.json') as data_file:
        data = json.load(data_file)
    event_items = data.get("0.0.2")
    for items in event_items:
        event_name=items['name']

    back_button_image = StringProperty('data/images/hamburger.png')
    title = StringProperty(event_name)
    navigate_back = BooleanProperty(False)

    def on_menu_press(self):
        app = App.get_running_app()
        if self.navigate_back:
            manager = app.navigation_screen.ids.nav_manager
            manager.transition.direction = 'right'
            manager.current = 'ScheduleScreen'
        else:
            app.navigationdrawer.toggle_state()

    Builder.load_string('''
<TopBar>
    size_hint: 1, None
    height: dp(50)
    width: dp(45)
    spacing: dp(15)
    canvas.before:
        Color:
            rgba: 69/255., 132/255., 182/255., 1
        Rectangle:
            size: self.size
            pos: self.pos
    ImageButton:
        source: root.back_button_image
        on_release: root.on_menu_press()
    Label:
        text: root.title
        shorten: True
        text_size: self.size
        font_size: dp(22)
        halign: 'left'
        valign: 'center'
    ''')

class NavigationScreen(Screen):

    Builder.load_string('''
<NavButton>
    padding: dp(10)
    spacing: dp(10)
    on_release:
        app.navigation_screen.ids.drawer.toggle_state()
        app.load_screen(root.navigate_to,
        manager=app.navigation_screen.ids.nav_manager)
    Image:
        source: root.icon_source
        size_hint_x: None
        width: self.height
    Label:
        text: root.menu_item_text
        text_size: self.size
        halign: 'left'
        valign: 'center'
        font_size: dp(18)
        color: 0, 0, 0, 1

<NavigationScreen>
    name: 'NavigationScreen'
    on_parent: app.navigation_screen = self
    NavigationDrawer
        id: drawer
        anim_type: 'slide_above_simple'
        side_panel_width: max(dp(250), 0.8 * self.width)
        on_parent: if self.parent: app.navigationdrawer = self
        LeftPanel
            id: leftpanel
            on_right: nav_manager.opacity = 1.15 - (self.right/drawer.side_panel_width)
        ScreenManager
            id: nav_manager
            on_parent: if self.parent: app.load_screen('WelcomeScreen', manager=self)

    ''')

    def on_pre_enter(self, onsuccess = False):
        menu_container = self.ids.leftpanel.ids.menu_buttons_container
        menu_container.clear_widgets()
        with open('eventsapp/data/jsonfiles/menuitems.json') as data_file:
            data = json.load(data_file)
        menuitems = data.get("0.0.1")
        for item in menuitems:
            bl = Factory.NavButton(navigate_to=item['navigate_to'],
                                   menu_item_text=item['menu_item_text'],
                                   icon_source=item['icon_source'])
            menu_container.add_widget(bl)