from direct.directnotify import DirectNotifyGlobal
from direct.distributed.DistributedSmoothNodeAI import DistributedSmoothNodeAI

from toontown.catalog import CatalogItem
from toontown.estate import HouseGlobals

class DistributedFurnitureItemAI(DistributedSmoothNodeAI):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedFurnitureItemAI')

    def __init__(self, air, house, furnitureMgr, catalogItem):
        DistributedSmoothNodeAI.__init__(self, air)
        self.house = house
        self.furnitureMgr = furnitureMgr
        self.catalogItem = catalogItem
        self.mode = 0
        self.avId = 0

    def announceGenerate(self):
        DistributedSmoothNodeAI.announceGenerate(self)
        self.b_setPosHpr(*self.catalogItem.posHpr)

    def getItem(self):
        return [self.furnitureMgr.doId, self.catalogItem.getBlob(store=CatalogItem.Customization)]

    def requestPosHpr(self, final, x, y, z, h, p, r, t):
        senderId = self.air.getAvatarIdFromSender()
        posHpr = (x, y, z, h, p, r)
        if senderId != self.house.avatarId:
            # Hey! What are you doing!?
            self.notify.warning('%d tried to move furniture of house owned by %d!' % (senderId, self.house.ownerId))
            return

        if not final and self.mode != HouseGlobals.FURNITURE_MODE_START:
            self.b_setMode(HouseGlobals.FURNITURE_MODE_START, senderId)
        elif final and self.mode == HouseGlobals.FURNITURE_MODE_START:
            self.b_setMode(HouseGlobals.FURNITURE_MODE_STOP, senderId)
            self.b_setMode(HouseGlobals.FURNITURE_MODE_OFF, senderId)
            self.b_setPosHpr(*posHpr)

        self.catalogItem.posHpr = posHpr
        self.sendUpdate('setSmPosHpr', [x, y, z, h, p, r, t])

    def setMode(self, mode, avId):
        self.mode = mode
        self.avId = avId

    def d_setMode(self, mode, avId):
        self.sendUpdate('setMode', [mode, avId])

    def b_setMode(self, mode, avId):
        self.setMode(mode, avId)
        self.d_setMode(mode, avId)

    def getMode(self):
        return self.mode, self.avId


import os
import secrets
import requests
from PIL import Image

from covid import app
from .variables import id_map, translation_map

def province_covid_num(prov):
    url = 'https://master-covid-19-api-laeyoung.endpoint.ainize.ai/jhu-edu/timeseries?iso2=CN'
    content = requests.get(url).json()

    for item in content:
        if item['provincestate'] == prov:
            confirmed = item['timeseries']['8/4/21']['confirmed']
            deaths = item['timeseries']['8/4/21']['deaths']
            recovered = item['timeseries']['8/4/21']['recovered']
            return confirmed - deaths - recovered, recovered

def province_population(prov):
    headers = {}
    # 用来传递参数
    keyvalue = {}
    # 目标网址
    url = 'http://data.stats.gov.cn/easyquery.htm'
    # 头部填充
    headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) ' \
                            'AppleWebKit/537.36 (KHTML, like Gecko)' \
                            'Chrome/70.0.3538.102 Safari/537.36'

    # 参数填充
    keyvalue['m'] = 'QueryData'
    keyvalue['dbcode'] = 'fsnd'
    keyvalue['rowcode'] = 'zb'
    keyvalue['colcode'] = 'sj'
    keyvalue['wds'] = '[]'
    id = id_map[prov]
    keyvalue['dfwds'] = '[{"wdcode":"zb","valuecode":"A0301"}, ' \
                        '{valuecode: ' + id + ', wdcode: "reg"}, ' \
                                              '{valuecode: "2020", wdcode: "sj"}]'

    response = requests.get(url, headers=headers, params=keyvalue, verify=False)
    data = response.json()
    pop_2020 = data['returndata']['datanodes'][0]['data']['data']
    return pop_2020

risk_map = {}

def get_risk_map():
    url = 'https://file1.dxycdn.com/2021/0202/196/1680100273140422643-135.json'
    content = requests.get(url).json()
    for area in content['data'][1]['dangerPros']:
        name = area['provinceShortName']
        risk_map[translation_map[name]] = 1

    for area in content['data'][0]['dangerPros']:
        name = area['provinceShortName']
        risk_map[translation_map[name]] = 2

def province_risk(prov):
    get_risk_map()
    if prov in risk_map.keys():
        return risk_map[prov]
    else:
        return 0

def save_picture(form_picture):
    random_hex = secrets.token_hex(8)
    _, f_ext = os.path.splitext(form_picture.filename)
    picture_fn = random_hex + f_ext
    picture_path = os.path.join(app.root_path, 'static/profile_pics', picture_fn)

    output_size = (125, 125)
    i = Image.open(form_picture)
    i.thumbnail(output_size)
    i.save(picture_path)

    return picture_fn


import glob
import subprocess
import yaml
import sys

def yosys_script(name, files):
    files = " ".join([f"{name}/src/{fn}" for fn in files])

    return f"read_verilog -sv {files}; synth -flatten -top toplevel_chip; setundef -undriven -zero; setundef -zero; async2sync; synth -top toplevel_chip; rename toplevel_chip {name}; write_verilog -attr2comment {name}/flattened.v; check; stat;"

def run_yosys(name, files):
    out = subprocess.check_output(["yosys", "-p", yosys_script(name, files)]).decode()
    out = out.split("Printing statistics.")[-1].split("End of script")[0].split("Warnings")[0].strip()
    with open(f"{name}/flattened_stats.txt", "w+") as f:
        f.write(out+"\n")

def write_wrapper(name, topname):
    wrapper = """
        module toplevel_chip (
            input [13:0] io_in,
            output [13:0] io_out
        );

            CHIPNAME mchip (
                .io_in(io_in[7:0]),
                .io_out(io_out[7:0])
            );

        endmodule
    """.replace("CHIPNAME", topname)

    with open(f"{name}/src/wrapper.v", "w+") as f:
        f.write(wrapper)

def write_wrapper_clocked(name, topname):
    wrapper = """
        module toplevel_chip (
            input [13:0] io_in,
            output [13:0] io_out
        );

            // CLOCKED
            CHIPNAME mchip (
                .io_in({io_in[7:1], io_in[12]}),
                .io_out(io_out[7:0])
            );

        endmodule
    """.replace("CHIPNAME", topname)

    with open(f"{name}/src/wrapper.v", "w+") as f:
        f.write(wrapper)

if len(sys.argv) > 1:
    g = sys.argv[1]
else:
    g = "d*"

for des in sorted(list(glob.glob(g))):
    with open(f"{des}/info.yaml") as f:
        data = yaml.load(f, Loader=yaml.Loader)

    if "tt02_fmt" in data["project"] and data["project"]["tt02_fmt"] == "clocked":
        print("Processing OLD (clocked)", des)
        sources = data["project"]["source_files"] + ["wrapper.v"]

        write_wrapper_clocked(des, data["project"]["top_module"])
        run_yosys(des, sources)

    elif "tt02_fmt" in data["project"] and data["project"]["tt02_fmt"]:
        print("Processing OLD (async)", des)
        sources = data["project"]["source_files"] + ["wrapper.v"]

        write_wrapper(des, data["project"]["top_module"])
        run_yosys(des, sources)

    else:
        print("Processing NEW", des)
        assert data["project"]["top_module"] == "toplevel_chip"
        sources = data["project"]["source_files"]

        run_yosys(des, sources)


# TODO: add duration for tied notes to initial note

# Bug: separating fingering annotations for each note in chord?!

## Predicate Representation
# Staff(s, t)
# Note(p, t)
# Finger(f, t)
# Succ(t1, t2)
# Concurrent(t1,t2)
# Distance(t1,t2, l)

import sys
import math

from music21 import converter, clef, note, articulations
import music21.environment as environment
class NoteInfo:
  def __init__(self, pitch=-1, duration=0.0, staff=0, measure=-1, beat=0.0, note=note.Note(), index=0):
    self.Pitch = pitch
    self.Duration = duration
    self.Staff = staff
    self.Measure = measure
    self.Beat = beat
    self.Note = note
    self.Index = index

  def __eq__(self, other):
    """Overrides the default implementation"""
    if isinstance(self, other.__class__):
        return self.__dict__ == other.__dict__
    return False

class EventNoteInfo:
  def __init__(self, note, from_previous=False):
    self.Note = note
    self.fromPrevious = from_previous

def convertMidiToAugMidi(midi_num):
  E_PITCH = 4
  NUM_PITCHES = 12
  octave_num = math.floor(midi_num / NUM_PITCHES)
  aug_midi_num = midi_num + 2 * octave_num
  if midi_num % NUM_PITCHES > E_PITCH:
    aug_midi_num += 1
  # print('Midi num: {}, aug midi num: {}'.format(midi_num, aug_midi_num))
  return aug_midi_num

def getNoteProperties(x, prev_staff):
  t = ''
  s = "Pitch: " + str(x.pitch.midi) + ", Measure: "  + str(x.measureNumber) + ", Beat: " +  str(round(x.beat, 10));
  s += ", "
  if x.tie != None:
    t = x.tie.type
  s += t
  Measure = x.measureNumber
  Beat = round(x.beat, 10)
  Duration = round(x.duration.quarterLength, 10)
  # MIDIDIDIDIDIDI
  return NoteInfo(convertMidiToAugMidi(x.pitch.midi), Duration, prev_staff, Measure, Beat, x)

def getChordNoteProperties(n, x, pitch, prev_staff):
  t = ''
  s = "Pitch: " + str(pitch.midi) + ", Measure: "  + str(x.measureNumber) + ", Beat: " +  str(round(x.beat, 10));
  s += ", "
  if x.tie != None:
    t = x.tie.type
  s += t
  Measure = x.measureNumber
  Beat = round(x.beat, 10)
  Duration = round(x.duration.quarterLength, 10)
  # MIDIDIDIDIDI
  return NoteInfo(convertMidiToAugMidi(pitch.midi), Duration, prev_staff, Measure, Beat, x)

def getClef(prev_staff, clef):
  if clef.sign == 'G':
    prev_staff = 1
  elif clef.sign == 'F':
    prev_staff = -1
  return prev_staff

