import config
import csv
import datetime
import main
import multiprocessing
import psycopg2
import time

sp = main.sp
cur = main.cur
lock = main.lock

def available_genres():
    try:
        print('Available genres for recommendation was requested!')
        results = sp.recommendation_genre_seeds()['genres']
        print('Available genres: ' + (', '.join(results)))
        return results

    except Exception as e:
        print('Available genres ERROR!')
        print(e)

def genre_song_label():
    try:
        row = []
        songs = get_songs_from_db()
        f = open('../datasets/labeled_songs.csv', 'w')

        with f:
            writer = csv.writer(f)
            for song in songs:
                artist_id = song[15]
                print('artist_id ' + artist_id)
                cur.execute("SELECT * FROM artists WHERE id=(%s);", (artist_id, ))
                artist = cur.fetchone()
                artist_genre = artist[2]

                if (artist_genre is None or artist_genre in ['', '[]', '{}']):
                    print('Artist genre is NULL!')
                    continue

                row = [artist_genre, str(song[0]), str(song[1]), str(song[2]), str(song[3]), str(song[4]),
                       str(song[5]), str(song[6]), str(song[7]), str(song[8]), str(song[9]), str(song[10]),
                       str(song[11]), str(song[12]), str(song[13]), str(song[14])]

                writer.writerow(row)

    except Exception as e:
        print('Song labeling ERROR!')
        print(e)

def get_artist(artist_id):
    try:
        print('Artist information for ' + artist_id + ' was requested!')
        artist_obj = sp.artist(artist_id)

        if (artist_obj == None):
            print('Artist information returned NULL!')
            return None

        print('Information for ' + artist_obj['name'] + ' was successfully fetched!')
        return artist_obj

    except Exception as e:
        print('Artist information ERROR!')
        print(e)

def get_album(album_id):
    try:
        print('Album information for ' + album_id + ' was requested!')
        album_obj = sp.album(album_id)

        if (album_obj == None):
            print('Album information returned NULL!')
            return None

        print('Information for ' + album_obj['name'] + ' was successfully fetched!')
        return album_obj

    except Exception as e:
        print('Artist information ERROR!')
        print(e)

def get_albums_by_artist(artist_id):
    try:
        print('Album information for ' + artist_id + ' was requested!')
        album_obj = sp.artist_albums(artist_id, album_type='album', limit=50)

        if (album_obj == None):
            print('Album information returned NULL!')
            return None

        for single_album in album_obj['items']:
            print('Information for ' + single_album['name'] + ' was successfully fetched!')

        return album_obj

    except Exception as e:
        print('Album information by artist ERROR!')
        print(e)

def get_songs_by_album(album_id):
    try:
        print('Song information for ' + album_id + ' was requested!')
        song_obj = sp.album_tracks(album_id, limit=50)

        if (song_obj == None):
            print('Song information returned NULL!')
            return None

        for single_song in song_obj['items']:
            print('Information for ' + single_song['name'] + ' was successfully fetched!')

        return song_obj

    except Exception as e:
        print('Song information ERROR!')
        print(e)

def get_song_features(song_id):
    try:
        audio_features = {}
        print('Song features for ' + song_id + ' was requested!')
        audio_obj = sp.audio_features(song_id)

        if (audio_obj == None):
            print('Song features returned NULL!')
            return None

        audio_features['acousticness'] = audio_obj[0]['acousticness']
        audio_features['instrumentalness'] = audio_obj[0]['instrumentalness']
        audio_features['valence'] = audio_obj[0]['valence']
        audio_features['loudness'] = audio_obj[0]['loudness']
        audio_features['energy'] = audio_obj[0]['energy']
        audio_features['liveness'] = audio_obj[0]['liveness']
        audio_features['danceability'] = audio_obj[0]['danceability']
        audio_features['tempo'] = audio_obj[0]['tempo']
        audio_features['speechiness'] = audio_obj[0]['speechiness']
        audio_features['mode'] = audio_obj[0]['mode']
        audio_features['duration_ms'] = audio_obj[0]['duration_ms']
        audio_features['time_signature'] = audio_obj[0]['time_signature']
        audio_features['key'] = audio_obj[0]['key']

        print('Song features for ' + song_id + ' was successfully fetched!')
        return audio_features

    except Exception as e:
        print('Song features ERROR!')
        print(e)

def get_artists_by_recommendation_genre(seeder):
    results = sp.recommendations(seed_genres=seeder, limit=50)
    results = results['tracks']
    results_pot = []

    for result in results:
        if (len(result['artists']) > 1):
            for single_artist in result['artists']:
                spotify_id = single_artist['id']
                lock.acquire()
                cur.execute("SELECT COUNT(*) FROM artists WHERE id=(%s);", (spotify_id, ))

                if (cur.fetchone()[0] == 1):
                    print(spotify_id + ' artist is already in DB.')
                    lock.release()
                    continue
                else:
                    lock.release()

                artist_obj = get_artist(spotify_id)
                if (not artist_obj):
                    print('Artist object is NULL!')
                    continue

                popularity = artist_obj['popularity']
                genres = artist_obj['genres']

                if (popularity < config.ENV['MIN_ARTIST_POP'] or (len(genres) == 0) or (genres is None)):
                    print('Not enough popularity or genre not found!')
                    continue

                name = single_artist['name']
                results_pot.append((spotify_id, name, genres, popularity))

        else:
            single_artist = result['artists'][0]
            spotify_id = single_artist['id']
            lock.acquire()
            cur.execute("SELECT COUNT(*) FROM artists WHERE id=(%s);", (spotify_id, ))

            if (cur.fetchone()[0] == 1):
                print(spotify_id + ' artist is already in DB.')
                lock.release()
                continue
            else:
                lock.release()

            artist_obj = get_artist(spotify_id)
            popularity = artist_obj['popularity']
            if (not artist_obj):
                print('Artist object is NULL!')
                continue
            if (popularity < config.ENV['MIN_ARTIST_POP']):
                continue

            name = single_artist['name']
            genres = artist_obj['genres']
            results_pot.append((spotify_id, name, genres, popularity))

    return results_pot

def insert_artists_by_genres(combinated_genre):
    try:
        seeder = combinated_genre
        artists = get_artists_by_recommendation_genre(seeder)

        for artist in artists:
            try:
                lock.acquire()
                cur.execute("SELECT COUNT(*) FROM artists WHERE id=(%s);", (artist[0], ))

                if ((len(artist[2]) == 0) or (artist[2] is None)):
                    print(artist[0] + ' artist genre is NOT FOUND!')
                    lock.release()
                elif (cur.fetchone()[0] == 1):
                    print(artist[0] + ' artist is already in DB.')
                    lock.release()
                    continue
                else:
                    lock.release()

                lock.acquire()
                cur.execute("""INSERT INTO artists (
                    id, name, genres, popularity, created_at)
                    VALUES (%s, %s, %s, %s, %s)""",
                    (artist[0], artist[1], artist[2], artist[3], datetime.datetime.utcnow()))
                lock.release()

            except psycopg2.IntegrityError as e:
                print('Exception was captured but program is still in progress.')  # Mostly to prevent DB from duplicated PKs.
                print(e)
                lock.release()
                continue

            except Exception as e:
                print(e)
                continue

    except KeyboardInterrupt:
        print('Process was interrupted!')
        return

def get_and_insert_artists(combinated_genres):
    try:
        num_active_processes = 0
        for single_combinated_genre in combinated_genres:
            concatenated_genre = ("-".join(single_combinated_genre))
            lock.acquire()
            cur.execute("SELECT COUNT(*) FROM combinated_genres WHERE name=(%s);", (concatenated_genre, ))

            if (cur.fetchone()[0] == 1):
                print("-".join(single_combinated_genre) + ' combinated genre was already fetched!')
                lock.release()
                continue
            else:
                lock.release()

            if (num_active_processes < config.ENV['NUM_PROCESSES']):
                p = multiprocessing.Process(target=insert_artists_by_genres, args=(single_combinated_genre,))
                p.daemon = True
                p.start()
                num_active_processes += 1
            else:
                insert_artists_by_genres(single_combinated_genre)
                time.sleep(config.ENV['MULTIPROCESS_SLEEP'])
                num_active_processes = 0

            lock.acquire()
            cur.execute("""INSERT INTO combinated_genres (
                    name, created_at)
                    VALUES (%s, %s)""",
                    (concatenated_genre, datetime.datetime.utcnow()))
            print("-".join(single_combinated_genre) + ' combinated genre was written in DB!')
            lock.release()

    except KeyboardInterrupt:
        print('User interrupted the process!')

    except Exception as e:
        print(e)

def insert_albums(artist):
    try:
        for album in get_albums_by_artist(artist[0])['items']:
            if (album == None):
                continue

            album_obj = get_album(album['id'])

            if (album_obj == None):
                continue

            album_id = album_obj['id']
            lock.acquire()
            cur.execute("SELECT COUNT(*) FROM albums WHERE id=(%s);", (album_id, ))

            if (cur.fetchone()[0] == 1):
                print(album_id + ' album is already in DB.')
                lock.release()
                continue
            else:
                lock.release()

            album_name = album_obj['name']
            # album_genres = album_obj['genres']
            total_tracks = album_obj['total_tracks']
            artist_id = artist[0]
            artist_name = artist[1]

            lock.acquire()
            cur.execute("""INSERT INTO albums (
                    id, name, total_tracks, artist_id, artist_name, created_at)
                    VALUES (%s, %s, %s, %s, %s, %s)""",
                    (album_id, album_name, total_tracks, artist_id, artist_name, datetime.datetime.utcnow()))
            print(album_id + ' album was written in DB.')
            lock.release()

    except KeyboardInterrupt:
        print('User interrupted the process!')

    except Exception as e:
        print(e)

