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

from mido import MidiFile, merge_tracks
# import numpy as np
from os import listdir
from os.path import exists
# import csv
import sys
import json
import copy

def pitch_class(note_position):
    p = note_position % 12
    switcher = {
        0: 'C',
        1: 'C#',
        2: 'D',
        3: 'D#',
        4: 'E',
        5: 'F',
        6: 'F#',
        7: 'G',
        8: 'G#',
        9: 'A',
        10: 'A#',
        11: 'B'
    }
    return switcher.get(p)

def pitch_class_to_lower(pitch_class):
    switcher = {
      'C': 'c',
      'C#': 'c#',
      'D': 'd',
      'D#': 'd#',
      'E': 'e',
      'F': 'f',
      'F#': 'f#',
      'G': 'g',
      'G#': 'g#',
      'A': 'a',
      'A#': 'a#',
      'B': 'b'
    }
    return switcher.get(pitch_class)

def parse_events(f):
    midi = MidiFile(f)
    events = []
    notes = []
    single_note_on = []
    tick = 0
    timing = 0
    current_tempo = 500000  # default tempo (bpm 120)
    sequence_position = 0
    note_id = 0
    end_of_track = 0

    for msg in merge_tracks(midi.tracks):
        tp = msg.type
        is_meta = msg.is_meta
        delta_tick = msg.time
        if delta_tick <= 0:
            delta_tick = 0
        tick = tick + delta_tick
        timing = timing + round(delta_tick * current_tempo / midi.ticks_per_beat)
        attributes = []
        channel = None
        note_velocity = None
        note_position = None
        tempo = None
        numerator = None
        denominator = None

        clocks_per_click = None
        notated_32nd_notes_per_beat = None
        key = None
        control = None
        value = None
        program = None
        if tp == 'note_on' or msg.type == 'note_off':
            channel = msg.channel
            note_position = msg.note
            note_velocity = msg.velocity
            if note_velocity == 0:
                tp = 'note_off'
            attributes= ['Channel', 'Note_position', 'Note_velocity']
        elif tp == 'control_change':
            channel = msg.channel
            control = msg.control
            value = msg.value
            attributes = ['Channel', 'Control', 'Value']
        elif tp == 'program_change':
            channel = msg.channel
            program = msg.program
            attributes = ['Channel', 'Program']
        elif tp == 'time_signature':
            numerator = msg.numerator
            denominator = msg.denominator
            clocks_per_click = msg.clocks_per_click
            notated_32nd_notes_per_beat = msg.notated_32nd_notes_per_beat
            attributes = ['Numerator', 'Denominator', 'Clocks_per_click', 'Notated_32nd_notes_per_beat']
        elif tp == 'key_signature':
            key = msg.key
            # Valid values: A A#m Ab Abm Am B Bb Bbm Bm C C# C#m Cb Cm D D#m Db Dm E Eb Ebm Em F F# F#m Fm G G#m Gb Gm
            attributes = ['key']
        elif tp == 'set_tempo':
            tempo = msg.tempo
            attributes = ['tempo']
        elif tp == 'end_of_track':
            end_of_track = tick

        event = {
            'Type': tp,
            'Is_meta': is_meta,
            'Delta_tick': delta_tick,
            'Tick': tick,
            'Timing': timing,
            'Current_tempo': current_tempo,
            'Sequence_position': sequence_position,
            'Attributes': attributes
        }
        if channel is not None:
            event['Channel'] = channel
        if note_position is not None:
            event['Note_position'] = note_position
        if note_velocity is not None:
            event['Note_velocity'] = note_velocity
        if tempo is not None:
            event['Tempo'] = tempo
        if numerator is not None:
            event['Numerator'] = numerator
        if denominator is not None:
            event['Denominator'] = denominator
        if clocks_per_click is not None:
            event['Clocks_per_click'] = clocks_per_click
        if notated_32nd_notes_per_beat is not None:
            event['Notated_32nd_notes_per_beat'] = notated_32nd_notes_per_beat
        if key is not None:
            event['Key'] = key
        if control is not None:
            event['Control'] = control
        if value is not None:
            event['Value'] = value
        if program is not None:
            event['Program'] = program
        events.append(event)
        if tp == 'set_tempo':
            current_tempo = msg.tempo
        if tp == 'time_signature':
            current_numerator = msg.numerator
            current_denominator = msg.denominator
        sequence_position = sequence_position + 1

        if event['Type'] == 'note_on':
            # 'ID'는 임시 아이디이고, 나중에 새로 할당함
            single_note_on.append({
                'ID': note_id,
                'Start_tick': event['Tick'],
                'End_tick': -1,
                'Start_timing': event['Timing'],
                'End_timing': -1,
                'Channel': event['Channel'],
                'Voice': -1,
                'Is_chord': False,
                'Note_position': event['Note_position'],
                'Note_velocity': event['Note_velocity'],
                'Note_pitch_class': '',
                'Note_octave': -1,
                'Note_duration': 0,
                'Following_rest_duration': 0
            })
            note_id = note_id + 1
        elif event['Type'] == 'note_off':
            try:
                note = next(s for s in single_note_on
                            if s['Channel'] == event['Channel'] and s['Note_position'] == event['Note_position'])
                single_note_on.remove(note)
                note['End_tick'] = event['Tick']
                note['End_timing'] = event['Timing']
                note['Note_pitch_class'] = pitch_class(event['Note_position'])
                note['Note_octave'] = (event['Note_position'] // 12) - 1
                notes.append(note)
            except StopIteration:
                pass

    def round_tick(tick):
        tpb = midi.ticks_per_beat
        unit_tick = tpb / 8  # 32nd note
        # do not consider triplet
        """
            unit_triplet_tick = tpb / 6     # (8/3)th note
            candidate1 = abs((tick / unit_tick) - round(tick / unit_tick))
            candidate2 = abs(((tick - unit_triplet_tick) / unit_tick) - round((tick - unit_triplet_tick) / unit_tick))
            candidate3 = abs(((tick - 2 * unit_triplet_tick) / unit_tick) - round((tick - 2 * unit_triplet_tick) / unit_tick))
            candidate4 = abs(((tick - 4 * unit_triplet_tick) / unit_tick) - round((tick - 4 * unit_triplet_tick) / unit_tick))
            candidate5 = abs(((tick - 8 * unit_triplet_tick) / unit_tick) - round((tick - 8 * unit_triplet_tick) / unit_tick))
            min_candidate = min(candidate1, candidate2, candidate3, candidate4, candidate5)
            if min_candidate == candidate1:
                return round(round(tick / unit_tick) * unit_tick)
            elif min_candidate == candidate2:
                return round(round((tick - unit_triplet_tick) / unit_tick) * unit_tick + unit_triplet_tick)
            elif min_candidate == candidate3:
                return round(round((tick - 2 * unit_triplet_tick) / unit_tick) * unit_tick + 2 * unit_triplet_tick)
            elif min_candidate == candidate4:
                return round(round((tick - 4 * unit_triplet_tick) / unit_tick) * unit_tick + 4 * unit_triplet_tick)
            else:
                return round(round((tick - 8 * unit_triplet_tick) / unit_tick) * unit_tick + 8 * unit_triplet_tick)
        """
        return round(round(tick / unit_tick) * unit_tick)

    current_numerator = 4     # default time signature (4/4)
    current_denominator = 4   # default time signature (4/4)
    notations = []
    time_sigs = list(filter(lambda e: e['Type'] == 'time_signature', events))
    time_sigs.sort(key=(lambda e: e['Tick']))
    time_sigs_index = 0

    key_sigs = list(map(lambda e: {
        'Type': 'key_signature',
        'Tick': round_tick(e['Tick']),
        'Options': e['Key']
    }, list(filter(lambda e: e['Type'] == 'key_signature', events))))

    def find_key_sigs_by_tick(tick):
        return next((ks for ks in key_sigs if ks['Tick'] == round_tick(tick)), None)

    temp_tick = 0
    while temp_tick < end_of_track:
        next_bar_tick = min(end_of_track,
                            temp_tick + round(midi.ticks_per_beat * 4 * current_numerator / current_denominator))
        if temp_tick == 0 and (len(time_sigs) <= 0 or not time_sigs[0]['Tick'] == 0):
            notations.append({
              'Type': 'time_signature',
              'Tick': temp_tick,
              'Options': '4/4'
            })

        if next_bar_tick == end_of_track:
            break
        elif len(time_sigs) <= time_sigs_index:
            temp_tick = next_bar_tick
            if find_key_sigs_by_tick(temp_tick) is None:
                notations.append({
                  'Type': 'bar',
                  'Tick': temp_tick,
                  'Options': {'type': 'single'}
                })
            else:
                notations.append({
                  'Type': 'bar',
                  'Tick': temp_tick,
                  'Options': {'type': 'double'}
                })
        elif next_bar_tick < round_tick(time_sigs[time_sigs_index]['Tick']):
            temp_tick = next_bar_tick
            if find_key_sigs_by_tick(temp_tick) is None:
                notations.append({
                  'Type': 'bar',
                  'Tick': temp_tick,
                  'Options': {'type': 'single'}
                })
            else:
                notations.append({
                  'Type': 'bar',
                  'Tick': temp_tick,
                  'Options': {'type': 'double'}
                })
        elif next_bar_tick == round_tick(time_sigs[time_sigs_index]['Tick']):
            temp_tick = next_bar_tick
            notations.append({
              'Type': 'bar',
              'Tick': temp_tick,
              'Options': {'type': 'double'}
            })
            notations.append({
                'Type': 'time_signature',
                'Tick': temp_tick,
                'Options': str(time_sigs[time_sigs_index]['Numerator']) +
                           '/' + str(time_sigs[time_sigs_index]['Denominator'])
            })
            current_numerator = time_sigs[time_sigs_index]['Numerator']
            current_denominator = time_sigs[time_sigs_index]['Denominator']
            time_sigs_index = time_sigs_index + 1
        else:
            temp_tick = round_tick(time_sigs[time_sigs_index]['Tick'])
            if not temp_tick == 0:
                notations.append({
                  'Type': 'bar',
                  'Tick': temp_tick,
                  'Options': {'type': 'double'}
                })
            notations.append({
                'Type': 'time_signature',
                'Tick': temp_tick,
                'Options': str(time_sigs[time_sigs_index]['Numerator']) +
                           '/' + str(time_sigs[time_sigs_index]['Denominator'])
            })
            current_numerator = time_sigs[time_sigs_index]['Numerator']
            current_denominator = time_sigs[time_sigs_index]['Denominator']
            time_sigs_index = time_sigs_index + 1

    # notations에 clef, set_tempo, key_signature도 삽입
    # 우선 Tick 순으로 정렬하고, Tick이 같으면 bar, clef, key_signature,
    # set_tempo, time_signature 순으로 정렬
    def ordering_notations(notation):
        order = {
            'bar': 0,
            'clef': 1,
            'key_signature': 2,
            'set_tempo': 3,
            'time_signature': 4,
            'note': 5,
            'rest': 5
        }
        return order[notation['Type']]

    """
    set_tempos = list(map(lambda e: {
        'Type': 'set_tempo',
        'Tick': round_tick(e['Tick']),
        'Options': e['Tempo']
    }, list(filter(lambda e: e['Type'] == 'set_tempo', events))))
    """
    notations = notations + key_sigs  # + set_tempos
    notations.sort(key=lambda e: (e['Tick'], ordering_notations(e)))

    def duration_split(duration_tick):
        n = round_tick(duration_tick) * 8 / midi.ticks_per_beat
        durations = []
        twos = []
        for i in [32, 16, 8, 4, 2, 1]:
            twos.append(round(n // i))
            n = n % i
        succession = False
        for i in range(0, 6):
            if i == 0:
                for _ in range(0, twos[0]):
                    durations.append(32)  # '1'
                    succession = True
            elif twos[i] == 1:
                if succession:
                    durations[-1] = durations[-1] + pow(2, 5 - i)  # durations[-1] + 'd'
                else:
                    durations.append(pow(2, 5 - i))  # str(pow(2, i))
                    succession = True
            else:
                succession = False
        return list(map(lambda d: round_tick(d * midi.ticks_per_beat / 8), durations))

    def duration_notation(split_duration, is_rest):
        n = round_tick(split_duration) * 8 / midi.ticks_per_beat
        durations = []
        twos = []
        for i in [32, 16, 8, 4, 2, 1]:
            twos.append(round(n // i))
            n = n % i
        succession = False
        for i in range(0, 6):
            if i == 0:
                for _ in range(0, twos[0]):
                    durations.append('1')
                    succession = True
            elif twos[i] == 1:
                if succession:
                    durations[-1] = durations[-1] + 'd'
                else:
                    durations.append(str(pow(2, i)))
                    succession = True
            else:
                succession = False
        if is_rest:
            for i in range(0, len(durations)):
                durations[i] = durations[i] + 'r'
        if len(durations) == 1:
            return durations[0]
        else:
            print("Duration not split error!")
            return durations

    def duration(note_start, note_end, rest_end):
        tpb = midi.ticks_per_beat
        round_start = round_tick(note_start)
        round_mid = round_tick(note_end)
        round_end = round_tick(rest_end)
        N = round_mid - round_start
        R = round_end - round_mid
        unit_tick = tpb / 8             # 32nd note
        """
        unit_triplet_tick = tpb / 6     # (8/3)th note

        # chech if triplet
        is_triplet = False
        if not round_start % unit_tick == 0 or not round_end % unit_tick == 0:
            is_triplet = True
            unit_tick = unit_triplet_tick
        """

        # 음표와 쉼표 길이를 구해서, VexFlow의 음표 길이 표현법으로 반환하기
        # Do not consider tuplets
        M = min(round(1.34 * N), N + R)
        if N == M:
            # R == 0
            return N, 0
        unit_N = N / unit_tick
        unit_M = M / unit_tick
        k = 0
        while pow(2, k) <= unit_M:
            k = k + 1
        while k >= 1:
            k = k - 1
            unit_note_duration = (unit_M // pow(2, k)) * pow(2, k)
            if unit_note_duration >= unit_N:
                note_duration = round_tick(unit_note_duration * unit_tick)
                return note_duration, N + R - note_duration

        print("Duration error!")
        return 0, 0

    # 음표나 쉼표의 duration 동안에 notations 중 하나 이상이 끼어들면
    # 해당 음표나 쉼표를 나눠야 한다. 음표를 나누면 붙임줄도 붙여야 한다.
    # 붙임줄로 붙어 있는 대상끼리는 mouseover나 onclick 시 함께 움직여야 한다.

    notes.sort(key=(lambda e: e["Start_tick"]))
    sorted_notes = sorted(notes, key=(lambda e: (e["Start_tick"], e['Note_position'])))

    voices = []
    note_notations = []
    count = 0
    for note in sorted_notes:
        note['ID'] = count
        count = count + 1

    def find_note_by_id(id):
        return next(note for note in notes if note['ID'] == id)

    def note_position_to_string(pos):
        return pitch_class_to_lower(pitch_class(pos)) + '/' + str((pos // 12) - 1)

    for note in notes:
        temp_voices = []    # 이 음표가 할당될 수 있는 voice 후보들
        for v_info in voices:
            if v_info['Channel'] == note['Channel']:
                # 틱 수 비교할 때 최소 리듬 단위의 배수로 반올림하여 계산
                if round_tick(v_info['Notes'][-1]['Start_tick']) == round_tick(note['Start_tick']) and \
                    round_tick(v_info['Notes'][-1]['End_tick']) == round_tick(note['End_tick']):
                    # Is_chord == True
                    temp_voices.append((v_info, abs(v_info['Notes'][-1]['Note_position'] - note['Note_position']), True))
                elif round_tick(v_info['Notes'][-1]['End_tick']) <= round_tick(note['Start_tick']):
                    # Is_chord == False
                    temp_voices.append((v_info, abs(v_info['Notes'][-1]['Note_position'] - note['Note_position']), False))
        if len(temp_voices) == 0:
            # new voice
            note['Voice'] = len(voices)
            voices.append({'Channel': note['Channel'], 'Notes': [note], 'Start': round_tick(note['Start_tick']), 'End': note['End_tick']})
        else:
            def take_second(element):
                return element[1]

            # choose voice such that the last note's position is nearest to `note`'s position
            temp_voices.sort(key=take_second)
            if temp_voices[0][2]:
                # 선택된 voice에 가장 마지막으로 들어간 음표가 이 음과 화음인 경우
                note['Is_chord'] = True
            else:
                # 선택된 voice에 가장 마지막으로 들어간 음표가 이 음과 화음이 아닌 경우
                # 바로 이전에 이 성부에 할당되었던 화음이 아닌 음표와, 뒤따르는 쉼표의 duration 결정
                last = -1
                IDs = []
                keys = []
                while len(voices[voices.index(temp_voices[0][0])]['Notes']) >= -1 * last and \
                    find_note_by_id(voices[voices.index(temp_voices[0][0])]['Notes'][last]['ID'])['Note_duration'] == 0:
                    old_start = voices[voices.index(temp_voices[0][0])]['Start']
                    old_end = voices[voices.index(temp_voices[0][0])]['End']
                    new_start = round_tick(note['Start_tick'])
                    old_id = voices[voices.index(temp_voices[0][0])]['Notes'][last]['ID']
                    old_note = find_note_by_id(old_id)
                    """
                    if not old_id == notes[old_id]['ID']:
                        print("ID error!")
                    """
                    old_note['Note_duration'], old_note['Following_rest_duration'] = \
                        duration(old_start, old_end, new_start)
                    if not old_note['Note_duration'] == 0:
                        if not old_note['Is_chord']:
                            # end of chord
                            IDs.insert(0, old_note['ID'])
                            keys.insert(0, old_note['Note_position'])
                            note_notations.append({
                                'Type': 'note',
                                'Tick': round_tick(old_note['Start_tick']),
                                'End_tick': round_tick(old_note['Start_tick']) + old_note['Note_duration'],
                                'IDs': sorted(IDs),
                                'Element_id': str(IDs[0]) + '-' + str(round_tick(old_note['Start_tick'])),
                                'Keys': sorted(keys),
                                'Channel': old_note['Channel'],
                                'Voice': old_note['Voice'],
                                'Options': {}
                            })
                            IDs = []
                            keys = []
                        else:
                            # 화음인 음표들을 하나로 묶기
                            # start or middle of chord
                            IDs.insert(0, old_note['ID'])
                            keys.insert(0, old_note['Note_position'])

                    if not old_note['Following_rest_duration'] == 0 and not old_note['Is_chord']:
                        note_notations.append({
                            'Type': 'rest',
                            'Tick': round_tick(old_note['Start_tick']) + old_note['Note_duration'],
                            'End_tick': new_start,
                            'Channel': old_note['Channel'],
                            'Voice': old_note['Voice'],
                            'Options': {}
                        })
                    last = last - 1

                voices[voices.index(temp_voices[0][0])]['Start'] = round_tick(note['Start_tick'])
                voices[voices.index(temp_voices[0][0])]['End'] = note['End_tick']
            note['Voice'] = voices.index(temp_voices[0][0])
            voices[voices.index(temp_voices[0][0])]['Notes'].append(note)

    for voice in voices:
        # 어떤 voice에서 처음 등장하는 음표의 시작 위치가 곡의 시작이 아닌 경우 맨 앞에 쉼표 추가
        if len(voice['Notes']) >= 1 and round_tick(find_note_by_id(voice['Notes'][0]['ID'])['Start_tick']) > 0:
            note_notations.append({
                'Type': 'rest',
                'Tick': 0,
                'End_tick': round_tick(find_note_by_id(voice['Notes'][0]['ID'])['Start_tick']),
                'Channel': find_note_by_id(voice['Notes'][0]['ID'])['Channel'],
                'Voice': find_note_by_id(voice['Notes'][0]['ID'])['Voice'],
                'Options': {}
            })
        # 각 voices별로 마지막 음표와 이와 화음인 음표들의 길이, 이에 뒤따르는 쉼표 길이를 곡이 끝나는 시점을 이용해서 구하기
        last = -1
        IDs = []
        keys = []
        while len(voice['Notes']) >= -1 * last and \
            find_note_by_id(voice['Notes'][last]['ID'])['Note_duration'] == 0:
            old_id = voice['Notes'][last]['ID']
            old_note = find_note_by_id(old_id)
            old_note['Note_duration'], old_note['Following_rest_duration'] = \
                duration(voice['Start'], voice['End'], end_of_track)
            if not old_note['Note_duration'] == 0:
                if not old_note['Is_chord']:
                    # end of chord
                    IDs.insert(0, old_note['ID'])
                    keys.insert(0, old_note['Note_position'])
                    note_notations.append({
                        'Type': 'note',
                        'Tick': round_tick(old_note['Start_tick']),
                        'End_tick': round_tick(old_note['Start_tick']) + old_note['Note_duration'],
                        'IDs': sorted(IDs),
                        'Element_id': str(IDs[0]) + '-' + str(round_tick(old_note['Start_tick'])),
                        'Keys': sorted(keys),
                        'Channel': old_note['Channel'],
                        'Voice': old_note['Voice'],
                        'Options': {}
                    })
                    IDs = []
                    keys = []
                else:
                    # 화음인 음표들을 하나로 묶기
                    # start or middle of chord
                    IDs.insert(0, old_note['ID'])
                    keys.insert(0, old_note['Note_position'])

            if not old_note['Following_rest_duration'] == 0 and not old_note['Is_chord']:
                note_notations.append({
                    'Type': 'rest',
                    'Tick': round_tick(old_note['Start_tick']) + old_note['Note_duration'],
                    'End_tick': round_tick(end_of_track),
                    'Channel': old_note['Channel'],
                    'Voice': old_note['Voice'],
                    'Options': {}
                })
            last = last - 1

    # 악보 표기와 붙임줄 구성
    staves = []     # staves[voice][measure]['Notations'] 안에 해당 성부, 해당 마디의 악보 기호들이 들어 있다.
    ties = []
    has_tie = False
    tie_from_id = ''
    tie_first_indices = []
    current_key_signature = 'C'

    def get_stem_direction(keys):
        if sum(keys) / len(keys) > 70:
            return -1
        else:
            return 1

    for i in range(0, len(voices)):
        # staves에 현재 voice를 갖고 measure가 0인 새 stave 객체 추가
        # append new voice and first measure
        staves.append([{
            'End_bar': 'end',
            'Key_signature': current_key_signature,
            'Notations': []
        }])
        voice_notations = list(filter(lambda nn: nn['Voice'] == i, note_notations))
        voice_notations.sort(key=lambda nn: nn['Tick'])
        i1 = 0
        i2 = 0
        staves[i][-1]['Notations'].append({
            'Type': 'clef',
            'Tick': 0,
            'Options': 'treble'
        })
        # this algorithm is similar to merging two sorted lists
        while i1 < len(notations) and i2 < len(voice_notations):
            if notations[i1]['Tick'] <= voice_notations[i2]['Tick']:
                # 음표나 쉼표가 아닌 기호(조표, 박자표 등)를 그릴 것
                # 마디 구분선을 만나면 구분선은 그리지 않고 새로운 마디를 추가한다.
                if notations[i1]['Type'] == 'bar':
                    staves[i][-1]['End_bar'] = notations[i1]['Options']['type']
                    staves[i].append({
                        'End_bar': 'end',
                        'Key_signature': current_key_signature,
                        'Notations': []
                    })
                elif notations[i1]['Type'] == 'key_signature':
                    current_key_signature = notations[i1]['Options']
                    staves[i][-1]['Key_signature'] = current_key_signature
                    staves[i][-1]['Notations'].append(notations[i1])
                else:
                    staves[i][-1]['Notations'].append(notations[i1])
                i1 = i1 + 1
            else:
                # 음표 또는 쉼표를 그릴 것
                if notations[i1]['Tick'] >= voice_notations[i2]['End_tick']:
                    # 지금 그리는 음표 또는 쉼표가 끝나고 나서 다른 기호가 오는 경우
                    if voice_notations[i2]['Type'] == 'rest':
                        # 복잡한 박자일 경우 쪼갠다.
                        # 복잡한 박자란? (2분음표 + 8분음표)처럼 dot으로 표현되지 않아 붙임줄이 필요한 박자
                        split_durations = duration_split(voice_notations[i2]['End_tick'] -
                                                         voice_notations[i2]['Tick'])
                        new_notations = []
                        t = voice_notations[i2]['Tick']
                        for split_index in range(1, len(split_durations)):
                            t = t + split_durations[split_index - 1]
                            new_note2 = copy.deepcopy(voice_notations[i2])
                            new_note2['Tick'] = round_tick(t)
                            new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                            new_note2['Options'] = {
                                'keys': ['b/4'],
                                'duration': duration_notation(split_durations[split_index], True)
                            }
                            new_notations.append(new_note2)
                        voice_notations[i2]['End_tick'] = round_tick(voice_notations[i2]['Tick'] + split_durations[0])
                        voice_notations[i2]['Options'] = {
                            'keys': ['b/4'],
                            'duration': duration_notation(voice_notations[i2]['End_tick'] -
                                                          voice_notations[i2]['Tick'], True)
                        }
                    else:
                        # 복잡한 박자일 경우 쪼갠다.
                        split_durations = duration_split(voice_notations[i2]['End_tick'] -
                                                         voice_notations[i2]['Tick'])
                        new_notations = []
                        t = voice_notations[i2]['Tick']
                        voice_notations[i2]['Element_id'] = str(voice_notations[i2]['IDs'][0]) + '-' + str(t)
                        if has_tie:
                            ties.append({
                                'from': tie_from_id,
                                'to': voice_notations[i2]['Element_id'],
                                'first_indices': tie_first_indices,
                                'last_indices': list(range(0, len(voice_notations[i2]['Keys'])))
                            })
                        tie_from_id = voice_notations[i2]['Element_id']
                        tie_first_indices = list(range(0, len(voice_notations[i2]['Keys'])))
                        for split_index in range(1, len(split_durations)):
                            t = t + split_durations[split_index - 1]
                            new_note2 = copy.deepcopy(voice_notations[i2])
                            new_note2['Tick'] = round_tick(t)
                            new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                            new_note2['Element_id'] = str(new_note2['IDs'][0]) + '-' + str(t)
                            new_note2['Options'] = {
                                'keys': list(map(note_position_to_string, new_note2['Keys'])),
                                'duration': duration_notation(split_durations[split_index], False),
                                'stem_direction': get_stem_direction(new_note2['Keys'])
                            }
                            new_notations.append(new_note2)
                            ties.append({
                                'from': tie_from_id,
                                'to': new_note2['Element_id'],
                                'first_indices': tie_first_indices,
                                'last_indices': list(range(0, len(new_note2['Keys'])))
                            })
                            tie_from_id = new_note2['Element_id']
                            tie_first_indices = list(range(0, len(new_note2['Keys'])))
                            # new_note2.pop('Keys', None)

                        voice_notations[i2]['End_tick'] = round_tick(voice_notations[i2]['Tick'] + split_durations[0])
                        voice_notations[i2]['Options'] = {
                            'clef': 'treble',
                            'keys': list(map(note_position_to_string, voice_notations[i2]['Keys'])),
                            'duration': duration_notation(voice_notations[i2]['End_tick'] -
                                                          voice_notations[i2]['Tick'], False),
                            'stem_direction': get_stem_direction(voice_notations[i2]['Keys'])
                        }
                        voice_notations[i2].pop('Keys', None)
                    staves[i][-1]['Notations'].append(voice_notations[i2])
                    for notation in new_notations:
                        notation.pop('Keys', None)
                    staves[i][-1]['Notations'] = staves[i][-1]['Notations'] + new_notations
                    i2 = i2 + 1
                    has_tie = False
                else:
                    # 지금 그리는 음표 또는 쉼표가 끝나기 전에 다른 기호가 끼어드는 경우
                    # 음표 또는 쉼표를 두 개로 쪼개고
                    # 음표의 경우 쪼개진 것들끼리 붙임줄로 이어야 한다.
                    # 기호 앞의 음표 또는 쉼표를 여기서 처리하고,
                    # 기호 뒤의 음표 또는 쉼표는 다음 iteration에서 처리하도록 넘긴다.
                    new_note = copy.deepcopy(voice_notations[i2])
                    new_note['End_tick'] = notations[i1]['Tick']
                    if new_note['Type'] == 'rest':
                        # 복잡한 박자일 경우 쪼갠다.
                        split_durations = duration_split(new_note['End_tick'] -
                                                         new_note['Tick'])
                        new_notations = []
                        t = new_note['Tick']
                        for split_index in range(1, len(split_durations)):
                            t = t + split_durations[split_index - 1]
                            new_note2 = copy.deepcopy(new_note)
                            new_note2['Tick'] = round_tick(t)
                            new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                            new_note2['Options'] = {
                                'keys': ['b/4'],
                                'duration': duration_notation(split_durations[split_index], True)
                            }
                            new_notations.append(new_note2)

                        new_note['End_tick'] = round_tick(new_note['Tick'] + split_durations[0])
                        new_note['Options'] = {
                            'keys': ['b/4'],
                            'duration': duration_notation(new_note['End_tick'] -
                                                          new_note['Tick'], True)
                        }
                    else:
                        # 복잡한 박자일 경우 쪼갠다.
                        split_durations = duration_split(new_note['End_tick'] -
                                                         new_note['Tick'])
                        new_notations = []
                        t = new_note['Tick']
                        new_note['Element_id'] = str(new_note['IDs'][0]) + '-' + str(t)
                        if has_tie:
                            ties.append({
                                'from': tie_from_id,
                                'to': new_note['Element_id'],
                                'first_indices': tie_first_indices,
                                'last_indices': list(range(0, len(new_note['Keys'])))
                            })
                        tie_from_id = new_note['Element_id']
                        tie_first_indices = list(range(0, len(new_note['Keys'])))
                        for split_index in range(1, len(split_durations)):
                            t = t + split_durations[split_index - 1]
                            new_note2 = copy.deepcopy(new_note)
                            new_note2['Tick'] = round_tick(t)
                            new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                            new_note2['Element_id'] = str(new_note2['IDs'][0]) + '-' + str(t)
                            new_note2['Options'] = {
                                'keys': list(map(note_position_to_string, new_note2['Keys'])),
                                'duration': duration_notation(split_durations[split_index], True),
                                'stem_direction': get_stem_direction(new_note2['Keys'])
                            }
                            new_notations.append(new_note2)
                            ties.append({
                                'from': tie_from_id,
                                'to': new_note2['Element_id'],
                                'first_indices': tie_first_indices,
                                'last_indices': list(range(0, len(new_note2['Keys'])))
                            })
                            tie_from_id = new_note2['Element_id']
                            tie_first_indices = list(range(0, len(new_note2['Keys'])))

                        new_note['End_tick'] = round_tick(new_note['Tick'] + split_durations[0])
                        new_note['Options'] = {
                            'clef': 'treble',
                            'keys': list(map(note_position_to_string, new_note['Keys'])),
                            'duration': duration_notation(new_note['End_tick'] -
                                                          new_note['Tick'], False),
                            'stem_direction': get_stem_direction(new_note['Keys'])
                        }
                        new_note.pop('Keys', None)
                    staves[i][-1]['Notations'].append(new_note)
                    for notation in new_notations:
                        notation.pop('Keys', None)
                    staves[i][-1]['Notations'] = staves[i][-1]['Notations'] + new_notations
                    voice_notations[i2]['Tick'] = notations[i1]['Tick']
                    has_tie = True

        while i1 < len(notations):
            # 음표나 쉼표가 아닌 기호(조표, 박자표 등)를 그릴 것
            # 마디 구분선을 만나면 구분선은 그리지 않고 새로운 마디를 추가한다.
            if notations[i1]['Type'] == 'bar':
                staves[i][-1]['End_bar'] = notations[i1]['Options']['type']
                staves[i].append({
                    'End_bar': 'end',
                    'Key_signature': current_key_signature,
                    'Notations': []
                })
            elif notations[i1]['Type'] == 'key_signature':
                current_key_signature = notations[i1]['Options']
                staves[i][-1]['Key_signature'] = current_key_signature
                staves[i][-1]['Notations'].append(notations[i1])
            else:
                staves[i][-1]['Notations'].append(notations[i1])
            i1 = i1 + 1

        while i2 < len(voice_notations):
            if voice_notations[i2]['Type'] == 'rest':
                # 복잡한 박자일 경우 쪼갠다.
                split_durations = duration_split(voice_notations[i2]['End_tick'] -
                                                 voice_notations[i2]['Tick'])
                new_notations = []
                t = voice_notations[i2]['Tick']
                for split_index in range(1, len(split_durations)):
                    t = t + split_durations[split_index - 1]
                    new_note2 = copy.deepcopy(voice_notations[i2])
                    new_note2['Tick'] = round_tick(t)
                    new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                    new_note2['Options'] = {
                        'keys': ['b/4'],
                        'duration': duration_notation(split_durations[split_index], True)
                    }
                    new_notations.append(new_note2)

                voice_notations[i2]['End_tick'] = round_tick(voice_notations[i2]['Tick'] + split_durations[0])
                voice_notations[i2]['Options'] = {
                    'keys': ['b/4'],
                    'duration': duration_notation(voice_notations[i2]['End_tick'] -
                                                  voice_notations[i2]['Tick'], True)
                }
            else:
                # 복잡한 박자일 경우 쪼갠다.
                split_durations = duration_split(voice_notations[i2]['End_tick'] -
                                                 voice_notations[i2]['Tick'])
                new_notations = []
                t = voice_notations[i2]['Tick']
                voice_notations[i2]['Element_id'] = str(voice_notations[i2]['IDs'][0]) + '-' + str(t)
                if has_tie:
                    ties.append({
                        'from': tie_from_id,
                        'to': voice_notations[i2]['Element_id'],
                        'first_indices': tie_first_indices,
                        'last_indices': list(range(0, len(voice_notations[i2]['Keys'])))
                    })
                tie_from_id = voice_notations[i2]['Element_id']
                tie_first_indices = list(range(0, len(voice_notations[i2]['Keys'])))
                for split_index in range(1, len(split_durations)):
                    t = t + split_durations[split_index - 1]
                    new_note2 = copy.deepcopy(voice_notations[i2])
                    new_note2['Tick'] = round_tick(t)
                    new_note2['End_tick'] = round_tick(t + split_durations[split_index])
                    new_note2['Element_id'] = str(new_note2['IDs'][0]) + '-' + str(t)
                    new_note2['Options'] = {
                        'keys': list(map(note_position_to_string, new_note2['Keys'])),
                        'duration': duration_notation(split_durations[split_index], True),
                        'stem_direction': get_stem_direction(new_note2['Keys'])
                    }
                    new_notations.append(new_note2)
                    ties.append({
                        'from': tie_from_id,
                        'to': new_note2['Element_id'],
                        'first_indices': tie_first_indices,
                        'last_indices': list(range(0, len(new_note2['Keys'])))
                    })
                    tie_from_id = new_note2['Element_id']
                    tie_first_indices = list(range(0, len(new_note2['Keys'])))

                voice_notations[i2]['End_tick'] = round_tick(voice_notations[i2]['Tick'] + split_durations[0])
                voice_notations[i2]['Options'] = {
                    'clef': 'treble',
                    'keys': list(map(note_position_to_string, voice_notations[i2]['Keys'])),
                    'duration': duration_notation(voice_notations[i2]['End_tick'] -
                                                  voice_notations[i2]['Tick'], False),
                    'stem_direction': get_stem_direction(voice_notations[i2]['Keys'])
                }
                voice_notations[i2].pop('Keys', None)
            staves[i][-1]['Notations'].append(voice_notations[i2])
            for notation in new_notations:
                notation.pop('Keys', None)
            staves[i][-1]['Notations'] = staves[i][-1]['Notations'] + new_notations
            i2 = i2 + 1
            has_tie = False

    score = {
        'Staves': staves,
        'Ties': ties
    }
    return events, notes, midi.ticks_per_beat, score

GO_UP = "\033[F"

def translate_dir_json(in_dir, out_file_list):
    if exists(out_file_list):
        f = open(out_file_list, 'r')
        file_list = json.loads(f.read())
        f.close()
    else:
        file_list = []
    mid_files = listdir(in_dir)
    n = len(mid_files)
    mid_files.sort()
    for i, in_path in enumerate(mid_files):
        fname = in_path.rstrip('.mid').rstrip('.MID').rstrip('.midi').rstrip('.MIDI')
        try:
            dup = next(d for d in file_list if d == fname)
            continue
        except StopIteration:
            pass
        print(GO_UP+'Processing file {} of {}: {}'.format(i, n, in_path))
        if not (in_dir[-1] == '\\' or in_dir[-1] == '/'):
            in_dir = in_dir + '/'
        try:
            events, notes, ticks_per_beat, score = parse_events(in_dir.replace('\\', '/')+in_path)
        except IOError as e:
            print(e)
            continue
        data = {
            'Filename': fname,
            'Ticks_per_beat': ticks_per_beat,
            'Events': events,
            'Notes': notes,
            'Score': score
        }
        file_list.append(fname)
        f = open(fname + '.json', 'w')
        f.write(json.dumps(data, separators=(',', ':')))
        f.close()
    f = open(out_file_list, 'w')
    f.write(json.dumps(file_list, indent=2))
    f.close()

if __name__ == '__main__':
    # simple tests
    if len(sys.argv) == 2:
        translate_dir_json(sys.argv[1], 'file_list.json')
    elif len(sys.argv) == 3:
        translate_dir_json(sys.argv[1], sys.argv[2])
    elif len(sys.argv) > 3:
        n = len(sys.argv[1:-1])
        for i, d in enumerate(sys.argv[1:-1]):
            print('Loading folder {} of {}'.format(i+1, n))
            translate_dir_json(d, sys.argv[-1])

    else:
        print('Usage:\n\tpython preprocess_midi.py <in_dir_1> ... <in_dir_n> <?out_file="file_list.json"?>')


class Solution:
    def findOrder(self, n: int, prerequisites: List[List[int]]) -> List[int]:
        adj=[[] for i in range(n)]
        indeg=[0]*n
        for i,j in prerequisites:
            adj[j].append(i)
            indeg[i]+=1
        q=[]
        c=0
        res=[]
        for deg in range(n):
            if(indeg[deg]==0):
                q.append(deg)
                c+=1
        while(q):
            x=q.pop()
            y=adj[x]
            res.append(x)
            for s in y:
                indeg[s]-=1
                if(indeg[s]==0):
                    q.append(s)
                    c+=1
        if(c==n):
            return res
        else:
            return []


import grpc
from concurrent import futures
import messages.session_pb2_grpc as pb2_grpc
from video_manager import VideoManager
from stream_peer import StreamPeer
from settings import SERVER_PORT, MEDIA_FOLDER

def parse_swarms(swarms):
   pass

def serve():

   stream_peer = StreamPeer("Bob", "localhost", SERVER_PORT)
   video_manager = VideoManager(MEDIA_FOLDER)
   stream_peer.add_video_manager(video_manager)
   stream_peer.get_swarms()
   server = grpc.server(futures.ThreadPoolExecutor(max_workers=5))
   pb2_grpc.add_StreamerServicer_to_server(stream_peer, server)
   server.add_insecure_port(f'[::]:{SERVER_PORT}')
   print("gRPC starting")
   server.start()
   server.wait_for_termination()

if __name__ == "__main__":
   serve()


# 统计用户信息，包括群体中点击广告的用户数、该群体用户数以及总用户数
# 统计行为信息，可能要尝试每种行为的总数、平均数等

import pandas as pd

df = pd.read_csv('../cluster/processed-data/user-profile3-behavior-cluster.csv')

res_dic = {'clk_users': {}, 'cluster_users': {}, 'total_users': {}, 'pv': {}, 'cart': {}, 'fav': {}, 'buy': {}, 'clk': {}}

for index, row in df.iterrows():
    if not res_dic['clk_users'].__contains__(row['cluster_type']):
        for key in res_dic:
            res_dic[key][row['cluster_type']] = 0
    # 点击广告的用户
    if int(row['clk']) != 0:
        res_dic['clk_users'][row['cluster_type']] += 1
    # 群体用户
    res_dic['cluster_users'][row['cluster_type']] += 1
    # pv
    res_dic['pv'][row['cluster_type']] += int(row['pv'])
    # cart
    res_dic['cart'][row['cluster_type']] += int(row['cart'])
    # fav
    res_dic['fav'][row['cluster_type']] += int(row['fav'])
    # buy
    res_dic['buy'][row['cluster_type']] += int(row['buy'])
    # clk
    res_dic['clk'][row['cluster_type']] += int(row['clk'])

# 总用户
for key in res_dic['cluster_users']:
    res_dic['total_users'][key] = df.shape[0]

print(res_dic)

df2 = pd.DataFrame(res_dic)

df2.index.name = 'cluster_type'

print(df2)

df2.to_csv('./processed-data/user-profile3-cluster-behavior-statics.csv', header = True)


import os
import shutil
import subprocess
from datetime import datetime
from pathlib import Path
from subprocess import CalledProcessError
from typing import Optional

from dateutil.parser import parse
from requests import HTTPError

from ..modifier import Command

class GitUtils:
    @classmethod
    def set_cwd_folder(cls, cwd: Optional[Path] = None):
        Command.set_cwd_folder(cwd)

    @classmethod
    @Command.exec()
    def version(cls) -> Optional[str]:
        return "git --version"

    @classmethod
    def is_enable(cls) -> bool:
        return cls.version() is not None

    @classmethod
    @Command.exec()
    def branch_all(cls) -> Optional[str]:
        return "git branch --all"

    @classmethod
    def current_branch(cls) -> Optional[str]:
        result = cls.branch_all()
        if result is not None:
            for out in result.splitlines():
                if out.startswith("*"):
                    out = out.strip().split(maxsplit=1)
                    return out[-1]

        return None

    @classmethod
    @Command.exec()
    def commit_id(cls) -> Optional[str]:
        return "git rev-parse --short HEAD"

    @classmethod
    @Command.exec()
    def commit_count(cls) -> Optional[str]:
        return "git rev-list --count HEAD"

    @classmethod
    def clone_and_zip(cls, url: str, out: Path) -> float:
        repo_dir = out.with_suffix("")
        if not cls.is_enable():
            raise RuntimeError("git command not found")

        try:
            subprocess.run(
                args=["git", "clone", url, repo_dir.as_posix(), "--depth=1"],
                cwd=out.parent.as_posix(),
                stderr=subprocess.DEVNULL,
                check=True
            )
        except CalledProcessError:
            shutil.rmtree(repo_dir, ignore_errors=True)
            raise HTTPError(f"git repository clone failed: {url}")

        try:
            result = subprocess.run(
                ["git", "log", "--format=%cd"],
                stdout=subprocess.PIPE,
                stderr=subprocess.DEVNULL,
                cwd=repo_dir.as_posix()
            ).stdout.decode("utf-8")

            last_committed = parse(result).timestamp()
        except CalledProcessError:
            last_committed = datetime.now().timestamp()

        for path in repo_dir.glob(".git*"):
            if path.is_dir():
                shutil.rmtree(path, ignore_errors=True)

            if path.is_file():
                os.remove(path)

        for root, _, files in os.walk(repo_dir):
            for file in files:
                path = os.path.join(root, file)
                os.utime(path, (last_committed, last_committed))

        shutil.make_archive(repo_dir.as_posix(), format="zip", root_dir=repo_dir)
        shutil.rmtree(repo_dir)

        return last_committed


nballoons = int(input())
heights = [int(_) for _ in input().split()]
tails = [0] * 1000001
shots = 0
for h in heights:
	if tails[h] > 0:
		tails[h] -= 1
		tails[h-1] += 1
	else:
		tails[h-1] += 1
		shots += 1
print(shots)


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

import matplotlib.pyplot as plt
import random
import timeit

x, y1, y2 = range(10000, 1000001, 10000), [], []
for i in x:
    t = timeit.Timer(f'del seq[0]', 'from __main__ import random, seq')
    seq = list(range(i))
    y1.append(t.timeit(1))
    seq = {k: None for k in range(i)}
    y2.append(t.timeit(1))

plt.ylim(top=0.001)
plt.ylabel('RunTime(ms)')
plt.plot(x, y1)
plt.plot(x, y2)
plt.show()

2-算法分析/03-比较列表和字典del操作的性能.py

03-比较列表和字典del操作的性能.py


import sys
sys.stdin = open("baek17387.txt")

"""
CCW 알고리즘! (Counter Clock Wise 알고리즘)

(x1, y1), (x2, y2),  (x3, y3) 에 대해서
임의의 세점에 대해서 방향성을 체크하는것
(x2-x1) * (y3-y1) - (y2-y1) * (x3-x1)
> 0 이면 1 반시계
< 0 이면 -1 시계
= 0 이면 0 을 반환 평행하다는것

따라서
A, B / C, D 에대해서
1                                       2
CCW(A, B, C) * CCW(A, B, D) <= 0 && CCW(C, D, A) * CCW(C, D, B) <= 0 일때,
만약 1, 2 둘다 0이라면

한번 반드시 반복하자!
"""

def ccw(x1, y1, x2, y2, x3, y3):
    # 신발끈 공식
    #  x1 x2 x3    (x1y2+x2y3+x3y1) - (x2y1+x3y2+x1y3) 이다 (신발끈 공식) <- 그냥 이걸로 가자.
    #  y1 y2 y3
    # x2y3-x1y3-x2y1 - (y2x3-y1x3-x1y2) 인것 이걸 +x1y1 -x1y1을 해주면 아래처럼 인수분해가 되는것!
    tmp = (x2-x1) * (y3-y1) - (y2 - y1) * (x3 - x1) # 이 꼴을 기억해 두자
    if tmp > 0:
        return 1 # 반시계
    elif tmp < 0:
        return -1 # 시계
    else:
        return 0  # 평행

x1, y1, x2, y2 = map(int, input().split())
x3, y3, x4 ,y4 = map(int, input().split())
answer = 0
# 작은쪽이 다른 선분 큰쪽 이하여야 한다.
if ccw(x1, y1, x2, y2, x3, y3) * ccw(x1, y1, x2, y2, x4, y4) == 0 and ccw(x3, y3, x4, y4, x1, y1) * ccw(x3, y3, x4, y4, x2, y2) == 0:
    if min(x1, x2) <= max(x3, x4) and min(x3, x4) <= max(x1, x2) and min(y1, y2) <= max(y3, y4) and min(y3, y4) <= max(y1, y2):
        answer = 1
elif ccw(x1, y1, x2, y2, x3, y3) * ccw(x1, y1, x2, y2, x4, y4) <= 0 and ccw(x3, y3, x4, y4, x1, y1) * ccw(x3, y3, x4, y4, x2, y2) <= 0:
    answer = 1

print(answer)


from typing import Dict, List

from django.contrib.auth import get_user_model
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string

User = get_user_model()

def send_html_to_email(
    to_list: List,
    subject: str,
    template_name,
    context: Dict,
    sender=settings.DEFAULT_FROM_EMAIL,
):
    # Parse html to string
    email_html_message = render_to_string(template_name, context)
    # Initialize a single email message which can be send to multiple recipients
    msg = EmailMultiAlternatives(
        subject=subject, body=email_html_message, from_email=sender, to=to_list
    )
    # Changes content type to text/html
    msg.content_subtype = "html"
    # Sends email and fail silently
    return msg.send()


from odoo import models, fields, api

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    contact_type_id = fields.Many2one(
        string='Contact type', comodel_name='res.partner.type',
        related='partner_invoice_id.contact_type_id', store=True)
    analytic_account_id = fields.Many2one(
        string='Analytic Account', comodel_name='account.analytic.account',
        compute='_compute_analytic_account_id', store=True, related=False,
        company_dependent=False, check_company=False, domain=False)

    @api.depends('partner_invoice_id', 'partner_invoice_id.contact_type_id',
                 'contact_type_id.analytic_account_id')
    def _compute_analytic_account_id(self):
        for sale in self:
            if (sale.partner_invoice_id.contact_type_id and
                    sale.partner_invoice_id.contact_type_id.with_company(
                        sale.company_id.id).analytic_account_id):
                sale.analytic_account_id = (
                    sale.partner_invoice_id.contact_type_id.with_company(
                        sale.company_id.id).analytic_account_id.id)


# Author: Joseph Pate
# Class: Ast 4994w
# Date: 30/10/2017
'''
This program implements the solution to the wave equation presented in Zumbusch (2009)

The problem is posed as:

u_tt = u_xx \in \Omega \times [0,T]
u(0,x) = 0
u_t(0,x) = 2

The numerical method is as follows.

To facilitate defining the bilinear form, let ()dt be integration wrt. time
()dx integration wrt. x and () be integration over the entire domain.

The bilinear form is

b(u,v) = (u_t, v)dx + (u_t, v_t) + (u_x, v_x) - (avg(u_x), jump(v))dt
		-(jump(u), avg(v_x))dt + 0.5/h *(jump(u), jump(v))dt

The linear form is
F(v) = (f,v) (u_t(0), v(0))dx

Then the numerical scheme is find u \in DG such that

b(u,v) = F(v) \forall v \in DG
'''
from dolfin import *
import sys

# define boundary function
def boundary(x, on_boundary):
	return on_boundary and near(x[0], 0.0, 1e-14)

# # define jump function
# def myjump(v, n, tol=1E-12):
# 	j = v('+')[0]*n('+')[0] + v('-')[0]*n('-')[0]
# 	return conditional(abs(n('-')[0]) > tol, j/n('-')[0], j)

# create mesh
mesh = RectangleMesh(Point(0,0),Point(10,1),100,10)

# create function space
DG = FiniteElement('DP', mesh.ufl_cell(), 1)
R = FiniteElement('R', mesh.ufl_cell(), 0)
element = MixedElement([DG, R])
V = FunctionSpace(mesh, element)

# create test and trial functions
u,r = TestFunctions(V)
v,q = TrialFunctions(V)

# define DG tools
h = CellSize(mesh)
n = FacetNormal(mesh)
h_avg = avg(h)
alpha = 0.5

# create initial conditions
ut0 = Expression('2.0', degree=1)

# source term
f = Expression('0.0', degree=1)

# boundary terms

# define bilinear form
b = u.dx(0)*v*dx(1) + (u.dx(0)*v.dx(0))*dx + (u.dx(1)*v.dx(1))*dx - (avg(u.dx(1))*jump(v))*dx(0)\
		-(jump(u)*avg(v.dx(1)))*dx(0) + alpha/h_avg*(jump(u)*jump(v))*dx(0)

# define linear functional
F = f*v*dx + ut0*v*dx(1)

# create boundary conditions
bc1 = DirichletBC(V, 0.0, boundary)

# solve linear system
U = Function(V)
solve(b == F, U, bc1)

# output solution
File('zumbusch.pvd') << U


from __future__ import absolute_import
from __future__ import division

from __future__ import print_function

import copy
import json
import types as python_types
from typing import List, Optional, Text
from tensorflow_data_validation import types
from tensorflow_data_validation.statistics.generators import stats_generator

from google.protobuf import json_format
from tensorflow_metadata.proto.v0 import schema_pb2

# TODO(b/68277922): Currently we use a single epsilon (error tolerance)
# parameter for all histograms. Set this parameter specific to each
# histogram based on the number of buckets.

# TODO(b/118833241): Set MI default configs when MI is a default generator
class StatsOptions(object):
  """Options for generating statistics."""

  def __init__(
      self,
      generators: Optional[List[stats_generator.StatsGenerator]] = None,
      feature_whitelist: Optional[List[types.FeatureName]] = None,
      schema: Optional[schema_pb2.Schema] = None,
      label_feature: Optional[types.FeatureName] = None,
      weight_feature: Optional[types.FeatureName] = None,
      slice_functions: Optional[List[types.SliceFunction]] = None,
      sample_rate: Optional[float] = None,
      num_top_values: int = 20,
      frequency_threshold: int = 1,
      weighted_frequency_threshold: float = 1.0,
      num_rank_histogram_buckets: int = 1000,
      num_values_histogram_buckets: int = 10,
      num_histogram_buckets: int = 10,
      num_quantiles_histogram_buckets: int = 10,
      epsilon: float = 0.01,
      infer_type_from_schema: bool = False,
      desired_batch_size: Optional[int] = None,
      enable_semantic_domain_stats: bool = False,
      semantic_domain_stats_sample_rate: Optional[float] = None):
    """Initializes statistics options.

    Args:
      generators: An optional list of statistics generators. A statistics
        generator must extend either CombinerStatsGenerator or
        TransformStatsGenerator.
      feature_whitelist: An optional list of names of the features to calculate
        statistics for.
      schema: An optional tensorflow_metadata Schema proto. Currently we use the
        schema to infer categorical and bytes features.
      label_feature: An optional feature name which represents the label.
      weight_feature: An optional feature name whose numeric value represents
          the weight of an example.
      slice_functions: An optional list of functions that generate slice keys
        for each example. Each slice function should take an example dict as
        input and return a list of zero or more slice keys.
      sample_rate: An optional sampling rate. If specified, statistics is
        computed over the sample.
      num_top_values: An optional number of most frequent feature values to keep
        for string features.
      frequency_threshold: An optional minimum number of examples the most
        frequent values must be present in.
      weighted_frequency_threshold: An optional minimum weighted number of
        examples the most frequent weighted values must be present in. This
        option is only relevant when a weight_feature is specified.
      num_rank_histogram_buckets: An optional number of buckets in the rank
        histogram for string features.
      num_values_histogram_buckets: An optional number of buckets in a quantiles
        histogram for the number of values per Feature, which is stored in
        CommonStatistics.num_values_histogram.
      num_histogram_buckets: An optional number of buckets in a standard
        NumericStatistics.histogram with equal-width buckets.
      num_quantiles_histogram_buckets: An optional number of buckets in a
        quantiles NumericStatistics.histogram.
      epsilon: An optional error tolerance for the computation of quantiles,
        typically a small fraction close to zero (e.g. 0.01). Higher values of
        epsilon increase the quantile approximation, and hence result in more
        unequal buckets, but could improve performance, and resource
        consumption.
      infer_type_from_schema: A boolean to indicate whether the feature types
          should be inferred from the schema. If set to True, an input schema
          must be provided. This flag is used only when generating statistics
          on CSV data.
      desired_batch_size: An optional number of examples to include in each
        batch that is passed to the statistics generators.
      enable_semantic_domain_stats: If True statistics for semantic domains are
        generated (e.g: image, text domains).
      semantic_domain_stats_sample_rate: An optional sampling rate for semantic
        domain statistics. If specified, semantic domain statistics is computed
        over a sample.
    """
    self.generators = generators
    self.feature_whitelist = feature_whitelist
    self.schema = schema
    self.label_feature = label_feature
    self.weight_feature = weight_feature
    self.slice_functions = slice_functions
    self.sample_rate = sample_rate
    self.num_top_values = num_top_values
    self.frequency_threshold = frequency_threshold
    self.weighted_frequency_threshold = weighted_frequency_threshold
    self.num_rank_histogram_buckets = num_rank_histogram_buckets
    self.num_values_histogram_buckets = num_values_histogram_buckets
    self.num_histogram_buckets = num_histogram_buckets
    self.num_quantiles_histogram_buckets = num_quantiles_histogram_buckets
    self.epsilon = epsilon
    self.infer_type_from_schema = infer_type_from_schema
    self.desired_batch_size = desired_batch_size
    self.enable_semantic_domain_stats = enable_semantic_domain_stats
    self.semantic_domain_stats_sample_rate = semantic_domain_stats_sample_rate

  def to_json(self) -> Text:
    """Convert from an object to JSON representation of the __dict__ attribute.

    Custom generators and slice_functions are skipped, meaning that they will
    not be used when running TFDV in a setting where the stats options have been
    json-serialized, first. This will happen in the case where TFDV is run as a
    TFX component. The schema proto will be json_encoded.

    Returns:
      A JSON representation of a filtered version of __dict__.
    """
    options_dict = copy.copy(self.__dict__)
    options_dict['_slice_functions'] = None
    options_dict['_generators'] = None
    if self.schema:
      del options_dict['_schema']
      options_dict['schema_json'] = json_format.MessageToJson(self.schema)
    return json.dumps(options_dict)

  @classmethod
  def from_json(cls, options_json: Text) -> 'StatsOptions':
    """Construct an instance of stats options from a JSON representation.

    Args:
      options_json: A JSON representation of the __dict__ attribute of a
        StatsOptions instance.

    Returns:
      A StatsOptions instance constructed by setting the __dict__ attribute to
      the deserialized value of options_json.
    """
    options_dict = json.loads(options_json)
    if 'schema_json' in options_dict:
      options_dict['_schema'] = json_format.Parse(options_dict['schema_json'],
                                                  schema_pb2.Schema())
      del options_dict['schema_json']
    options = cls()
    options.__dict__ = options_dict
    return options

  @property
  def generators(self) -> Optional[List[stats_generator.StatsGenerator]]:
    return self._generators

  @generators.setter
  def generators(
      self, generators: Optional[List[stats_generator.StatsGenerator]]) -> None:
    if generators is not None:
      if not isinstance(generators, list):
        raise TypeError('generators is of type %s, should be a list.' %
                        type(generators).__name__)
      for generator in generators:
        if not isinstance(generator, (
            stats_generator.CombinerStatsGenerator,
            stats_generator.TransformStatsGenerator,
            stats_generator.CombinerFeatureStatsGenerator,
        )):
          raise TypeError(
              'Statistics generator must extend one of '
              'CombinerStatsGenerator, TransformStatsGenerator, or '
              'CombinerFeatureStatsGenerator found object of type %s.' %
              generator.__class__.__name__)
    self._generators = generators

  @property
  def feature_whitelist(self) -> Optional[List[types.FeatureName]]:
    return self._feature_whitelist

  @feature_whitelist.setter
  def feature_whitelist(
      self, feature_whitelist: Optional[List[types.FeatureName]]) -> None:
    if feature_whitelist is not None and not isinstance(feature_whitelist,
                                                        list):
      raise TypeError('feature_whitelist is of type %s, should be a list.' %
                      type(feature_whitelist).__name__)
    self._feature_whitelist = feature_whitelist

  @property
  def schema(self) -> Optional[schema_pb2.Schema]:
    return self._schema

  @schema.setter
  def schema(self, schema: Optional[schema_pb2.Schema]) -> None:
    if schema is not None and not isinstance(schema, schema_pb2.Schema):
      raise TypeError('schema is of type %s, should be a Schema proto.' %
                      type(schema).__name__)
    self._schema = schema

  @property
  def slice_functions(self) -> Optional[List[types.SliceFunction]]:
    return self._slice_functions

  @slice_functions.setter
  def slice_functions(
      self, slice_functions: Optional[List[types.SliceFunction]]) -> None:
    if slice_functions is not None:
      if not isinstance(slice_functions, list):
        raise TypeError('slice_functions is of type %s, should be a list.' %
                        type(slice_functions).__name__)
      for slice_function in slice_functions:
        if not isinstance(slice_function, python_types.FunctionType):
          raise TypeError('slice_functions must contain functions only.')
    self._slice_functions = slice_functions

  @property
  def sample_rate(self) -> Optional[float]:
    return self._sample_rate

  @sample_rate.setter
  def sample_rate(self, sample_rate: Optional[float]):
    if sample_rate is not None:
      if not 0 < sample_rate <= 1:
        raise ValueError('Invalid sample_rate %f' % sample_rate)
    self._sample_rate = sample_rate

  @property
  def num_values_histogram_buckets(self) -> int:
    return self._num_values_histogram_buckets

  @num_values_histogram_buckets.setter
  def num_values_histogram_buckets(self,
                                   num_values_histogram_buckets: int) -> None:
    # TODO(b/120164508): Disallow num_values_histogram_buckets = 1 because it
    # causes the underlying quantile op to fail. If the quantile op is modified
    # to support num_quantiles = 1, then allow num_values_histogram_buckets = 1.
    if num_values_histogram_buckets <= 1:
      raise ValueError('Invalid num_values_histogram_buckets %d' %
                       num_values_histogram_buckets)
    self._num_values_histogram_buckets = num_values_histogram_buckets

  @property
  def num_histogram_buckets(self) -> int:
    return self._num_histogram_buckets

  @num_histogram_buckets.setter
  def num_histogram_buckets(self, num_histogram_buckets: int) -> None:
    if num_histogram_buckets < 1:
      raise ValueError(
          'Invalid num_histogram_buckets %d' % num_histogram_buckets)
    self._num_histogram_buckets = num_histogram_buckets

  @property
  def num_quantiles_histogram_buckets(self) -> int:
    return self._num_quantiles_histogram_buckets

  @num_quantiles_histogram_buckets.setter
  def num_quantiles_histogram_buckets(
      self, num_quantiles_histogram_buckets: int) -> None:
    if num_quantiles_histogram_buckets < 1:
      raise ValueError('Invalid num_quantiles_histogram_buckets %d' %
                       num_quantiles_histogram_buckets)
    self._num_quantiles_histogram_buckets = num_quantiles_histogram_buckets

  @property
  def desired_batch_size(self) -> Optional[int]:
    return self._desired_batch_size

  @desired_batch_size.setter
  def desired_batch_size(self, desired_batch_size: Optional[int]) -> None:
    if desired_batch_size is not None and desired_batch_size < 1:
      raise ValueError('Invalid desired_batch_size %d' %
                       desired_batch_size)
    self._desired_batch_size = desired_batch_size

  @property
  def semantic_domain_stats_sample_rate(self) -> Optional[float]:
    return self._semantic_domain_stats_sample_rate

  @semantic_domain_stats_sample_rate.setter
  def semantic_domain_stats_sample_rate(
      self, semantic_domain_stats_sample_rate: Optional[float]):
    if semantic_domain_stats_sample_rate is not None:
      if not 0 < semantic_domain_stats_sample_rate <= 1:
        raise ValueError('Invalid semantic_domain_stats_sample_rate %f'
                         % semantic_domain_stats_sample_rate)
    self._semantic_domain_stats_sample_rate = semantic_domain_stats_sample_rate


import os
import argparse
import typing

from pydub import AudioSegment

def import_clips(files, directory: list, format: str, framerate: int) -> dict:
    clips = {}
    for filename in files:
        clips[filename] = AudioSegment.from_file(directory+'/'+filename, format=format, framerate=framerate)

    return clips

def segment_clips(clips: dict, clip_length: int, output, format: str) -> dict:
    segmented = {}
    if output is not None:
        file_num = 0
    for filename, clip in clips.items():
        if output is None:
            segmented.update({filename[:-4]+str(seg_clip[0])+'.'+format: seg_clip[1] for seg_clip in enumerate(clip[::clip_length])})
        else:
            segmented.update({output+str(file_num)+'_'+str(seg_clip[0])+'.'+format: seg_clip[1] for seg_clip in enumerate(clip[::clip_length])})
            file_num += 1

    return segmented

def main(args):
    clips = import_clips(os.listdir(args.directory), args.directory, args.input_format, int(args.framerate))
    segmented = segment_clips(clips, args.clip_length*1000, args.prefix, args.output_format)

    for filename, segment in segmented.items():
        with open(filename, 'wb') as sound:
            segment.export(sound, format=args.output_format)

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description='Segment audio clips into smaller segments of themselves.')
    parser.add_argument('--directory', '-d', default='./', help='Use this argument to specify the directory that contains the clips you want segmented. If not specified, the current directory is attempted.')
    parser.add_argument('--clip_length', '-c', default='10', type=int, help='Use this argument to specify the length of the output clips. Specify time in seconds. If not specified, the default is 10 seconds.')
    parser.add_argument('--framerate', '-f', default=44100, type=int, help='Use this argument to specify the framerate the audio should be imported with. The default is 44100 Hz.')
    parser.add_argument('--input_format', '-I', default='mp3', help='Use this argument to specify the input file format. mp3, wav, etc. Default is mp3.')
    parser.add_argument('--output_format', '-O', default='mp3', help='Use this argument to specify the output file format. mp3, wav, etc. Default is mp3.')
    parser.add_argument('--prefix', '-p', default=None, help='Use this argument to specify the prefix of outputted clips. The default is the name of the filename.')
    main(parser.parse_args())


from django.conf import settings
from django.contrib.auth.tokens import default_token_generator
from django.core.mail import send_mail
from django.db import IntegrityError
from django.db.models import Avg
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import status
from rest_framework.decorators import action, api_view
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import (DestroyAPIView, ListCreateAPIView,
                                     get_object_or_404)
from rest_framework.pagination import PageNumberPagination
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from rest_framework_simplejwt.tokens import AccessToken

from api.filters import TitlesFilter
from api.permissions import (IsAdmin, IsAdminOrOwnerOrReadOnly,
                             IsAdminOrReadOnly)
from api.serializers import (CategorySerializer, CommentSerializer,
                             GenreSerializer, ReviewSerializer,
                             SignupSerializer, TitleReadSerializer,
                             TitleWriteSerializer, TokenSerializer,
                             UserEditSerializer, UserSerializer)
from reviews.models import Category, Genre, Review, Title
from users.models import User

class TitleViewSet(ModelViewSet):
    queryset = Title.objects.annotate(rating=Avg("reviews__score"))
    permission_classes = (IsAdminOrReadOnly,)
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    ordering_fields = ("name",)
    filterset_class = TitlesFilter

    def get_serializer_class(self):
        if self.action in ("list", "retrieve"):
            return TitleReadSerializer
        return TitleWriteSerializer

class CategoryGenreMixinViewSet(
    ListCreateAPIView, DestroyAPIView, GenericViewSet
):
    pagination_class = PageNumberPagination
    permission_classes = (IsAdminOrReadOnly,)
    filter_backends = (SearchFilter,)
    search_fields = ("name",)
    lookup_field = "slug"

    def get(self, request, *args, **kwargs):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)

class CategoryViewSet(CategoryGenreMixinViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

class GenreViewSet(CategoryGenreMixinViewSet):
    queryset = Genre.objects.all()
    serializer_class = GenreSerializer

class ReviewViewSet(ModelViewSet):
    serializer_class = ReviewSerializer
    permission_classes = (IsAdminOrOwnerOrReadOnly,)

    def get_title(self):
        return get_object_or_404(Title, id=self.kwargs.get("title_id"))

    def get_queryset(self):
        return self.get_title().reviews.select_related("author")

    def perform_create(self, serializer):
        serializer.save(author=self.request.user, title=self.get_title())

class CommentViewSet(ModelViewSet):
    serializer_class = CommentSerializer
    permission_classes = (IsAdminOrOwnerOrReadOnly,)

    def get_review(self):
        return get_object_or_404(Review, id=self.kwargs.get("review_id"))

    def get_queryset(self):
        return self.get_review().comments.select_related("author")

    def perform_create(self, serializer):
        serializer.save(author=self.request.user, review=self.get_review())

class UserViewSet(ModelViewSet):
    lookup_field = "username"
    queryset = User.objects.all()
    serializer_class = UserSerializer
    pagination_class = PageNumberPagination
    permission_classes = (IsAdmin,)

    @action(
        methods=["get", "patch"],
        detail=False,
        url_path="me",
        permission_classes=(IsAuthenticated,),
        serializer_class=UserEditSerializer,
    )
    def users_own_profile(self, request):
        user = request.user
        if request.method == "PATCH":
            serializer = self.get_serializer(
                user, data=request.data, partial=True
            )
            serializer.is_valid(raise_exception=True)
            serializer.save()
        else:
            serializer = self.get_serializer(user)
        return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(["POST"])
def signup(request):
    LOGIN_ERROR = "Это имя пользователя уже занято!"
    EMAIL_ERROR = "Эта электронная почта уже занята!"
    serializer = SignupSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    try:
        username = serializer.validated_data.get("username")
        email = serializer.validated_data.get("email")
        user, _ = User.objects.get_or_create(username=username, email=email)
    except IntegrityError:
        real_error = (
            LOGIN_ERROR
            if User.objects.filter(username=username).exists()
            else EMAIL_ERROR
        )
        return Response(real_error, status.HTTP_400_BAD_REQUEST)

    confirmation_code = default_token_generator.make_token(user)
    send_mail(
        subject="Регистрация в проекте YaMDb",
        message=f"Ваш проверочный код: {confirmation_code}",
        from_email=settings.DEFAULT_FROM_EMAIL,
        recipient_list=[user.email],
    )
    return Response(serializer.data, status=status.HTTP_200_OK)

@api_view(["POST"])
def get_token(request):
    serializer = TokenSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    user = get_object_or_404(
        User, username=serializer.validated_data.get("username")
    )
    if default_token_generator.check_token(
        user, serializer.validated_data.get("confirmation_code")
    ):
        token = AccessToken.for_user(user)
        return Response({"token": str(token)}, status=status.HTTP_200_OK)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


from ContratoIndefinido import ContratoIndefinido
from ContratoPracticas import ContratoPracticas
from ContratoTemporal import ContratoTemporal

contrato_indefinido = ContratoIndefinido("1", "12345678H")
contrato_indefinido.set_nombre("Max")
contrato_indefinido.set_apellidos("Griven")
contrato_indefinido.set_salario_bruto_mensual(2000)
contrato_indefinido.set_irpf(0.15)
contrato_indefinido.set_pagas_prorrateadas(True)

contrato_temporal = ContratoTemporal("2", "87654321Z")
contrato_temporal.set_irpf(0.15)
contrato_temporal.set_nombre("Pablo")
contrato_temporal.set_apellidos("Perez")

contrato_practicas = ContratoPracticas("3", "5453534J")
contrato_practicas.set_irpf(0.15)
contrato_practicas.set_nombre("Antonio")
contrato_practicas.set_apellidos("Sanchez")

print(contrato_indefinido)
print(contrato_temporal)
print(contrato_practicas)


import openpyxl
import public as public

class HomePageDy:
    home_Page_Data = [{"FirstName": "Neeraj", "LastName": "Kumar", "Gender": "Male"}, {"FirstName": "Priya", "LastName": "Kumari", "Gender": "Female"}]

    @staticmethod
    def getTestData(test_case_name):
        dict = {}
        book = openpyxl.load_workbook("E:\\SourceSoft\\Demo.xlsx")
        sheet = book.active

        for i in range(1, sheet.max_row + 1):
            if sheet.cell(row=i, column=1).value == test_case_name:
                for j in range(2, sheet.max_column + 1):
                    dict[sheet.cell(row=1, column=j).value] = sheet.cell(row=i, column=j).value

        return[dict]


# coding=utf8
import json

import copy
import tornado.web
from mecloud.api.BaseHandler import BaseHandler
from mecloud.helper.ClassHelper import ClassHelper
from mecloud.helper.Util import MeEncoder, checkKeysAndValue, checkKeys
from mecloud.lib import log
from mecloud.model.MeError import *
from mecloud.model.MeObject import MeObject
from mecloud.model.MeQuery import MeQuery
from mecloud.model.MeUser import MeUser
from mecloud.helper.CountHelper import *

class ShareRecordHandler(BaseHandler):
    # @tornado.web.authenticated
    def get(self, action=None):
        if action == "sharerecord":#根据分享记录返回人或face的信息
            if not self.request.arguments.has_key('compareId'):
                self.write(ERR_PATH_PERMISSION.message)
                return
            compareId = self.get_argument("compareId")
            shareRecordHelper = ClassHelper("ShareRecords")
            srItem = shareRecordHelper.get(compareId)
            if srItem:
                srItem = self.filter_field(srItem)
                result = {}
                if srItem['shareType'] < 2:
                    item = self.getUser(srItem['shareTargetId'],srItem['shareType'])
                    if item:
                        result['nickname'] = item['nickName']
                        result['avatar'] = item['avatar']
                        if "user" in item:
                            result['userId'] = item['user']
                        else:
                            result['userId'] = item['_id']
                else:
                    result = self.getFace(srItem['shareTargetId'])
                result.update(srItem)
                self.write(json.dumps(result, cls=MeEncoder))
            else:
                self.write(ERR_PATH_PERMISSION.message)

        else:
            self.write(ERR_PATH_PERMISSION.message)

    def getUser(self, userId, isUser=-1):
        if isUser == 1:
            userHelper = ClassHelper("UserInfo")
            obj = userHelper.find_one({'user': userId}) or {}
        else:
            obj = ClassHelper("BackupUser").get(userId) or {}
        if not obj:
            userHelper = ClassHelper("UserInfo")
            obj = userHelper.find_one({'user':userId}) or {}
        return self.filter_field(obj)

    def getFace(self, faceId):
        faceHelper = ClassHelper("Face")
        obj = faceHelper.find_one(query={"_id":faceId},keys={"rect":1,"possible.score":1,"file":1}) or {}
        item = {}
        item['faceId'] = faceId
        item['rect'] = obj['rect']
        item['file'] = obj['file']
        item['score'] = obj['possible'][0]['score']
        # user = {}
        # if obj:
        #     if "uploader" in obj:
        #         user = self.getUser(obj['uploader'],1)
        #     elif "backupUser" in obj:
        #         user = self.getUser(obj['backupUser'], 0)
        #     else:
        #         pass
        #     user = self.filter_field(user)
        # obj = self.filter_field(obj)
        return item


from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
from .models import Room, Messages
# Create your views here.

def index(request):
    return render(request,'index.html')

def room(request, room):
    username = request.GET.get('username')
    roomInfo  = Room.objects.get(name=room)
    context = {
        'username' : username,
        'room' :room,
        'roomInfo' : roomInfo
    }
    return render(request,'chatRoom.html',context)

def checkview(request):
    room = request.POST.get('roomName', '')
    username = request.POST.get('username', '')

    if Room.objects.filter(name = room).exists():
        return(redirect('/'+room+'/?username='+username))
    else:
        newRoom = Room.objects.create(name=room)
        newRoom.save()
        return(redirect('/'+room+'/?username='+username))

def send(request):
    message = request.POST.get('message','')
    username = request.POST.get('username','')
    roomId = request.POST.get('roomId','')

    newMessage = Messages.objects.create(message = message, user = username, roomName = roomId )

    newMessage.save()

    return HttpResponse('Message sent successfully')

def getMessages(request, room):
    roomDetails = Room.objects.get(name = room)
    messages = Messages.objects.filter(roomName = roomDetails.id)
    return JsonResponse({"messages":list(messages.values())})


from analogainas.search_spaces import config_space
from analogainas.evaluators import XGBoostEvaluator
from analogainas.search_algorithms import EAOptimizer, Worker

CS = config_space('CIFAR-10')  # Search Space Definition
surrogate = XGBoostEvaluator(model_type="XGBRanker", load_weight=True) #
optimizer = EAOptimizer(surrogate, population_size=20, nb_iter=50) # The default population size is 100.

nb_runs = 2
worker = Worker(CS, optimizer=optimizer, runs=nb_runs)

worker.search()
worker.summary()

best_config = worker.best_config
best_model = worker.best_arch


import json

import requests
from templates import Message

class Mandrill:

    api_url = 'https://mandrillapp.com/api/1.0'

    def __init__(self, config):
        self.api_key = config.get('api_key');

        if not self.api_key:
            raise AttributeError("config: mandrill requires api_key")

        return

    def send(self, message):
        data = self.create_message_data(message)

        headers = {'content-type': 'application/json'}
        result = requests.post(self.api_url + '/messages/send.json', data, headers=headers)
        return result.status_code is 200

    def create_message_data(self, message=Message):
        data = {'key': self.api_key, 'message': {}}
        data['message']['html'] = message.body_html
        data['message']['text'] = message.body_text
        data['message']['subject'] = message.subject
        data['message']['from_email'] = message.from_email
        data['message']['from_name'] = message.from_name

        if message.from_email != message.reply_to_email:
            if message.reply_to_name:
                data['message']['headers'] = {'Reply-To': message.reply_to_name + ' <' + message.reply_to_email + '>'}
            else:
                data['message']['headers'] = {'Reply-To': message.reply_to_email}

        to = []
        for key, value in message.to.iteritems():
            to.append({
                'email': key,
                'name': value,
                'type': 'to'
            })

        for key, value in message.cc.iteritems():
            to.append({
                'email': key,
                'name': value,
                'type': 'cc'
            })

        for key, value in message.bcc.iteritems():
            to.append({
                'email': key,
                'name': value,
                'type': 'bcc'
            })

        data['message']['to'] = to

        return json.dumps(data, separators=(',',':'))


from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist
from django.db import models, transaction
from django.db.models import F
from django.utils.translation import ugettext_lazy as _

from addresses.models import Address
from coupons.models import Coupon
from items.models import Item, WearSize
from lib.utils import get_sentinel_user_anonymous, get_sentinel_user_deleted

from .managers import OrderQuerySet

class Order(models.Model):
    CREATED = "created"
    PAID = "paid"
    UNPAID = "unpaid"
    SHIPPED = "shipped"
    REFUNDED = "refunded"
    ORDER_STATUS_CHOICES = (
        (CREATED, _("Created")),
        (PAID, _("Paid")),
        (UNPAID, _("Unpaid")),
        (SHIPPED, _("Shipped")),
        (REFUNDED, _("Refunded")),
    )
    user = models.ForeignKey(
        get_user_model(),
        on_delete=models.SET(get_sentinel_user_deleted),
        verbose_name=_("User"),
        blank=True,
        null=True,
        default=get_sentinel_user_anonymous,
    )
    shipping_address = models.ForeignKey(
        Address,
        related_name="shipping_address",
        on_delete=models.SET_NULL,
        verbose_name=_("Shipping address"),
        null=True,
    )
    billing_address = models.ForeignKey(
        Address,
        related_name="billing_address",
        on_delete=models.SET_NULL,
        verbose_name=_("Billing address"),
        null=True,
        blank=True,
    )
    coupon = models.ForeignKey(
        Coupon,
        related_name="orders",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        verbose_name=_("Coupon"),
    )
    discount = models.DecimalField(
        _("Discount"), max_digits=5, decimal_places=2, blank=True, null=True, default=0,
    )
    created_date = models.DateTimeField(_("Created at"), auto_now_add=True)
    updated_date = models.DateTimeField(_("Ordered at"), auto_now=True)
    status = models.CharField(
        _("Status"), max_length=120, default="created", choices=ORDER_STATUS_CHOICES
    )
    braintree_id = models.CharField(_("Braintree id"), max_length=150, blank=True)
    session = models.CharField(_("Session"), max_length=100)

    objects = OrderQuerySet.as_manager()

    class Meta:
        verbose_name = _("Order")
        verbose_name_plural = _("Orders")

    def __str__(self):
        return f"Order - {self.id}"

    @property
    def get_total(self):
        total = sum(item.get_cost() for item in self.items.all())
        return total - self.discount

    @property
    def items_quantity(self):
        total = 0
        for order_item in self.items.all():
            total += order_item.quantity
        return total

    @property
    def get_email(self):
        if self.user == get_sentinel_user_anonymous():
            return self.shipping_address.email
        return self.user.email

    def paid(self):
        if self.status == "paid":
            return True
        return False

class OrderItem(models.Model):
    order = models.ForeignKey(
        Order, related_name="items", on_delete=models.CASCADE, verbose_name=_("Order")
    )
    item = models.ForeignKey(
        Item,
        related_name="order_items",
        on_delete=models.CASCADE,
        verbose_name=_("Item"),
    )
    size = models.CharField(
        _("Size"), max_length=4, choices=WearSize.SIZES, blank=True, null=True
    )
    price = models.DecimalField(_("Price"), max_digits=5, decimal_places=2)
    quantity = models.PositiveIntegerField(_("Quantity"), default=1)

    class Meta:
        verbose_name = _("Order Item")
        verbose_name_plural = _("Order Items")

    def __str__(self):
        return f"{self.quantity} of {self.item.title} - {self.size}"

    @transaction.atomic
    def save(self, *args, **kwargs):
        if not self.pk:
            try:
                item = WearSize.objects.get(item=self.item.id, size=self.size)
            except ObjectDoesNotExist:
                item = self.item
            item.quantity = F("quantity") - self.quantity
            item.save()
        super(OrderItem, self).save(*args, **kwargs)

    def get_cost(self):
        return self.price * self.quantity


class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.rigth = None

    def printAsLinkedList(self):
        print (self.value)
        if self.rigth is not None:
            self.rigth.printAsLinkedList()

#
# Exercise taken from:
# Flatten a binary tree into linked list
# https://www.geeksforgeeks.org/flatten-a-binary-tree-into-linked-list/
#
# Explanation:
# The flatten method is used recursively to create a linked list in place.
# Returns the last node so we can use it in a high order Node
#
def flatten(node):
    if node is None:
        return None

    left = node.left
    rigth = node.rigth

    lastNode = node
    if left is not None:
        lastNode = flatten(left)

        # Last Node replaces the right node
        lastNode.rigth = rigth
        node.rigth = left

    node.left = None

    if rigth is not None:
        lastNode = flatten(rigth)

    return lastNode

def example1():
    node6 = Node(6)
    node5 = Node(5)
    node5.rigth = node6
    node3 = Node(3)
    node4 = Node(4)
    node2 = Node(2)
    node2.left = node3
    node2.rigth = node4
    node1 = Node(1)
    node1.left = node2
    node1.rigth =node5
    binaryTree = node1

    return binaryTree

def main():
    binaryTree = example1()

    print('* right branch without flatten:')

    binaryTree.printAsLinkedList()

    flatten(binaryTree)

    print('* right branch flatten:')

    binaryTree.printAsLinkedList()

if __name__ == "__main__":
    main()


import  json

# number=[2,3,4,5,6,7,8]
# file_name="number_json"
# # with open(file_name,'w') as f:
#     # json.dump(number,f)
#
# with open(file_name) as f:
#     number=json.load(f)
# print(number)

# 保存和读取用户生成的数据

# uesename=input('What is your name？按回车结束')
filename='username.json'
# with open(filename,'a') as f:
#     json.dump(uesename,f)
#     print(f"Well remeber you when you come back,{uesename}\n")

with  open(filename) as f:
    aaa=json.load(f)
    print(aaa)


from AES_SubBytes import SubByte
from AES_ShiftRows import ShiftRow
from AES_MixColumn import MixColumn
from AES_Key_Schedule import KeySchedule
from AES_AddRoundKey import AddRoundKey

SubByteLayer = SubByte()
ShiftRowLayer = ShiftRow()
MixColumnLayer = MixColumn()
KeyExpansion = KeySchedule()
AddRoundKey = AddRoundKey()

dados_bytes = open("Arquivo editado.txt", "rb")
dadosCompleto = dados_bytes.read()

chave_bytes = open("chave.txt", "rb")
chave = chave_bytes.read()

###################################Lendo arquivos para as operações########################################

dados = b'' #Variável de leitura, com ela montamos o Estado do AES

#Calcular as chavez de cada round
chaveRound = []
for i in range(10):
	if i == 0:
		chaveRound.append(KeyExpansion.Key_Expansion(chave, i))
	else:
		chaveRound.append(KeyExpansion.Key_Expansion(chaveRound[i-1], i))

while True:
	resp = input("Encriptar ou decriptar? (E) ou (D)")

	if resp.upper() == "E":
		#Encriptar
		textoCifrado = b''

		while True:
			if len(dadosCompleto) % 16 == 0:
				break
			else:
				dadosCompleto += b' '

		for byte in range(len(dadosCompleto)):
			dados += bytes([dadosCompleto[byte]]) #Lendo um bloco para decriptar
			if len(dados) == 16:
				#Adicionar chave antes do round 1
				estado = AddRoundKey.AddKey(dados, chave)

				#Os rounds se iniciam
				for r in range(10):
					if r != 9:
						estado = SubByteLayer.SubByte_Layer(estado)
						mEstado = ShiftRowLayer.ShiftRow_Layer(estado)
						mEstado = MixColumnLayer.MixColumn_Layer(mEstado)
						estado = AddRoundKey.RoundKey(mEstado, chaveRound[r])
					else:
						estado = SubByteLayer.SubByte_Layer(estado)
						mEstado = ShiftRowLayer.ShiftRow_Layer(estado)
						estado = AddRoundKey.RoundKey(mEstado, chaveRound[r])

				textoCifrado+=estado #Incrementamos o resultado nessa variável para escrever o arquivo cifrado
				dados = b''          #Necessário deixar essa variável vazia para que possamos ler outro bloco

		novo_arquivo = open("Arquivo editado.txt", "wb")
		novo_arquivo.write(textoCifrado)
		novo_arquivo.close()
		break

	elif resp.upper() == "D":
		#Decriptar
		textoPlano = b''
		for byte in range(len(dadosCompleto)):
			dados += bytes([dadosCompleto[byte]]) #Lendo um bloco para decriptar
			if len(dados) == 16:
				for r in range(9, -1, -1):

					#Os rounds se iniciam
					if r == 9:
						mEstado = AddRoundKey.Inv_RoundKey(dados, chaveRound[r])
						estado = ShiftRowLayer.Inv_ShiftRow_Layer(mEstado)
						estado = SubByteLayer.Inv_SubByte_Layer(estado)
					else:
						mEstado = AddRoundKey.Inv_RoundKey(estado, chaveRound[r])
						mEstado = MixColumnLayer.Inv_MixColumn_Layer(mEstado)
						estado = ShiftRowLayer.Inv_ShiftRow_Layer(mEstado)
						estado = SubByteLayer.Inv_SubByte_Layer(estado)

				estado = AddRoundKey.AddKey(estado, chave) #Adicionar chave após os rounds

				textoPlano+=estado #Incrementamos o resultado nessa variável para escrever o arquivo decriptado
				dados = b''        #Necessário deixar essa variável vazia para que possamos ler outro bloco

		textoPlano = textoPlano.rstrip(b' ')

		novo_arquivo = open("Arquivo.txt", "wb")
		novo_arquivo.write(textoPlano)
		novo_arquivo.close()
		break

	else:
		print(" \"E\" para encriptar e \"D\" para decriptar, nada além.")


import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader
from tqdm import tqdm

dataset = torchvision.datasets.CIFAR10("./dataset", train=False,
                                       transform=torchvision.transforms.ToTensor(), download=True)
dataloader = DataLoader(dataset, batch_size=64, drop_last=True)

class Test(nn.Module):
    def __init__(self):
        super(Test, self).__init__()
        self.linear = Linear(196608, 10)

    def forward(self, input):
        return self.linear(input)

test = Test()

for data in tqdm(dataloader):
    imgs, targets = data
    output = test(torch.flatten(imgs))
    print(imgs.shape)
    print(output.shape)


import torch
from pytorch3d.ops.iou_box3d import box3d_overlap
from geometry.boxes3d import GenericBoxes3D

def box3d_iou(box1, box2):
    b1 = GenericBoxes3D(box1[:, :4], box1[:, 4:7], box1[:, 7:10])
    corners1 = b1.corners.clone()
    b2 = GenericBoxes3D(box2[:, :4], box2[:, 4:7], box2[:, 7:10])
    corners2 = b2.corners.clone()
    vol, iou =  box3d_overlap(corners1, corners2)
    return iou

def nms3d(box3d_tensor, nms_thresh=0.5):
    # box3d_tensor: Nx12 [[cls, prob, q0,q1,q2,q3, x,y,z, w,l,h]]
    N = box3d_tensor.size(0)
    if N <= 1:
        return box3d_tensor
    else:
        mask = torch.ones(N).bool()
        p_obj = box3d_tensor[:, 1]
        p_obj, idx = p_obj.sort(descending=True)
        box3d_sorted = box3d_tensor.index_select(0, idx).clone()
        box_pred = box3d_sorted[:, 2:].clone()
        for i in range(N-1):
            if mask[i] > 0:
                iou = box3d_iou(box_pred[i, :].unsqueeze(0), box_pred[(i+1):, :])
                iou = iou.squeeze(0)
                mask_box = iou > nms_thresh
                need_mask = mask[(i+1):]
                need_mask[mask_box] = 0
                mask[(i+1):] = need_mask
        return box3d_sorted[mask, :].clone()

def box3d_distance(box1, box2):
    #box1: Nx10  box2: Mx10
    # return NxM
    xyz1 = box1[:, 4:7].unsqueeze(1)
    xyz2 = box2[:, 4:7].unsqueeze(0)
    dis1 = (xyz1 - xyz2) **2
    # dis2 = dis1.sum(dim=2)
    dis2 = dis1[:,:,:2].sum(dim=2)
    return torch.sqrt(dis2)

def nms_distance(box3d_tensor, distance_thresh=0.5):
    # box3d_tensor: Nx12 [[cls, prob, q0,q1,q2,q3, x,y,z, w,l,h]]
    N = box3d_tensor.size(0)
    if N <= 1:
        return box3d_tensor
    else:
        mask = torch.ones(N).bool()
        p_obj = box3d_tensor[:, 1]
        p_obj, idx = p_obj.sort(descending=True)
        box3d_sorted = box3d_tensor.index_select(0, idx).clone()
        box_pred = box3d_sorted[:, 2:].clone()
        for i in range(N-1):
            if mask[i] > 0:
                distance = box3d_distance(box_pred[i, :].unsqueeze(0), box_pred[(i+1):, :])
                distance = distance.squeeze(0)
                mask_box = distance < distance_thresh
                need_mask = mask[(i+1):]
                need_mask[mask_box] = 0
                mask[(i+1):] = need_mask
        return box3d_sorted[mask, :].clone()


"""CLI interface for reversewebsockify."""

import logging
import json
import os.path
import tornado.escape
import tornado.ioloop
import tornado.options
import tornado.web
import tornado.websocket
import tornado.concurrent
import tornado.gen
from tornado.queues import Queue
from tornado.options import define, options

define("port", default=8888, help="run on the given port", type=int)
q = Queue()

class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            (r"/", MainHandler),
            (r"/ws", SocketHandler),
        ]
        settings = dict(
            template_path=os.path.join(os.path.dirname(__file__), 'templates'),
            static_path=os.path.join(os.path.dirname(__file__), 'static'),
        )
        super(Application, self).__init__(handlers, **settings)

class MainHandler(tornado.web.RequestHandler):
    @tornado.gen.coroutine
    def get(self):
        self.data_future = q.get()
        SocketHandler.broadcast(self.request.full_url())
        data = yield self.data_future
        self.write(data)
        self.set_status(200)
        self.finish()
    @tornado.gen.coroutine
    def post(self):
        self.data_future = q.get()
        SocketHandler.broadcast(json.loads(self.request.body))
        data = yield self.data_future
        self.write(data)
        self.set_status(200)
        self.finish()
    def on_connection_close(self):
        self.msg_future.set_result(None)

class SocketHandler(tornado.websocket.WebSocketHandler):
    waiters = set()

    def check_origin(self, origin):
        return True

    def open(self):
        SocketHandler.waiters.add(self)
        logging.info(
            'New WebSocket Connection: %d total',
            len(SocketHandler.waiters)
        )

    def select_subprotocol(self, subprotocol):
        if len(subprotocol):
            return subprotocol[0]
        return super().select_subprotocol(subprotocol)

    async def on_message(self, message):
        logging.info('new message: %s', message)
        await q.put(message)

    def on_close(self):
        SocketHandler.waiters.remove(self)
        logging.info(
            'Disconnected WebSocket (%d total)',
            len(SocketHandler.waiters)
        )

    @classmethod
    def broadcast(cls, data):
        for waiter in cls.waiters:
            try:
                waiter.write_message(data, binary=True)
            except tornado.websocket.WebSocketClosedError:
                logging.error("Error sending message", exc_info=True)

def relay():
    tornado.options.parse_command_line()
    app = Application()
    app.listen(options.port)
    tornado.ioloop.IOLoop.current().start()

def cli() -> None:
    relay()