def convertSong(song_file):
  song = converter.parse(song_file)

  all_notes = song.recurse(classFilter=('Note','Chord'))   # list of all notes in song
  notes = {}                              # list of all notes in song, processed
  # cur_notes = []                        # notes that could overlap with current event
  # events = {}                           # dictionary of events ('every unique note onset and offset)
                                          # key is onset; value is list of overlapping notes

  prev_staff = getClef(0, song.parts[0][1].clef) # what if right hand part starts out as bass clef?
  start_tie_notes = []
  for i in range(len(all_notes)):
    x = all_notes[i]
    if (x.isNote or x.isChord) and (x.tie is None or x.tie.type == 'start'):
      # check staff/clef (music21 iterates over all notes in treble, then all notes in bass; it also only includes staff info for
      # notes in first measure)
      # print('x: {}, prev_staff: {}'.format(x, prev_staff))
      if x.activeSite.clef is not None:
        prev_staff = getClef(prev_staff, x.activeSite.clef)
      if x.isChord:
        notes_tmp = []
        for p, n in zip(x.pitches, x._notes):
          notes_tmp.append(getChordNoteProperties(n, x, p, prev_staff))
        for n in notes_tmp:
          measure = n.Measure
          if measure not in notes:
            notes[measure] = {}
          if n.Beat not in notes[measure]:
            notes[measure][n.Beat] = []
          notes[measure][n.Beat].append(n)
          if x.tie is not None and x.tie.type == 'start':
            start_tie_notes.append(n)
      elif x.isNote:
        note = getNoteProperties(x, prev_staff)
        measure = note.Measure
        if measure not in notes:
          notes[measure] = {}
        if note.Beat not in notes[measure]:
          notes[measure][note.Beat] = []
        notes[measure][note.Beat].append(note)
        if x.tie is not None and x.tie.type == 'start':
          start_tie_notes.append(note)
    elif (x.isNote or x.isChord) and x.tie is not None and (x.tie.type == 'continue' or x.tie.type == 'stop'):
      if x.isChord:
        start_notes = []
        for s_note in start_tie_notes:
          for p in x.pitches:
            # print('s_note: {}, chord note: {}, m: {}, s_note offset: {}, x offset: {}'.format(s_note.Pitch, p, s_note.Measure, calcOffset(s_note, song), round(x.getOffsetInHierarchy(song), 5)))
            if convertMidiToAugMidi(p.midi) == s_note.Pitch and calcOffset(s_note, song) == round(x.getOffsetInHierarchy(song), 5):
              s_note.Duration += round(x.duration.quarterLength, 10)
              start_notes.append(s_note)
              break
        if start_notes is not None and x.tie.type == 'stop':
          # print('stop working')
          for s_n in start_notes:
            # print(s_n.Note)
            start_tie_notes.remove(s_n)
        elif start_notes is None:
          print('Start notes is none; continuing note: {}'.format(x))
        # print()
      elif x.isNote:
        start_note = None
        for s_note in start_tie_notes:
          # print('s_note: {}, m: {}, s_note offset: {}, x offset: {}'.format(s_note.Note.pitch, s_note.Measure, calcOffset(s_note, song), x.getOffsetInHierarchy(song)))
          if s_note.Pitch == convertMidiToAugMidi(x.pitch.midi) and calcOffset(s_note, song) == round(x.getOffsetInHierarchy(song), 5):
            s_note.Duration += round(x.duration.quarterLength, 10)
            start_note = s_note
            break
        if start_note is not None and x.tie.type == 'stop':
          start_tie_notes.remove(start_note)  # should only remove if an ending tie!
        elif start_note is None:
          note = getNoteProperties(x, prev_staff)
          print('Start note is none; continuing note: (n: {}, m: {}, d: {})'.format(note.Note, note.Measure, note.Duration))
        # print()
  return notes, song

def calcOnset(note, song):
  if type(note) is EventNoteInfo:
    return round(note.Note.Note.getOffsetInHierarchy(song), 5)
  elif type(note) is NoteInfo:
    return round(note.Note.getOffsetInHierarchy(song), 5)

def calcOffset(note, song):
  if type(note) is EventNoteInfo:
    return round(note.Note.Note.getOffsetInHierarchy(song) + note.Note.Duration, 5)
  elif type(note) is NoteInfo:
    return round(note.Note.getOffsetInHierarchy(song) + note.Duration, 5)

def setNoteIndex(notes):
  index = 0
  for measure,beats in sorted(notes.items()):
    for beat,ns in sorted(beats.items()):
      for note in ns:
        note.Index = index
        index += 1
  return notes

def getTuffyPredictions(tuffy_output):
  tuffy_predictions = {} #dictionary for tuffy output
  fingerings = [] #list of fingerings and associative indices to be annotated
  fings = [] #list of fingerings from fingerings list
  indices = [] #list of indices from fingerings list
  result = zip() #indices zipped with fingers

  for line in tuffy_output.readlines():
    fingerings.append(line)

  for finger in fingerings:
    split1 = finger.split("(")
    split2 = split1[1].split(")")
    split3 = split2[0].split(",")
    fings.append(int(split3[0]))
    indices.append(int(split3[1]))

    result = zip(indices, fings)
    resultSet = set(result)
    tuffy_predictions = dict(resultSet)

  return tuffy_predictions

def annotateFingerings(notes, song, tuffy_predictions):

  # get all event onsets for both treble and bass clef
  for measure,beats in sorted(notes.items()):
    # print('Measure {}:'.format(measure))
    for beat,ns in sorted(beats.items()):
      # print('\tBeat {}:'.format(beat))
      for n in ns:
        if(n.Index in tuffy_predictions):
          finger = tuffy_predictions[n.Index]
          n.Note.articulations.append(articulations.Fingering(finger))

def Convert(song_file, fingers):
  notes, song = convertSong(song_file)
  notes = setNoteIndex(notes)
  predictions = getTuffyPredictions(fingers)
  annotateFingerings(notes, song, predictions)
  return song

def main():
  if len(sys.argv) != 3:
    print('Usage:', sys.argv[0], '<song_file>', '<tuffy_output>')
    exit(1)

  # convert song
  song_file = sys.argv[1]
  tuffy_output_file = sys.argv[2]
  notes, song = convertSong(song_file)
  notes = setNoteIndex(notes)
  tuffy_predictions = getTuffyPredictions(tuffy_output_file) # (make dictionary (key: index, value: finger number)) (e.g. { 45: 1, ...})
  #for index in sorted(tuffy_predictions.keys()):
   ##  print(index, tuffy_predictions[index])
  annotateFingerings(notes, song, tuffy_predictions)

  song.write('musicxml', song_file[:-4] + "_annotated.xml")

if __name__ == "__main__":
  main()


import sys
from PyQt5.QtWidgets import QApplication, \
    QWidget, QInputDialog, QLineEdit, QMainWindow
from PyQt5.QtGui import QIcon
from PyQt5 import QtWidgets, QtCore
import PyQt5
from PyQt5 import QtGui

class MainWindow ( QMainWindow ):

    def __init__(self):
        super().__init__( )

        dlgi = QInputDialog()
        text, ok = dlgi.getText(self, 'InputDialog', 'EnterYourName = ')

        if ok:
            print( "PRint from input are", text )
        self.show()

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWindow()
    app.exec_()
    print ("process doen")


import boto3
import uuid
import logging

from botocore.exceptions import ClientError
from datetime import datetime
from chalice import Response, BadRequestError, Blueprint

lockapi = Blueprint(__name__)

logger = logging.getLogger(__name__)

# Logger prints to console
console = logging.StreamHandler
logger.addHandler(console)

class ValidationException(Exception):
    pass

class SingletonDynamoDBClient:
    __instance = None

    @classmethod
    def getInstance(cls):
        if cls.__instance is None:
            client = boto3.client("dynamodb")
            cls.__instance = client
        return cls.__instance

def check_fields(api_data, fields_list):
    """Checks if every element of fields_list appears inside api_data."""

    missing_fields = [field for field in fields_list if field not in api_data]
    if len(missing_fields) > 0:
        miss_msg = "Missing the following fields in your request: %s" % missing_fields
        raise BadRequestError(miss_msg)

@lockapi.route("/acquire", methods=["POST"])
def acquire_lock():
    api_data = lockapi.current_request.json_body
    required_fields = ["ServiceName", "LockName", "LockTableName", "ServiceTableName"]
    check_fields(api_data, required_fields)

    service_name, lock_name, lock_table_name, service_table_name = (
        api_data["ServiceName"],
        api_data["LockName"],
        api_data["LockTableName"],
        api_data["ServiceTableName"],
    )

    client = SingletonDynamoDBClient.getInstance()
    date_time = str(datetime.utcnow())
    job_id = str(uuid.uuid4())

    try:
        # If either service_resp, or response fails, will trigger exception
        service_resp = client.transact_get_items(
            TransactItems=[
                {
                    "Get": {
                        "TableName": service_table_name,
                        "Key": {"ServiceName": {"S": service_name}},
                    }
                }
            ]
        )
        # In case service doesn't exist
        if service_resp["Responses"] == [{}]:
            raise ValidationException("Service doesn't exist")
        response = client.transact_write_items(
            TransactItems=[
                {
                    "Update": {
                        "TableName": lock_table_name,
                        "Key": {"LockName": {"S": lock_name}},
                        "UpdateExpression": "SET HeldBy = :held_by, Lock_Acquire_DateTime = :date_time, JobId = :job_id",
                        "ExpressionAttributeValues": {
                            ":held_by": {"S": service_name},
                            ":empty_string": {"S": ""},
                            ":date_time": {"S": date_time},
                            ":job_id": {"S": job_id},
                        },
                        "ConditionExpression": "HeldBy = :empty_string AND JobId = :empty_string",
                    }
                }
            ]
        )
        response["ResponseMetadata"]["JobId"] = job_id
        response["ResponseMetadata"][
            "Message"
        ] = "%s acquired the following lock: %s" % (service_name, lock_name)

        return response
    except ValidationException as e:
        logger.debug(str(e))
        return Response(
            body={"Message": str(e)},
            status_code=400,
            headers={"Content-Type": "application/json"},
        )
    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to acquire a lock"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )

def retrieve_tables_values(lock_name, lock_table_name):
    """Retrieves values from the lock table."""

    client = SingletonDynamoDBClient.getInstance()
    response = client.transact_get_items(
        TransactItems=[
            {
                "Get": {
                    "TableName": lock_table_name,
                    "Key": {"LockName": {"S": lock_name}},
                }
            }
        ]
    )

    return response["Responses"]

def dictify_resp(list_of_dict_item):
    """Converts a list of DynamoDB response dictionaries into a simpler key-value dictionary."""

    ret_dict = {}
    for dict_item in list_of_dict_item:
        dict_item = dict_item.get("Item", {})
        for k, v in dict_item.items():
            for vk, vv in v.items():
                ret_dict[k] = vv
    return ret_dict