def insert_songs(album):
    try:
        for song in get_songs_by_album(album[0])['items']:

            if (song == None):
                continue

            song_id = song['id']
            lock.acquire()
            cur.execute("SELECT COUNT(*) FROM songs WHERE id=(%s);", (song_id, ))

            if (cur.fetchone()[0] == 1):
                print(song_id + ' song is already in DB.')
                lock.release()
                continue
            else:
                lock.release()

            song_name = song['name']
            song_feature_obj = get_song_features(song_id)

            if (song_feature_obj == None):
                continue

            acousticness = song_feature_obj['acousticness']
            instrumentalness = song_feature_obj['instrumentalness']
            valence = song_feature_obj['valence']
            loudness = song_feature_obj['loudness']
            energy = song_feature_obj['energy']
            liveness = song_feature_obj['liveness']
            danceability = song_feature_obj['danceability']
            tempo = song_feature_obj['tempo']
            speechiness = song_feature_obj['speechiness']
            mode = song_feature_obj['mode']
            duration_ms = song_feature_obj['duration_ms']
            time_signature = song_feature_obj['time_signature']
            key = song_feature_obj['key']

            artist_id = album[3]
            artist_name = album[4]
            album_id = album[0]
            album_name = album[1]

            lock.acquire()
            cur.execute("""INSERT INTO songs (
                    id, name,
                    acousticness, instrumentalness, valence, loudness, energy, liveness, danceability, tempo, speechiness,
                    mode, duration_ms, time_signature, key,
                    artist_id, artist_name, album_id, album_name,
                    created_at)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
                    (song_id, song_name,
                    acousticness, instrumentalness, valence, loudness, energy, liveness, danceability, tempo, speechiness,
                    mode, duration_ms, time_signature, key,
                    artist_id, artist_name, album_id, album_name,
                    datetime.datetime.utcnow()))
            print(song_id + ' song was written in DB.')
            lock.release()

    except KeyboardInterrupt:
        print('User interrupted the process!')

    except Exception as e:
        print(e)

def insert_predictions(prediction):
    try:
        if (prediction == None):
            print('Prediction is NONE!')
            return

        song_id = prediction['id']
        song_name = prediction['name']
        r_b = float(prediction['probs'][0][0])
        rap = float(prediction['probs'][0][1])
        electronic = float(prediction['probs'][0][2])
        rock = float(prediction['probs'][0][3])
        new_age = float(prediction['probs'][0][4])
        classical = float(prediction['probs'][0][5])
        reggae = float(prediction['probs'][0][6])
        blues = float(prediction['probs'][0][7])
        country = float(prediction['probs'][0][8])
        world = float(prediction['probs'][0][9])
        folk = float(prediction['probs'][0][10])
        easy_listening = float(prediction['probs'][0][11])
        jazz = float(prediction['probs'][0][12])
        vocal = float(prediction['probs'][0][13])
        punk = float(prediction['probs'][0][14])
        alternative = float(prediction['probs'][0][15])
        pop = float(prediction['probs'][0][16])
        heavy_metal = float(prediction['probs'][0][17])

        lock.acquire()
        cur.execute("""INSERT INTO song_genre_predictions (
                    id, name, r_b, rap, electronic, rock, new_age, classical, reggae, blues, country, world, folk, easy_listening, jazz, vocal, punk, alternative, pop, heavy_metal, created_at)
                    VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
                    (song_id, song_name, r_b, rap, electronic, rock, new_age, classical, reggae, blues, country, world, folk, easy_listening, jazz, vocal, punk, alternative, pop, heavy_metal, datetime.datetime.utcnow()))
        print(song_id + ' song was written in DB.')
        lock.release()

    except KeyboardInterrupt:
        print('User interrupted the process!')

    except Exception as e:
        print(e)

def plt_predictions():
    # Sample prediction bar charts for genre classifier model results.
    # Save results as 'png' in 'figures' folder.
    # Radiohead - Alternative/Rock
    # Justin Bieber - Pop
    # Nirvana - Rock
    # 6ix9ine - Rap

    genres = ['r_b', 'rap', 'electronic', 'rock', 'new_age', 'classical', 'reggae', 'blues', 'country',
    'world', 'folk', 'easy_listening', 'jazz', 'vocal', 'punk', 'alternative', 'pop', 'heavy_metal']
    artist_names = ['radiohead', 'justin_bieber', 'nirvana', '6ix9ine']
    artist_id = {
        'radiohead': '4Z8W4fKeB5YxbusRsdQVPb',
        'justin_bieber': '1uNFoZAHBGtllmzznpCI3s',
        'nirvana': '6olE6TJLqED3rqDCT0FyPh',
        '6ix9ine': '7gZfnEnfiaHzxARJ2LeXrf'
    }

    for artist_name in artist_names:
        songs = get_songs_of_artist_from_db(artist_id[artist_name])
        song_ids = [x[0] for x in songs]
        for song_id in song_ids:
            prediction = get_genre_predictions_from_db(song_id)
            song_name = prediction[0][1].replace('/', '_').replace('.', '_')
            prediction = [[x[2:20] for x in prediction]]
            prediction = prediction[0][0]
            plt.subplots(num=None, figsize=(18, 10), dpi=60, facecolor='w', edgecolor='k')
            plt.xlabel('Genre Correlation Value')
            plt.ylabel('Genres')
            plt.barh(genres, prediction)
            plt.title(song_name)
            plt.savefig('figures/' + artist_name + '/' + song_name + '-' + song_id)
            # plt.show()
            plt.clf()
            plt.close()

def get_artists_from_db():
    cur.execute("SELECT * FROM artists ORDER BY RANDOM()")
    return cur.fetchall()

def get_albums_from_db():
    cur.execute("SELECT * FROM albums ORDER BY RANDOM()")
    return cur.fetchall()

def get_songs_from_db():
    cur.execute("SELECT * FROM songs ORDER BY RANDOM()")
    return cur.fetchall()

def get_count_songs_from_db():
    cur.execute("SELECT COUNT(*) FROM songs")
    return cur.fetchall()[0][0]

def artists_genre_occurrences():
    cur.execute("SELECT genres, COUNT(genres) FROM artists GROUP BY genres ORDER BY COUNT(genres) DESC")
    return cur.fetchall()

def get_genre_predictions_from_db(song_id):
    cur.execute("SELECT * FROM song_genre_predictions WHERE id=%s", (song_id,))
    return cur.fetchall()

def get_songs_of_artist_from_db(artist_id):
    cur.execute("SELECT * FROM songs WHERE artist_id=%s", (artist_id,))
    return cur.fetchall()


import cv2
from datetime import datetime
from app.ml.yolo_v3 import YoloV3

import kivy

kivy.require('1.0.6')
from kivy.core.window import Window
from kivymd.app import MDApp
from kivy.clock import Clock
from kivymd.uix.screen import MDScreen
from kivymd.uix.button.button import MDIconButton
from kivymd.uix.label.label import MDLabel
from kivy.uix.image import Image
from kivy.uix.anchorlayout import AnchorLayout
from kivy.graphics.texture import Texture
from constants import Constants

class WildlifeCameraTrapApp(MDApp):
    boxes = []
    class_names = []
    confidences = []
    should_detect = False
    recording = False
    original_recorder = None
    marked_recorder = None
    last_object_detected_time = None
    fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')

    def build(self):
        self._load_model()
        return self._create_layout()

    # Run continuously to get webcam feed
    def update(self, *args):
        _, frame = self.capture.read()
        elapsed_time = (datetime.now() - self.starting_time).total_seconds()
        current_fps = self.frame_id / elapsed_time
        original_frame = frame.copy()
        self.frame_id += 1
        if self.should_detect:
            boxes, confidences, class_names = self.yolo_v3.detect_objects(frame)
            # when objects are detected
            if len(boxes):
                if not self.recording:
                    self.recording = True
                    self.original_recorder = cv2.VideoWriter(
                        f'./app/data/{self.last_object_detected_time.strftime(Constants.FILENAME_DATEFORMAT)}_original.mp4',
                        self.fourcc,
                        current_fps,
                        (original_frame.shape[1],
                         original_frame.shape[0]),
                    1)
                    self.marked_recorder = cv2.VideoWriter(
                        f'./app/data/{self.last_object_detected_time.strftime(Constants.FILENAME_DATEFORMAT)}_marked.mp4',
                        self.fourcc,
                        current_fps,
                        (frame.shape[1],
                         frame.shape[0]),
                    1)
                self.boxes = boxes
                self.confidences = confidences
                self.class_names = class_names
                self.last_object_detected_time = datetime.now()
                self.recording_status_label.text = Constants.OBJECT_RECORDING
                print('detecting objects')
            # Only check if still recording
            elif self.recording:
                if self._seconds_since_last_detection() > Constants.IDLE_SECONDS:
                    self._stop_recording()
                    self.recording_status_label.text = Constants.NO_OBJECT_DETECTED
                    print('not detecting objects, going idle')
                    # Clean up old detections
                    self.boxes = []
                    self.class_names = []
                    self.confidences = []
                else:
                    print('not detecting objects')

            for box, confidence, class_name in zip(self.boxes, self.confidences, self.class_names):
                x, y, w, h = box
                color = Constants.CLASS_COLORS_TO_USE[class_name]
                cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
                cv2.rectangle(frame, (x, y), (x + w, y + 30), color, -1)
                cv2.putText(frame,
                            f'{class_name} ({confidence:.1%})',
                            (x, y + 30),
                            self.font,
                            2,
                            (255, 255, 255, 0),
                            2,
                            lineType=cv2.LINE_AA)

            opacity = max(1 - (self._seconds_since_last_detection() / Constants.IDLE_SECONDS), 0)
            # We show the bounding boxes with different opacity to indicate the time since last detection
            # Most opaque => most recent detection
            frame = cv2.addWeighted(frame, opacity, original_frame, 1 - opacity, gamma=0)

        if self.recording:
            self.marked_recorder.write(frame)
            print('add frame')
            self.original_recorder.write(original_frame)
        # Flip horizontal and convert image to texture
        buf = cv2.flip(frame, 0).tobytes()
        img_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        img_texture.blit_buffer(buf, colorfmt='bgr', bufferfmt='ubyte')
        self.web_cam.texture = img_texture

    # Recording function to capture objects if present
    def start_stop_recording(self, *args):
        if self.start_stop_recording_button.icon == Constants.START_RECORDING:
            self.should_detect = True
            self.start_stop_recording_button.icon = Constants.STOP_RECORDING
            self.recording_status_label.text = Constants.NO_OBJECT_DETECTED
        elif self.start_stop_recording_button.icon == Constants.STOP_RECORDING:
            self.should_detect = False
            if self.recording:
                self._stop_recording()
            self.start_stop_recording_button.icon = Constants.START_RECORDING
            self.recording_status_label.text = Constants.NOT_RECORDING

    def _create_layout(self):
        # Loading camera
        self.capture = cv2.VideoCapture(0)
        self.font = cv2.FONT_HERSHEY_COMPLEX_SMALL
        self.starting_time = datetime.now()
        self.frame_id = 0
        self.last_object_detected_time = datetime.now()
        Clock.schedule_interval(self.update, timeout=(1.0/Constants.MIN_FPS))

        # Main layout components
        self.should_detect = False
        self.recording = False
        self.web_cam = Image(
            size=Window.size,
            size_hint=(1, 1)
        )
        self.start_stop_recording_button = MDIconButton(
            icon=Constants.START_RECORDING,
            icon_color=(1, 0, 0, 1),
            md_bg_color=(1, 1, 1, 1),
            icon_size='40sp',
            on_press=self.start_stop_recording
        )
        self.recording_status_label = MDLabel(
            text=Constants.NOT_RECORDING,
            size_hint=(1, .1),
            halign="center",
            font_style="H5"
        )

        base_screen = MDScreen()
        base_screen.add_widget(self.web_cam)
        top_center = AnchorLayout(anchor_x='center', anchor_y='top', padding=[10, 10, 10, 10])
        top_center.add_widget(self.recording_status_label)
        base_screen.add_widget(top_center)
        side_layout = AnchorLayout(anchor_x='right', anchor_y='center', padding=[10, 10, 10, 10])
        side_layout.add_widget(self.start_stop_recording_button)
        base_screen.add_widget(side_layout)
        return base_screen

    def _load_model(self):
        self.yolo_v3 = YoloV3()

    def _seconds_since_last_detection(self):
        return (datetime.now() - self.last_object_detected_time).total_seconds()

    def _stop_recording(self):
        self.recording = False
        self.original_recorder.release()
        self.original_recorder = None
        self.marked_recorder.release()
        self.marked_recorder = None

if __name__ == '__main__':
    WildlifeCameraTrapApp().run()


# Driving linear regression algo

# y = mx+b
# m = mean(x)mean(y)-mean(xy)/mean(x)square-((x)square)mean
# b = mean(y) - m(mean(x))

#          ^     _
# y = 1-SE(y)/SE(y)

from statistics import mean
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import style
import random

style.use('fivethirtyeight')

# xs = np.array([1, 2, 3, 4, 5, 6], dtype=np.float)
# ys = np.array([5, 4, 6, 5, 6, 7], dtype=np.float)

# create a random data points
# varience : how much each point can vary from the previous point
# step : how far to step on average per point

def create_dataset(howmany, varience, step=2, correlation=False):
    val = 1
    ys = []
    for i in range(howmany):
        y = val+random.randrange(-varience, varience)
        ys.append(y)

        if correlation and correlation == 'pos':
            val += step
        elif correlation and correlation == 'neg':
            val -= step

    xs = [i for i in range(len(ys))]

    return np.array(xs, dtype=np.float64), np.array(ys, dtype=np.float64)

xs, ys = create_dataset(40, 10, correlation='pos')

def best_fit(xs, ys):
    #                  _ _   __     _       ___
    # formula  :->  m=(x.y - xy) / (x)^2 - (x^2)
    #                 _    _
    #               b=y - mx

    m = (((mean(xs)*mean(ys)) - mean(xs*ys)) /
         ((mean(xs))**2 - mean(xs**2)))

    b = mean(ys) - m*mean(xs)

    return m, b

m, b = best_fit(xs, ys)

# y = mx+b
regression_line = [(m*x)+b for x in xs]

# predictions
given_x = []
for i in range(41, 50, 1):
    given_x.append(i)
predict_y = [(m*x)+b for x in given_x]

#                     ^     _
# Formula  r^2 = 1-SE(y)/SE(y)
def square_error(ys_orig, ys_line):
    return sum((ys_line - ys_orig) ** 2)

def coefficient_of_determination(ys_orig, ys_line):

    y_mean_line = [mean(ys_orig) for ys in ys_orig]
    print(y_mean_line)

    square_error_regr = square_error(ys_orig, ys_line)
    square_error_y_mean = square_error(ys_orig, y_mean_line)

    return 1 - (square_error_regr / square_error_y_mean)

r_squared = coefficient_of_determination(ys, regression_line)
print(r_squared)

# plot
plt.scatter(xs, ys, label='data')
plt.legend(loc=4)
plt.plot(given_x, predict_y, color='red')
plt.plot(xs, regression_line)
plt.show()


# Author: Xinyi Wang
# Date: 2021/10/05

import scipy.io as io
import numpy as np

def getCsf(mat_file, video_num):

    video_num = int(video_num)
    X_mat = io.loadmat(mat_file)
    X3 = np.asarray(X_mat['feats_mat'], dtype=np.float)
    # print(X3)
    # print(type(X3))
    cnnsa_feats = X3[video_num]
    io.savemat('../../tmp/tempmat_path/cnnsa_feats.mat', {'cnnsa_feats': cnnsa_feats})

    return cnnsa_feats

if __name__ == "__main__":
    mat_file = '/mnt/storage/home/um20242/scratch/RAPIQUE-VSFA-Saliency/feat_file/YOUTUBE_UGC_360P_RAPIQUE_VSFACNN_SALIENCY_feats.mat'
    cnnsa_feats = getCsf(mat_file, 1)
    print(cnnsa_feats)


from decimal import *
from django import template
from core.models import *
from pos.models import *
register = template.Library()
import datetime

@register.filter
def getBrand(value, salesLine):
    product = Product.objects.filter(id=salesLine.item_id)
    brand = Brand.objects.filter(id=product[0].brand_id)
    return brand[0].brand

@register.filter
def getModel(value, salesLine):
    product = Product.objects.filter(id=salesLine.item_id)
    return product[0].model

@register.filter
def getDesc(value, salesLine):
    product = Product.objects.filter(id=salesLine.item_id)
    return product[0].description

@register.filter
def getType(value, salesLine):
    product = Product.objects.filter(id=salesLine.item_id)
    category = ProductCategory.objects.filter(id=product[0].category_id)
    return category[0].name

@register.filter
def getSellEx(value, salesLine):
    GST = D(settings.GST)
    minusGST = salesLine.unitPrice / GST
    minusGST *= salesLine.quantity
    minusGST = str(round(minusGST, 2))
    return minusGST

@register.filter
def getNett(value, salesLine):
    product = Product.objects.filter(id=salesLine.item_id)
    return product[0].spanNet * salesLine.quantity

@register.filter
def getSellInc(value, salesLine):
    sellInc = salesLine.unitPrice * salesLine.quantity
    return sellInc

@register.filter
def getPriceMinusGST(price):
    GST = D(settings.GST)
    priceMinusGST = price / GST
    priceMinusGST = str(round(priceMinusGST, 2))
    priceMinusGST = Decimal(priceMinusGST)
    return priceMinusGST

@register.filter
def getGPDollar(value, salesLine):  # GP$ = SellPrice(ex) - SpanNett(ex)
    sellMinusGST = getPriceMinusGST(salesLine.unitPrice)
    product = Product.objects.filter(id=salesLine.item_id)
    spanNet = product[0].spanNet
    spanNet = Decimal(spanNet)
    sellMinusGST *= salesLine.quantity
    spanNet *= salesLine.quantity
    GPDollar = sellMinusGST - spanNet
    return GPDollar

@register.filter
def getGPPerc(value, salesLine):  # GP% = ((sell ex - nett ex) / sell ex) x 100
    GST = D(settings.GST)
    sellEx = salesLine.unitPrice / GST
    sellEx = Decimal(sellEx)
    product = Product.objects.filter(id=salesLine.item_id)
    nettEx = product[0].spanNet
    if sellEx == 0:
        GPPerc = 0
    else:
        GPPerc = ((sellEx-nettEx) / sellEx) * 100
    GPPerc = str(round(GPPerc, 2))
    return GPPerc

#  from sales class-----------------------------------------------
class Sales():
    pass

@register.filter
def getSalesExWarrantiesPerSalesperson(value, salesPerson, filteredSalesByDate):
    numberOfWarranties = getWarrantiesPerSalesperson(value, salesPerson, filteredSalesByDate)
    numberOfSales = getNumSalesPerSalesperson(value, salesPerson, filteredSalesByDate)
    numberOfSalesExWarranties = numberOfSales - numberOfWarranties
    return numberOfSalesExWarranties

@register.filter
def getStrikeRate(value, salesPerson, filteredSalesByDate):
    numberOfSalesExWarranties = getSalesExWarrantiesPerSalesperson(value, salesPerson, filteredSalesByDate)
    numberOfWarranties = getWarrantiesPerSalesperson(value, salesPerson, filteredSalesByDate)
    if len(filteredSalesByDate) == 0:
        strikeRate = "na"
    else:
        strikeRate = "{0:.0f}%".format(float(numberOfWarranties)/numberOfSalesExWarranties * 100)
    return strikeRate

@register.filter
def getNumSalesPerSalesperson(value, salesPerson, filteredSalesByDate):
    sales = filteredSalesByDate.filter(salesPerson=salesPerson)
    salesLines = SalesLine.objects.filter(sale__in=sales)
    return salesLines.count()

@register.filter
def getWarrantiesPerSalesperson(value, salesPerson, filteredSalesByDate):
    sales = filteredSalesByDate.filter(salesPerson=salesPerson)
    salesLines = SalesLine.objects.filter(sale__in=sales)
    warranties = Warranty.objects.all()
    warrantyList = []
    for warranty in warranties:
        warrantyList.append(warranty.product_ptr)
    salesLines = salesLines.filter(item__in=warrantyList)
    return salesLines.count()