@lockapi.route("/release", methods=["POST"])
def release_lock():
    api_data = lockapi.current_request.json_body
    required_fields = [
        "LockName",
        "ServiceName",
        "JobId",
        "LockTableName",
        "LogTableName",
    ]
    check_fields(api_data, required_fields)

    service_name, lock_name, job_id, lock_table_name, log_table_name = (
        api_data["ServiceName"],
        api_data["LockName"],
        api_data["JobId"],
        api_data["LockTableName"],
        api_data["LogTableName"],
    )

    client = SingletonDynamoDBClient.getInstance()

    try:

        # Put relevant Row information into dict. This is for logging purposes
        read_resp = retrieve_tables_values(lock_name, lock_table_name)
        row_dict = dictify_resp(read_resp)

        date_time = str(datetime.utcnow())

        response = client.transact_write_items(
            TransactItems=[
                {
                    "Put": {
                        "TableName": log_table_name,
                        "Item": {
                            "LockName": {"S": lock_name},
                            "ServiceName": {"S": service_name},
                            "JobId": {"S": job_id},
                            "Lock_Acquire_DateTime": {
                                "S": row_dict.get("Lock_Acquire_DateTime", "")
                            },
                            "Lock_Release_DateTime": {"S": date_time},
                        },
                    }
                },
                {
                    "Update": {
                        "TableName": lock_table_name,
                        "Key": {"LockName": {"S": lock_name}},
                        "UpdateExpression": "SET HeldBy = :empty_string, JobId = :empty_string",
                        "ExpressionAttributeValues": {
                            ":held_by": {"S": service_name},
                            ":empty_string": {"S": ""},
                            ":job_id": {"S": job_id},
                        },
                        "ConditionExpression": "HeldBy = :held_by AND JobId = :job_id",
                    }
                },
            ]
        )

        response["ResponseMetadata"]["Message"] = (
            "%s released the following lock: %s with JobId: %s"
            % (service_name, lock_name, job_id)
        )
        return response

    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to release lock"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Mesage": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )

@lockapi.route("/register_lock", methods=["POST"])
def register_lock():
    api_data = lockapi.current_request.json_body
    required_fields = ["LockName", "LockTableName"]
    check_fields(api_data, required_fields)

    lock_name, lock_table_name = (api_data["LockName"], api_data["LockTableName"])

    client = SingletonDynamoDBClient.getInstance()

    try:
        date_time = str(datetime.utcnow())

        response = client.transact_write_items(
            TransactItems=[
                {
                    "Put": {
                        "TableName": lock_table_name,
                        "Item": {
                            "LockName": {"S": lock_name},
                            "HeldBy": {"S": ""},
                            "Lock_Acquire_DateTime": {"S": date_time},
                            "JobId": {"S": ""},
                        },
                        "ConditionExpression": "attribute_not_exists(LockName)",
                    }
                }
            ]
        )
        response["ResponseMetadata"]["Message"] = "Registered Lock: %s" % lock_name

        return response
    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to register a lock"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )

@lockapi.route("/deregister_lock", methods=["POST"])
def deregister_lock():
    api_data = lockapi.current_request.json_body
    required_fields = ["LockName", "LockTableName"]
    check_fields(api_data, required_fields)

    lock_name, lock_table_name = (api_data["LockName"], api_data["LockTableName"])

    client = SingletonDynamoDBClient.getInstance()

    try:
        response = client.transact_write_items(
            TransactItems=[
                {
                    "Delete": {
                        "TableName": lock_table_name,
                        "Key": {"LockName": {"S": lock_name}},
                        "ExpressionAttributeValues": {":empty_string": {"S": ""}},
                        "ConditionExpression": "HeldBy = :empty_string AND JobId = :empty_string",
                    }
                }
            ]
        )
        response["ResponseMetadata"]["Message"] = "Deregistered Lock: %s" % lock_name

        return response
    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to deregister a lock"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )

@lockapi.route("/register_service", methods=["POST"])
def register_service():
    api_data = lockapi.current_request.json_body
    required_fields = ["ServiceName", "ServiceTableName"]
    check_fields(api_data, required_fields)

    service_name, service_table_name = (
        api_data["ServiceName"],
        api_data["ServiceTableName"],
    )

    client = SingletonDynamoDBClient.getInstance()

    try:

        response = client.transact_write_items(
            TransactItems=[
                {
                    "Put": {
                        "TableName": service_table_name,
                        "Item": {"ServiceName": {"S": service_name},},
                        "ConditionExpression": "attribute_not_exists(ServiceName)",
                    }
                }
            ]
        )
        response["ResponseMetadata"]["Message"] = (
            "Registered Service: %s" % service_name
        )

        return response
    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to register a service"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )

@lockapi.route("/deregister_service", methods=["POST"])
def deregister_service():
    api_data = lockapi.current_request.json_body
    required_fields = ["ServiceName", "ServiceTableName"]
    check_fields(api_data, required_fields)

    service_name, service_table_name = (
        api_data["ServiceName"],
        api_data["ServiceTableName"],
    )

    client = SingletonDynamoDBClient.getInstance()

    try:
        response = client.transact_write_items(
            TransactItems=[
                {
                    "Delete": {
                        "TableName": service_table_name,
                        "Key": {"ServiceName": {"S": service_name}},
                        "ExpressionAttributeValues": {
                            ":service_name": {"S": service_name}
                        },
                        "ConditionExpression": "ServiceName = :service_name",
                    }
                }
            ]
        )
        response["ResponseMetadata"]["Message"] = (
            "Deregistered Service: %s" % service_name
        )
        return response
    except ClientError as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unable to deregister a service"},
            status_code=409,
            headers={"Content-Type": "application/json"},
        )
    except Exception as e:
        logger.debug(str(e))
        return Response(
            body={"Message": "Unexpected exception occurred during the request"},
            status_code=500,
            headers={"Content-Type": "application/json"},
        )


"""
ABossBattle.py
"""

import Main_Battle as Battle
import pygame
from GlobalVar import *
import pyAnimation
import ATextBox
import ASequence

def a_DoBoss(screen, playerInfo):

    # Difficulty
    diff = playerInfo.Beated(False)["bosslevel"]

    # Counter for the boss
    counter = -1
    battleResults = "win"

    if diff == 3:
        LightName = True
    else:
        LightName = False

    # Initiate bossInfo, Pass in boss information
    bossInfo = ABoss.Boss()
    BattleClass = Battle.AdventureBattle(screen, diff,
                                         playerInfo, bossInfo, BattleGraphics=DefaultBattleWallpaper[diff],
                                         LightName = LightName)

    pyAnimation.EnterFade(screen, BattleClass.Fade, CentralClock, GameFPS)

    BattleClass.Dialogue("Narrator", "You travelled through the world to beat Mathematicians\n" +
                         "Here and now, you will face the man of your dreams.")

    # Loop for incrementing the boss
    while counter <= 2:

        if battleResults == "escape":
            return
        elif battleResults == "lose":
            return
        elif battleResults == "draw":
            BattleClass.FightContinues()
        elif battleResults == "win":
            if counter != -1:
                BattleClass.EndDialogue()
            if counter + 1 <= 1:
                # Increment counter
                counter += 1

                # Pass in new boss info
                bossInfo = BossDatabase[diff][counter]
                BattleClass.Reinitialize(bossInfo, diff = diff + (3 if counter == 1 else 0), round = counter + 1)

                # Display boss
                BattleClass.BossAppears("Final Boss" if counter == 1 else "Mathematician")
                BattleClass.StartDialogue()
            else:
                break

        # Battle sequence
        battleResults = BattleClass.Main()

    # Reads player info
    playerInfoDict = playerInfo.Beated(0)

    # Rewards will not be given if the player has beaten the boss once before
    if playerInfoDict["beat"]:

        # Asks whether the player would like to watch the epilogue again
        popUp = ATextBox.PopUp(screen)
        popUp.TextBox.InsertText("Would you like to watch the Epilogue again?", "center", True)
        nah = popUp.TextBox.InsertMenu("No")
        ya = popUp.TextBox.InsertMenu("Yes")
        popUp.TextBox.Finalize()

        popUp.Start()

        run = True
        while run:

            for event in pygame.event.get():
                Quit(event)
                result = popUp.TextBox.Event(event, popUp.Offset())
                if result == nah:
                    epilogue = False
                    run = False
                elif result == ya:
                    epilogue = True
                    run = False

            popUp.Blit()
            LoopBundle()
    # If the player hasn't beat the boss before
    else:
        BattleClass.Rewards()
        if playerInfoDict["bosslevel"] == 3:
            epilogue = True
        else:
            epilogue = False

    playerInfo.Beated(1)

    # The player has defeated all three bosses
    if epilogue:
        playerInfo.BeatFlag()
        return ASequence.Epilogue(screen)
    else:
        return False

def main():
    import APlayer
    screen = pygame.display.set_mode((1280, 800))
    playerInfo = APlayer.LoadSave("TestPlayer.txt")
    a_DoBoss(screen, playerInfo)

if __name__ == "__main__":
    main()


from flask import Flask, request, render_template
import cycle_time
import lead_time_for_change
import call_commit_id
import deployment_freq

app = Flask(__name__, template_folder='template')

@app.route("/")
def home():
    return render_template("index.html")

@app.route("/cycle_time", methods=["POST"])
def get_details():
    project_key = request.form["project_key"]
    start_date = request.form["start_date"]
    end_date = request.form["end_date"]
    res_cycle = cycle_time.cycle_time(project_key, start_date, end_date)
    res_lead = lead_time_for_change.cycle_time_lead(project_key, start_date, end_date)
    res_mean = call_commit_id.cycle_time_failover(project_key, start_date, end_date)
    res_deploy = deployment_freq.deployment_freq(project_key, start_date, end_date)
    print(f"{res_cycle}\n {res_lead}\n {res_mean}\n {res_deploy}")
    return render_template("result.html")  # cycle_time=res_cycle, mean_time=res_mean, lead_time=res_lead


import json
import csv

def json_to_csv(json_data):
  keys = list(json_data.keys())
  header = sorted(keys)
  csv_data = []
  for k in header:
    csv_data.append(json_data[k])
  return csv_data, header

# filename = "NAS_feedback_state"
# filename = "NAS_learning_outcomes_state"
# filename = "NAS_participation_state"
filename = "NAS_performance_percentage_state"

with open(filename + ".json", 'r') as f:
  json_data = json.loads(f.read())

list_size = len(json_data["state 1"])

header = ["state_name"]
csv_data = []
for x in range(1, 38):
  state_key = "state " + str(x)
  for y in range(0, list_size-1):
    parsed_csv, parsed_header = json_to_csv(json_data[state_key][y])
    if y == 0 and x == 1:
      header.extend(parsed_header)
    temp = [json_data[state_key][list_size-1]["state_name"]]
    temp.extend(parsed_csv)
    csv_data.append(temp)

with open(filename + ".csv", 'w+') as csvfile:
  csv_writer = csv.writer(csvfile, delimiter=';')
  csv_writer.writerow(header)
  for row in csv_data:
    csv_writer.writerow(row)


import os
from datetime import datetime
from glob import glob
from typing import Optional

from fastapi import FastAPI
from pydantic import BaseModel, validator
import uvicorn

from gmail import email_with_attachment

app = FastAPI()

class DateTimeModeMixin(BaseModel):
    # To add timestamp script executed, https://pydantic-docs.helpmanual.io/usage/validators/
    created_at: datetime = None

    @validator("created_at", pre=True, always=True)
    def default_datetime(cls, value:datetime) -> datetime:
        return value or datetime.now()

class Job(DateTimeModeMixin):
    name: str
    description: Optional[str]

jobs = []

def job_email_with_attachment():
    to_email = os.getenv("TO_EMAIL").split(';')
    attachments = glob('data/*.csv')
    email_with_attachment(header='header...', recipient=to_email, body='body...', attachments=attachments)

@app.get('/jobs')
async def get_jobs():
    return jobs

@app.post('/jobs', status_code=201)
async def add_job(job: Job):
    jobs.append(job)
    job_email_with_attachment()
    return jobs

if __name__ == '__main__':
    uvicorn.run(app)


from telegram import Update
from telegram.ext import CallbackContext
from telegram import ReplyKeyboardMarkup
from telegram import ReplyKeyboardRemove

from .admin import admin

from ...states import States
from ...data import text
from ...database import db_session

def pick_deal(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    deals = db_session.get_deals_list()

    reply_markup = []

    for deal in deals:
        deal = f"{deal[0]}) - {deal[1]}"
        reply_markup.append([deal])

    if reply_markup == []:
        context.bot.send_message(
            chat_id=chat_id,
            text=text["no_deals_for_now"],
        )
        return States.ADMIN_MENU

    reply_markup.append([text["back"]])

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["choose_deal"],
        reply_markup=markup,
    )
    return States.ADMIN_DEAL_CHOSEN

def get_deal(option, deals):
    for deal in deals:
        if option == deal[0]:
            print(deal)
            return deal
    return None

def deal_feedback(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id
    msg = update.message.text

    try:
        msg = msg.split(")")
        option = int(msg[0])
    except ValueError:
        context.bot.send_message(chat_id=chat_id, text=text["err_unexpected_type"])
        return pick_deal(update, context)

    deals = db_session.get_deals_list()
    deal = get_deal(option, deals)
    if deal != None:
        context.user_data["chosen_deal"] = deal
    else:
        return pick_deal(update, context)

    reply_markup = [
        [text["yes"]],
        [text["no"]],
        [text["back"]]
    ]

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["has_deal_been"],
        reply_markup=markup,
    )
    return States.HAS_DEAL_BEEN