@register.filter
def getRep(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    user_id = sale[0].salesPerson_id
    user = Staff.objects.filter(id=user_id)
    return user[0].name

@register.filter
def getRepForWarranty(value, salesLine):
    salesLine = SalesLine.objects.get(id=int(salesLine))
    sale = Sale.objects.filter(id=str(salesLine.sale))
    user_id = sale[0].salesPerson_id
    user = Staff.objects.filter(id=user_id)
    return user[0].name

@register.filter
def getInvoiceRef(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    sale_id = sale[0].id
    saleInvoice = SaleInvoice.objects.filter(sale_id=sale_id)
    invoiceRef = saleInvoice[0].reference
    return invoiceRef

@register.filter
def getSaleCode(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    code = sale[0].code
    return code

@register.filter
def getCust(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    customer_id = sale[0].customer_id
    customer = Customer.objects.filter(id=customer_id)
    firstName = customer[0].firstName
    lastName = customer[0].lastName
    return firstName + " " + lastName

@register.filter
def getDateSold(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    purchaseDate = sale[0].purchaseDate
    return purchaseDate

@register.filter
def getPaymentDate(value, salesLine):
    sale = Sale.objects.filter(id=salesLine.sale_id)
    fullPaymentDate = sale[0].fullPaymentDate
    return fullPaymentDate

#  Distribution_SalesbyCustomer-----------------------------------------------
class Distribution_SalesbyCustomer():
    pass

@register.filter
def filterSalesByDate(startDate, endDate):
    filteredSales = Sale.objects.filter(created__range=[startDate, endDate])
    return filteredSales

@register.filter
def getSalesTotalInc(reportType, arg, filteredSalesByDate):
    salesTotal = 0
    salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
    for salesLine in salesLines:
        unitPrice = salesLine.unitPrice
        unitPrice *= salesLine.quantity
        unitPrice = round(unitPrice, 2)
        salesTotal += unitPrice
    return salesTotal

@register.filter
def getState(postcode):
    postcodes = Postcode.objects.filter(code=postcode)
    return postcodes[0].state

@register.filter
def getType(postcode):
    return "tba"

@register.filter
def getSalesTotalEx(reportType, arg, filteredSalesByDate):
    salesTotal = 0
    salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
    for salesLine in salesLines:
        GST = D(settings.GST)
        minusGST = salesLine.unitPrice / GST
        minusGST *= salesLine.quantity
        minusGST = round(minusGST, 2)
        salesTotal += minusGST
    return salesTotal

@register.filter
def getCostPriceTotal(reportType, arg, filteredSalesByDate):
    costPriceTotal = 0
    salesTotal = getSalesTotalEx(reportType, arg, filteredSalesByDate)
    if salesTotal < 0:
        costPriceTotal = "NA"
    else:
        salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
        for salesLine in salesLines:
            product = Product.objects.get(id=salesLine.item.id)
            costPrice = product.costPrice
            costPrice *= salesLine.quantity
            costPriceTotal += costPrice
    return costPriceTotal

@register.filter
def getGPDollarTotal(reportType, arg, filteredSalesByDate):
    GPDollarTotal = 0
    salesTotal = getSalesTotalEx(reportType, arg, filteredSalesByDate)
    if salesTotal < 0:
        GPDollarTotal = "NA"
    else:
        salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
        for salesLine in salesLines:
            GPDollar = getGPDollar(True, salesLine)
            GPDollarTotal += GPDollar
    return GPDollarTotal

@register.filter
def getGPPercTotal(reportType, arg, filteredSalesByDate):
    GPPercentTotal = 0
    totalProducts = 0
    salesTotal = getSalesTotalEx(reportType, arg, filteredSalesByDate)
    if salesTotal < 0:
        GPPercentTotal = "NA"
    else:
        salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
        for salesLine in salesLines:
            GPPerc = getGPPerc(True, salesLine)
            GPPerc = float(GPPerc)
            GPPerc *= salesLine.quantity
            GPPercentTotal += GPPerc
            totalProducts += salesLine.quantity
        if totalProducts == 0:
            GPPercentTotal = 0
        else:
            GPPercentTotal /= totalProducts
    return GPPercentTotal

def getReportSalesLines(reportType, arg, filteredSalesByDate):
    if reportType == 1:  # Distribution
        postcode = arg
        customersPerPostcode = Customer.objects.filter(ppostcode=postcode)
        salesPerPostcode = filteredSalesByDate.filter(customer__in=customersPerPostcode)
        salesLines = SalesLine.objects.filter(sale__in=salesPerPostcode)
    elif reportType == 2:  # Sales By Customer
        customer = arg
        salesPerCustomer = filteredSalesByDate.filter(customer=customer)
        salesLines = SalesLine.objects.filter(sale__in=salesPerCustomer)
    elif reportType == 3:  # Sales Person
        salesPerson = arg
        salesPerSalesPerson = filteredSalesByDate.filter(salesPerson=salesPerson)
        salesLines = SalesLine.objects.filter(sale__in=salesPerSalesPerson)
    else:
        salesLines = []
    return salesLines

@register.filter
def getQuantityOfSalesByCust(reportType, arg, filteredSalesByDate):
    qtyTotal = 0
    salesLines = getReportSalesLines(reportType, arg, filteredSalesByDate)
    for salesLine in salesLines:
        if not salesLine.quantity < 0:
            qtyTotal += salesLine.quantity
    return qtyTotal


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

wsPort                          = 81

BLINKER_BLE                     = 0
BLINKER_WIFI                    = 1
BLINKER_MQTT                    = 2

W_BUTTON                        = 0
W_SLIDER                        = 1
W_TOGGLE                        = 2
W_RGB                           = 3

J_Xaxis                         = 0
J_Yaxis                         = 1

Yaw                             = 0
Pitch                           = 1
Roll                            = 2
AHRS_state                      = 3

LONG                            = 0
LAT                             = 1

R                               = 0
G                               = 1
B                               = 2

CONNECTING                      = 0
CONNECTED                       = 1
DISCONNECTED                    = 2

BLINKER_DEBUG                   = 0
BLINKER_DEBUG_ALL               = 1

BLINKER_VERSION                 = '0.1.0'

BLINKER_MAX_READ_SIZE           = 256
BLINKER_MAX_SEND_SIZE           = 128

BLINKER_DIY_WIFI                = 'blinker'
BLINKER_DIY_MQTT                = 'blinker'

BLINKER_CONNECT_TIMEOUT_MS      = 10000
BLINKER_STREAM_TIMEOUT          = 100
BLINKER_MQTT_MSG_LIMIT          = 1000
BLINKER_SMS_MSG_LIMIT           = 60000
BLINKER_PUSH_MSG_LIMIT          = 60000
BLINKER_WECHAT_MSG_LIMIT        = 60000
BLINKER_WEATHER_MSG_LIMIT       = 60000
BLINKER_AQI_MSG_LIMIT           = 60000
BLINKER_MQTT_KEEPALIVE          = 120000
BLINKER_CMD_ON                  = 'on'
BLINKER_CMD_OFF                 = 'off'
BLINKER_CMD_JOYSTICK            = 'joy'
BLINKER_CMD_GYRO                = 'gyro'
BLINKER_CMD_AHRS                = 'ahrs'
BLINKER_CMD_GPS                 = 'gps'
BLINKER_CMD_VIBRATE             = 'vibrate'
BLINKER_CMD_BUTTON_TAP          = 'tap'
BLINKER_CMD_BUTTON_PRESSED      = 'press'
BLINKER_CMD_BUTTON_RELEASED     = 'pressup'
BLINKER_CMD_NEWLINE             = '\n'
BLINKER_CMD_INTERSPACE          = ' '
BLINKER_CMD_GET                 = 'get'
BLINKER_CMD_STATE               = 'state'
BLINKER_CMD_ONLINE              = 'online'
BLINKER_CMD_CONNECTED           = 'connected'
BLINKER_CMD_VERSION             = 'version'
BLINKER_CMD_NOTICE              = 'notice'
BLINKER_CMD_NOTFOUND            = 'device not found'
BLINKER_CMD_SWITCH              = 'swi'
BLINKER_CMD_VALUE               = 'val'
BLINKER_CMD_ICON                = 'ico'
BLINKER_CMD_COLOR               = 'col'
BLINKER_CMD_TITLE               = 'tit'
BLINKER_CMD_CONTENT             = 'con'
BLINKER_CMD_TEXT                = 'tex'
BLINKER_CMD_TEXT1               = 'tex1'
BLINKER_CMD_TEXTCOLOR           = 'tco'
BLINKER_CMD_UNIT                = 'uni'
BLINKER_CMD_BUILTIN_SWITCH      = 'switch'
BLINKER_JOYSTICK_VALUE_DEFAULT  = 128

BLINKER_MQTT_ALIYUN_HOST        = 'public.iot-as-mqtt.cn-shanghai.aliyuncs.com'
BLINKER_MQTT_ALIYUN_PORT        = 1883

BLINKER_MQTT_QCLOUD_HOST        = 'iotcloud-mqtt.gz.tencentdevices.com'
BLINKER_MQTT_QCLOUD_PORT        = 1883

BLINKER_ALIGENIE_LIGHT          = 'light'
BLINKER_ALIGENIE_OUTLET         = 'outlet'
BLINKER_ALIGENIE_SENSOR         = 'sensor'
BLINKER_DUEROS_LIGHT            = 'LIGHT'
BLINKER_DUEROS_OUTLET           = 'SOCKET'
BLINKER_DUEROS_SENSOR           = 'AIR_MONITOR'


#!/usr/bin/env python
"""Sample script of word embedding model.

This code implements skip-gram model and continuous-bow model.
Use ../ptb/download.py to download 'ptb.train.txt'.
"""
import argparse
import collections
import time

import numpy as np
import six.moves.cPickle as pickle

import chainer
from chainer import cuda
import chainer.functions as F
import chainer.optimizers as O

parser = argparse.ArgumentParser()
parser.add_argument('--gpu', '-g', default=-1, type=int,
                    help='GPU ID (negative value indicates CPU)')
parser.add_argument('--unit', '-u', default=100, type=int,
                    help='number of units')
parser.add_argument('--window', '-w', default=5, type=int,
                    help='window size')
parser.add_argument('--batchsize', '-b', type=int, default=100,
                    help='learning minibatch size')
parser.add_argument('--epoch', '-e', default=10, type=int,
                    help='number of epochs to learn')
parser.add_argument('--model', '-m', choices=['skipgram', 'cbow'],
                    default='skipgram',
                    help='model type ("skipgram", "cbow")')
parser.add_argument('--out-type', '-o', choices=['hsm', 'ns', 'original'],
                    default='hsm',
                    help='output model type ("hsm": hierarchical softmax, '
                    '"ns": negative sampling, "original": no approximation)')
args = parser.parse_args()
xp = cuda.cupy if args.gpu >= 0 else np

print('GPU: {}'.format(args.gpu))
print('# unit: {}'.format(args.unit))
print('Window: {}'.format(args.window))
print('Minibatch-size: {}'.format(args.batchsize))
print('# epoch: {}'.format(args.epoch))
print('Training model: {}'.format(args.model))
print('Output type: {}'.format(args.out_type))
print('')

def continuous_bow(dataset, position):
    h = None

    # use random window size in the same way as the original word2vec
    # implementation.
    w = np.random.randint(args.window - 1) + 1
    for offset in range(-w, w + 1):
        if offset == 0:
            continue
        d = xp.asarray(dataset[position + offset])
        x = chainer.Variable(d)
        e = model.embed(x)
        h = h + e if h is not None else e

    d = xp.asarray(dataset[position])
    t = chainer.Variable(d)
    return loss_func(h, t)

def skip_gram(dataset, position):
    d = xp.asarray(dataset[position])
    t = chainer.Variable(d)

    # use random window size in the same way as the original word2vec
    # implementation.
    w = np.random.randint(args.window - 1) + 1
    loss = None
    for offset in range(-w, w + 1):
        if offset == 0:
            continue
        d = xp.asarray(dataset[position + offset])
        x = chainer.Variable(d)
        e = model.embed(x)

        loss_i = loss_func(e, t)
        loss = loss_i if loss is None else loss + loss_i

    return loss

if args.gpu >= 0:
    cuda.get_device(args.gpu).use()

index2word = {}
word2index = {}
counts = collections.Counter()
dataset = []
with open('ptb.train.txt') as f:
    for line in f:
        for word in line.split():
            if word not in word2index:
                ind = len(word2index)
                word2index[word] = ind
                index2word[ind] = word
            counts[word2index[word]] += 1
            dataset.append(word2index[word])

n_vocab = len(word2index)

print('n_vocab: %d' % n_vocab)
print('data length: %d' % len(dataset))

if args.model == 'skipgram':
    train_model = skip_gram
elif args.model == 'cbow':
    train_model = continuous_bow
else:
    raise Exception('Unknown model type: {}'.format(args.model))

model = chainer.FunctionSet(
    embed=F.EmbedID(n_vocab, args.unit),
)

if args.out_type == 'hsm':
    tree = F.create_huffman_tree(counts)
    model.l = F.BinaryHierarchicalSoftmax(args.unit, tree)
    loss_func = model.l
elif args.out_type == 'ns':
    cs = [counts[w] for w in range(len(counts))]
    model.l = F.NegativeSampling(args.unit, cs, 20)
    loss_func = model.l
elif args.out_type == 'original':
    model.l = F.Linear(args.unit, n_vocab)
    loss_func = lambda h, t: F.softmax_cross_entropy(model.l(h), t)
else:
    raise Exception('Unknown output type: {}'.format(args.out_type))

if args.gpu >= 0:
    model.to_gpu()

dataset = np.array(dataset, dtype=np.int32)

optimizer = O.Adam()
optimizer.setup(model)

begin_time = time.time()
cur_at = begin_time
word_count = 0
skip = (len(dataset) - args.window * 2) // args.batchsize
next_count = 100000
for epoch in range(args.epoch):
    accum_loss = 0
    print('epoch: {0}'.format(epoch))
    indexes = np.random.permutation(skip)
    for i in indexes:
        if word_count >= next_count:
            now = time.time()
            duration = now - cur_at
            throuput = 100000. / (now - cur_at)
            print('{} words, {:.2f} sec, {:.2f} words/sec'.format(
                word_count, duration, throuput))
            next_count += 100000
            cur_at = now

        position = np.array(
            range(0, args.batchsize)) * skip + (args.window + i)
        loss = train_model(dataset, position)
        accum_loss += loss.data
        word_count += args.batchsize

        optimizer.zero_grads()
        loss.backward()
        optimizer.update()

    print(accum_loss)

model.to_cpu()
with open('model.pickle', 'wb') as f:
    obj = (model, index2word, word2index)
    pickle.dump(obj, f)


import matplotlib.pyplot as plt #import matplotlib yang digunakan sebagai visualisasi gambar
#matplotlib inline
import cv2 #mengimport atau memanggil cv2 dari opencv untuk pengolahan citra serta pembacaan gambar
from skimage import data #import data dari skimage sbagai acuan atau contoh
from skimage.io import imread#import library imread yang berfungsi untuk membaca citra
from skimage.color import rgb2gray #import library yang berfungsi untuk melakukan perubahan warna citra original menjadi gray
import numpy as np #import library numpy untuk operasi numerik
citra1 = cv2.imread("gambar/BMW 3. jpeg", cv2.IMREAD_GRAYSCALE) #membaca atau menampilkan gambar
citra2 = cv2.imread("gambar/BMW 4.jpeg", cv2.IMREAD_GRAYSCALE) #membaca atau menampilkan gambar

#menampilkan kedua shape dari gambar 1 dan gambar 2
print('Shape citra 1 : ', citra1.shape)
print('Shape citra 1 : ', citra2.shape)

fig, axes = plt.subplots(1, 2, figsize=(10, 10))#pembuatan subplots untuk gambar yang akan ditampilkan dengan 1 baris dan 2 kolom
ax = axes.ravel()#pengubahan arrau menjadi satu dimensi

ax[0].imshow(citra1, cmap = 'gray') #penampilan citra 1 untuk subplot pertama denga warna gray
ax[0].set_title("Citra 1")#pemberian judul pada gambar 1 yang akan ditampilkan
ax[1].imshow(citra2, cmap = 'gray') #menampilkan citra 1 untuk subplot kedua dengan warna gray
ax[1].set_title("Citra 2")#pemberian judul pada gambar 2 yang akan ditampilkan

#pembuatan copyan img 1 dan img 2 dengan tipe data yang sama
copyCitra1 = citra1.copy().astype(float)
copyCitra2 = citra2.copy().astype(float)
#mengcopy dimensi img 1 dan pembuatan array kosong namun dengan ukuran yang sama
m1,n1 = copyCitra1.shape
output1 = np.empty([m1, n1])
#mengcopy dimensi img2 dan pembuatan array kosong namun dengan ukuran yang sama
m2,n2 = copyCitra2.shape
output2 = np.empty([m2, n2])

print('Shape copy citra 1 : ', copyCitra1.shape) #penampilan shape dari copyan gambar 1
print('Shape output citra 1 : ', output1.shape) #penampilan shape dari output
#penampilan nilai m1 dan n1
print('m1 : ',m1)
print('n1 : ',n1)
print()

print('Shape copy citra 2 : ', copyCitra2.shape)#penampilan shape dari copyan gambar 2
print('Shape output citra 3 : ', output2.shape)#penampilan shape dari output
#menampilkannilai m2 dan n2
print('m2 : ',m2)
print('n2 : ',n2)
print()

#filter batas pada input 1
#proses penentuan filter batas pada input 1 dengan menggunakan iterasi terhadap setiap baris dan kolom
for baris in range(0, m1-1):
    for kolom in range(0, n1-1):

        a1 = baris #penentuan nilai baris
        b1 = kolom #penentuan nilai kolom
        #rumus penentuan perhitungan filter batas
        arr = np.array([copyCitra1[a1-1, b1-1], copyCitra1[a1-1, b1], copyCitra1[a1, b1+1], \
            copyCitra1[a1, b1-1], copyCitra1[a1, b1+1], copyCitra1[a1+1, b1-1],  \
            copyCitra1[a1+1, b1], copyCitra1[a1+1, b1+1]])

        minPiksel = np.amin(arr); #penentuan nilai piksel minimum
        maksPiksel = np.amax(arr);# penentuan nilai piksel maximum
        #penentuan nilai pixel dengan menggunakan metode if else
        if copyCitra1[baris, kolom] < minPiksel : #
            output1[baris, kolom] = minPiksel
        else :
            if copyCitra1[baris, kolom] > maksPiksel :
                output1[baris, kolom] = maksPiksel
            else :
                output1[baris, kolom] = copyCitra1[baris, kolom]

#filter batas pada input 2
#proses penentuan filter batas pada input 2 dengan menggunakan iterasi terhadap setiap baris dan kolom
for baris in range(0, m2-1):
    for kolom in range(0, n2-1):

        a1 = baris #penentuan nilai baris
        b1 = kolom #penentuan nilai kolom
        #rumus penentuan perhitungan filter batas
        arr = np.array([copyCitra2[a1-1, b1-1], copyCitra2[a1-1, b1], copyCitra2[a1, b1+1], \
            copyCitra2[a1, b1-1], copyCitra2[a1, b1+1], copyCitra2[a1+1, b1-1],  \
            copyCitra2[a1+1, b1], copyCitra2[a1+1, b1+1]])

        minPiksel = np.amin(arr); #penentuan nilai piksel minimum
        maksPiksel = np.amax(arr);# penentuan nilai piksel maximum
        #penentuan nilai pixel dengan menggunakan metode if else
        if copyCitra2[baris, kolom] < minPiksel : #
            output2[baris, kolom] = minPiksel
        else :
            if copyCitra2[baris, kolom] > maksPiksel :
                output2[baris, kolom] = maksPiksel
            else :
                output2[baris, kolom] = copyCitra2[baris, kolom]
#pembuatan subplots untuk kedua gambar hasil output yang akan ditampilkan seta mengubah array menjadi satu dimensi
fig, axes = plt.subplots(2, 2, figsize=(10, 10))
ax = axes.ravel()

ax[0].imshow(citra1, cmap = 'gray')#menampilkan image 1 dengan warna gray pada subplots 1
ax[0].set_title("Input Citra 1")#memberikan judul pada image 1 sebagai input

ax[1].imshow(citra2, cmap = 'gray')#menampilkan image 2 dengan warna gray pada subplots 2
ax[1].set_title("Input Citra 1")#memberikan judul pada image 2 sebagai input

ax[2].imshow(output1, cmap = 'gray')#menampilkan hasil keluaran filter batas pada image 1 dengan warna gray pada subplot ke 3
ax[2].set_title("Output Citra 1")# memberikan judul pada hasil keluaran image 1

ax[3].imshow(output2, cmap = 'gray')#menampilkan hasil keluaran filter batas pada image 2 dengan warna gray pada subplot ke 4
ax[3].set_title("Output Citra 2")#memberikan judul pada hasil keluaran image 2


import nltk

from nltk.tokenize import word_tokenize, sent_tokenize
import heapq

nltk.download('stopwords')
from nltk.corpus import stopwords
def nltk_summarizer(raw_text):
    stopWords = set(stopwords.words("english"))
    word_frequency={}
    for word in nltk.word_tokenize(raw_text):
        if word not in stopWords:
            if word not in word_frequency.keys():
                word_frequency[word]=1
            else:
                word_frequency[word]+=1
    maximum_frequency=max(word_frequency.values())
    for word in word_frequency.keys():
        word_frequency[word]=(word_frequency[word]/maximum_frequency)

    sentence_list=nltk.sent_tokenize(raw_text)
    sentence_score={}
    for sent in sentence_list:
        for word in nltk.word_tokenize(sent.lower()):
            if word in word_frequency.keys():
                if len(sent.split(' '))<30:
                    sentence_score[sent]=word_frequency[word]
                else:
                    sentence_score[sent]=word_frequency[word]

    summary_sentence=heapq.nlargest(7,sentence_score,key=sentence_score.get)
    summary=' '.join(summary_sentence)
    return summary


import maya.cmds as cmds
import pymel.core as pm

class UI(object):
    def __init__(self):
        title = 'curvyEdges'
        version = '1.01'

        self.ceObj = spline(self)

        if pm.window('curvyEdgesWin', exists=True):
            pm.deleteUI('curvyEdgesWin')

        with pm.window('curvyEdgesWin', title='{0} | {1}'.format(title, version),
                       mnb=False, mxb=False, sizeable=False) as window:
            with pm.columnLayout():

                # curve Frame
                with pm.frameLayout(l='Curve Settings', cll=True, cl=False, bs='out'):
                    with pm.columnLayout():
                        self.curveType = pm.radioButtonGrp(l='Curve Type:', sl=0, nrb=2, cw3=[96, 96, 128],
                                                           labelArray2=['BezierCurve', 'NurbsCurve'])
                        self.spans = pm.intSliderGrp(field=True, l='Curve Spans:', minValue=2, maxValue=24,
                                                     fieldMinValue=2, fieldMaxValue=128, value=2, cw3=[96, 64, 128])
                        with pm.rowColumnLayout(nc=2, cw=[1, 96], co=[1, 'right', 1]):
                            self.selOnly = pm.checkBox(v=False, l='Selection Only')
                            pm.button(l='Create Curve', c=self._create, width=201)

                # Deformer Frame
                with pm.frameLayout(l='Deformer Settings', bs='out', cl=False, cll=True):
                    with pm.columnLayout():
                        self.currentCrv = pm.textFieldGrp(editable=False, l='Current Curve:', cw2=[96, 195])

                        self.deformers = [attrSlider(1, 0, 1, 'envelope', self.ceObj),
                                          attrSlider(1, -10, 10, 'tension', self.ceObj),
                                          attrSlider(0, 0, 256, 'dropoffDistance[0]', self.ceObj),
                                          attrSlider(1, 0, 2, 'scale[0]', self.ceObj),
                                          attrSlider(1, 0, 1, 'rotation', self.ceObj)]

            window.show()
            pm.scriptJob(event=['SelectionChanged', self.select], protected=True, p=window)
            self.select()

    def _create(self, *args):
        try:
            self.ceObj.create(self.curveType.getSelect(), self.spans.getValue(), self.selOnly.getValue())
            for i in self.deformers:
                i.setEnable(True)
                i.get()
        except:
            pass

    def select(self, *args):
        try:
            self.ceObj.select()
            for i in self.deformers:
                i.setEnable(True)
                i.get()
        except:
            self.setCurrentCurve('Select a curvyEdges curve!')
            for i in self.deformers:
                i.setEnable(False)

    def setCurrentCurve(self, curve):
        self.currentCrv.setText(curve)

class spline(object):
    def __init__(self, uiObj):
        self.uiObj = uiObj

    def create(self, curveType, spans, selOnly):
        sel = pm.selected()
        cmds.CreateCurveFromPoly()
        curve = pm.selected()
        pm.rebuildCurve(curve, spans=spans)
        # set UI curve
        self.uiObj.setCurrentCurve(curve[0].shortName())

        if curveType == 1:
            pm.nurbsCurveToBezier()
        pm.delete(curve, ch=True)

        # Deform
        if selOnly:
            sel = pm.polyListComponentConversion(sel, fe=True, tv=True)
            self.wire = pm.wire(sel, w=curve)
        else:
            #Object
            self.wire = pm.wire(sel[0].node(), w=curve)

    def select(self):
        sel = pm.selected()
        if isinstance(sel[0], pm.nt.Transform):
            if not isinstance(sel[0].getShape(), pm.nt.NurbsCurve):
                raise Exception('Invalid Selection Type')

        elif isinstance(sel[0], pm.NurbsCurveCV):
            sel = [i.node().getParent() for i in sel]

        else:
            raise Exception('Invalid Selection Type')

        self.wire = pm.listConnections(sel[0].getShape())
        self.uiObj.setCurrentCurve(sel[0].shortName())

class attrSlider(object):
    def __init__(self, value, min, max, name, ceObj):
        self.name = name
        self.ceObj = ceObj

        self.undoState = False
        self.attr = pm.floatSliderGrp(field=True, l=self.name, value=value, pre=3, enable=False,
                                      minValue=min, maxValue=max, dc=lambda *args: self.set(cc=False),
                                      cc=lambda *args: self.set(cc=True), cw3=[96, 64, 128])

        pm.scriptJob(event=['Undo', self.get], protected=True, p=self.attr)

    def get(self, *args):
        try:
            value = getattr(self.ceObj.wire[0], self.name).get(self.attr.getValue())
            self.attr.setValue(value)
        except:
            AttributeError('{0} node does not exist'.format(self.ceObj.wire[0]))

    def set(self, cc=False):
        if not cc and not self.undoState:
            self.undoState = True
            pm.undoInfo(openChunk=True)

        try:
            getattr(self.ceObj.wire[0], self.name).set(self.attr.getValue())
        except:
            AttributeError('{0} node does no longer exist'.format(self.ceObj.wire[0]))

        if cc and self.undoState:
            pm.undoInfo(closeChunk=True)
            self.undoState = False

    def setEnable(self, val):
        self.attr.setEnable(val)

if __name__ == "__main__":
    UI()


from pymatgen.core import Element
from collections import OrderedDict
import numpy as np
from typing import Union, List
from pymatgen.core.composition import Composition
import pandas as pd
from numpy.typing import ArrayLike

class ElementOneHotRepresentation:
    def __init__(self, one_hot: ArrayLike, element_dict: OrderedDict, elements: list):
        self.element_dict = element_dict
        self.keys = elements
        self.one_hot = one_hot

    def as_array(self) -> np.ndarray:
        return self.one_hot

    def as_df(self) -> pd.DataFrame:
        df_one_hot = pd.DataFrame(self.one_hot, index=self.element_dict).T
        return df_one_hot

    @property
    def array(self) -> np.ndarray:
        return self.one_hot

    @property
    def df(self) -> pd.DataFrame:
        return pd.DataFrame(self.one_hot, index=self.element_dict).T

class ElementOneHotGenerator:
    """
    A generator class that converts chemical formulas into one-hot vector representations.

    Attributes:
        element_dict (OrderedDict): A dictionary mapping element symbols to their atomic numbers or custom indices.
        keys (list): List of element symbols present in the `element_dict`.

    Methods:
        fit(N=100, elements=None): Initializes the `element_dict` and `keys`.
        _transform(chemical_formula): Internal method to generate one-hot vector representation for a given chemical formula.
        _generate_one_hot(chemical_formula): Helper method to generate one-hot vector or None-filled vector based on the chemical formula.
        transform_as_array(chemical_formula): Returns the one-hot vector representation as a numpy array for a given chemical formula.
        transform_as_df(chemical_formula): Returns the one-hot vector representation as a pandas DataFrame for a given chemical formula.

    Example:

        formula = "SrTiO3H2"
        gen = ElementOneHotGenerator()
        array = gen.transform_as_df(formula)
        print(array)
        print("-"*30)

        gen = ElementOneHotGenerator()
        gen.fit(N=80)
        array = gen.transform_as_df(formula)
        print(array)
        print("-"*30)

        formula = "SrTiO3H2"
        gen = ElementOneHotGenerator()
        gen.fit(elements=["O","Ti","Sr","H"])
        array = gen.transform_as_df(formula)
        print(array)
        print("-"*30)

        formula = "H0.2He0.7O0.1"
        gen = ElementOneHotGenerator()
        array = gen.transform_as_df(formula)
        print(array)

    """

    def __init__(self, N: int = 100):
        """
        Initializes the ElementOneHotGenerator with a default atomic number range.

        fit(N=100) is automatically done.
        if you want to change the representation, you can overwirte it by fit().

        Args:
            N (int): Maximum atomic number to consider for one-hot encoding (default is 100).
        """
        self.fit(N=N)

    def fit(self, N: int = 100, elements: Union[List[str], None] = None):
        """
        Initializes the `element_dict` and `keys` based on the given atomic number range or element list.

        Args:
            N (int): Maximum atomic number to consider for one-hot encoding.
            elements (List[str], optional): List of element symbols to be used for one-hot encoding.

        Raises:
            ValueError: If the provided `elements` have duplicates or if neither `N` nor `elements` are provided.
        """
        # Z=1からZ=100までの元素名をOrdered辞書に格納
        element_dict = OrderedDict()
        if elements is not None:
            if isinstance(elements, list):
                _elements = list(set(elements))
                if len(elements) != len(_elements):
                    raise ValueError('elements must not be duplicated.')
                for i, element_name in enumerate(elements):
                    element_dict[element_name] = i
                self.element_dict = element_dict
                self.keys = elements
            else:
                raise ValueError('elements must be list.')
        elif N is not None:
            if isinstance(N, int):
                for z in range(1, N + 1):
                    element = Element.from_Z(z)
                    element_dict[element.symbol] = z
                self.element_dict = element_dict
                self.keys = list(element_dict.keys())
            else:
                raise ValueError('N must be int.')
        else:
            raise ValueError('N or elements must be set.')

    def _transform(self, chemical_formula: str) -> np.ndarray:
        """
        Generates the one-hot vector representation for a given chemical formula.

        Args:
            chemical_formula (str): The chemical formula to transform.

        Returns:
            np.ndarray: One-hot vector representation of the chemical formula.
        """
        # 実数が入ったone hot vector を返す。
        chemical_formula = chemical_formula.replace("[", "(")
        chemical_formula = chemical_formula.replace("]", ")")
        composition = Composition(chemical_formula)
        element_dict = self.element_dict
        N = len(element_dict)
        one_hot = np.zeros(N)
        for n in composition.fractional_composition:
            n = str(n)
            z = element_dict[n]
            value = composition.fractional_composition[n]
            z = z - 1
            one_hot[z] = value
        return one_hot

    def _generate_one_hot(self, chemical_formula: str) -> np.ndarray:
        """
        Generates a one-hot vector (filled with real numbers or None) for a given chemical formula.

        Args:
            chemical_formula (str): The chemical formula to transform.

        Returns:
            np.ndarray: One-hot vector filled with real numbers or None values.
        """

        # 実数が入ったone hot vector もしくはNoneが入った one hot vectorを返す。

        try:
            one_hot = self._transform(chemical_formula)
        except KeyError:
            print("KeyError", chemical_formula)
            N = len(self.keys)
            one_hot = np.full(N, None)
        except ValueError:
            print("ValueError", chemical_formula)
            N = len(self.keys)
            one_hot = np.full(N, None)
        return one_hot

    def transform(self, chemical_formula: str) -> ElementOneHotRepresentation:
        return ElementOneHotRepresentation(self._generate_one_hot(chemical_formula), self.element_dict, self.keys)

if __name__ == "__main__":
    formula = "SrTiO3H2"
    gen = ElementOneHotGenerator()
    rep = gen.transform(formula)
    print(rep.as_array())
    print("-" * 30)

    gen = ElementOneHotGenerator()
    gen.fit(N=80)
    rep = gen.transform(formula)
    print(rep.as_df())
    print("-" * 30)

    formula = "SrTiO3H2"
    gen = ElementOneHotGenerator()
    gen.fit(elements=["O", "Ti", "Sr", "H"])
    rep = gen.transform(formula)
    print(rep.as_df())
    print("-" * 30)

    formula = "H0.2He0.7O0.1"
    gen = ElementOneHotGenerator()
    array = gen.transform(formula)
    print(array.as_df())


import typing as t
import typer
import json
import git
import sys
import os
import pathlib
import subprocess

fuam_path: pathlib.Path = pathlib.Path(os.path.dirname(os.path.abspath(sys.argv[0])))
cli: typer.Typer = typer.Typer()

@cli.command()
def configure() -> None:
    print("fuam configure 0.1\n")
    evaluate_response = lambda x, d: True if (x == "yes" or x == "y") else (d if x == "" else False)

    configuration: t.Dict[str, t.Union[str, bool, None]] = {
        "flipperzero-firmware-dir": None,
        "auto-build": None,
        "auto-upload": None
    }

    if (evaluate_response(input("Do you have the Flipper Zero firmware downloaded? [y/N] "), False)):
        configuration["flipperzero-firmware-dir"] = str(pathlib.Path(input("Path to the Flipper Zero firmware: ")))
    elif (evaluate_response(input("Do you want to download the Flipper Zero Firmware? [Y/n] "), True)):
        configuration["flipperzero-firmware-dir"] = f"{pathlib.Path(f'{fuam_path}/firmware')}"
        print("Downloading flipperdevices@flipperzero-firmware from github...")
        git.Repo.clone_from("https://github.com/flipperdevices/flipperzero-firmware/", configuration["flipperzero-firmware-dir"], None, None, ["--recursive"])
    else:
        print("Re-run `fuam configure` after you downloaded the Flipper Zero firmware")
        exit(0)

    configuration["auto-build"] = evaluate_response(input("Do you want fuam to build the application after download? [Y/n] "), True)

    if (configuration["auto-build"]):
        configuration["auto-upload"] = evaluate_response(input("Do you want fuam to upload the application after being built [Y/n] "), True)

    with open(str(pathlib.Path(f'{fuam_path}/configuration.fuam')), "w") as f:
        json.dump(configuration, f, indent=4)
        print(f"Saved configuration file to {pathlib.Path(f'{fuam_path}/configuration.fuam')}")

@cli.command()
def get(link: str, app_id: str, dist_name: t.Optional[t.Union[str, None]] = None) -> None:
    print("fuam get 0.1\n")
    dist: str = dist_name if dist_name != None else pathlib.Path(link).name # Funky solution, but this will return the last part of the URL

    with open(str(pathlib.Path(f"{faum_path}/configuration.fuam"))) as f:
        configuration: t.Dict[str, t.Union[str, bool, None]] = json.load(f)

    dist_path: pathlib.Path = pathlib.Path(f"{configuration['flipperzero-firmware-dir']}/applications_user/{dist}")
    print(f"Downloading {link} to {dist_path}...")
    git.Repo.clone_from(link, dist_path, None, None, ["--recursive"])

    if (configuration["auto-build"]):
        os.chdir(configuration["flipperzero-firmware-dir"])
        subprocess.run([str(pathlib.Path("./fbt")), f"fbt_{app_id}"])

        if (configuration["auto-upload"]):
            subprocess.run([str(pathlib.Path("./fbt")), "launch_app", f"APPSRC='{pathlib.Path(f'./applications_user/{dist}')}"])

@cli.command()
def version() -> None:
    print("Flipper User Application Manager 0.1")

if __name__ == "__main__":
    cli()


"""AdventOfCode Day18."""
import re

test_input_1 = """1 + 2 * 3 + 4 * 5 + 6"""
test_input_2 = """1 + (2 * 3) + (4 * (5 + 6))"""
test_input_3 = """5 + (8 * 3 + 9 + 3 * 4 * 3)"""
test_input_4 = """5 * 9 * (7 * 3 * 3 + 9 * 3 + (8 + 6 * 4))"""
test_input_5 = """((2 + 4 * 9) * (6 + 9 * 8 + 6) + 6) + 2 + 4 * 2"""
test_input_6 = """2 * 3 + (4 * 5)"""

OPERATORS = ["*", "+"]

def get_input():
    """Get puzzle input."""
    with open("input/day18.txt") as f:
        return f.read()

def part1(input_str: str):
    """Part1."""
    lines = input_str.strip().split("\n")
    sum = 0
    for line in lines:
        sum += calculate(line, False)
    return sum

def part2(input_str: str):
    """Part1."""
    lines = input_str.strip().split("\n")
    sum = 0
    for line in lines:
        x = calculate(line, True)
        # print(f"result: {x} formula: {line}")
        sum += x
    return sum

def calculate(input_str: str, part2: bool):
    """Input formula string and return result."""
    s = input_str
    while True:
        formulas = re.findall(
            r"(?P<formula>\((?P<formula_without_brackets>[0-9\+\*\s]+)\))", s
        )
        if len(formulas) == 0:
            break
        for formula in formulas:
            formula_result = calculate(formula[1], part2)
            s = s.replace(formula[0], str(formula_result))

    if part2:
        while True:
            formulas = re.findall(r"(?P<formula>[0-9]+ \+ [0-9]+)", s)
            if len(formulas) == 0:
                break
            for formula in formulas:
                result = formula.split(" ")
                s = s.replace(formula, str(int(result[0]) + int(result[2])), 1)

    operator = ""
    sum = 0
    for idx, c in enumerate(s.strip().split(" ")):
        if idx == 0:
            sum += int(c)
            continue
        elif c in OPERATORS:
            operator = c  # noqa
        else:
            if operator == "+":
                sum = sum + int(c)
            else:
                sum = int(c) * sum
    return sum

if __name__ == "__main__":
    assert calculate(test_input_1, False) == 71
    assert calculate(test_input_2, False) == 51
    print(f"Part1: {part1(get_input())}")
    assert calculate(test_input_2, True) == 51
    assert calculate(test_input_3, True) == 1445
    assert calculate(test_input_4, True) == 669060
    assert calculate(test_input_5, True) == 23340
    assert calculate(test_input_6, True) == 46
    print(f"Part2: {part2(get_input())}")


from transformers import BertTokenizer,GPT2LMHeadModel, AutoModelForCausalLM
hf_model_path = 'IDEA-CCNL/Wenzhong2.0-GPT2-110M-BertTokenizer-chinese'
tokenizer = BertTokenizer.from_pretrained(hf_model_path)
# model = GPT2LMHeadModel.from_pretrained(hf_model_path)
model = AutoModelForCausalLM.from_pretrained(hf_model_path)

def generate_word_level(input_text,n_return=5,max_length=128,top_p=0.9):
    inputs = tokenizer(input_text,return_tensors='pt',add_special_tokens=False).to(model.device)
    gen = model.generate(
                            inputs=inputs['input_ids'],
                            max_length=max_length,
                            do_sample=True,
                            top_p=top_p,
                            eos_token_id=21133,
                            pad_token_id=0,
                            num_return_sequences=n_return)

    sentences = tokenizer.batch_decode(gen)
    for idx,sentence in enumerate(sentences):
        print(f'sentence {idx}: {sentence}')
        print('*'*20)
    return gen
# 西湖的景色
outputs = generate_word_level('眼角斜瞥着柳翎那略微有些阴沉的脸庞。萧炎',n_return=5,max_length=128)
print(outputs)


"""
height means from top to this position, there are how many '1'
left means at current position, what is the index of left bound of the rectangle with height[j]. 0 means at this position, no rectangle.
right means the right bound index of this rectangle. 'n' means no rectangle.
"""
def maximalRectangle(matrix):
        if not matrix:
            return
        n = len(matrix[0])
        left, right, height = [0]*n, [n]*n, [0]*n
        res = 0

        for row in matrix:
            # calculate right
            currentRight = n
            for i in range(n-1,-1,-1):
                if row[i] == 1:
                    right[i] = min(right[i],currentRight)
                else:
                    right[i] = n
                    currentRight = i

            currentLeft = 0
            for i in range(n):
                # calculate height
                height[i] = height[i]+1 if row[i] == 1 else 0
                # calculate left
                if row[i] == 1:
                    left[i] = max(left[i],currentLeft)
                else:
                    left[i] = 0
                    currentLeft = i+1
                # calculate Rectangle
                res = max(res,height[i]*(right[i]-left[i]))
            print(left)
            print(right)
            print(height)
            print('\n')
        return res

# Driver Code
if __name__ == '__main__':
    A = [[0, 1, 1, 0],
         [1, 1, 1, 1],
         [1, 1, 1, 1],
         [1, 1, 0, 0]]
    print(maximalRectangle(A))


import numpy as np
import matplotlib.pyplot as plt
import math

def count(arr):
    tally = dict()
    for ele in arr:
        if ele not in tally.keys():
            tally[ele] = 0
        tally[ele] += 1
    return tally

def save_plot(x, y, name):
    plt.plot(x, y, 'o-')
    plt.xlim((0, 100))
    plt.savefig(name, bbox_inches="tight")
    plt.cla()

class CustomizedTheromEncoder():
    def __init__(self, encoding_len=8, debug_mode=False):
        self.thresholds = []
        self.debug_mode = debug_mode
        self.encoding_len = encoding_len

    def fit(self, data):
        temp_data = data
        temp_data.sort()
        if self.debug_mode:
            print(temp_data)
        tally = count(temp_data)
        if self.debug_mode:
            print(tally)

        temp_data_without_zero = temp_data[tally[0.0]:]
        total_num = len(temp_data_without_zero)
        if self.debug_mode:
            print('total_num: ', str(total_num))
        each_part = total_num / self.encoding_len
        if self.debug_mode:
            print('each part num: ', str(each_part))
        each_part_int = int(each_part)
        if self.debug_mode:
            print('each part int num: ', str(each_part_int))

        splited_data = []
        start_idx = 0
        for i in range(self.encoding_len):
            end_idx = start_idx + each_part_int
            if self.debug_mode:
                print('start idx: ', str(start_idx))
                print('end idx: ', str(end_idx))

            # if next element is same as last one in sub arr, move it into current sub array
            while end_idx < total_num and temp_data_without_zero[end_idx - 1] == temp_data_without_zero[end_idx]:
                end_idx += 1

            cur_sub_arr = temp_data_without_zero[start_idx:end_idx]
            splited_data.append(cur_sub_arr)

            start_idx = end_idx

        if self.debug_mode:
            print(splited_data)

            for i in splited_data:
                print(i)
                print(len(i))

        for sub in splited_data:
            if len(sub) != 0:
                self.thresholds.append(sub[0])

        if self.debug_mode:
            print("thresholds")
            print(self.thresholds)

    def encode(self, val):
        result = []
        for t in self.thresholds:
            if val > t:
                result.append(1)
            else:
                result.append(0)
        return result

    def transform(self, data):
        result = []
        for row in data:
            new_row = []
            for ele in row:
                new_row.append(self.encode(ele))
            result.append(new_row)

        return result

class StandardTheromEncoder:
    def __init__(self, encoding_len=8, debug_mode=False):
        self.interval = 0
        self.debug_mode = debug_mode
        self.encoding_len = encoding_len

    def fit(self, data):
        max_num = np.max(data)
        min_num = np.min(data)
        if self.debug_mode:
            print('max num: ', str(max_num))
            print('min num: ', str(min_num))

        self.interval = math.ceil((max_num - min_num) / self.encoding_len)
        if self.debug_mode:
            print('interval: ', str(self.interval))

    def encode(self, val):
        result = []
        for i in range(self.encoding_len):
            if val > i * self.interval:
                result.append(1)
            else:
                result.append(0)
        return result

    def transform(self, data):
        result = []
        for row in data:
            new_row = []
            for ele in row:
                new_row.append(self.encode(ele))
            result.append(new_row)

        return result


'''
https://www.codewars.com/kata/58f5c63f1e26ecda7e000029/python
In this simple Kata your task is to create a function that turns a string into a Mexican Wave.
You will be passed a string and you must return that string in an array where an uppercase letter is a person standing up.
'''

def wave(people):
    content = []
    for i ,person in enumerate(people):
        people_e = [p for p in people]
        people_e.pop(i)
        people_e.insert(i ,person.upper())
        people_e = ''.join(people_e)
        if people_e.islower(): continue
        content.append(people_e)
    return content

print(wave('hello piwo'))

'''
def wave(str):
    return [str[:i] + str[i].upper() + str[i+1:] for i in range(len(str)) if str[i].isalpha()]
'''


"""Functions for deriving indices"""

import xarray as xr
import numpy as np

def effective_temp(T):
    """Compute effective temperature
    Effective Temp = (1/2)*(yesterday's effective temp) + (1/2)*(today's actual temp)
    To make sense of the expansion, today's ET is consist of a portion of the actual temperature of each day up to today--half of today's temp, 1/4 of yesterday's temp, 1/8 of the day before yesterday's temp etc, thus it's "an exponentially smoothed temperature" as stated in the glossary of the reference.
    This derivation only considers 4 days of temperature data in the computation of EFT: today, yesterday, the day before yesterday, and two days before yesterday. Thus, the first 3 timesteps of the EFT will be NaN.

    Parameters
    ----------
    T: xr.DataArray
        Daily air temperature in any units

    Returns
    --------
    eft: xr.DataArray
        Effective temperature

    References
    ----------
    https://www.nationalgas.com/document/132516/download
    """
    # Get "yesterday" temp by shifting the time index back one time step (1 day)
    # Get "day before" temp by shifting the time index back two time steps (2 days)
    # Get "2 days before yesterday" temp by shifting the time index back three time steps (3 days)
    T_minus1 = T.shift(time=1)
    T_minus2 = T.shift(time=2)
    T_minus3 = T.shift(time=3)

    # Compute EFT, using 3 days back
    # Effective temp for 2 days before yesterday is set to the temperature of that day
    eft_minus3 = T_minus3
    eft_minus2 = eft_minus3 * 0.5 + T_minus2 * 0.5
    eft_minus1 = eft_minus2 * 0.5 + T_minus1 * 0.5
    eft = eft_minus1 * 0.5 + T * 0.5

    # Assign same attributes as input data
    # Or else, the output data will have no attributes :(
    eft.attrs = T.attrs

    return eft

def noaa_heat_index(T, RH):
    """Compute the NOAA Heat Index.
    See references for more information on the derivation on this index.

    Parameters
    ----------
    T: xr.DataArray
        Temperature in deg F
    RH: xr.DataArray
        Relative Humidity in percentage (0-100)

    Returns
    --------
    HI: xr.DataArray
        Heat index per timestep

    References
    -----------
    NOAA: https://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml
    NCAR NCL documentation: https://www.ncl.ucar.edu/Document/Functions/Heat_stress/heat_index_nws.shtml

    """
    T = T.reindex_like(RH)  # Need to have the same dimension/coordinate orders
    HI = (
        -42.379
        + 2.04901523 * T
        + 10.14333127 * RH
        - 0.22475541 * T * RH
        - 0.00683783 * T * T
        - 0.05481717 * RH * RH
        + 0.00122874 * T * T * RH
        + 0.00085282 * T * RH * RH
        - 0.00000199 * T * T * RH * RH
    )

    # Adjust for high temperature, low relative humidity
    # 80 < T < 112 (deg F)
    # RH < 13%
    adj_highT_lowRH = ((13 - RH) / 4) * ((17 - abs(T - 95)) / 17) ** (
        1 / 2
    )  # Adjustment
    HI_highT_lowRH = HI - adj_highT_lowRH  # Subtract adjustment from HI

    # Adjust for low temperature, high relative humidity
    # 80 < T < 87 (deg F)
    # RH > 85%
    adj_lowT_highRH = ((RH - 85) / 10) * ((87 - T) / 5)  # Adjustment
    HI_lowT_highRH = HI + adj_lowT_highRH  # Add adjustment from HI

    # Use different equation if heat index if the heat index value < 80
    low_HI = 0.5 * (T + 61.0 + ((T - 68.0) * 1.2) + (RH * 0.094))

    # Adjust heat index depending on different condions for RH, T, and valid range of HI
    HI = xr.where((RH < 13) & (T > 80) & (T < 112), HI_highT_lowRH, HI)
    HI = xr.where(((RH > 85) & (T < 87) & (T > 80)), HI_lowT_highRH, HI)
    HI = xr.where((HI < 80), low_HI, HI)

    # Following NCAR documentation (see function references), for temperature values less than 40F, the HI is set to the ambient temperature.
    HI = xr.where((T < 40), T, HI)

    # Reassign coordinate attributes
    # For some reason, these get improperly assigned in the xr.where step
    for coord in list(HI.coords):
        HI[coord].attrs = RH[coord].attrs

    # Assign units attribute
    HI.attrs["units"] = "degF"
    return HI

## ========== FOSBERG FIRE INDEX AND RELATED HELPER FUNCTIONS ==========

def fosberg_fire_index(t2_F, rh_percent, windspeed_mph):
    """Compute the Fosberg Fire Weather Index.
    Use hourly weather as inputs.
    Ensure that the input variables are in the correct units (see below).

    Parameters
    ----------
    t2_F: xr.DataArray
        Air temperature in units of Fahrenheit
    rh_percent: xr.DataArray
        Relative humidity in units of 0-100 (percent)
    windspeed_mph: xr.DataArray
        Windspeed in units of miles per hour

    Returns
    -------
    FFWI: xr.DataArray
        Fosberg Fire Weather Index computed for each grid cell

    References
    ----------
    https://a.atmos.washington.edu/wrfrt/descript/definitions/fosbergindex.html
    https://github.com/sharppy/SHARPpy/blob/main/sharppy/sharptab/fire.py
    https://www.spc.noaa.gov/exper/firecomp/INFO/fosbinfo.html

    """
    # Compute the equilibrium moisture constant
    m_low, m_mid, m_high = _equilibrium_moisture_constant(h=rh_percent, T=t2_F)

    # For RH < 10%, use the low m value.
    # For RH >= 10%, use the mid value
    m = xr.where(rh_percent < 10, m_low, m_mid)
    # For RH > 50%, use the high m value.
    m = xr.where(rh_percent > 50, m_high, m)

    # Compute the moisture dampening coefficient
    n = _moisture_dampening_coeff(m)

    # Compute the index
    U = windspeed_mph
    FFWI = (n * ((1 + U**2) ** 0.5)) / 0.3002

    # If fosberg index > 100, reset to 100
    FFWI = xr.where(FFWI < 100, FFWI, 100, keep_attrs=True)

    # If fosberg index is negative, set to 0
    FFWI = xr.where(FFWI > 0, FFWI, 0, keep_attrs=True)

    # Reassign coordinate attributes
    # For some reason, these get improperly assigned in the xr.where step
    for coord in list(FFWI.coords):
        FFWI[coord].attrs = t2_F[coord].attrs

    # Add descriptive attributes
    FFWI.name = "Fosberg Fire Weather Index"
    FFWI.attrs["units"] = "[0 to 100]"

    return FFWI

# Define some helper functions
def _equilibrium_moisture_constant(h, T):
    """Compute the equilibrium moisture constant.
    Dependent on relative humidity percent.
    Used to compute Fosberg Fire Weather Index.
    Will return three values corresponding to the level of humidity.

    Parameters
    ----------
    h: xr.DataArray
        relative humidity in units of 0-100 (percent)
    T: xr.DataArray
        air temperature in units of Fahrenheit

    Returns
    -------
    m_low: xr.DataArray
        equilibrium moisture constant for low humidity (<10%)
    m_mid: xr.DataArray
        equilibrium moisture constant for 10% < humidity <= 50%
    m_high: xr.DataArray
        equilibrium moisture constant for high humidity (>50%)

    """
    # h < 10: Low humidity
    m_low = 0.03229 + 0.281073 * h - 0.000578 * h * T

    # (10 < h <= 50): Mid humiditiy
    m_mid = 2.22749 + 0.160107 * h - 0.01478 * T

    # h > 50: High humidity
    m_high = 21.0606 + 0.005565 * (h**2) - 0.00035 * h * T - 0.483199 * h

    return (m_low, m_mid, m_high)

def _moisture_dampening_coeff(m):
    """Compute the moisture dampening coefficient.
    Used to compute Fosberg Fire Weather Index.

    Parameters
    ----------
    m: xr.DataArray
        equilibrium moisture constant

    """
    n = 1 - 2 * (m / 30) + 1.5 * (m / 30) ** 2 - 0.5 * (m / 30) ** 3
    return n


import sys
sys.stdin=open('../input.txt', 'r')

def size(n):
    q=[n]
    cnt=0
    while q:
        cnt+=1
        a=q.pop()
        q.extend(V1[a])
    return cnt

for t in range(1, int(input())+1):
    v, e, n1, n2 = map(int, input().split())
    n3=9**9
    V1 = [[] for _ in range(v+1)]
    V2 = [[] for _ in range(v+1)]
    data = [*map(int, input().split())]
    for i in range(e):
        V1[data[2*i]].append(data[2*i+1])
        V2[data[2*i+1]].append(data[2*i])
    while n1 != n3:
        n1=V2[n1][0]
        n3=n2
        while n3>1 and n1 != n3:
            n3=V2[n3][0]
    print('#%i'%t, n1, size(n1))


from pyrogram import filters,Client
import wikipedia
wikipedia.set_lang("it")
cprefix="/"

@Client.on_message(filters.command("wiki",cprefix))
async def my_handler(client, message):
    send = await message.reply_text("Cercando...")
    try:
        await send.edit_text(str(wikipedia.summary(message.text.split(" ",1)[1])))
    except Exception as e:
        await send.edit_text(e)
@Client.on_message(filters.command("wikilang",cprefix))
async def lingua(client, message):

    try:
        wikipedia.set_lang(message.command[1])
        await message.reply_text("Lingua cambiata con successo!")
    except:
        await message.reply_text("Mi sa... che hai inserito una lingua che non esiste")


GRAVITATIONAL_CONSTANT = 6.6743e-11  # unit of G : m^3 * kg^-1 * s^-2

def gravitational_law(
    force, mass_1, mass_2, distance):

    product_of_mass = mass_1 * mass_2

    if (force, mass_1, mass_2, distance).count(0) != 1:
        raise ValueError("One and only one argument must be 0")
    if force < 0:
        raise ValueError("Gravitational force can not be negative")
    if distance < 0:
        raise ValueError("Distance can not be negative")
    if mass_1 < 0 or mass_2 < 0:
        raise ValueError("Mass can not be negative")
    if force == 0:
        force = GRAVITATIONAL_CONSTANT * product_of_mass / (distance**2)
        return {"force": force}
    elif mass_1 == 0:
        mass_1 = (force) * (distance**2) / (GRAVITATIONAL_CONSTANT * mass_2)
        return {"mass_1": mass_1}
    elif mass_2 == 0:
        mass_2 = (force) * (distance**2) / (GRAVITATIONAL_CONSTANT * mass_1)
        return {"mass_2": mass_2}
    elif distance == 0:
        distance = (GRAVITATIONAL_CONSTANT * product_of_mass / (force)) ** 0.5
        return {"distance": distance}
    raise ValueError("One and only one argument must be 0")

if __name__ == "__main__":
    print('Enter the in following values and enter 0 in unknown value.')
    force  =  float(input('Enter the amount of force:'))
    mass_1 = float(input('Enter the amount of mass:'))
    mass_2 = float(input('Enter the amount of mass:'))
    distance = float(input('Enter the amount of distance:'))
    print(gravitational_law(
    force, mass_1, mass_2, distance))


from django.shortcuts import render
from django.views.generic import TemplateView, ListView
import django_tables2
import books.models
import books.filters
import books.tables

class FilteredSingleTableView(django_tables2.SingleTableView):
    filter_class = None

    def get_table_data(self):
        data = super(FilteredSingleTableView, self).get_table_data()
        self.filter = self.filter_class(self.request.GET, queryset=data)
        return self.filter.qs

    def get_context_data(self, **kwargs):
        context = super(FilteredSingleTableView, self).get_context_data(**kwargs)
        context['filter'] = self.filter
        return context

class BookFilteredSingleTableView(FilteredSingleTableView):
    model = books.models.Book
    table_class = books.tables.BookTable
    filter_class = books.filters.BookFilter

class BookSingleTableView(django_tables2.SingleTableView):
    model = books.models.Book
    table_class = books.tables.BookTable

class FilteredTableView(ListView):
    model = books.models.Book

    def get_context_data(self, **kwargs):
        context = super(FilteredTableView, self).get_context_data(**kwargs)
        filter = books.filters.BookFilter(self.request.GET, queryset=self.object_list)

        table = books.tables.BookTable(filter.qs)
        django_tables2.RequestConfig(self.request, ).configure(table )

        context['filter'] = filter
        context['table'] = table
        return context

class FilterExListView(ListView):
    model = books.models.Book

    def get_context_data(self, **kwargs):
        context = super(FilterExListView, self).get_context_data(**kwargs)
        filter = books.filters.BookFilterEx(self.request.GET, queryset=self.object_list)

        table = books.tables.BookTable(filter.qs)
        django_tables2.RequestConfig(self.request, ).configure(table )

        context['filter'] = filter
        context['table'] = table

        return context


# Released under the MIT License. See LICENSE for details.
#
"""Defines AppDelegate class for handling high level app functionality."""
from __future__ import annotations

from typing import TYPE_CHECKING

import babase

if TYPE_CHECKING:
    from typing import Callable
    import bascenev1

class AppDelegate:
    """Defines handlers for high level app functionality.

    Category: App Classes
    """

    def create_default_game_settings_ui(
        self,
        gameclass: type[bascenev1.GameActivity],
        sessiontype: type[bascenev1.Session],
        settings: dict | None,
        completion_call: Callable[[dict | None], None],
    ) -> None:
        """Launch a UI to configure the given game config.

        It should manipulate the contents of config and call completion_call
        when done.
        """
        # Replace the main window once we come up successfully.
        from bauiv1lib.playlist.editgame import PlaylistEditGameWindow

        assert babase.app.classic is not None
        babase.app.ui_v1.clear_main_menu_window(transition='out_left')
        babase.app.ui_v1.set_main_menu_window(
            PlaylistEditGameWindow(
                gameclass,
                sessiontype,
                settings,
                completion_call=completion_call,
            ).get_root_widget()
        )


import pygame
import snake as s
import animal as a
import config as cfg
import random
import util as u
from game import Game

from pygame.locals import (
    K_UP,
    K_DOWN,
    K_LEFT,
    K_RIGHT,
)

class SnakeGame(Game):
    def init(self):
        self.snake = s.Snake((cfg.BLOCK_SIZE, cfg.BLOCK_SIZE))
        self.last_keys = []

    def setup_events(self):
        self.GAME_TICK = pygame.USEREVENT + 1
        pygame.time.set_timer(self.GAME_TICK, cfg.TICK_RATE)

        self.SPAWN_ANIMAL = pygame.USEREVENT + 2
        pygame.time.set_timer(self.SPAWN_ANIMAL, 1000)

    def process_event(self, event):
        if event.type == self.GAME_TICK:
            self.snake.tick(self.move_dir())
        elif event.type == self.SPAWN_ANIMAL:
            animal = a.Animal((0, 0))
            self.random_animal_position(animal)
            while pygame.sprite.spritecollideany(animal, self.all_sprites):
                self.random_animal_position(animal)
            self.all_sprites.add(animal)
        return True

    def random_animal_position(self, animal):
        animal.rect.center = u.roundup(random.randint(Game.game_field.left + cfg.BLOCK_SIZE, Game.game_field.width - cfg.BLOCK_SIZE), cfg.BLOCK_SIZE), \
                    u.roundup(random.randint(Game.game_field.top + cfg.BLOCK_SIZE, Game.game_field.height - cfg.BLOCK_SIZE), cfg.BLOCK_SIZE)

    def move_dir(self):
        if len(self.last_keys) == 0:
            return None
        elif self.last_keys[K_UP]:
            if(self.snake.head.last_dir == K_DOWN):
                return None
            return K_UP
        elif self.last_keys[K_DOWN]:
            if(self.snake.head.last_dir == K_UP):
                return None
            return K_DOWN
        elif self.last_keys[K_LEFT]:
            if(self.snake.head.last_dir == K_RIGHT):
                return None
            return K_LEFT
        elif self.last_keys[K_RIGHT]:
            if(self.snake.head.last_dir == K_LEFT):
                return None
            return K_RIGHT

    def update(self):
        pressed_keys = pygame.key.get_pressed()
        if (pressed_keys[K_UP] or pressed_keys[K_DOWN] or pressed_keys[K_LEFT] or pressed_keys[K_RIGHT]):
            self.last_keys = pressed_keys
        return self.snake.update()

SnakeGame().run()