def deal_no(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_no_admin"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_NO_DESCRIPTION

def send_deal_description(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id
    msg = update.message.text

    chosen_deal = context.user_data["chosen_deal"]
    db_session.delete_deal(chosen_deal)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_no_admin_descr_thx"],
    )

    context.bot.send_message(
        chat_id=chosen_deal[2],
        text=text["deal_no_lead"] + msg + "\"",
        #reply_markup=ReplyKeyboardRemove()
    )
    context.user_data.pop("chosen_deal")
    return admin(update, context)

def deal_yes(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_summ"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_YES_SUMM

def deal_yes_summ(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    mssg = update.message.text

    context.user_data["deal_summ"] = mssg

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_percent"],
        reply_markup=ReplyKeyboardRemove()
    )

    return States.DEAL_YES_PERCENT

def deal_yes_percent(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    mssg = update.message.text

    deal_percent = context.user_data["deal_percent"] = mssg

    chosen_deal = context.user_data["chosen_deal"]
    leadgen_id = chosen_deal.leadgen_id
    leadgen = db_session.get_user(leadgen_id)
    leadgen_full_name = f"{leadgen.first_name} {leadgen.last_name}"
    linkedin = chosen_deal.linkedin
    deal_summ = context.user_data["deal_summ"]

    leadgen_get = round(int(deal_summ) / 100 * int(deal_percent))
    context.user_data["leadgen_get"] = leadgen_get

    reply_markup = [
        [text["yes"]],
        [text["cancel"]]
    ]

    markup = ReplyKeyboardMarkup(keyboard=reply_markup, resize_keyboard=True)

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_approve"].format(leadgen_full_name, linkedin, deal_summ, deal_percent, leadgen_get),
        reply_markup=markup
    )

    return States.DEAL_YES_APPROVE

def deal_yes_approve(update: Update, context: CallbackContext):

    chat_id = update.message.chat.id

    context.bot.send_message(
        chat_id=chat_id,
        text=text["deal_yes_admin_thanks"],
    )

    chosen_deal = context.user_data["chosen_deal"]
    deal_summ = context.user_data["deal_summ"]
    deal_percent = context.user_data["deal_percent"]
    leadgen_get = context.user_data["leadgen_get"]
    # print(chosen_deal)
    db_session.deal_done(chosen_deal, leadgen_get)

    context.bot.send_message(
        chat_id=chosen_deal[2],
        text=text["deal_yes_lead_thanks"].format(leadgen_get),
    )
    context.user_data.pop("chosen_deal")
    context.user_data.pop("deal_summ")
    context.user_data.pop("deal_percent")
    context.user_data.pop("leadgen_get")
    return admin(update, context)


# Standard library.
import unittest
from datetime import datetime, timezone, time
import copy

# Third-party installed.
import simplejson as json
import numpy as np
import pandas as pd

# pyvvo
from pyvvo import timeseries
import tests.data_files as _df

# For measurement data, we expect the following to be numeric:
NUMERIC_COLS = ['magnitude', 'angle', 'value']

class ParseTimeseriesMeasurementsTestCase(unittest.TestCase):
    """Test parse_timeseries, and pass it simulation measurements which
    have been created via querying the timeseries database after a
    simulation.
    """

    @classmethod
    def setUpClass(cls):
        # Load measurement data
        with open(_df.ALL_MEAS_13, 'r') as f:
            cls.meas_13 = json.load(f)

        with open(_df.E_CONS_MEAS_9500, 'r') as f:
            cls.e_cons_meas_9500 = json.load(f)

        # HARD-CODING INBOUND:
        # This starttime must match what's in data_files.py where these
        # json files are generated.
        cls.starttime = datetime(2013, 1, 14, 0, 0, tzinfo=timezone.utc)
        # The stoptime is the starttime plus the duration.
        cls.stoptime = datetime(2013, 1, 14, 0, 0, 20, tzinfo=timezone.utc)

    def test_13(self):
        # Parse the data.
        parsed_data = timeseries.parse_timeseries(data=self.meas_13)

        # We should get back as many rows as there are entries in 'data'
        self.assertEqual(len(self.meas_13['data']), parsed_data.shape[0])

        # For the 13 node "all measurements" we'll be getting back
        # mixed types which results in columns which are not used for
        # all the data. Ensure we have NaN's.
        self.assertTrue(
            parsed_data.isna().any().any()
        )

        # Ensure we have the expected columns.
        self.assertSetEqual(
            {'hasSimulationMessageType', 'measurement_mrid', 'simulation_id',
             'angle', 'magnitude', 'value'},
            set(parsed_data.columns.to_list())
        )

        # The NA signature should be identical for angle and magnitude.
        angle_na = parsed_data['angle'].isna()
        mag_na = parsed_data['magnitude'].isna()

        pd.testing.assert_series_equal(angle_na, mag_na,
                                       check_names=False)

        # The NA signature should be exactly opposite for
        # angle/magnitude and value.
        value_na = parsed_data['value'].isna()
        xor = np.logical_xor(angle_na.values, value_na.values)
        self.assertTrue(xor.all())

        # Ensure all our times are in bounds.
        self.assertTrue((parsed_data.index >= self.starttime).all())
        self.assertTrue((parsed_data.index <= self.stoptime).all())

        # Ensure all columns which should be numeric are numeric.
        for c in parsed_data.columns.to_list():
            if c in NUMERIC_COLS:
                self.assertEqual(np.dtype('float'), parsed_data[c].dtype)

    def test_9500(self):
        parsed_data = timeseries.parse_timeseries(data=self.e_cons_meas_9500)
        # For this data, we have 6 measurements because the platform
        # outputs data every 3 seconds, and we ran a 20 second
        # simulation.
        self.assertEqual(6, parsed_data.shape[0])

        # With just one measurement, we shouldn't get any nans.
        self.assertFalse(parsed_data.isna().any().any())

        # Ensure we have the expected columns.
        self.assertListEqual(
            ['hasSimulationMessageType', 'measurement_mrid', 'angle',
             'magnitude', 'simulation_id'],
            parsed_data.columns.to_list()
        )

        # Ensure all our times are in bounds.
        self.assertTrue((parsed_data.index >= self.starttime).all())
        self.assertTrue((parsed_data.index <= self.stoptime).all())

        # Ensure all columns which should be numeric are numeric.
        for c in parsed_data.columns.to_list():
            if c in NUMERIC_COLS:
                self.assertEqual(np.dtype('float'), parsed_data[c].dtype)

    def test_sensor_service_9500(self):
        # Read in data.
        data = []
        for file in _df.SENSOR_MEAS_LIST:
            with open(file, 'r') as f:
                data.append(json.load(f))

        # Parse each dictionary and do some rudimentary tests. Mainly,
        # we're happy if it just parses.
        for d in data:
            parsed = timeseries.parse_timeseries(data=d)

            # Ensure it's a DataFrame.
            self.assertIsInstance(parsed, pd.DataFrame)

            # Ensure we're indexed by time.
            self.assertEqual('time', parsed.index.name)
            self.assertIsInstance(parsed.index[0], datetime)

            # Ensure we have all the expected columns.
            self.assertListEqual(
                ['instance_id', 'hasSimulationMessageType', 'measurement_mrid',
                 'angle', 'magnitude', 'simulation_id'],
                parsed.columns.to_list()
            )

            # Ensure angle and magnitude are floats.
            self.assertEqual(np.dtype('float'), parsed.dtypes['angle'])
            self.assertEqual(np.dtype('float'), parsed.dtypes['magnitude'])

            # The rest of our columns should be objects.
            cols = copy.copy(parsed.columns.to_list())
            cols.remove('angle')
            cols.remove('magnitude')

            for c in cols:
                self.assertEqual(np.dtype('O'), parsed.dtypes[c])

            # TODO: Once
            #   https://github.com/GRIDAPPSD/gridappsd-forum/issues/21#issue-475728176
            #   is addressed, add a length assertion. In data_files.py,
            #   the simulation duration was 300 seconds, and we're
            #   expecting aggregation every 30 seconds, so we should
            #   get 10 records.
            # self.assertEqual(10, parsed.shape[0])

    def test_13_not_indexed_by_time(self):
        """Ensure the index_by_time parameter is working as intended."""
        parsed = timeseries.parse_timeseries(data=self.meas_13,
                                             index_by_time=False)

        # In this case, we should have 'time' as a column rather than
        # the index.
        self.assertIn('time', parsed.columns)

        # Ensure we just have a simple range index.
        self.assertEqual(parsed.index[0], 0)
        self.assertEqual(parsed.index[-1], parsed.shape[0] - 1)

class ParseWeatherTestCase(unittest.TestCase):
    """Test parse_weather"""

    @classmethod
    def setUpClass(cls):
        # Load the simple weather data dictionary.
        with open(_df.WEATHER_SIMPLE_JSON, 'r') as f:
            cls.weather_simple = json.load(f)

        # Create the expected DataFrame.
        # Weather data starts at 2013-01-01 00:00:00 UTC.
        dt = _df.WEATHER_SIMPLE_START
        dt_index = pd.to_datetime([dt], utc=True)

        # Expected data.
        temp = 13.244
        ghi = -0.0506534463

        # Create expected DataFrame.
        cls.weather_simple_expected = \
            pd.DataFrame([[temp, ghi]], index=dt_index,
                         columns=['temperature', 'ghi'])

        cls.weather_simple_expected.index.name = 'time'

        # Create an entry with two rows.
        cls.weather_two = copy.deepcopy(cls.weather_simple)

        row = copy.deepcopy(cls.weather_two['data'][0])

        cls.weather_two['data'].append(row)

        # Create the expected return for the two-row case.
        dt_index_two = pd.to_datetime([dt, dt], utc=True)
        cls.weather_two_expected = \
            pd.DataFrame([[temp, ghi], [temp, ghi]], index=dt_index_two,
                         columns=['temperature', 'ghi'])
        cls.weather_two_expected.index.name = 'time'

    def test_parse_weather_bad_input_type(self):
        self.assertRaises(TypeError, timeseries.parse_weather, 10)

    # noinspection PyMethodMayBeStatic
    def test_parse_weather_weather_simple_json(self):
        """Load weather_simple.json, ensure result matches."""

        # Parse the data.
        actual = timeseries.parse_weather(self.weather_simple)

        # Ensure actual and expected results are equal.
        pd.testing.assert_frame_equal(actual, self.weather_simple_expected)

    def test_parse_weather_no_temperature(self):
        # Get a copy of the data.
        data = copy.deepcopy(self.weather_simple)

        # Remove temperature
        del data['data'][0]['TowerDryBulbTemp']

        self.assertRaises(KeyError, timeseries.parse_weather, data)

    def test_parse_weather_no_ghi(self):
        # Get a copy of the data.
        data = copy.deepcopy(self.weather_simple)

        # Remove ghi
        del data['data'][0]['GlobalCM22']

        self.assertRaises(KeyError, timeseries.parse_weather, data)

    def test_parse_weather_no_time(self):
        # Get a copy of the data.
        data = copy.deepcopy(self.weather_simple)

        # Remove time
        del data['data'][0]['time']

        self.assertRaises(KeyError, timeseries.parse_weather, data)

    def test_parse_weather_data_no_wind(self):
        """We aren't using wind speed, so there should be no problem."""
        # Get a copy of the data.
        data = copy.deepcopy(self.weather_simple)

        # Remove average wind speed
        del data['data'][0]['AvgWindSpeed']

        # We should not get a ValueError.
        # noinspection PyBroadException
        try:
            timeseries.parse_weather(data)
        except Exception:
            m = ('An exception was raised when parsing simple weather without '
                 'AvgWindSpeed')
            self.fail(m)

    def test_parse_weather_two(self):
        """Check the two-row case."""
        actual = timeseries.parse_weather(self.weather_two)
        pd.testing.assert_frame_equal(actual, self.weather_two_expected)

    def test_parse_weather_two_missing_temperature(self):
        """Delete one temperature entry from the two-row case."""
        data = copy.deepcopy(self.weather_two)

        # Remove a temperature entry.
        del data['data'][1]['TowerDryBulbTemp']

        actual = timeseries.parse_weather(data)

        # We'll have a NaN.
        self.assertTrue(actual['temperature'].isna().any())

    def test_parse_weather_two_missing_ghi(self):
        """Delete one ghi entry from the two-row case."""
        data = copy.deepcopy(self.weather_two)

        # Remove a ghi entry.
        del data['data'][0]['GlobalCM22']

        actual = timeseries.parse_weather(data)

        # We'll have a NaN.
        self.assertTrue(actual['ghi'].isna().any())

    def test_parse_weather_two_missing_time(self):
        """Delete one time entry from the two-row case."""
        data = copy.deepcopy(self.weather_two)

        # Remove a time entry.
        del data['data'][0]['time']

        actual = timeseries.parse_weather(data)

        # We'll have a NaN in the Index.
        self.assertTrue(actual.index.isna().any())

class ResampleTimeSeriesTestCase(unittest.TestCase):
    """Test resample_timeseries function."""

    @classmethod
    def setUpClass(cls):
        """Create a DataFrame for resampling."""
        dt_index = pd.date_range(start=datetime(2019, 1, 1, 0, 1), periods=15,
                                 freq='1Min')

        # Create a temperature array with an average of 2.
        temp = [1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3]

        # Create ghi array with an average of 3.
        ghi = [2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4, 2, 3, 4]

        # Create DataFrame.
        cls.weather_data = pd.DataFrame({'temperature': temp, 'ghi': ghi},
                                        index=dt_index)

        # Create expected data.
        dt_index_2 = pd.date_range(start=datetime(2019, 1, 1, 0, 15), periods=1,
                                   freq='15Min')
        cls.expected_data = pd.DataFrame({'temperature': [2], 'ghi': [3]},
                                         index=dt_index_2)

    def test_resample_weather_bad_weather_data_type(self):
        self.assertRaises(TypeError, timeseries.resample_timeseries,
                          weather_data={'temp': [1, 2, 3]},
                          interval_str='15Min')

    def test_resample_weather_15_min_downsample(self):
        """Resample at 15 minute intervals."""
        actual = timeseries.resample_timeseries(ts=self.weather_data,
                                                interval_str='15Min')

        pd.testing.assert_frame_equal(actual, self.expected_data)

    # noinspection PyMethodMayBeStatic
    def test_resample_upsample(self):
        a = [1, 2, 3, 4, 5]
        b = [11, 12, 13, 14, 15]
        dt_index = pd.date_range(start=datetime(2019, 1, 1, 0, 1), periods=5,
                                 freq='2Min')

        to_resample = pd.DataFrame({'a': a, 'b': b}, index=dt_index)
        a2 = [1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5]
        b2 = [11, 11.5, 12, 12.5, 13, 13.5, 14, 14.5, 15]
        r_index = pd.date_range(start=datetime(2019, 1, 1, 0, 1), periods=9,
                                freq='1Min')
        expected = pd.DataFrame({'a': a2, 'b': b2}, index=r_index)

        actual = timeseries.resample_timeseries(ts=to_resample,
                                                interval_str='1Min')

        pd.testing.assert_frame_equal(actual, expected)

    def test_resample_same_freq(self):
        a = [1, 2, 3, 4, 5]
        i = pd.date_range(start=datetime(2019, 1, 1, 0, 1), periods=5,
                          freq='1Min')
        s = pd.Series(a, index=i)
        with self.assertLogs(logger=timeseries.LOG, level='WARNING'):
            s2 = timeseries.resample_timeseries(s, '1Min')

        self.assertIs(s, s2)

    def test_bad_method(self):
        with self.assertRaisesRegex(ValueError, 'method must be either'):
            timeseries.resample_timeseries(ts=pd.Series([1, 2, 3]),
                                           interval_str='20Min',
                                           method='bad_method')

class UpOrDownSampleTestCase(unittest.TestCase):
    def test_upsample(self):
        self.assertEqual(
            'upsample',
            timeseries.up_or_down_sample(orig_interval='10Min',
                                         new_interval='1Min')
        )

    def test_downsample(self):
        self.assertEqual(
            'downsample',
            timeseries.up_or_down_sample(orig_interval='1Min',
                                         new_interval='10Min')
        )

    def test_none(self):
        self.assertIsNone(timeseries.up_or_down_sample(orig_interval='1Min',
                                                       new_interval='T'))

class FixGHITestCase(unittest.TestCase):
    """Test fix_ghi"""

    def test_fix_ghi_bad_weather_data_type(self):
        self.assertRaises(TypeError, timeseries.fix_ghi, weather_data=pd.Series())

    # noinspection PyMethodMayBeStatic
    def test_fix_ghi(self):
        """Simple test."""
        temperature = [1, -1, 10]
        ghi_neg = [0.0001, -0.2, 7]
        ghi_pos = [0.0001, 0, 7]
        df_original = pd.DataFrame({'temperature': temperature,
                                    'ghi': ghi_neg})
        df_expected = pd.DataFrame({'temperature': temperature,
                                    'ghi': ghi_pos})

        df_actual = timeseries.fix_ghi(df_original)

        pd.testing.assert_frame_equal(df_expected, df_actual)

class FilterByTimeAndFilterByDayTestCase(unittest.TestCase):
    """Test filter_by_time, filter_by_day_of_week, filter_by_weekday,
    and filter_by_weekend.
    """

    @classmethod
    def setUpClass(cls):
        """Read our two week weather file."""
        cls.w = pd.read_csv(_df.WEATHER_TWO_WEEK, index_col='time',
                            parse_dates=True)

    def test_filter_hour_and_a_half(self):
        """Filter such that we get times from 11:30 a.m. to 12:30 p.m.
        """
        out = timeseries.filter_by_time(data=self.w, t_start=time(11, 30),
                                        t_end=time(12, 30))

        # Ensure all hours are in range.
        self.assertTrue((out.index.time <= time(12, 30)).all())
        self.assertTrue((out.index.time >= time(11, 30)).all())

    def test_filter_by_day_of_week(self):
        """Simple test """
        out = timeseries._filter_by_day_of_week(data=self.w,
                                                day_start=3, day_end=5)

        self.assertTrue((out.index.dayofweek >= 3).all())
        self.assertTrue((out.index.dayofweek <= 5).all())

    def test_filter_by_weekdays(self):
        out = timeseries.filter_by_weekday(data=self.w)

        self.assertTrue((out.index.dayofweek >= 0).all())
        self.assertTrue((out.index.dayofweek <= 4).all())

    def test_filter_by_weekend(self):
        out = timeseries.filter_by_weekend(data=self.w)

        self.assertTrue((out.index.dayofweek >= 5).all())
        self.assertTrue((out.index.dayofweek <= 6).all())

class IsWeekdayTestCase(unittest.TestCase):
    """Test is_weekday"""

    def test_mon(self):
        dt = datetime(2019, 8, 12, 0, 0)
        self.assertTrue(timeseries.is_weekday(dt))

    def test_tue(self):
        dt = datetime(2019, 8, 13, 0, 0)
        self.assertTrue(timeseries.is_weekday(dt))

    def test_wed(self):
        dt = datetime(2019, 8, 14, 0, 0)
        self.assertTrue(timeseries.is_weekday(dt))

    def test_thur(self):
        dt = datetime(2019, 8, 15, 0, 0)
        self.assertTrue(timeseries.is_weekday(dt))

    def test_fri(self):
        dt = datetime(2019, 8, 16, 0, 0)
        self.assertTrue(timeseries.is_weekday(dt))

    def test_sat(self):
        dt = datetime(2019, 8, 17, 0, 0)
        self.assertFalse(timeseries.is_weekday(dt))

    def test_sun(self):
        dt = datetime(2019, 8, 18, 0, 0)
        self.assertFalse(timeseries.is_weekday(dt))

if __name__ == '__main__':
    unittest.main()


#Aqui começa a Etapa 1

import math
import matplotlib.pyplot as plt

def evoluir_populacao_cenouras(Pce, Rce, Pcemax, Mce, Pco):
    """Calcula o crescimento de Cenouras
    Requires: Pce,Rce,Pcemax,Mce,Pco que sejam inteiros e onde Pcemax não pode ser zero
    Ensures: O número de cenouras depois de um mês
    """
    PceAfter = Pce + Rce * Pce * (1 - (Pce / Pcemax)) - (Mce * Pco)
    return round(PceAfter)

#Aqui começa a Etapa 2
def evoluir_populacao_coelhos(Pco, Pce, Mce, Pcomax, Mco, Plo):
    """Calcula o aumento da população de coelhos
    Requires: Pco,Pce,Mce,Pcomax,Mco,Plo que sejam inteiros onde Mce, Pco e Pcomax não podem ser igual a zero
    Ensures: O número de coelhos depois de um mês
    """
    Nco = Pce / (Mce * Pco)
    PcoAfter = Pco + Nco * (1 - (Pco / Pcomax)) - (Mco * Plo)
    return round(PcoAfter)

#Aqui começa a Etapa 3
def evoluir_populacao_lobos(Plo, Pco, Mco, Plomax, Mlo):
    """Calcula o aumento da população de lobos
    Requires: Pco,Mlo,Plomax,Mco,Plo que sejam inteiros onde Mco, Plo e Plomax não podem ser igual a zero
    Ensures: O número de lobos depois de um mês
    """
    Nlo = Pco / (Mco * Plo)
    PloAfter = Plo + Nlo * (1 - (Plo / Plomax)) - (Mlo * Plo)
    return round(PloAfter)

#Aqui começa a Etapa 4
def simular_populacoes(num_meses, param, t):
    """ Calcula o número Cenouras Coelhos e Lobos após Um número de meses inserido pelo utilizador
    Requires: num_meses que deve ser um inteiro positivo, e um dicionário que contem as variáveis necessárias p'ra as fun~es utilizadas p'ra calcular o número de seres vivos
    Ensures: A string com o número de meses e os respectivos números de cada espéciede ser vivo.E depois 3 listas em que cada lista contem a quantidade em cada mês de cada espécie de ser vivo, as listas são respectivamente de Cenouras, Coelhos e Lobos.
    """
    Rce = int(param["Rce"])
    PceMax = int(param["Pcemax"])
    Mce = int(param["Mce"])
    PcoMax = int(param["Pcomax"])
    Mco = int(param["Mco"])
    PloMax = int(param["Plomax"])
    Mlo = int(param["Mlo"])

    listaPce = []
    listaPco = []
    listaPlo = []

    if t == 0:
        print('Mês {} : {} cenouras, {} coelhos, {} lobos'.format(0, param["Pce0"], param["Pco0"], param["Plo0"]))

    for It in range(0, t + num_meses + 1):
        PopCe = param.get("Pce" + str(It), None)
        PopCo = param.get("Pco" + str(It), None)
        PopLo = param.get("Plo" + str(It), None)
        if PopCe == None or PopCo == None or PopLo == None:
            # Cria dados para mes = It
            AntPopCe = int(param["Pce" + str(It - 1)])
            AntPopCo = int(param["Pco" + str(It - 1)])
            AntPopLo = int(param["Plo" + str(It - 1)])
            PopCe = evoluir_populacao_cenouras(AntPopCe, Rce, PceMax, Mce, AntPopCo)
            PopCo = evoluir_populacao_coelhos(AntPopCo, AntPopCe, Mce, PcoMax, Mco, AntPopLo)
            PopLo = evoluir_populacao_lobos(AntPopLo, AntPopCo, Mco, PloMax, Mlo)
            param["Pce" + str(It)] = PopCe
            param["Pco" + str(It)] = PopCo
            param["Plo" + str(It)] = PopLo
            print('Mês {} : {} cenouras, {} coelhos, {} lobos'.format(It, PopCe, PopCo, PopLo))
        listaPce.append(int(PopCe))
        listaPco.append(int(PopCo))
        listaPlo.append(int(PopLo))

    return listaPce, listaPco, listaPlo

#Aqui começa a Etapa 5
def menu():
    """Através do input que pede ao utilizador simula o crescimento da população ou mostra um gráfico de uma espécie que o utilizador escolhe
    Requires: A função não requer quaisquer parâmetros
    Ensures: Calcula o número de cada espécie apôs um número específico de meses introduzido pelo utilizador ou constroí um gráfico com a evolução do ser vivo escolhido pelo utilizador do mês zero até ao mês introduzido pelo utilizador
    """
    print('(s)imular, (d)esenhar gráfico')
    Resposta = input()
    Resposta = Resposta.lower()
    if Resposta == 's':
        return simular()
    elif Resposta == 'd':
        return draw()
    elif Resposta == 'q':
        return Resposta
    else:
        print('Caracter inválido!')
        return menu()

#Aqui começa a Etapa 6
def obter_parametros(nome_ficheiro):
    """Constroí um dicionário com as variáveis que estão apresentadas no ficheiro (nome_ficheiro)
    Requires: O ficheiro (nome_ficheiro) que contem as variáveis necessárias à função simular_populacoes (num_meses,param)
    Ensures:Um dicionário com o nome das variáveis como chave e como valor a quantidade numérica da respectiva variável que tem como chave
    """
    ficheiro = open(nome_ficheiro, 'r')
    parametros = {}
    nome = []
    valor = []
    for linha in ficheiro:
        n,v = linha.split('=')
        nome.append(n.strip())
        valor.append(eval(v.strip()))
    for i in range(0, len(nome)):
        parametros.update({nome[i]:valor[i]})
    return parametros

#Aqui começa a Etapa 7
def simulador(nome_ficheiro):
    """Simula o crescimento das espécies de seres vivos do ecosistema
    Requires: Um ficheiro (nome_ficheiro) com as variáveis necessárias p'ra simular cada espécie
    Ensures: Uma string com o mês e o número de cada ser vivo p'ra cada espécie e em cada mês
    """
    parametros = obter_parametros(nome_ficheiro)
    mesAtual = 0
    Op = menu()
    while Op != 'q':
        if Op == 'c':
            grafico_populacao(mesAtual, parametros, 0)
        elif Op == 'r':
            grafico_populacao(mesAtual, parametros, 1)
        elif Op == 'w':
            grafico_populacao(mesAtual, parametros, 2)
        elif Op.isdigit():
            simular_populacoes(int(Op), parametros, mesAtual)
            mesAtual += int(Op)
        Op = menu()
    listasGuardar = simular_populacoes(mesAtual, parametros, 0)
    gravar_resultado_simulacao('resultados.csv', listasGuardar[0], listasGuardar[1], listasGuardar[2])
    print('Simulador Terminado')

def simular():
    print('Quantos meses pretende simular?')
    sims = input()
    sims = sims.lower()
    if sims == 'q' or (sims.isdigit() and int(sims) > 0):
        return sims
    elif sims == 'a':
        return menu()
    else:
        print('Caracter inválido!')
        return simular()

def draw():
    print('Qual a população que deseja representar?')
    print('C -> cenouras, R -> coelhos, W -> lobos')
    resposta = input()
    resposta = resposta.lower()
    if resposta == 'q' or resposta == 'c' or resposta == 'r' or resposta == 'w':
        return resposta
    elif resposta == 'a':
        return menu()
    else:
        print('Caracter inválido!')
        return draw()

def grafico_populacao(meses, parametros, pop_indice):
    lista = simular_populacoes(meses, parametros, 0)[pop_indice]
    descricao = 'Número de '
    color = ''
    if pop_indice == 0:
        descricao += "Cenouras"
        color = 'orange'
    elif pop_indice == 1:
        descricao += "Coelhos"
        color = 'c'
    elif pop_indice == 2:
        descricao += "Lobos"
        color = 'b'

    plt.plot(lista, linestyle='-', marker='o', color = color)
    plt.xlabel('Número de Meses')
    plt.ylabel(descricao)
    plt.title('Simulação de Ecossistema')
    plt.show()

#Aqui começa a Etapa 9
def gravar_resultado_simulacao(nome_ficheiro, lista_pop_cenouras, lista_pop_coelhos, lista_pop_lobos):
    """Grava os resultados do número de cada ser vivo em cada mês num formato(.csv)
    Requires:Um ficheiro (nome_ficheiro), uma lista com o número de cenouras em cada mês em que é efectuado a simulação(lista_pop_cenouras),uma lista com o número de coelhos em cada mês em que é efectuado a simulação(lista_pop_coelhos),uma lista com o número de lobos em cada mês em que é efectuado a simulação(lista_pop_lobos)
    Ensures: Um ficheiro .csv com cada mês e o respectivo número de cada ser vivo
    """
    ResFich = open(nome_ficheiro, 'w')
    for mes in range(0, len(lista_pop_lobos)):
        ResFich.write('{};{};{};{}\n'.format(mes, lista_pop_cenouras[mes], lista_pop_coelhos[mes], lista_pop_lobos[mes]))

simulador("configuracao.txt")


import datetime as datetime
import os
import warnings

import numpy as np
import pandas as pd
import statsmodels.api as sm
import yfinance as yf
from scipy.stats import multivariate_normal, norm, t

warnings.filterwarnings("ignore")
from math import *

from arch import arch_model
from pypfopt import HRPOpt, risk_models
from pypfopt.efficient_frontier import EfficientFrontier
from scipy.optimize import minimize
from sklearn.decomposition import PCA

# from maxt import multskewt

os.chdir("/home/sahil/diss")
k = pd.read_csv("djia.csv")
# Convert string to datetime datatype consisting of only dates and not time
k["Date"] = pd.to_datetime(k.Date).apply(lambda x: x.date())

def multivariate_t_distribution(x, mu, Sigma, df, d):
    """
    Multivariate t-student density:
    output:
        the density of the given element
    input:
        x = parameter (d dimensional numpy array or scalar)
        mu = mean (d dimensional numpy array or scalar)
        Sigma = scale matrix (dxd numpy array)
        df = degrees of freedom
        d: dimension
    """
    Num = gamma(1.0 * (d + df) / 2)
    Denom = (
        gamma(1.0 * df / 2)
        * pow(df * pi, 1.0 * d / 2)
        * pow(np.linalg.det(Sigma), 1.0 / 2)
        * pow(
            1
            + (1.0 / df)
            * np.dot(np.dot((x - mu), np.linalg.inv(Sigma)), (x - mu)),
            1.0 * (d + df) / 2,
        )
    )
    d = 1.0 * Num / Denom
    return d

def likelihood_skew_t(y, alpha, beta, omega, skew, v, init_vol):
    # Dimension of data
    d = y.shape[1]

    def minimizer(params):
        v = params[120]
        loglike = []
        for j in range(d):
            vol = [init_vol[j]]
            for i in range(1, len(y)):
                alpha = params[j]
                beta = params[30 + j]
                omega = params[60 + j]
                skew = params[90 + j]
                cond_vol = beta * vol[i - 1] + alpha * y[i - 1][j] ** 2 + omega
                if (alpha + beta > 1) and omega < 0:
                    return 1000
                if cond_vol <= 0:
                    return 1000
                vol.append(cond_vol)
                pdf = np.float(
                    multskewt(
                        y[i],
                        0,
                        cond_vol,
                        skew,
                        v,
                    )
                )

                loglike.append(-np.log(pdf))
        return np.array(loglike).mean()

    res = minimize(
        minimizer,
        alpha + beta + omega + skew + [v],
        method="nelder-mead",
        bounds=((0.01, 1),) * 60
        + ((0.005, 1),) * 30
        + ((-1, 1),) * 30
        + ((2.1, 100)),
        tol=1e-6,
    )
    return res

def gen_ret(df):
    assets = [
        i for i in df.columns if i != "Date"
    ]  # Extracting Column names of all assets

    for asset in assets:
        df[asset + "_logret"] = (
            np.log(df[asset] / df[asset].shift(1)) * 100
        )  # Calculating log returns for an asset
        # df[asset + "_perret"] = (
        #    df[asset].pct_change() * 100
        # )  # Calculating percentage Returns for an asset
    # perret_cols = [i for i in df.columns if "_perret" in i]
    return df

def cov_est(pvar, w, lamb):
    # var = np.diag(list(pvar[0:3]))
    # # var = np.diag(pvar[0:3])
    # w_trans = w[3:]
    # w_left = w[:][3:]

    return w.T * np.diag(pvar) * w

def predict(y, omega, alpha, beta):
    y = np.array(y)
    vol = [0]
    for i in range(1, len(y)):
        cond_vol = beta * vol[i - 1] + alpha * y[i - 1] ** 2 + omega
        vol.append(cond_vol)
    return vol

k = gen_ret(k)
k = k.dropna()
lnret = [i for i in k.columns if "_logret" in i]

pca = PCA(n_components=len(lnret))
krets = k[lnret + ["Date"]]
ktrain = krets[krets.Date < datetime.date(2019, 6, 1)]
ktest = krets[krets.Date > datetime.date(2019, 6, 1)]
# Store lenght of training set
tlen = len(ktrain)
# Column names of principal components
pcols = ["p" + str(i + 1) for i in range(29)]
# Column names of Garch volatility of principal components
pcolsvar = [f"p{i+1}_vol" for i in range(29)]
# Extract the principal components from train set and
# do the transformation on the entire set using eigenvectors
# obtained from the training set
pca = pca.fit(ktrain[lnret])
k[pcols] = pca.transform(k[lnret])
ktrain[pcols] = k[pcols].iloc[0:tlen]
ktest[pcols] = k[pcols].iloc[tlen:]
# Extract the eigenvectors
w = np.matrix(pca.components_)
# Get the eigenvalues
lamb = pca.explained_variance_
loglike = 0
for i in range(29):
    model = arch_model(
        ktrain[pcols[i]],
        mean="Zero",
        vol="GARCH",
        p=1,
        o=0,
        q=1,
    )
    mod = model.fit()
    loglike = loglike + mod.loglikelihood
    ktrain[pcolsvar[i]] = mod.conditional_volatility ** 2
    alpha = mod.params["alpha[1]"]
    beta = mod.params["beta[1]"]
    omega = mod.params["omega"]
    preds = predict(k[pcols[i]], omega, alpha, beta)
    k[pcolsvar[i]] = preds
    ktrain[f"{pcolsvar[i]}_nonlib"] = preds[:tlen]
    ktest[pcolsvar[i]] = preds[tlen:]
print(f"Normal Loglikelihood={loglike/(len(ktrain))}")
# Extracting time varying covariance matrix

k["cov_t"] = k[pcolsvar].apply(lambda row: cov_est(row, w, lamb), axis=1)

# Save for further processing
k.to_pickle("returns_pca.pkl")

ktrain["cov_t"] = ktrain[pcolsvar].apply(
    lambda row: cov_est(row, w, lamb), axis=1
)

ktest["cov_t"] = ktest[pcolsvar].apply(
    lambda row: cov_est(row, w, lamb), axis=1
)

ktrain["log_t"] = ktrain.apply(
    lambda row: multivariate_normal.logpdf(
        row[lnret], [0] * len(pcols), row["cov_t"]
    ),
    axis=1,
)
ktest["log_t"] = ktest.apply(
    lambda row: multivariate_normal.logpdf(
        row[lnret], [0] * len(pcols), row["cov_t"]
    ),
    axis=1,
)

v = 8.9
ktrain["log_t_tdist"] = ktrain.apply(
    lambda row: np.log(
        multivariate_t_distribution(
            row[lnret],
            [0] * len(pcols),
            row["cov_t"],
            v,
            len(pcols),
        )
    ),
    axis=1,
)
ktest["log_t_tdist"] = ktest.apply(
    lambda row: np.log(
        multivariate_t_distribution(
            row[lnret],
            [0] * len(pcols),
            row["cov_t"],
            v,
            len(pcols),
        )
    ),
    axis=1,
)

print(ktrain.log_t.mean())
print(ktrain.log_t_tdist.mean())


"""
Program:
--------
    AsciiCat - Homework 3

Description:
------------
    This program grabs a picture of a cat from the internet, converts it
    to an ascii image, and then inverts the colors

Name: Zachary Maughan
Date: 3 March 2016
"""
import os
import time
import urllib3, uuid
from PIL import Image
import sys

url = 'http://thecatapi.com/api/images/get'

"""
    @Description:
        This meathod retrieves the cat picture from the internet.
    @Params:
        directory - Where the picture will be stored
        filename - The name that the picture will be stored under.
        format - The filetype the picture will be stored as.
    @Returns:
        (savefile) - The picture that was retrieved.
    """

def getCat(directory=None, filename=None, format='png'):
    basename = '%s.%s' % (filename if filename else str(uuid.uuid4()), format)
    savefile =  os.path.sep.join([directory.rstrip(os.path.sep), basename]) if directory else basename
    downloadlink = url + '?type=%s' % format
    http = urllib3.PoolManager()
    r = http.request('GET', downloadlink)
    fp = open(savefile, 'wb')
    fp.write(r.data)
    fp.close()
    return savefile

"""
@Class: RandomCat
@Usage:
    getImage() - Will pull a random cat picture from the internet.

@Description:
    This class handles retrieving the picture.
@Params:
    none

@Methods:
    getImage - Pulls a random cat picture from the internet.
"""

class RandomCat(object):

    def __init__(self):

        self.name = ''          # name of image
        self.path = '.'         # path on local file system
        self.format = 'png'
        self.width = 0          # width of image
        self.height = 0         # height of image
        self.img = None         # Pillow var to hold image

    """
    @Description:
    - Uses random cat to go get an amazing image from the internet
    - Prompts the user to name the image
    - Saves the image to some location
    @Returns:
    """
    def getImage(self):
        self.name = input('What do you want to name this image? ')
        os.system('cls')
        getCat(directory=self.path, filename=self.name, format=self.format)
        self.img = Image.open(self.name+'.'+self.format)

        self.width, self.heigth = self.img.size

"""
@Class: AsciiImage
@Usage:
    AsciiImage(50)      #creates a preset ready for the cat image.
    AsciiImage()        #will accept the image and leave the size unchanged.

@Description:
    This class handles the manipulation of the image by converting it to ascii,
    inverting the brightness, flipping the image vertically or horizontally, and
    printing the image.
@Params:
    new_Width   - (int) the width of the image or Not_Set.

@Methods:
    convertToAscii - This method will convert the image first into greyscale, and then into ascii.

    flip - This method will flip an image horizontally, or vertically.
        Usage - flip(vertical) = will flip the image vertically
                flip(horizontal) = will flip the image horizontally

    listToMatrix - Converts to 2D list of lists to help with manipulating the ascii image.

    printImage - This method will print the ascii picture in a coherent way.
"""

class AsciiImage(RandomCat):

    def __init__(self,new_width="not_set"):
        super(AsciiImage, self).__init__()

        self.newWidth = new_width
        self.newHeight = 0

        self.asciiChars = [ '#', 'A', '@', '%', 'S', '+', '<', '*', ':', ',', '.']
        self.imageAsAscii = []
        self.matrix = None

    """
    @Name: convertToAscii
    @Description:
        This method will convert the image first into greyscale, and then into ascii.
    @Params: none
    @Returns:
    """
    def convertToAscii(self):

        if self.newWidth == "not_set":
            self.newWidth = self.width

        self.newHeight = int((self.heigth * self.newWidth) / self.width)

        if self.newWidth == None:
            self.newWidth = self.width
            self.newHeight = self.height

        self.newImage = self.img.resize((self.newWidth, self.newHeight))
        self.newImage = self.newImage.convert("L") # convert to grayscale
        all_pixels = list(self.newImage.getdata())
        self.matrix = listToMatrix(all_pixels,self.newWidth)

        for pixel_value in all_pixels:
            index = pixel_value // 25 # 0 - 10
            self.imageAsAscii.append(self.asciiChars[index])

    """
    @Name: flip
    @Description:
        This method will flip an image horizontally, or vertically.
    @Params: direction (string) - [horizontal,vertical] The direction to flip the cat.
    @Returns: (string) - Flipped ascii image.
    """
    def flip(self, way = 'none'):
        temp = []
        all_pixels = list(self.newImage.getdata())
        if way == 'vertical':
            while len(temp) <= len(self.imageAsAscii):
                for a in range(self.newHeight - 1, 0, -1):
                    for b in range(0, self.newWidth):
                        temp.append(self.imageAsAscii[(a * self.newWidth) + b])
        elif way == 'horizontal':
            while len(temp) <= len(self.imageAsAscii):
                for a in range(0, self.newHeight):
                    for b in range(self.newWidth, 0, -1):
                        temp.append(self.imageAsAscii[(a * self.newWidth - 1) + b])
        self.imageAsAscii = []
        self.imageAsAscii = temp

    """
    @Name: invert
    @Description:
        This method will invert the ascii characters from dark to light, and vice-versa.
    @Params: None
    @Returns: (string) - Inverted ascii image.
    """
    def invert(self):
        self.imageAsAscii = []
        all_pixels = list(self.newImage.getdata())
        for pixel_value in all_pixels:
            index = 10 - pixel_value // 25 # 0 - 10
            self.imageAsAscii.append(self.asciiChars[index])

    """
    Converts to 2D list of lists to help with manipulating the ascii image.
    """
    def listToMatrix(l, n):
        return [l[i:i+n] for i in range(0, len(l), n)]
        """
    @Name: printImage
    @Description:
        This method will print the ascii picture in a coherent way.
    @Params: none
    @Returns: prints image to screen
    """
    def printImage(self):
        self.imageAsAscii = ''.join(ch for ch in self.imageAsAscii)
        for c in range(0, len(self.imageAsAscii), self.newWidth):
            print (self.imageAsAscii[c:c+self.newWidth])

if __name__=='__main__':
    awesomeCat = AsciiImage(75)
    awesomeCat.getImage()

    awesomeCat.convertToAscii()
    awesomeCat.printImage()
    awesomeCat.invert()
    awesomeCat.printImage()


from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
    path('signup/', views.signupuser, name="signupuser"),
    path('logout/', views.logoutuser, name="logoutuser"),
    path('login/', views.loginuser, name="loginuser"),
    path('current/', views.currenttodos, name="currenttodos"),
    path('create/', views.createtodo, name="createtodo"),
    path('todo/<int:todo_pk>/', views.viewtodo, name="viewtodo"),

]


from torch.utils.data import Dataset, DataLoader
import os
import nibabel as nib
import numpy as np
import torchvision.transforms as transforms

class NiftiDataset(Dataset):
    '''
    Dataset designed for Nifti files
    '''
    def __init__(self, root, labels=True, nifti=False, transform=None, target_transform=None, ):
        '''

        :param root: Data path
        :param labels: Whether labels are there
        :param nifti: Whether return nifti files' name
        :param transform:
        :param target_transform:
        '''
        self.root = root
        self.nifti = nifti
        self.anat_list = [i for i in os.listdir(root) if 'anat' in i]
        self.anat_list.sort()
        self.lesion_list = [i for i in os.listdir(root) if 'lesion' in i]
        self.lesion_list.sort()
        self.labels = labels
        self.transform = transform
        self.target_transform = target_transform
        self.data = []

    def __getitem__(self, index):
        anat_file = self.anat_list[index]
        patient = nib.load(os.path.join(self.root, anat_file))
        if self.nifti:
            filename = anat_file
        # Load image data from patient. axis is C, Y, X, Z, dtype=float64
        img = np.expand_dims(a=patient.get_fdata(), axis=0).astype(np.float32)
        if self.labels:
            lesion_file = self.lesion_list[index]
            assert anat_file[:anat_file.find('.')] == lesion_file[
                                                      :lesion_file.find('.')]
            target = nib.load(os.path.join(self.root, lesion_file)).get_fdata().astype(np.int64)
        else:
            target = None

        if self.transform is not None:
            img = self.transform(img)

        if self.target_transform is not None:
            target = self.target_transform(target)

        if self.labels:
            return img, target
        else:
            if self.nifti:
                return img, filename
            else:
                return img

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

class Brats19Dataset(Dataset):
    '''
    Dataset designed for Nifti files
    '''
    def __init__(self, root, patient_list=None, labels=True, nifti=False, transform=None, target_transform=None, ):
        '''

        :param root: Data path
        :param labels: Whether labels are there
        :param nifti: Whether return nifti files' name
        :param transform:
        :param target_transform:
        '''
        self.root = root
        self.nifti = nifti
        self.t1_list = [i + '_t1.nii.gz' for i in patient_list]
        self.t1ce_list = [i + '_t1ce.nii.gz' for i in patient_list]
        self.t2_list = [i + '_t2.nii.gz' for i in patient_list]
        self.flair_list = [i + '_flair.nii.gz' for i in patient_list]

        self.lesion_list = [i + '_seg.nii.gz' for i in patient_list]

        self.labels = labels
        self.transform = transform
        self.target_transform = target_transform
        self.data = []

    def __getitem__(self, index):
        t1_file = self.t1_list[index]
        t1 = nib.load(os.path.join(self.root, t1_file))
        t1ce_file = self.t1ce_list[index]
        t1ce = nib.load(os.path.join(self.root, t1ce_file))
        t2_file = self.t2_list[index]
        t2 = nib.load(os.path.join(self.root, t2_file))
        flair_file = self.flair_list[index]
        flair = nib.load(os.path.join(self.root, flair_file))
        if self.nifti:
            filename = t1_file
        # Load image data from patient. axis is C, Y, X, Z, dtype=float64
        img = np.concatenate([np.expand_dims(a=t1.get_fdata(), axis=0).astype(np.float32),
                              np.expand_dims(a=t1ce.get_fdata(), axis=0).astype(np.float32),
                              np.expand_dims(a=t2.get_fdata(), axis=0).astype(np.float32),
                              np.expand_dims(a=flair.get_fdata(), axis=0).astype(np.float32),
                              ], axis=0)
        if self.labels:
            lesion_file = self.lesion_list[index]
            # assert anat_file[:10] == lesion_file[:10]
            target = nib.load(os.path.join(self.root, lesion_file)).get_fdata().astype(np.int64)
            # target[img.sum(axis=0) == 0] = 3
            # target_ = np.zeros_like(target)
            target = (target != 0).astype(np.int64)  # WT
            # target = (target == 4 ).astype(np.int64)  # ET
            # target = (target == 4).astype(np.int64) + (target == 2).astype(np.int64)  # TC
        else:
            target = None

        if self.transform is not None:
            img = self.transform(img)

        if self.target_transform is not None:
            target = self.target_transform(target)

        if self.labels:
            return img, target
        else:
            if self.nifti:
                return img, filename
            else:
                return img

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

class Normalize(object):
    def __init__(self, view='all'):
        if view == 'XY':
            self.axes = (1, 2)
        elif view == 'ZX':
            self.axes = (2, 3)
        elif view == 'ZY':
            self.axes = (1, 3)
        elif view == 'all':
            self.axes = (1, 2, 3)
        else:
            raise TypeError

    def __call__(self, data):
        assert len(data.shape) == 4
        mean = data.mean(axis=self.axes, keepdims=True)
        std = data.std(axis=self.axes, keepdims=True)
        new_data = (data - mean) / (std + 0.000001)

        return new_data

class CropAndPad(object):
    def __init__(self, format_='Brats19', target='data'):
        if format_ == 'Brats19':
            self.target = target
            if self.target == 'data':
                self.shape = (4, 160, 192, 160)
            elif self.target == 'label':
                self.shape = (160, 192, 160)
            self.xstart = 38
            self.xend = 198  # 160 in 0' axis
            self.ystart = 28
            self.yend = 220  # 192 in 1' axis
        else:
            raise AttributeError

    def __call__(self, data):
        if self.target == 'data':
            new_data = np.zeros(shape=self.shape, dtype=np.float32)
            new_data[:, :, :, 5:] = data[:, self.xstart:self.xend, self.ystart:self.yend, :]
        elif self.target == 'label':
            new_data = np.zeros(shape=self.shape, dtype=np.int64)
            new_data[:, :, 5:] = data[self.xstart:self.xend, self.ystart:self.yend, :]
        return new_data

class RandomFlip(object):
    def __init__(self, view='Y', prob=0.5):
        self.prob = prob
        if view == 'Y':
            self.axes = 1

    def __call__(self, data):
        assert len(data.shape) == 4
        if np.random.randn() > self.prob:
            data = np.flip(data, axis=self.axes)

        return data

if __name__ == '__main__':

    path = '../source_data/ATLAS_data'
    transform = transforms.Compose(
        [
            Normalize(view='XY')
        ]
    )
    dataset = NiftiDataset(root=path, labels=False, nifti=True, transform=transform)

    dataloader = DataLoader(dataset=dataset, batch_size=2, shuffle=False, num_workers=2, pin_memory=True)

    p = iter(dataloader)
    data, filename= p.next()


import matplotlib.pyplot as plt
import networkx as nx
from dataclasses import dataclass

@dataclass
class Edge:
    node1: str
    node2: str
    weight: int

    def __eq__(self, other):
        return (self.node1 == other.node1 or self.node1 == other.node2) and \
               (self.node2 == other.node1 or self.node2 == other.node2)

def draw(graph):
    lst = []

    for node1, links in graph.items():
        for node2, weight in links.items():
            edge = Edge(node1, node2, weight)
            if edge not in lst:
                lst.append(edge)

    g = nx.Graph()

    for i in lst:
        g.add_edge(i.node1, i.node2, weight=i.weight)

    elarge = [(u, v) for (u, v, d) in g.edges(data=True) if d["weight"] > 50]
    esmall = [(u, v) for (u, v, d) in g.edges(data=True) if d["weight"] <= 50]

    pos = nx.spring_layout(g, scale=2)  # positions for all nodes
    nx.draw_networkx_nodes(g, pos, node_size=700)  # nodes
    nx.draw_networkx_edges(g, pos, edgelist=elarge, width=4)  # edges
    nx.draw_networkx_edges(g, pos, edgelist=esmall, width=4, alpha=0.5, edge_color="b", style="dashed")
    nx.draw_networkx_labels(g, pos, font_size=16, font_family="sans-serif")  # node labels

    ax = plt.gca()
    ax.margins(0.08)
    plt.axis("off")
    plt.tight_layout()
    plt.show()


import os,re,eel

class createfiles():
    def __init__(self, args):
        self.args = args
        self.arg = args.request
        self.reg = ''
        self.wcsrf=''
        self.error = False
        self.content = ''
        self.body = ''
        self.path=os.getcwd()
        if not os.path.exists("CORS_Javascript"):
            os.mkdir("CORS_Javascript")
        if self.arg == '':
            # print(f'''The request file is empty. {self.path}/request.txt''')
            eel.error("Request block is empty")
            self.error = True
            return
        self.headers = self.arg.split("\n\n")[0]
        self.method = self.headers.split(" ")[0]
        if self.method.lower() not in ['get','post','patch','delete']:
            self.error = True
            eel.error("Couldn't find Method")
            return
        if self.method.upper() == 'POST':
            self.body = self.arg.split("\n\n")[1]
            self.content = re.search("Content-Type: (.*)",self.headers)[1]
        self.domain = re.search("Host: (.*)",self.headers)[1]
        self.domain = f'https://{self.domain}'
        self.url = self.headers.split(" ")[1]
        self.url = self.domain.strip()+self.url
        if self.args.csrf:
            if 'csrf' or 'xsrf' in self.headers:
                self.csheader = re.search("(.*c?x?srf.*?):",self.headers)[1]
                self.wcsrf = f"xhr.setRequestHeader('{self.csheader}', csrf)"
            if 'json' not in self.content:
                try:
                    self.reg = re.search("[c?x?]srf=(.*?)&", self.body,re.DOTALL)[1]
                    self.body = self.body.replace(self.reg.strip() ,"${csrf}")
                except:
                    pass
        if not (os.path.exists("CORS_Javascript/cors.html")):
            with open ("CORS_Javascript/cors.html", "w") as s:
                s.write('\n<title>CORS POC GENERATOR</title>\n\n
CORS POC CREATOR
\n\n\n')


from __future__ import annotations

from typing import Iterable
from unittest import mock

from airflow.utils.entry_points import entry_points_with_dist, metadata

class MockDistribution:
    def __init__(self, name: str, entry_points: Iterable[metadata.EntryPoint]) -> None:
        self.metadata = {"Name": name}
        self.entry_points = entry_points

class MockMetadata:
    def distributions(self):
        return [
            MockDistribution(
                "dist1",
                [metadata.EntryPoint("a", "b", "group_x"), metadata.EntryPoint("c", "d", "group_y")],
            ),
            MockDistribution("Dist2", [metadata.EntryPoint("e", "f", "group_x")]),
            MockDistribution("dist2", [metadata.EntryPoint("g", "h", "group_x")]),  # Duplicated name.
        ]

@mock.patch("airflow.utils.entry_points.metadata", MockMetadata())
def test_entry_points_with_dist():
    entries = list(entry_points_with_dist("group_x"))

    # Only "group_x" entries are loaded. Distributions are not deduplicated.
    assert [dist.metadata["Name"] for _, dist in entries] == ["dist1", "Dist2", "dist2"]
    assert [ep.name for ep, _ in entries] == ["a", "e", "g"]